From 2c578ca683c1f69e42883bd11ddd169f48eaa144 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 24 Oct 2019 18:01:46 +0200 Subject: [PATCH 001/409] Ports move force and move resist, movement/pushing/pulling tweaks & co. --- .../lavaland_surface_ash_walker1.dmm | 2 +- _maps/RandomZLevels/VR/snowdin_VR.dmm | 6 +- _maps/RandomZLevels/caves.dmm | 16 +-- _maps/RandomZLevels/snowdin.dmm | 6 +- code/__DEFINES/misc.dm | 24 ---- code/__DEFINES/move_force.dm | 20 ++++ code/__DEFINES/time.dm | 24 ++++ code/__HELPERS/unsorted.dm | 2 +- code/controllers/subsystem/throwing.dm | 1 + code/datums/components/spawner.dm | 49 ++++++++ code/datums/martial/cqc.dm | 2 +- code/datums/martial/psychotic_brawl.dm | 2 +- code/datums/martial/sleeping_carp.dm | 2 +- code/game/atoms.dm | 2 +- code/game/atoms_movable.dm | 52 +++++--- .../game/gamemodes/clown_ops/clown_weapons.dm | 4 +- code/game/machinery/doors/door.dm | 1 + code/game/machinery/shieldgen.dm | 3 + .../game/mecha/equipment/tools/other_tools.dm | 4 +- code/game/mecha/equipment/weapons/weapons.dm | 2 +- code/game/mecha/mecha_defense.dm | 4 +- code/game/objects/effects/effects.dm | 1 + code/game/objects/items.dm | 18 +-- code/game/objects/items/dice.dm | 2 +- code/game/objects/items/handcuffs.dm | 4 +- code/game/objects/items/melee/misc.dm | 8 +- code/game/objects/items/singularityhammer.dm | 6 +- code/game/objects/items/stacks/bscrystal.dm | 2 +- code/game/objects/items/stacks/stack.dm | 2 +- code/game/objects/items/stunbaton.dm | 2 +- code/game/objects/items/theft_tools.dm | 2 +- code/game/objects/items/toys.dm | 8 +- code/game/objects/obj_defense.dm | 13 +- code/game/objects/objs.dm | 2 +- .../objects/structures/ghost_role_spawners.dm | 2 + code/game/objects/structures/grille.dm | 2 +- .../lavaland}/necropolis_tendril.dm | 64 +++++----- code/game/objects/structures/spawner.dm | 75 ++++++++++++ .../turfs/simulated/floor/plating/asteroid.dm | 8 +- code/game/turfs/simulated/lava.dm | 2 +- code/game/turfs/simulated/wall/misc_walls.dm | 2 +- .../clock_weapons/ratvarian_spear.dm | 8 +- code/modules/antagonists/cult/cult_items.dm | 18 +-- code/modules/antagonists/revenant/revenant.dm | 4 +- code/modules/assembly/infrared.dm | 2 +- code/modules/assembly/mousetrap.dm | 4 +- .../environmental/LINDA_turf_tile.dm | 3 +- .../atmospherics/machinery/atmosmachinery.dm | 1 + code/modules/events/immovable_rod.dm | 3 + code/modules/flufftext/Hallucination.dm | 4 +- code/modules/food_and_drinks/drinks/drinks.dm | 4 +- .../food_and_drinks/drinks/drinks/bottle.dm | 6 +- .../food_and_drinks/food/snacks_egg.dm | 2 +- .../food_and_drinks/food/snacks_other.dm | 4 +- .../food_and_drinks/food/snacks_pie.dm | 2 +- code/modules/food_and_drinks/pizzabox.dm | 2 +- code/modules/holiday/halloween/jacqueen.dm | 2 +- code/modules/holodeck/items.dm | 4 +- code/modules/hydroponics/grown.dm | 2 +- code/modules/hydroponics/growninedible.dm | 2 +- code/modules/mining/fulton.dm | 3 +- code/modules/mining/ores_coins.dm | 2 +- code/modules/mob/camera/camera.dm | 3 +- code/modules/mob/dead/dead.dm | 1 + .../modules/mob/dead/new_player/new_player.dm | 4 +- code/modules/mob/dead/observer/observer.dm | 5 - .../mob/living/carbon/alien/alien_defense.dm | 2 +- .../carbon/alien/humanoid/caste/hunter.dm | 16 +-- .../mob/living/carbon/alien/larva/larva.dm | 2 +- .../living/carbon/alien/special/facehugger.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 20 ++-- .../mob/living/carbon/carbon_defense.dm | 2 +- .../mob/living/carbon/human/human_defense.dm | 2 +- .../mob/living/carbon/monkey/combat.dm | 2 +- code/modules/mob/living/living.dm | 56 +++++---- code/modules/mob/living/living_defense.dm | 6 +- code/modules/mob/living/silicon/ai/ai.dm | 11 +- code/modules/mob/living/silicon/ai/death.dm | 2 +- .../mob/living/silicon/pai/pai_shell.dm | 2 +- .../mob/living/simple_animal/bot/honkbot.dm | 2 +- .../mob/living/simple_animal/bot/mulebot.dm | 4 +- .../mob/living/simple_animal/bot/secbot.dm | 2 +- .../mob/living/simple_animal/constructs.dm | 2 +- .../simple_animal/guardian/types/charger.dm | 14 +-- .../simple_animal/hostile/jungle/leaper.dm | 2 +- .../simple_animal/hostile/jungle/mook.dm | 2 +- .../simple_animal/hostile/jungle/seedling.dm | 2 +- .../hostile/megafauna/bubblegum.dm | 6 +- .../hostile/megafauna/megafauna.dm | 4 +- .../hostile/megafauna/swarmer.dm | 1 - .../hostile/mining_mobs/goliath.dm | 8 +- .../hostile/mining_mobs/hivelord.dm | 10 +- .../hostile/mining_mobs/mining_mobs.dm | 2 +- .../living/simple_animal/hostile/mushroom.dm | 2 +- .../simple_animal/hostile/netherworld.dm | 23 ++-- .../living/simple_animal/hostile/statue.dm | 5 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- .../mob/living/simple_animal/slime/slime.dm | 4 +- .../mob/living/simple_animal/spawner.dm | 113 ------------------ code/modules/mob/mob_movement.dm | 3 +- code/modules/ninja/energy_katana.dm | 2 +- code/modules/paperwork/paperplane.dm | 2 +- code/modules/power/gravitygenerator.dm | 1 + code/modules/power/lighting.dm | 2 +- .../power/singularity/containment_field.dm | 1 + .../power/singularity/field_generator.dm | 2 + code/modules/power/singularity/singularity.dm | 1 + .../mapGenerators/lavaland.dm | 6 +- .../projectiles/ammunition/_ammunition.dm | 2 +- code/modules/reagents/reagent_containers.dm | 4 +- code/modules/recycling/disposal/bin.dm | 2 +- .../ruins/objects_and_mobs/ash_walker_den.dm | 33 ++--- code/modules/shuttle/on_move.dm | 2 +- code/modules/spells/spell_types/conjure.dm | 2 +- code/modules/spells/spell_types/wizard.dm | 2 +- code/modules/surgery/bodyparts/bodyparts.dm | 2 +- code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/anchored_mobs.dm | 9 ++ .../living/silicon/robot/dogborg_equipment.dm | 16 +-- .../projectiles/guns/ballistic/spinfusor.dm | 6 +- tgstation.dme | 6 +- 121 files changed, 553 insertions(+), 437 deletions(-) create mode 100644 code/__DEFINES/move_force.dm create mode 100644 code/datums/components/spawner.dm rename code/{modules/mob/living/simple_animal/hostile/mining_mobs => game/objects/structures/lavaland}/necropolis_tendril.dm (71%) create mode 100644 code/game/objects/structures/spawner.dm delete mode 100644 code/modules/mob/living/simple_animal/spawner.dm create mode 100644 code/modules/unit_tests/anchored_mobs.dm diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm index ed5b07168f..1b4b6a5d43 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm @@ -266,7 +266,7 @@ /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "aH" = ( -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker, +/obj/structure/lavaland/ash_walker, /turf/open/lava/smooth{ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, diff --git a/_maps/RandomZLevels/VR/snowdin_VR.dmm b/_maps/RandomZLevels/VR/snowdin_VR.dmm index 8f6eda450c..0e67b7227c 100644 --- a/_maps/RandomZLevels/VR/snowdin_VR.dmm +++ b/_maps/RandomZLevels/VR/snowdin_VR.dmm @@ -3669,7 +3669,7 @@ /area/awaymission/snowdin/cave/cavern) "im" = ( /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 5 }, /turf/open/floor/engine/cult{ @@ -8272,7 +8272,7 @@ /turf/open/floor/engine/cult, /area/awaymission/snowdin/post/cavern2) "sb" = ( -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, @@ -10173,7 +10173,7 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index a25808d933..66ab3e60a8 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -103,7 +103,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_four) "at" = ( -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, @@ -164,7 +164,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_four) "aB" = ( -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -374,7 +374,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_three) "be" = ( -/mob/living/simple_animal/hostile/spawner/mining/goliath, +/obj/structure/spawner/mining/goliath, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -504,7 +504,7 @@ /area/awaymission/caves/BMP_asteroid/level_three) "bw" = ( /obj/effect/decal/cleanable/blood, -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -930,7 +930,7 @@ /turf/closed/wall, /area/awaymission/caves/BMP_asteroid/level_two) "cL" = ( -/mob/living/simple_animal/hostile/spawner/mining/basilisk, +/obj/structure/spawner/mining/basilisk, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -1644,7 +1644,7 @@ /turf/open/floor/plasteel, /area/awaymission/caves/listeningpost) "fb" = ( -/mob/living/simple_animal/hostile/spawner/mining/hivelord, +/obj/structure/spawner/mining/hivelord, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -2133,7 +2133,7 @@ /turf/open/floor/plasteel/recharge_floor, /area/awaymission/caves/BMP_asteroid) "gD" = ( -/mob/living/simple_animal/hostile/spawner/mining/hivelord, +/obj/structure/spawner/mining/hivelord, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -2206,7 +2206,7 @@ }, /area/awaymission/caves/BMP_asteroid) "gQ" = ( -/mob/living/simple_animal/hostile/spawner/mining/basilisk, +/obj/structure/spawner/mining/basilisk, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index 525c8fcf7b..13171fddcc 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -3664,7 +3664,7 @@ /area/awaymission/snowdin/cave/cavern) "im" = ( /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 5 }, /turf/open/floor/engine/cult{ @@ -8327,7 +8327,7 @@ /turf/open/floor/engine/cult, /area/awaymission/snowdin/post/cavern2) "sb" = ( -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, @@ -10237,7 +10237,7 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index bccf1f28dd..5ca0c99a63 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -25,30 +25,6 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define NOT_IMPLEMENTED "NOT_IMPLEMENTED" -#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day - -#define JANUARY 1 -#define FEBRUARY 2 -#define MARCH 3 -#define APRIL 4 -#define MAY 5 -#define JUNE 6 -#define JULY 7 -#define AUGUST 8 -#define SEPTEMBER 9 -#define OCTOBER 10 -#define NOVEMBER 11 -#define DECEMBER 12 - -//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead -#define NEW_YEAR "New Year" -#define VALENTINES "Valentine's Day" -#define APRIL_FOOLS "April Fool's Day" -#define EASTER "Easter" -#define HALLOWEEN "Halloween" -#define CHRISTMAS "Christmas" -#define FESTIVE_SEASON "Festive Season" - //Human Overlays Indexes///////// //LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS #define MUTATIONS_LAYER 31 //mutations. Tk headglows, cold resistance glow, etc diff --git a/code/__DEFINES/move_force.dm b/code/__DEFINES/move_force.dm new file mode 100644 index 0000000000..ec31388c72 --- /dev/null +++ b/code/__DEFINES/move_force.dm @@ -0,0 +1,20 @@ +//Defaults +#define MOVE_FORCE_DEFAULT 1000 +#define MOVE_RESIST_DEFAULT 1000 +#define PULL_FORCE_DEFAULT 1000 + +//Factors/modifiers +#define MOVE_FORCE_PULL_RATIO 1 //Same move force to pull objects +#define MOVE_FORCE_PUSH_RATIO 1 //Same move force to normally push +#define MOVE_FORCE_FORCEPUSH_RATIO 2 //2x move force to forcefully push +#define MOVE_FORCE_CRUSH_RATIO 3 //3x move force to do things like crush objects +#define MOVE_FORCE_THROW_RATIO 1 //Same force throw as resist to throw objects + +#define MOVE_FORCE_OVERPOWERING (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 10) +#define MOVE_FORCE_EXTREMELY_STRONG (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 3) +#define MOVE_FORCE_VERY_STRONG ((MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO) - 1) +#define MOVE_FORCE_STRONG (MOVE_FORCE_DEFAULT * 2) +#define MOVE_FORCE_NORMAL MOVE_FORCE_DEFAULT +#define MOVE_FORCE_WEAK (MOVE_FORCE_DEFAULT / 2) +#define MOVE_FORCE_VERY_WEAK ((MOVE_FORCE_DEFAULT / MOVE_FORCE_CRUSH_RATIO) + 1) +#define MOVE_FORCE_EXTREMELY_WEAK (MOVE_FORCE_DEFAULT / (MOVE_FORCE_CRUSH_RATIO * 3)) \ No newline at end of file diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index f13f13510b..e1fff1879e 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -1,3 +1,27 @@ +#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day + +#define JANUARY 1 +#define FEBRUARY 2 +#define MARCH 3 +#define APRIL 4 +#define MAY 5 +#define JUNE 6 +#define JULY 7 +#define AUGUST 8 +#define SEPTEMBER 9 +#define OCTOBER 10 +#define NOVEMBER 11 +#define DECEMBER 12 + +//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead +#define NEW_YEAR "New Year" +#define VALENTINES "Valentine's Day" +#define APRIL_FOOLS "April Fool's Day" +#define EASTER "Easter" +#define HALLOWEEN "Halloween" +#define CHRISTMAS "Christmas" +#define FESTIVE_SEASON "Festive Season" + /* Days of the week to make it easier to reference them. diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 3c8d62ce3a..da74045418 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1291,7 +1291,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) invisibility = 101 density = FALSE see_in_dark = 1e6 - anchored = TRUE + move_resist = INFINITY var/ready_to_die = FALSE /mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 77ad712b99..bf79cbda34 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -54,6 +54,7 @@ SUBSYSTEM_DEF(throwing) var/dist_y var/dx var/dy + var/force = MOVE_FORCE_DEFAULT var/pure_diagonal var/diagonal_error var/datum/callback/callback diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm new file mode 100644 index 0000000000..dc46603b1e --- /dev/null +++ b/code/datums/components/spawner.dm @@ -0,0 +1,49 @@ +/datum/component/spawner + var/mob_types = list(/mob/living/simple_animal/hostile/carp) + var/spawn_time = 300 //30 seconds default + var/list/spawned_mobs = list() + var/spawn_delay = 0 + var/max_mobs = 5 + var/spawn_text = "emerges from" + var/list/faction = list("mining") + +/datum/component/spawner/Initialize(_mob_types, _spawn_time, _faction, _spawn_text, _max_mobs) + if(_spawn_time) + spawn_time=_spawn_time + if(_mob_types) + mob_types=_mob_types + if(_faction) + faction=_faction + if(_spawn_text) + spawn_text=_spawn_text + if(_max_mobs) + max_mobs=_max_mobs + + RegisterSignal(parent, list(COMSIG_PARENT_QDELETED), .proc/stop_spawning) + START_PROCESSING(SSprocessing, src) + +/datum/component/spawner/process() + try_spawn_mob() + + +/datum/component/spawner/proc/stop_spawning(force, hint) + STOP_PROCESSING(SSprocessing, src) + for(var/mob/living/simple_animal/L in spawned_mobs) + if(L.nest == src) + L.nest = null + spawned_mobs = null + +/datum/component/spawner/proc/try_spawn_mob() + var/atom/P = parent + if(spawned_mobs.len >= max_mobs) + return 0 + if(spawn_delay > world.time) + return 0 + spawn_delay = world.time + spawn_time + var/chosen_mob_type = pick(mob_types) + var/mob/living/simple_animal/L = new chosen_mob_type(P.loc) + L.flags_1 |= (P.flags_1 & ADMIN_SPAWNED_1) + spawned_mobs += L + L.nest = src + L.faction = src.faction + P.visible_message("[L] [spawn_text] [P].") \ No newline at end of file diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index c7644997ee..390122bc81 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -127,7 +127,7 @@ if(A.grab_state >= GRAB_AGGRESSIVE) D.grabbedby(A, 1) else - A.start_pulling(D, 1) + A.start_pulling(D, supress_message = TRUE) if(A.pulling) D.stop_pulling() log_combat(A, D, "grabbed", addition="aggressively") diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index 34301516dc..50e3f7d334 100644 --- a/code/datums/martial/psychotic_brawl.dm +++ b/code/datums/martial/psychotic_brawl.dm @@ -25,7 +25,7 @@ if(A.grab_state >= GRAB_AGGRESSIVE) D.grabbedby(A, 1) else - A.start_pulling(D, 1) + A.start_pulling(D, supress_message = TRUE) if(A.pulling) D.drop_all_held_items() D.stop_pulling() diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 801e8c8c7a..933d96b179 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -108,7 +108,7 @@ if(A.grab_state >= GRAB_AGGRESSIVE) D.grabbedby(A, 1) else - A.start_pulling(D, 1) + A.start_pulling(D, supress_message = TRUE) if(A.pulling) D.drop_all_held_items() D.stop_pulling() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 7c9dc3f4fe..e41b0986cb 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -313,7 +313,7 @@ SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) return -/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) +/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 83762240bc..61cea6945e 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -3,6 +3,9 @@ var/last_move = null var/last_move_time = 0 var/anchored = FALSE + var/move_resist = MOVE_RESIST_DEFAULT + var/move_force = MOVE_FORCE_DEFAULT + var/pull_force = PULL_FORCE_DEFAULT var/datum/thrownthing/throwing = null var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported var/throw_range = 7 @@ -71,20 +74,20 @@ return FALSE return ..() -/atom/movable/proc/start_pulling(atom/movable/AM,gs) +/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) if(QDELETED(AM)) return FALSE - if(!(AM.can_be_pulled(src))) + if(!(AM.can_be_pulled(src, state, force))) return FALSE // If we're pulling something then drop what we're currently pulling and pull this instead. if(pulling) - if(gs==0) + if(state == 0) stop_pulling() return FALSE // Are we trying to pull something we are already pulling? Then enter grab cycle and end. if(AM == pulling) - grab_state = gs + grab_state = state if(istype(AM,/mob/living)) var/mob/living/AMob = AM AMob.grabbedby(src) @@ -95,11 +98,12 @@ AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM AM.pulledby = src - grab_state = gs + grab_state = state if(ismob(AM)) var/mob/M = AM log_combat(src, M, "grabbed", addition="passive grab") - visible_message("[src] has grabbed [M] passively!") + if(!supress_message) + visible_message("[src] has grabbed [M] passively!") return TRUE /atom/movable/proc/stop_pulling() @@ -461,17 +465,19 @@ /atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) set waitfor = 0 SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) - return hit_atom.hitby(src) + return hit_atom.hitby(src, throwingdatum=throwingdatum) -/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked) - if(!anchored && hitpush) +/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum) + if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO)))) step(src, AM.dir) ..() -/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) - return throw_at(target, range, speed, thrower, spin, diagonals_first, callback) +/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY) + if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY)) + return + return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force) -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) //If this returns FALSE then callback will not be called. +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY) //If this returns FALSE then callback will not be called. . = FALSE if (!target || speed <= 0) return @@ -517,6 +523,7 @@ TT.speed = speed TT.thrower = thrower TT.diagonals_first = diagonals_first + TT.force = force TT.callback = callback var/dist_x = abs(target.x - src.x) @@ -565,6 +572,22 @@ return 0 return 1 +/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + +/atom/movable/proc/force_push(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.force_pushed(src, force, direction) + if(!silent && .) + visible_message("[src] forcefully pushes against [AM]!", "You forcefully push against [AM]!") + +/atom/movable/proc/move_crush(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.move_crushed(src, force, direction) + if(!silent && .) + visible_message("[src] crushes past [AM]!", "You crush [AM]!") + +/atom/movable/proc/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + /atom/movable/CanPass(atom/movable/mover, turf/target) if(mover in buckled_mobs) return 1 @@ -784,14 +807,15 @@ /atom/movable/proc/get_cell() return -/atom/movable/proc/can_be_pulled(user) +/atom/movable/proc/can_be_pulled(user, grab_state, force) if(src == user || !isturf(loc)) return FALSE if(anchored || throwing) return FALSE + if(force < (move_resist * MOVE_FORCE_PULL_RATIO)) + return FALSE return TRUE - /obj/item/proc/do_pickup_animation(atom/target) set waitfor = FALSE if(!istype(loc, /turf)) diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index 9d1a3b650c..60ae5685ec 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -145,9 +145,9 @@ C.throw_mode_on() //so they can catch it on the return. return ..() -/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom) +/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(active) - var/caught = hit_atom.hitby(src, 0, 0) + var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it GET_COMPONENT(slipper, /datum/component/slippery) slipper.Slip(hit_atom) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index a2da7de29a..15b3c66c8b 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -5,6 +5,7 @@ icon_state = "door1" opacity = 1 density = TRUE + move_resist = MOVE_FORCE_VERY_STRONG layer = OPEN_DOOR_LAYER power_channel = ENVIRON max_integrity = 350 diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index fc6577a4f1..16016b8e18 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -4,6 +4,7 @@ icon = 'icons/effects/effects.dmi' icon_state = "shield-old" density = TRUE + move_resist = INFINITY opacity = 0 anchored = TRUE resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF @@ -93,6 +94,7 @@ /obj/machinery/shieldgen/proc/shields_up() active = TRUE update_icon() + move_resist = INFINITY for(var/turf/target_tile in range(shield_range, src)) if(isspaceturf(target_tile) && !(locate(/obj/structure/emergency_shield) in target_tile)) @@ -101,6 +103,7 @@ /obj/machinery/shieldgen/proc/shields_down() active = FALSE + move_resist = initial(move_resist) update_icon() QDEL_LIST(deployed_shields) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index a8ba9850ff..07ecdec508 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -84,7 +84,7 @@ switch(mode) if(1) if(!locked) - if(!istype(target) || target.anchored) + if(!istype(target) || target.anchored || target.move_resist >= MOVE_FORCE_EXTREMELY_STRON) occupant_message("Unable to lock on [target]") return locked = target @@ -110,7 +110,7 @@ else atoms = orange(3, target) for(var/atom/movable/A in atoms) - if(A.anchored) + if(A.anchored || A.move_resist >= MOVE_FORCE_EXTREMELY_STRONG) continue spawn(0) var/iter = 5-get_dist(A,target) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 9f8f3ef742..5d4d0e5899 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -436,7 +436,7 @@ throwforce = 35 icon_state = "punching_glove" -/obj/item/punching_glove/throw_impact(atom/hit_atom) +/obj/item/punching_glove/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) if(ismovableatom(hit_atom)) var/atom/movable/AM = hit_atom diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 62a62b569d..90cd5df79c 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -108,8 +108,8 @@ /obj/mecha/attack_tk() return -/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper - log_message("Hit by [A].", color="red") +/obj/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper + log_message("Hit by [AM].", color="red") . = ..() diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index 410923fe25..ccde9c2254 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -4,6 +4,7 @@ /obj/effect icon = 'icons/effects/effects.dmi' resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + move_resist = INFINITY obj_flags = 0 /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6a706fede9..542c3249ac 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -544,21 +544,21 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) else return -/obj/item/throw_impact(atom/A, datum/thrownthing/throwingdatum) - if(A && !QDELETED(A)) - SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A, throwingdatum) - if(is_hot() && isliving(A)) - var/mob/living/L = A +/obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(hit_atom && !QDELETED(hit_atom)) + SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) + if(is_hot() && isliving(hit_atom)) + var/mob/living/L = hit_atom L.IgniteMob() var/itempush = 1 if(w_class < 4) itempush = 0 //too light to push anything - return A.hitby(src, 0, itempush) + return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum) -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) thrownby = thrower callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own - . = ..(target, range, speed, thrower, spin, diagonals_first, callback) + . = ..(target, range, speed, thrower, spin, diagonals_first, callback, force) /obj/item/proc/after_throw(datum/callback/callback) if (callback) //call the original callback @@ -649,7 +649,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) else . = "" -/obj/item/hitby(atom/movable/AM) +/obj/item/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) return /obj/item/attack_hulk(mob/living/carbon/human/user) diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index cb0d4ec4ac..c6af6246bf 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -160,7 +160,7 @@ /obj/item/dice/attack_self(mob/user) diceroll(user) -/obj/item/dice/throw_impact(atom/target) +/obj/item/dice/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) diceroll(thrownby) . = ..() diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 246dd77684..d27ab8231b 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -340,7 +340,7 @@ return playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1) -/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed, return//abort var/mob/living/carbon/C = hit_atom @@ -368,7 +368,7 @@ w_class = WEIGHT_CLASS_SMALL breakouttime = 60 -/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscarbon(hit_atom)) var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom)) B.Crossed(hit_atom) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 10b84917bb..7494eb8e1c 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -332,13 +332,13 @@ if(proximity_flag) consume_everything(target) -/obj/item/melee/supermatter_sword/throw_impact(target) +/obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() - if(ismob(target)) - var/mob/M + if(ismob(hit_atom)) + var/mob/M = hit_atom if(src.loc == M) M.dropItemToGround(src) - consume_everything(target) + consume_everything(hit_atom) /obj/item/melee/supermatter_sword/pickup(user) ..() diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm index b6559c9091..1c20fcfacc 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/singularityhammer.dm @@ -105,10 +105,10 @@ playsound(src.loc, "sparks", 50, 1) shock(M) -/obj/item/twohanded/mjollnir/throw_impact(atom/target) +/obj/item/twohanded/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() - if(isliving(target)) - shock(target) + if(isliving(hit_atom)) + shock(hit_atom) /obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 49a735af9c..2d494ca186 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -35,7 +35,7 @@ /obj/item/stack/ore/bluespace_crystal/proc/blink_mob(mob/living/L) do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) -/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom) +/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) // not caught in mid-air visible_message("[src] fizzles and disappears upon impact!") var/turf/T = get_turf(hit_atom) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 155d1f1643..ea9440830d 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -335,7 +335,7 @@ merge(o) . = ..() -/obj/item/stack/hitby(atom/movable/AM, skip, hitpush) +/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(istype(AM, merge_type)) merge(AM) . = ..() diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index bfe630ba01..81956f147c 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -40,7 +40,7 @@ cell = new preload_cell_type(src) update_icon() -/obj/item/melee/baton/throw_impact(atom/hit_atom) +/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() //Only mob/living types have stun handling if(status && prob(throw_hit_chance) && iscarbon(hit_atom)) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index b99be7e988..243787dcb4 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -235,7 +235,7 @@ if(proximity && ismovableatom(O) && O != sliver) Consume(O, user) -/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins +/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins if(sliver) sliver.forceMove(loc) to_chat(usr, "\The [sliver] falls out of \the [src] as you throw them.") diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 46fabea8b0..2e4c45fa96 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -84,7 +84,7 @@ else return ..() -/obj/item/toy/balloon/throw_impact(atom/hit_atom) +/obj/item/toy/balloon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? balloon_burst(hit_atom) @@ -384,7 +384,7 @@ /obj/item/toy/snappop/fire_act(exposed_temperature, exposed_volume) pop_burst() -/obj/item/toy/snappop/throw_impact(atom/hit_atom) +/obj/item/toy/snappop/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) pop_burst() @@ -1006,7 +1006,7 @@ icon_state = "minimeteor" w_class = WEIGHT_CLASS_SMALL -/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) +/obj/item/toy/minimeteor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) for(var/mob/M in urange(10, src)) @@ -1055,7 +1055,7 @@ if(user.dropItemToGround(src)) throw_at(target, throw_range, throw_speed) -/obj/item/toy/snowball/throw_impact(atom/hit_atom) +/obj/item/toy/snowball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) playsound(src, 'sound/effects/pop.ogg', 20, 1) qdel(src) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 70a05a8d40..2d99f0e073 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -46,7 +46,7 @@ if(BURN) playsound(src.loc, 'sound/items/welder.ogg', 100, 1) -/obj/hitby(atom/movable/AM) +/obj/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) ..() var/throwdamage = AM.throwforce if(isobj(AM)) @@ -126,6 +126,17 @@ if(. && !play_soundeffect) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) +/obj/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return TRUE + +/obj/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + collision_damage(pusher, force, direction) + return TRUE + +/obj/proc/collision_damage(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10) + take_damage(amt, BRUTE) + /obj/attack_slime(mob/living/simple_animal/slime/user) if(!user.is_adult) return diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 6dd8a43130..cd19ceda50 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -80,7 +80,7 @@ SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) anchored = anchorvalue -/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) +/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) ..() if(obj_flags & FROZEN) visible_message("[src] shatters into a million pieces!") diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index b820e93c7b..e71a2720ae 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -44,6 +44,7 @@ roundstart = FALSE death = FALSE anchored = FALSE + move_resist = MOVE_FORCE_NORMAL density = FALSE flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. You would never leave its beautiful expanse. \ You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest." @@ -118,6 +119,7 @@ roundstart = FALSE death = FALSE anchored = FALSE + move_resist = MOVE_FORCE_NORMAL density = FALSE var/has_owner = FALSE var/can_transfer = TRUE //if golems can switch bodies to this new shell diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 00d1690d86..460059ffbf 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -258,7 +258,7 @@ take_damage(1, BURN, 0, 0) ..() -/obj/structure/grille/hitby(AM as mob|obj) +/obj/structure/grille/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(isobj(AM)) if(prob(50) && anchored && !broken) var/obj/O = AM diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm similarity index 71% rename from code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm rename to code/game/objects/structures/lavaland/necropolis_tendril.dm index e3c81b2639..b1e9a81087 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm +++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm @@ -1,39 +1,32 @@ //Necropolis Tendrils, which spawn lavaland monsters and break into a chasm when killed -/obj/effect/light_emitter/tendril - set_luminosity = 4 - set_cap = 2.5 - light_color = LIGHT_COLOR_LAVA - -/mob/living/simple_animal/hostile/spawner/lavaland +/obj/structure/spawner/lavaland name = "necropolis tendril" desc = "A vile tendril of corruption, originating deep underground. Terrible monsters are pouring out of it." + icon = 'icons/mob/nest.dmi' icon_state = "tendril" - icon_living = "tendril" - icon_dead = "tendril" + faction = list("mining") - weather_immunities = list("lava","ash") - health = 250 - maxHealth = 250 max_mobs = 3 - spawn_time = 300 //30 seconds default + max_integrity = 250 mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril) - spawn_text = "emerges from" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = INFINITY - loot = list(/obj/effect/collapse, /obj/structure/closet/crate/necropolis/tendril) - del_on_death = 1 + + move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it + anchored = TRUE + resistance_flags = FIRE_PROOF | LAVA_PROOF + var/gps = null var/obj/effect/light_emitter/tendril/emitted_light -/mob/living/simple_animal/hostile/spawner/lavaland/goliath + +/obj/structure/spawner/lavaland/goliath mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril) -/mob/living/simple_animal/hostile/spawner/lavaland/legion +/obj/structure/spawner/lavaland/legion mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril) -/mob/living/simple_animal/hostile/spawner/lavaland/Initialize() +GLOBAL_LIST_INIT(tendrils, list()) +/obj/structure/spawner/lavaland/Initialize() . = ..() emitted_light = new(loc) for(var/F in RANGE_TURFS(1, src)) @@ -41,18 +34,19 @@ var/turf/closed/mineral/M = F M.ScrapeAway(null, CHANGETURF_IGNORE_AIR) gps = new /obj/item/gps/internal(src) + GLOB.tendrils += src -/mob/living/simple_animal/hostile/spawner/lavaland/Destroy() - QDEL_NULL(emitted_light) - QDEL_NULL(gps) +/obj/structure/spawner/lavaland/deconstruct(disassembled) + new /obj/effect/collapse(loc) + new /obj/structure/closet/crate/necropolis/tendril(loc) return ..() -/mob/living/simple_animal/hostile/spawner/lavaland/death() + +/obj/structure/spawner/lavaland/Destroy() var/last_tendril = TRUE - for(var/mob/living/simple_animal/hostile/spawner/lavaland/other in GLOB.mob_living_list) - if(other != src) - last_tendril = FALSE - break + if(GLOB.tendrils.len>1) + last_tendril = FALSE + if(last_tendril && !(flags_1 & ADMIN_SPAWNED_1)) if(SSmedals.hub_enabled) for(var/mob/living/L in view(7,src)) @@ -60,7 +54,15 @@ continue SSmedals.UnlockMedal("[BOSS_MEDAL_TENDRIL] [ALL_KILL_MEDAL]", L.client) SSmedals.SetScore(TENDRIL_CLEAR_SCORE, L.client, 1) - ..() + GLOB.tendrils -= src + QDEL_NULL(emitted_light) + QDEL_NULL(gps) + return ..() + +/obj/effect/light_emitter/tendril + set_luminosity = 4 + set_cap = 2.5 + light_color = LIGHT_COLOR_LAVA /obj/effect/collapse name = "collapsing necropolis tendril" @@ -92,4 +94,4 @@ for(var/turf/T in range(2,src)) if(!T.density) T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland) - qdel(src) + qdel(src) \ No newline at end of file diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm new file mode 100644 index 0000000000..e67ef7af60 --- /dev/null +++ b/code/game/objects/structures/spawner.dm @@ -0,0 +1,75 @@ +/obj/structure/spawner + name = "monster nest" + icon = 'icons/mob/animal.dmi' + icon_state = "hole" + max_integrity = 100 + + move_resist = MOVE_FORCE_EXTREMELY_STRONG + anchored = TRUE + density = TRUE + + var/max_mobs = 5 + var/spawn_time = 300 //30 seconds default + var/mob_types = list(/mob/living/simple_animal/hostile/carp) + var/spawn_text = "emerges from" + var/faction = list("hostile") + +/obj/structure/spawner/Initialize() + . = ..() + AddComponent(/datum/component/spawner, mob_types, spawn_time, faction, spawn_text, max_mobs) + +/obj/structure/spawner/syndicate + name = "warp beacon" + icon = 'icons/obj/device.dmi' + icon_state = "syndbeacon" + spawn_text = "warps in from" + mob_types = list(/mob/living/simple_animal/hostile/syndicate/ranged) + faction = list(ROLE_SYNDICATE) + +/obj/structure/spawner/skeleton + name = "bone pit" + desc = "A pit full of bones, and some still seem to be moving..." + icon_state = "hole" + icon = 'icons/mob/nest.dmi' + max_integrity = 150 + max_mobs = 15 + spawn_time = 150 + mob_types = list(/mob/living/simple_animal/hostile/skeleton) + spawn_text = "climbs out of" + faction = list("skeleton") + +/obj/structure/spawner/mining + name = "monster den" + desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining asteroids." + icon_state = "hole" + max_integrity = 200 + max_mobs = 3 + icon = 'icons/mob/nest.dmi' + spawn_text = "crawls out of" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/simple_animal/hostile/asteroid/fugu) + faction = list("mining") + +/obj/structure/spawner/mining/goldgrub + name = "goldgrub den" + desc = "A den housing a nest of goldgrubs, annoying but arguably much better than anything else you'll find in a nest." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub) + +/obj/structure/spawner/mining/goliath + name = "goliath den" + desc = "A den housing a nest of goliaths, oh god why?" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath) + +/obj/structure/spawner/mining/hivelord + name = "hivelord den" + desc = "A den housing a nest of hivelords." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord) + +/obj/structure/spawner/mining/basilisk + name = "basilisk den" + desc = "A den housing a nest of basilisks, bring a coat." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk) + +/obj/structure/spawner/mining/wumborian + name = "wumborian fugu den" + desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu) \ No newline at end of file diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index d9966ee55c..d46c2363e3 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -155,9 +155,9 @@ has_data = TRUE /turf/open/floor/plating/asteroid/airless/cave/volcanic - mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 3, \ - /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /mob/living/simple_animal/hostile/spawner/lavaland = 2, \ - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /mob/living/simple_animal/hostile/spawner/lavaland/legion = 3, \ + mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \ + /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /obj/structure/spawner/lavaland = 2, \ + /mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /obj/structure/spawner/lavaland/legion = 3, \ SPAWN_MEGAFAUNA = 6, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10) data_having_type = /turf/open/floor/plating/asteroid/airless/cave/volcanic/has_data @@ -278,7 +278,7 @@ return //if there's a megafauna within standard view don't spawn anything at all if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(H, /mob/living/simple_animal/hostile/asteroid)) return //if the random is a standard mob, avoid spawning if there's another one within 12 tiles - if((ispath(randumb, /mob/living/simple_animal/hostile/spawner/lavaland) || istype(H, /mob/living/simple_animal/hostile/spawner/lavaland)) && get_dist(src, H) <= 2) + if((ispath(randumb, /obj/structure/spawner/lavaland) || istype(H, /obj/structure/spawner/lavaland)) && get_dist(src, H) <= 2) return //prevents tendrils spawning in each other's collapse range new randumb(T) diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index e24736ecf3..6a5a8aee3c 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -36,7 +36,7 @@ if(burn_stuff(AM)) START_PROCESSING(SSobj, src) -/turf/open/lava/hitby(atom/movable/AM) +/turf/open/lava/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(burn_stuff(AM)) START_PROCESSING(SSobj, src) diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm index 8b63d60939..d445be91cb 100644 --- a/code/game/turfs/simulated/wall/misc_walls.dm +++ b/code/game/turfs/simulated/wall/misc_walls.dm @@ -25,7 +25,7 @@ if(stored_pulling) stored_pulling.setDir(get_dir(stored_pulling.loc, newloc)) stored_pulling.forceMove(src) - H.start_pulling(stored_pulling, TRUE) + H.start_pulling(stored_pulling, supress_message = TRUE) /turf/closed/wall/mineral/cult/ratvar_act() . = ..() diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm index 3ad6684725..a004714e5e 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm @@ -45,10 +45,10 @@ bonus_damage *= 3 //total 30 damage on cultists, 50 with ratvar GLOB.clockwork_vitality += target.adjustFireLoss(bonus_damage) //adds the damage done to existing vitality -/obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/target) - var/turf/T = get_turf(target) - if(isliving(target)) - var/mob/living/L = target +/obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(is_servant_of_ratvar(L)) if(L.put_in_active_hand(src)) L.visible_message("[L] catches [src] out of the air!") diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 10759afcd0..445e4c9302 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -264,7 +264,7 @@ to_chat(user, "The bola seems to take on a life of its own!") throw_impact(user) -/obj/item/restraints/legcuffs/bola/cult/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/cult/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscultist(hit_atom)) return . = ..() @@ -689,10 +689,10 @@ /obj/item/twohanded/cult_spear/update_icon() icon_state = "bloodspear[wielded]" -/obj/item/twohanded/cult_spear/throw_impact(atom/target) - var/turf/T = get_turf(target) - if(isliving(target)) - var/mob/living/L = target +/obj/item/twohanded/cult_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(iscultist(L)) playsound(src, 'sound/weapons/throwtap.ogg', 50) if(L.put_in_active_hand(src)) @@ -983,11 +983,11 @@ return TRUE return FALSE -/obj/item/shield/mirror/throw_impact(atom/target, throwingdatum) - var/turf/T = get_turf(target) +/obj/item/shield/mirror/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) var/datum/thrownthing/D = throwingdatum - if(isliving(target)) - var/mob/living/L = target + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(iscultist(L)) playsound(src, 'sound/weapons/throwtap.ogg', 50) if(L.put_in_active_hand(src)) diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index f380fa68e9..66eab69f39 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -43,7 +43,7 @@ wander = FALSE density = FALSE movement_type = FLYING - anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING mob_size = MOB_SIZE_TINY pass_flags = PASSTABLE | PASSGRILLE | PASSMOB speed = 1 @@ -360,7 +360,7 @@ user.dropItemToGround(src) scatter() -/obj/item/ectoplasm/revenant/throw_impact(atom/hit_atom) +/obj/item/ectoplasm/revenant/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(inert) return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 07f31a6678..e9855bce46 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -142,7 +142,7 @@ . = ..() olddir = dir -/obj/item/assembly/infra/throw_impact() +/obj/item/assembly/infra/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!olddir) return diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index a2a9fb0105..9889a9e2c6 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -130,10 +130,10 @@ return FALSE -/obj/item/assembly/mousetrap/hitby(A as mob|obj) +/obj/item/assembly/mousetrap/hitby(atom/hit_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(!armed) return ..() - visible_message("[src] is triggered by [A].") + visible_message("[src] is triggered by [hit_atom].") triggered(null) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index ea555c9489..3967fc39b5 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -266,12 +266,13 @@ /atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0) var/const/PROBABILITY_OFFSET = 25 var/const/PROBABILITY_BASE_PRECENT = 75 + var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5) set waitfor = 0 var/move_prob = 100 if (pressure_resistance > 0) move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET move_prob += pressure_resistance_prob_delta - if (move_prob > PROBABILITY_OFFSET && prob(move_prob)) + if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO)))) step(src, direction) last_high_pressure_movement_air_cycle = SSair.times_fired diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 7d095869cb..c9b5eab18e 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -14,6 +14,7 @@ Pipelines + Other Objects -> Pipe network /obj/machinery/atmospherics anchored = TRUE + move_resist = INFINITY //Moving a connected machine without actually doing the normal (dis)connection things will probably cause a LOT of issues. idle_power_usage = 0 active_power_usage = 0 power_channel = ENVIRON diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index e041d566e9..27ca16fd3c 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -43,6 +43,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 icon = 'icons/obj/objects.dmi' icon_state = "immrod" throwforce = 100 + move_force = INFINITY + move_resist = INFINITY + pull_force = INFINITY density = TRUE anchored = TRUE var/mob/living/wizard diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index bac2e0bb65..b9f355a8cc 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -213,9 +213,9 @@ GLOBAL_LIST_INIT(hallucination_list, list( . = ..() name = "alien hunter ([rand(1, 1000)])" -/obj/effect/hallucination/simple/xeno/throw_impact(A) +/obj/effect/hallucination/simple/xeno/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) update_icon("alienh_pounce") - if(A == target && target.stat!=DEAD) + if(hit_atom == target && target.stat!=DEAD) target.Knockdown(100) target.visible_message("[target] flails around wildly.","[name] pounces on you!") diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 7b1d8be85e..40489eba9b 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -101,10 +101,10 @@ to_chat(user, "You heat [name] with [I]!") ..() -/obj/item/reagent_containers/food/drinks/throw_impact(atom/target, datum/thrownthing/throwinfo) +/obj/item/reagent_containers/food/drinks/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!.) //if the bottle wasn't caught - smash(target, throwinfo.thrower, TRUE) + smash(hit_atom, throwingdatum?.thrower, TRUE) /obj/item/reagent_containers/food/drinks/proc/smash(atom/target, mob/thrower, ranged = FALSE) if(!isGlass) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index e72b624ae5..16878bcf75 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -442,7 +442,7 @@ isGlass = FALSE return -/obj/item/reagent_containers/food/drinks/bottle/molotov/throw_impact(atom/target,datum/thrownthing/throwdata) +/obj/item/reagent_containers/food/drinks/bottle/molotov/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/firestarter = 0 for(var/datum/reagent/R in reagents.reagent_list) for(var/A in accelerants) @@ -450,8 +450,8 @@ firestarter = 1 break if(firestarter && active) - target.fire_act() - new /obj/effect/hotspot(get_turf(target)) + hit_atom.fire_act() + new /obj/effect/hotspot(get_turf(hit_atom)) ..() /obj/item/reagent_containers/food/drinks/bottle/molotov/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/food_and_drinks/food/snacks_egg.dm b/code/modules/food_and_drinks/food/snacks_egg.dm index 510783479e..fdc02c96e4 100644 --- a/code/modules/food_and_drinks/food/snacks_egg.dm +++ b/code/modules/food_and_drinks/food/snacks_egg.dm @@ -31,7 +31,7 @@ var/color = mix_color_from_reagents(reagents.reagent_list) add_atom_colour(color, FIXED_COLOUR_PRIORITY) -/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? var/turf/T = get_turf(hit_atom) new/obj/effect/decal/cleanable/egg_smudge(T) diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index ad0824dd79..3a60e991a9 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -439,8 +439,8 @@ head.color = C add_overlay(head) -/obj/item/reagent_containers/food/snacks/lollipop/throw_impact(atom/A) - ..(A) +/obj/item/reagent_containers/food/snacks/lollipop/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + ..(hit_atom) throw_speed = 1 throwforce = 0 diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm index bc66d353e1..f32ebbb3a0 100644 --- a/code/modules/food_and_drinks/food/snacks_pie.dm +++ b/code/modules/food_and_drinks/food/snacks_pie.dm @@ -29,7 +29,7 @@ foodtype = GRAIN | DAIRY | SUGAR var/stunning = TRUE -/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!.) //if we're not being caught splat(hit_atom) diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index d608a73560..58f7985291 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -231,7 +231,7 @@ if(boxes.len >= 3 && prob(25 * boxes.len)) disperse_pizzas() -/obj/item/pizzabox/throw_impact(atom/movable/AM) +/obj/item/pizzabox/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(boxes.len >= 2 && prob(20 * boxes.len)) disperse_pizzas() diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index b2f69df2e4..b033755650 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -422,7 +422,7 @@ reagents.add_reagent(R, 30) name = "[R] Potion" -/obj/item/reagent_containers/potion_container/throw_impact(atom/target) +/obj/item/reagent_containers/potion_container/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() sleep(20) var/datum/effect_system/smoke_spread/chem/s = new() diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index 5c143f7a25..54c940dfbc 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -80,7 +80,7 @@ item_state = "dodgeball" desc = "Used for playing the most violent and degrading of childhood games." -/obj/item/toy/beach_ball/holoball/dodgeball/throw_impact(atom/hit_atom) +/obj/item/toy/beach_ball/holoball/dodgeball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if((ishuman(hit_atom))) var/mob/living/carbon/M = hit_atom @@ -123,7 +123,7 @@ else ..() -/obj/structure/holohoop/hitby(atom/movable/AM) +/obj/structure/holohoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if (isitem(AM) && !istype(AM,/obj/item/projectile)) if(prob(50)) AM.forceMove(get_turf(src)) diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 096c7b5b2b..5cc7fcc57a 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -91,7 +91,7 @@ squash(user) ..() -/obj/item/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? if(seed) for(var/datum/plant_gene/trait/T in seed.genes) diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm index c0e3beaf79..3ef6c1472f 100644 --- a/code/modules/hydroponics/growninedible.dm +++ b/code/modules/hydroponics/growninedible.dm @@ -48,7 +48,7 @@ return 1 return 0 -/obj/item/grown/throw_impact(atom/hit_atom) +/obj/item/grown/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? if(seed) for(var/datum/plant_gene/trait/T in seed.genes) diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index f97d3612a8..af8860c02b 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) var/uses_left = 3 var/can_use_indoors var/safe_for_living_creatures = 1 + var/max_force_fulton = MOVE_FORCE_STRONG /obj/item/extraction_pack/examine() . = ..() @@ -57,7 +58,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) return if(!isturf(A.loc)) // no extracting stuff inside other stuff return - if(A.anchored) + if(A.anchored || (A.move_resist > max_force_fulton)) return to_chat(user, "You start attaching the pack to [A]...") if(do_after(user,50,target=A)) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 69361e8685..1ce735b0b8 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ recipes = GLOB.sand_recipes . = ..() -/obj/item/stack/ore/glass/throw_impact(atom/hit_atom) +/obj/item/stack/ore/glass/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(..() || !ishuman(hit_atom)) return var/mob/living/carbon/human/C = hit_atom diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm index ee89167f29..dffaf9e4e7 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/camera/camera.dm @@ -3,7 +3,8 @@ /mob/camera name = "camera mob" density = FALSE - anchored = TRUE + move_force = INFINITY + move_resist = INFINITY status_flags = GODMODE // You can't damage it. mouse_opacity = MOUSE_OPACITY_TRANSPARENT see_in_dark = 7 diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 35dbe0828f..213a6fd6db 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -4,6 +4,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) /mob/dead sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF + move_resist = INFINITY throwforce = 0 /mob/dead/Initialize() diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 591fc650b4..54c09184a3 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -12,8 +12,6 @@ stat = DEAD canmove = FALSE - anchored = TRUE // don't get pushed around - var/mob/living/new_character //for instant transfer once the round is set up //Used to make sure someone doesn't get spammed with messages if they're ineligible for roles @@ -151,7 +149,7 @@ message_admins(msg) to_chat(usr, "The round is either not ready, or has already finished...") return - + if(!GLOB.enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") return diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index d599d55886..e6a57f3180 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -12,7 +12,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) stat = DEAD density = FALSE canmove = 0 - anchored = TRUE // don't get pushed around see_invisible = SEE_INVISIBLE_OBSERVER see_in_dark = 100 invisibility = INVISIBILITY_OBSERVER @@ -619,10 +618,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(src, "This creature is too powerful for you to possess!") return 0 - if(istype (target, /mob/living/simple_animal/hostile/spawner)) - to_chat(src, "This isn't really a creature, now is it!") - return 0 - if(!can_reenter_round) to_chat(src, "You are unable to re-enter the round.") return FALSE diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index b9e27c0637..daffca106f 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -5,7 +5,7 @@ /mob/living/carbon/alien/get_ear_protection() return 2 //no ears -/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush) +/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) ..(AM, skipcatch = TRUE, hitpush = FALSE) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index fe682b5c99..c75718e65c 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -54,18 +54,18 @@ weather_immunities -= "lava" update_icons() -/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) +/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!leaping) return ..() pounce_cooldown = world.time + pounce_cooldown_time - if(A) - if(isliving(A)) - var/mob/living/L = A + if(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom var/blocked = FALSE - if(ishuman(A)) - var/mob/living/carbon/human/H = A + if(ishuman(hit_atom)) + var/mob/living/carbon/human/H = hit_atom if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK)) blocked = TRUE if(!blocked) @@ -77,8 +77,8 @@ Knockdown(40, 1, 1) toggle_leap(0) - else if(A.density && !A.CanPass(src)) - visible_message("[src] smashes into [A]!", "[src] smashes into [A]!") + else if(hit_atom.density && !hit_atom.CanPass(src)) + visible_message("[src] smashes into [hit_atom]!", "[src] smashes into [hit_atom]!") Knockdown(40, 1, 1) if(leaping) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index e1e079cbae..3b150a2264 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -57,7 +57,7 @@ /mob/living/carbon/alien/larva/toggle_throw_mode() return -/mob/living/carbon/alien/larva/start_pulling() +/mob/living/carbon/alien/larva/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) return /mob/living/carbon/alien/larva/stripPanelUnequip(obj/item/what, mob/who) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index e66d70f492..6b04233464 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -115,7 +115,7 @@ if(icon_state == "[initial(icon_state)]_thrown") icon_state = "[initial(icon_state)]" -/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom) +/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(stat == CONSCIOUS) icon_state = "[initial(icon_state)]" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 263edf42c2..a81545fbe5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -94,15 +94,13 @@ return 1 return ..() -/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum) +/mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() var/hurt = TRUE - if(istype(throwingdatum, /datum/thrownthing)) - var/datum/thrownthing/D = throwingdatum - if(iscyborg(D.thrower)) - var/mob/living/silicon/robot/R = D.thrower - if(!R.emagged) - hurt = FALSE + if(throwingdatum?.thrower && iscyborg(throwingdatum.thrower)) + var/mob/living/silicon/robot/R = throwingdatum.thrower + if(!R.emagged) + hurt = FALSE if(hit_atom.density && isturf(hit_atom)) if(hurt) Knockdown(20) @@ -160,7 +158,7 @@ //END OF CIT CHANGES var/atom/movable/thrown_thing - var/obj/item/I = src.get_active_held_item() + var/obj/item/I = get_active_held_item() if(!I) if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE) @@ -188,11 +186,11 @@ if(thrown_thing) visible_message("[src] has thrown [thrown_thing].") - src.log_message("has thrown [thrown_thing]", LOG_ATTACK) + log_message("has thrown [thrown_thing]", LOG_ATTACK) do_attack_animation(target, no_effect = 1) playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) newtonian_move(get_dir(target, src)) - thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src) + thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force) /mob/living/carbon/restrained(ignore_grab) . = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)) @@ -448,7 +446,7 @@ I.throw_at(target,I.throw_range,I.throw_speed,src) if(61 to 90) //throw it down to the floor var/turf/target = get_turf(loc) - I.throw_at(target,I.throw_range,I.throw_speed,src) + I.safe_throw_at(target,I.throw_range,I.throw_speed,src, force = move_force) /mob/living/carbon/Stat() ..() diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index bc64c8303b..626923a003 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -58,7 +58,7 @@ return return TRUE -/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) +/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(!skipcatch) //ugly, but easy if(can_catch_item()) if(istype(AM, /obj/item)) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index a44779e05e..3333459dca 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -124,7 +124,7 @@ return TRUE return FALSE -/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(dna && dna.species) var/spec_return = dna.species.spec_hitby(AM, src) if(spec_return) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 25bc243f07..180c638448 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -384,7 +384,7 @@ retaliate(Proj.firer) ..() -/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 812733ebe2..5afd2adace 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -59,7 +59,7 @@ return if(ismovableatom(A)) var/atom/movable/AM = A - if(PushAM(AM)) + if(PushAM(AM, move_force)) return /mob/living/Bumped(atom/movable/AM) @@ -202,33 +202,43 @@ return //Called when we want to push an atom/movable -/mob/living/proc/PushAM(atom/movable/AM) +/mob/living/proc/PushAM(atom/movable/AM, force = move_force) if(now_pushing) - return 1 + return TRUE if(moving_diagonally)// no pushing during diagonal moves. - return 1 + return TRUE if(!client && (mob_size < MOB_SIZE_SMALL)) return - if(!AM.anchored) - now_pushing = 1 - var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - var/obj/structure/window/W = AM - if(W.fulltile) - for(var/obj/structure/window/win in get_step(W,t)) - now_pushing = 0 - return - if(pulling == AM) - stop_pulling() - var/current_dir - if(isliving(AM)) - current_dir = AM.dir - step(AM, t) - if(current_dir) - AM.setDir(current_dir) - now_pushing = 0 + now_pushing = TRUE + var/t = get_dir(src, AM) + var/push_anchored = FALSE + if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force) + if(move_crush(AM, move_force, t)) + push_anchored = TRUE + if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally + if(force_push(AM, move_force, t, push_anchored)) + push_anchored = TRUE + if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO))) + now_pushing = FALSE + return + if (istype(AM, /obj/structure/window)) + var/obj/structure/window/W = AM + if(W.fulltile) + for(var/obj/structure/window/win in get_step(W,t)) + now_pushing = FALSE + return + if(pulling == AM) + stop_pulling() + var/current_dir + if(isliving(AM)) + current_dir = AM.dir + if(step(AM, t)) + step(src, t) + if(current_dir) + AM.setDir(current_dir) + now_pushing = FALSE -/mob/living/start_pulling(atom/movable/AM, supress_message = 0) +/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE) if(!AM || !src) return FALSE if(!(AM.can_be_pulled(src))) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 9d04f288cd..fe35f1bf57 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -55,7 +55,7 @@ else return 0 -/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) +/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest @@ -120,7 +120,7 @@ adjust_fire_stacks(3) IgniteMob() -/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0) +/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE) if(user == anchored || !isturf(user.loc)) return FALSE @@ -146,7 +146,7 @@ return FALSE if(!user.pulling || user.pulling != src) - user.start_pulling(src, supress_message) + user.start_pulling(src, supress_message = supress_message) return if(!(status_flags & CANPUSH) || HAS_TRAIT(src, TRAIT_PUSHIMMUNE)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1b1eb1a805..551d9f4a99 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -16,7 +16,7 @@ name = "AI" icon = 'icons/mob/ai.dmi' icon_state = "ai" - anchored = TRUE + move_resist = MOVE_FORCE_VERY_STRONG density = TRUE canmove = FALSE status_flags = CANSTUN|CANPUSH @@ -318,9 +318,14 @@ return // stop if(incapacitated()) return - anchored = !anchored // Toggles the anchor + var/is_anchored = FALSE + if(move_resist == MOVE_FORCE_VERY_STRONG) + move_resist = MOVE_FORCE_VERY_STRONG + else + is_anchored = TRUE + move_resist = MOVE_FORCE_NORMAL - to_chat(src, "You are now [anchored ? "" : "un"]anchored.") + to_chat(src, "You are now [is_anchored ? "" : "un"]anchored.") // the message in the [] will change depending whether or not the AI is anchored /mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 301d2bd218..319d94611b 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -14,7 +14,7 @@ cameraFollow = null - anchored = FALSE //unbolt floorbolts + move_resist = MOVE_FORCE_NORMAL update_canmove() if(eyeobj) eyeobj.setLoc(get_turf(src)) diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index 164a3e7389..ecb80961cb 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -99,7 +99,7 @@ if(loc != card) visible_message("[src] [rest? "lays down for a moment..." : "perks up from the ground"]") -/mob/living/silicon/pai/start_pulling(atom/movable/AM) +/mob/living/silicon/pai/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) return FALSE /mob/living/silicon/pai/proc/toggle_integrated_light() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 1c19cd82a1..62667c0e58 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -155,7 +155,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, bike_horn(A) -/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) +/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) playsound(src, honksound, 50, TRUE, -1) var/obj/item/I = AM diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 1bc7493684..66bfd64a7d 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -13,8 +13,8 @@ desc = "A Multiple Utility Load Effector bot." icon_state = "mulebot0" density = TRUE - anchored = TRUE - animate_movement=1 + move_resist = MOVE_FORCE_STRONG + animate_movement = 1 health = 50 maxHealth = 50 damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index f22139ac22..fe02339403 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -221,7 +221,7 @@ Auto Patrol: []"}, ..() -/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby)) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 3cc8822d02..ea7f5fe5ae 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -338,7 +338,7 @@ stored_pulling.forceMove(loc) forceMove(AM) if(stored_pulling) - start_pulling(stored_pulling, TRUE) //drag anything we're pulling through the wall with us by magic + start_pulling(stored_pulling, supress_message = TRUE) //drag anything we're pulling through the wall with us by magic /mob/living/simple_animal/hostile/construct/harvester/AttackingTarget() if(iscarbon(target)) diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 3ece5d4e27..184da11d02 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -44,18 +44,18 @@ if(!charging) ..() -/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/A) +/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!charging) return ..() - else if(A) - if(isliving(A) && A != summoner) - var/mob/living/L = A + else if(hit_atom) + if(isliving(hit_atom) && hit_atom != summoner) + var/mob/living/L = hit_atom var/blocked = FALSE - if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them + if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them blocked = TRUE - if(ishuman(A)) - var/mob/living/carbon/human/H = A + if(ishuman(hit_atom)) + var/mob/living/carbon/human/H = hit_atom if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK)) blocked = TRUE if(!blocked) diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index d1e8f1f49e..72ae49eb0d 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -249,7 +249,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/Goto() return -/mob/living/simple_animal/hostile/jungle/leaper/throw_impact() +/mob/living/simple_animal/hostile/jungle/leaper/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) return /mob/living/simple_animal/hostile/jungle/leaper/update_icons() diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm index 29f48c7295..b786637592 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -147,7 +147,7 @@ update_icons() Goto(target, move_to_delay, minimum_distance) -/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, throwingdatum) +/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(isliving(hit_atom) && attack_state == MOOK_ATTACK_ACTIVE) var/mob/living/L = hit_atom diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm index 1a894734d8..8a1cfb7125 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm @@ -29,7 +29,7 @@ projectilesound = 'sound/weapons/pierce.ogg' robust_searching = TRUE stat_attack = UNCONSCIOUS - anchored = TRUE + move_resist = MOVE_FORCE_EXTREMELY_STRONG var/combatant_state = SEEDLING_STATE_NEUTRAL var/obj/seedling_weakpoint/weak_point var/mob/living/beam_debuff_target 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 45745bd84e..83abde2fca 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -158,12 +158,12 @@ Difficulty: Hard DestroySurroundings() ..() -/mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/A) +/mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!charging) return ..() - else if(isliving(A)) - var/mob/living/L = A + else if(isliving(hit_atom)) + var/mob/living/L = hit_atom L.visible_message("[src] slams into [L]!", "[src] slams into you!") L.apply_damage(40, BRUTE) playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) 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 d62f59cdd7..2ac8dd80c0 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -21,7 +21,9 @@ maxbodytemp = INFINITY vision_range = 4 aggro_vision_range = 15 - anchored = TRUE + move_force = MOVE_FORCE_OVERPOWERING + move_resist = MOVE_FORCE_OVERPOWERING + pull_force = MOVE_FORCE_OVERPOWERING mob_size = MOB_SIZE_LARGE layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index 786d7a9775..c7d90f9556 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa weather_immunities = list("lava","ash") stop_automated_movement = TRUE wander = FALSE - anchored = TRUE layer = BELOW_MOB_LAYER AIStatus = AI_OFF var/swarmer_spawn_cooldown = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index 15f2a0a834..c17e98a7db 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -27,7 +27,9 @@ throw_message = "does nothing to the rocky hide of the" vision_range = 4 aggro_vision_range = 7 - anchored = TRUE //Stays anchored until death as to be unpullable + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG var/pre_attack = 0 var/pre_attack_icon = "Goliath_preattack" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) @@ -51,7 +53,9 @@ . = 1 /mob/living/simple_animal/hostile/asteroid/goliath/death(gibbed) - anchored = FALSE + move_force = MOVE_FORCE_DEFAULT + move_resist = MOVE_RESIST_DEFAULT + pull_force = PULL_FORCE_DEFAULT ..(gibbed) /mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index 82f85766c2..9e398ce0da 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -217,7 +217,7 @@ can_infest_dead = TRUE //Legion that spawns Legions -/mob/living/simple_animal/hostile/spawner/legion +/mob/living/simple_animal/hostile/big_legion name = "legion" desc = "One of many." icon = 'icons/mob/lavaland/64x64megafauna.dmi' @@ -226,10 +226,6 @@ icon_dead = "legion" health = 450 maxHealth = 450 - max_mobs = 3 - spawn_time = 200 - spawn_text = "peels itself off from" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion) melee_damage_lower = 20 melee_damage_upper = 20 anchored = FALSE @@ -252,6 +248,10 @@ see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE +/mob/living/simple_animal/hostile/big_legion/Initialize() + .=..() + AddComponent(/datum/component/spawner, list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion), 200, faction, "peels itself off from", 3) + //Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms. /obj/effect/mob_spawn/human/corpse/charredskeleton name = "charred skeletal remains" diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index 05dec578bd..c040931979 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -45,7 +45,7 @@ visible_message("[P] has a reduced effect on [src]!") ..() -/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy +/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)//No floor tiling them to death, wiseguy if(istype(AM, /obj/item)) var/obj/item/T = AM if(!stat) diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index dbaa8ab5fa..67a2282abc 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -170,7 +170,7 @@ if(M.a_intent == INTENT_HARM) Bruise() -/mob/living/simple_animal/hostile/mushroom/hitby(atom/movable/AM) +/mob/living/simple_animal/hostile/mushroom/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) ..() if(istype(AM, /obj/item)) var/obj/item/T = AM diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index 8210fd6490..d144ad272b 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -65,33 +65,30 @@ attacktext = "punches" deathmessage = "falls apart into a fine dust." -/mob/living/simple_animal/hostile/spawner/nether +/obj/structure/spawner/nether name = "netherworld link" desc = "A direct link to another dimension full of creatures not very happy to see you. Entering the link would be a very bad idea." icon_state = "nether" - icon_living = "nether" - health = 50 - maxHealth = 50 + max_integrity = 50 spawn_time = 600 //1 minute max_mobs = 15 - mob_biotypes = list(MOB_INORGANIC) icon = 'icons/mob/nest.dmi' spawn_text = "crawls through" mob_types = list(/mob/living/simple_animal/hostile/netherworld/migo, /mob/living/simple_animal/hostile/netherworld, /mob/living/simple_animal/hostile/netherworld/blankbody) - 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) faction = list("nether") - deathmessage = "shatters into oblivion." - del_on_death = TRUE -/mob/living/simple_animal/hostile/spawner/nether/attack_hand(mob/user) +/obj/structure/spawner/nether/Initialize() + .=..() + START_PROCESSING(SSprocessing, src) + +/obj/structure/spawner/nether/attack_hand(mob/user) user.visible_message("[user] is violently pulled into the link!", \ "Touching the portal, you are quickly pulled through into a world of unimaginable horror!") contents.Add(user) -/mob/living/simple_animal/hostile/spawner/nether/Life() - ..() - var/list/C = src.get_contents() - for(var/mob/living/M in C) + +/obj/structure/spawner/nether/process() + for(var/mob/living/M in contents) if(M) playsound(src, 'sound/magic/demon_consume.ogg', 50, 1) M.adjustBruteLoss(60) diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 804989e71e..f38d77cd90 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -43,7 +43,10 @@ search_objects = 1 // So that it can see through walls sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS - anchored = TRUE + + move_force = MOVE_FORCE_EXTREMELY_STRONG + move_resist = MOVE_FORCE_EXTREMELY_STRONG + pull_force = MOVE_FORCE_EXTREMELY_STRONG var/cannot_be_seen = 1 var/mob/living/creator = null diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 1f81899d8a..3f72022d24 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -65,7 +65,7 @@ var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against var/gold_core_spawnable = NO_SPAWN //If the mob can be spawned with a gold slime core. HOSTILE_SPAWN are spawned with plasma, FRIENDLY_SPAWN are spawned with blood - var/mob/living/simple_animal/hostile/spawner/nest + var/datum/component/spawner/nest var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 2001c61e12..655933a0bd 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -61,7 +61,7 @@ var/mood = "" // To show its face var/mutator_used = FALSE //So you can't shove a dozen mutators into a single slime var/force_stasis = FALSE - + do_footstep = TRUE var/static/regex/slime_name_regex = new("\\w+ (baby|adult) slime \\(\\d+\\)") @@ -245,7 +245,7 @@ /mob/living/simple_animal/slime/doUnEquip(obj/item/W) return -/mob/living/simple_animal/slime/start_pulling(atom/movable/AM) +/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) return /mob/living/simple_animal/slime/attack_ui(slot) diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm deleted file mode 100644 index 0b97a940e4..0000000000 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ /dev/null @@ -1,113 +0,0 @@ -/mob/living/simple_animal/hostile/spawner - name = "monster nest" - icon = 'icons/mob/animal.dmi' - health = 100 - maxHealth = 100 - gender = NEUTER - var/list/spawned_mobs = list() - var/max_mobs = 5 - var/spawn_delay = 0 - var/spawn_time = 300 //30 seconds default - var/mob_types = list(/mob/living/simple_animal/hostile/carp) - var/spawn_text = "emerges from" - status_flags = 0 - anchored = TRUE - AIStatus = AI_OFF - a_intent = INTENT_HARM - stop_automated_movement = 1 - wander = 0 - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = 350 - layer = BELOW_MOB_LAYER - sentience_type = SENTIENCE_BOSS - - -/mob/living/simple_animal/hostile/spawner/Destroy() - for(var/mob/living/simple_animal/L in spawned_mobs) - if(L.nest == src) - L.nest = null - spawned_mobs = null - return ..() - -/mob/living/simple_animal/hostile/spawner/Life() - . = ..() - if(!.) // dead - return - spawn_mob() - -/mob/living/simple_animal/hostile/spawner/proc/spawn_mob() - if(spawned_mobs.len >= max_mobs) - return 0 - if(spawn_delay > world.time) - return 0 - spawn_delay = world.time + spawn_time - var/chosen_mob_type = pick(mob_types) - var/mob/living/simple_animal/L = new chosen_mob_type(src.loc) - L.flags_1 |= (flags_1 & ADMIN_SPAWNED_1) //If we were admin spawned, lets have our children count as that as well. - spawned_mobs += L - L.nest = src - L.faction = src.faction - visible_message("[L] [spawn_text] [src].") - -/mob/living/simple_animal/hostile/spawner/syndicate - name = "warp beacon" - icon = 'icons/obj/device.dmi' - icon_state = "syndbeacon" - spawn_text = "warps in from" - mob_types = list(/mob/living/simple_animal/hostile/syndicate/ranged) - faction = list(ROLE_SYNDICATE) - -/mob/living/simple_animal/hostile/spawner/skeleton - name = "bone pit" - desc = "A pit full of bones, and some still seem to be moving..." - icon_state = "hole" - icon_living = "hole" - icon = 'icons/mob/nest.dmi' - health = 150 - maxHealth = 150 - max_mobs = 15 - spawn_time = 150 - mob_types = list(/mob/living/simple_animal/hostile/skeleton) - spawn_text = "climbs out of" - 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) - faction = list("skeleton") - -/mob/living/simple_animal/hostile/spawner/mining - name = "monster den" - desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining asteroids." - icon_state = "hole" - icon_living = "hole" - health = 200 - maxHealth = 200 - max_mobs = 3 - icon = 'icons/mob/nest.dmi' - spawn_text = "crawls out of" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/simple_animal/hostile/asteroid/fugu) - 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) - faction = list("mining") - -/mob/living/simple_animal/hostile/spawner/mining/goldgrub - name = "goldgrub den" - desc = "A den housing a nest of goldgrubs, annoying but arguably much better than anything else you'll find in a nest." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub) - -/mob/living/simple_animal/hostile/spawner/mining/goliath - name = "goliath den" - desc = "A den housing a nest of goliaths, oh god why?" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath) - -/mob/living/simple_animal/hostile/spawner/mining/hivelord - name = "hivelord den" - desc = "A den housing a nest of hivelords." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord) - -/mob/living/simple_animal/hostile/spawner/mining/basilisk - name = "basilisk den" - desc = "A den housing a nest of basilisks, bring a coat." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk) - -/mob/living/simple_animal/hostile/spawner/mining/wumborian - name = "wumborian fugu den" - desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 82e2b11f8e..85d8f94deb 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -108,8 +108,7 @@ if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully add_delay *= 2 - if(mob.loc != oldloc) - move_delay += add_delay + move_delay += add_delay if(.) // If mob is null here, we deserve the runtime if(mob.throwing) mob.throwing.finalize(FALSE) diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index 97c41faf12..e6d53d914f 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -56,7 +56,7 @@ //If we hit the Ninja who owns this Katana, they catch it. //Works for if the Ninja throws it or it throws itself or someone tries //To throw it at the ninja -/obj/item/energy_katana/throw_impact(atom/hit_atom) +/obj/item/energy_katana/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(ishuman(hit_atom)) var/mob/living/carbon/human/H = hit_atom if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja)) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 4b08ccf608..a896eb9034 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -97,7 +97,7 @@ /obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback) . = ..(target, range, speed, thrower, FALSE, diagonals_first, callback) -/obj/item/paperplane/throw_impact(atom/hit_atom) +/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscarbon(hit_atom)) var/mob/living/carbon/C = hit_atom if(C.can_catch_item(TRUE)) diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 4d8cdaa778..6cedab99a4 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne desc = "A device which produces a graviton field when set up." icon = 'icons/obj/machines/gravity_generator.dmi' density = TRUE + move_resist = INFINITY use_power = NO_POWER_USE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/sprite_number = 0 diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 8d99cbb485..f995993ea2 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -758,7 +758,7 @@ /obj/item/light/bulb/broken status = LIGHT_BROKEN -/obj/item/light/throw_impact(atom/hit_atom) +/obj/item/light/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //not caught by a mob shatter() diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 3b0f7e7f6f..491be4a83d 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -6,6 +6,7 @@ icon = 'icons/obj/singularity.dmi' icon_state = "Contain_F" density = FALSE + move_resist = INFINITY resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF use_power = NO_POWER_USE interaction_flags_atom = NONE diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 6be89b43f4..cc6adb6b36 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -245,6 +245,7 @@ field_generator power level display if(state != FG_WELDED || !anchored) turn_off() return + move_resist = INFINITY spawn(1) setup_field(1) spawn(2) @@ -335,6 +336,7 @@ field_generator power level display message_admins("A singulo exists and a containment field has failed at [ADMIN_VERBOSEJMP(T)].") investigate_log("has failed whilst a singulo exists at [AREACOORD(T)].", INVESTIGATE_SINGULO) O.last_warning = world.time + move_resist = initial(move_resist) /obj/machinery/field/generator/shock(mob/living/user) if(fields.len) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 35710f8d61..dbd16b8c08 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -7,6 +7,7 @@ icon_state = "singularity_s1" anchored = TRUE density = TRUE + move_resist = INFINITY layer = MASSIVE_OBJ_LAYER light_range = 6 appearance_flags = 0 diff --git a/code/modules/procedural_mapping/mapGenerators/lavaland.dm b/code/modules/procedural_mapping/mapGenerators/lavaland.dm index e6d7b00e8d..9e50b3ae95 100644 --- a/code/modules/procedural_mapping/mapGenerators/lavaland.dm +++ b/code/modules/procedural_mapping/mapGenerators/lavaland.dm @@ -16,9 +16,9 @@ /datum/mapGeneratorModule/splatterLayer/lavalandTendrils spawnableTurfs = list() - spawnableAtoms = list(/mob/living/simple_animal/hostile/spawner/lavaland = 5, - /mob/living/simple_animal/hostile/spawner/lavaland/legion = 5, - /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 5) + spawnableAtoms = list(/obj/structure/spawner/lavaland = 5, + /obj/structure/spawner/lavaland/legion = 5, + /obj/structure/spawner/lavaland/goliath = 5) /datum/mapGenerator/lavaland/ground_only modules = list(/datum/mapGeneratorModule/bottomLayer/lavaland_default) diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm index 87fdbc65b0..2a7d61f268 100644 --- a/code/modules/projectiles/ammunition/_ammunition.dm +++ b/code/modules/projectiles/ammunition/_ammunition.dm @@ -65,7 +65,7 @@ else return ..() -/obj/item/ammo_casing/throw_impact(atom/A) +/obj/item/ammo_casing/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(heavy_metal) bounce_away(FALSE, NONE) . = ..() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index b3f9591f64..26bbb20e6a 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -78,9 +78,9 @@ reagents.expose_temperature(exposed_temperature) ..() -/obj/item/reagent_containers/throw_impact(atom/target) +/obj/item/reagent_containers/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() - SplashReagents(target, TRUE) + SplashReagents(hit_atom, TRUE) /obj/item/reagent_containers/proc/bartender_check(atom/target) . = FALSE diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index a4a6a7d473..7bddb46d50 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -355,7 +355,7 @@ ui.soft_update_fields() -/obj/machinery/disposal/bin/hitby(atom/movable/AM) +/obj/machinery/disposal/bin/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(isitem(AM) && AM.CanEnterDisposals()) if(prob(75)) AM.forceMove(src) diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm index 5425ddbdc4..2401fc63a0 100644 --- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm @@ -1,26 +1,31 @@ #define ASH_WALKER_SPAWN_THRESHOLD 2 //The ash walker den consumes corpses or unconscious mobs to create ash walker eggs. For more info on those, check ghost_role_spawners.dm -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker +/obj/structure/lavaland/ash_walker name = "necropolis tendril nest" desc = "A vile tendril of corruption. It's surrounded by a nest of rapidly growing eggs..." + icon = 'icons/mob/nest.dmi' icon_state = "ash_walker_nest" - icon_living = "ash_walker_nest" - icon_dead = "ash_walker_nest" - faction = list("ashwalker") - health = 200 - maxHealth = 200 - loot = list(/obj/effect/collapse) + move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it + anchored = TRUE + density = TRUE + resistance_flags = FIRE_PROOF | LAVA_PROOF + max_integrity = 200 + var/faction = list("ashwalker") var/meat_counter = 6 -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/death() +/obj/structure/lavaland/ash_walker/Initialize() + .=..() + START_PROCESSING(SSprocessing, src) + +/obj/structure/lavaland/ash_walker/deconstruct(disassembled) new /obj/item/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs))) - return ..() + new /obj/effect/collapse(loc) -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/Life() +/obj/structure/lavaland/ash_walker/process() consume() - return ..() + spawn_mob() -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/proc/consume() +/obj/structure/lavaland/ash_walker/proc/consume() for(var/mob/living/H in view(src, 1)) //Only for corpse right next to/on same tile if(H.stat) visible_message("Serrated tendrils eagerly pull [H] to [src], tearing the body apart as its blood seeps over the eggs.") @@ -33,9 +38,9 @@ else meat_counter++ H.gib() - adjustHealth(-maxHealth * 0.05)//restores 5% hp of tendril + obj_integrity = min(obj_integrity + max_integrity*0.05,max_integrity)//restores 5% hp of tendril -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/spawn_mob() +/obj/structure/lavaland/ash_walker/proc/spawn_mob() if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD) new /obj/effect/mob_spawn/human/ash_walker(get_step(loc, pick(GLOB.alldirs))) visible_message("One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!") diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index dd2d7483e3..91243e04b7 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -131,7 +131,7 @@ All ShuttleMove procs go here var/range = throw_force * 10 range = CEILING(rand(range-(range*0.1), range+(range*0.1)), 10)/10 var/speed = range/5 - throw_at(target, range, speed) + safe_throw_at(target, range, speed) ///////////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/spells/spell_types/conjure.dm b/code/modules/spells/spell_types/conjure.dm index 3ebded7487..2b7be7b4d7 100644 --- a/code/modules/spells/spell_types/conjure.dm +++ b/code/modules/spells/spell_types/conjure.dm @@ -63,7 +63,7 @@ clothes_req = FALSE charge_max = 600 cooldown_min = 200 - summon_type = list(/mob/living/simple_animal/hostile/spawner/nether) + summon_type = list(/obj/structure/spawner/nether) summon_amt = 1 range = 1 cast_sound = 'sound/weapons/marauder.ogg' diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index c4d2c34a71..005a52a382 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -363,7 +363,7 @@ icon_state = "snappop" w_class = WEIGHT_CLASS_TINY -/obj/item/spellpacket/lightningbolt/throw_impact(atom/hit_atom) +/obj/item/spellpacket/lightningbolt/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) if(isliving(hit_atom)) var/mob/living/M = hit_atom diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index dffb7bf355..52261eac4e 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -116,7 +116,7 @@ else return ..() -/obj/item/bodypart/throw_impact(atom/hit_atom) +/obj/item/bodypart/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(status != BODYPART_ROBOTIC) playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 8da5d7c113..66f3d4f544 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -2,6 +2,7 @@ //Keep this sorted alphabetically #ifdef UNIT_TESTS +#include "anchored_mobs.dm" #include "reagent_id_typos.dm" #include "reagent_recipe_collisions.dm" #include "spawn_humans.dm" diff --git a/code/modules/unit_tests/anchored_mobs.dm b/code/modules/unit_tests/anchored_mobs.dm new file mode 100644 index 0000000000..5324179bb7 --- /dev/null +++ b/code/modules/unit_tests/anchored_mobs.dm @@ -0,0 +1,9 @@ +/datum/unit_test/anchored_mobs/Run() + var/list/L = list() + for(var/i in typesof(/mob)) + var/mob/M = i + if(initial(M.anchored)) + L += "[i]" + if(!L.len) + return //passed! + Fail("The following mobs are defined as anchored. This is incompatible with the new move force/resist system and needs to be revised.: [L.Join(" ")]") \ No newline at end of file diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm index de3f43f8ee..adecad7885 100644 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm @@ -351,17 +351,17 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! cell.use(750) //Less than a stunbaton since stunbatons hit everytime. weather_immunities -= "lava" -/mob/living/silicon/robot/throw_impact(atom/A) +/mob/living/silicon/robot/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!leaping) return ..() - if(A) - if(isliving(A)) - var/mob/living/L = A + if(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom var/blocked = 0 - if(ishuman(A)) - var/mob/living/carbon/human/H = A + if(ishuman(hit_atom)) + var/mob/living/carbon/human/H = hit_atom if(H.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK)) blocked = 1 if(!blocked) @@ -377,8 +377,8 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! pounce_cooldown = !pounce_cooldown spawn(pounce_cooldown_time) //3s by default pounce_cooldown = !pounce_cooldown - else if(A.density && !A.CanPass(src)) - visible_message("[src] smashes into [A]!", "You smash into [A]!") + else if(hit_atom.density && !hit_atom.CanPass(src)) + visible_message("[src] smashes into [hit_atom]!", "You smash into [hit_atom]!") playsound(src, 'sound/items/trayhit1.ogg', 50, 1) Knockdown(15, 1, 1) diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm index d16df6b285..5c4775a1e1 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm @@ -22,11 +22,11 @@ throwforce = 15 //still deadly when thrown throw_speed = 3 -/obj/item/ammo_casing/caseless/spinfusor/throw_impact(atom/target) //disks detonate when thrown +/obj/item/ammo_casing/caseless/spinfusor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) //disks detonate when thrown if(!..()) // not caught in mid-air visible_message("[src] detonates!") - playsound(src.loc, "sparks", 50, 1) - explosion(target, -1, -1, 1, 1, -1) + playsound(loc, "sparks", 50, 1) + explosion(hit_atom, -1, -1, 1, 1, -1) qdel(src) return 1 diff --git a/tgstation.dme b/tgstation.dme index 702f34f80c..d1e526d6ea 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -68,6 +68,7 @@ #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\monkeys.dm" +#include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\movespeed_modification.dm" #include "code\__DEFINES\nanites.dm" #include "code\__DEFINES\networks.dm" @@ -377,6 +378,7 @@ #include "code\datums\components\rotation.dm" #include "code\datums\components\signal_redirect.dm" #include "code\datums\components\slippery.dm" +#include "code\datums\components\spawner.dm" #include "code\datums\components\spooky.dm" #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" @@ -1022,6 +1024,7 @@ #include "code\game\objects\structures\reflector.dm" #include "code\game\objects\structures\safe.dm" #include "code\game\objects\structures\showcase.dm" +#include "code\game\objects\structures\spawner.dm" #include "code\game\objects\structures\spirit_board.dm" #include "code\game\objects\structures\statues.dm" #include "code\game\objects\structures\table_frames.dm" @@ -1063,6 +1066,7 @@ #include "code\game\objects\structures\crates_lockers\crates\large.dm" #include "code\game\objects\structures\crates_lockers\crates\secure.dm" #include "code\game\objects\structures\crates_lockers\crates\wooden.dm" +#include "code\game\objects\structures\lavaland\necropolis_tendril.dm" #include "code\game\objects\structures\signs\_signs.dm" #include "code\game\objects\structures\signs\signs_departments.dm" #include "code\game\objects\structures\signs\signs_maps.dm" @@ -2171,7 +2175,6 @@ #include "code\modules\mob\living\simple_animal\simple_animal.dm" #include "code\modules\mob\living\simple_animal\simple_animal_vr.dm" #include "code\modules\mob\living\simple_animal\simplemob_vore_values.dm" -#include "code\modules\mob\living\simple_animal\spawner.dm" #include "code\modules\mob\living\simple_animal\status_procs.dm" #include "code\modules\mob\living\simple_animal\bot\bot.dm" #include "code\modules\mob\living\simple_animal\bot\cleanbot.dm" @@ -2275,7 +2278,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\gutlunch.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\hivelord.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\necropolis_tendril.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\bat.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\frog.dm" From a5c95f20b644355c4649ab0bbc9dd5a4d1a5e369 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 24 Oct 2019 19:58:32 +0200 Subject: [PATCH 002/409] typo. --- code/game/mecha/equipment/tools/other_tools.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 07ecdec508..fdb620cc67 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -84,7 +84,7 @@ switch(mode) if(1) if(!locked) - if(!istype(target) || target.anchored || target.move_resist >= MOVE_FORCE_EXTREMELY_STRON) + if(!istype(target) || target.anchored || target.move_resist >= MOVE_FORCE_EXTREMELY_STRONG) occupant_message("Unable to lock on [target]") return locked = target From b29fc9aa5865cf1786f7b7ee38e2fc711f9fefdf Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 24 Oct 2019 20:44:29 +0200 Subject: [PATCH 003/409] fermis code looks very 2k17, sad. --- code/modules/holiday/halloween/halloween.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm index 5635994a7a..151bb26076 100644 --- a/code/modules/holiday/halloween/halloween.dm +++ b/code/modules/holiday/halloween/halloween.dm @@ -132,7 +132,7 @@ speak_emote = list("howls") emote_hear = list("wails","screeches") density = FALSE - anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING incorporeal_move = 1 layer = 4 var/timer = 0 From b3ef41a10ff6064b5cf368c84067877310384b98 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 14:02:17 +0100 Subject: [PATCH 004/409] Fixing living being unable to pull anything. --- code/modules/mob/living/living.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index df3366187d..5389f1b099 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -241,7 +241,7 @@ /mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE) if(!AM || !src) return FALSE - if(!(AM.can_be_pulled(src))) + if(!(AM.can_be_pulled(src, state, force))) return FALSE if(throwing || incapacitated()) return FALSE From 27af7b271f4f999cfd56ffbf240a7d642be3d36f Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Fri, 6 Dec 2019 20:12:30 +0100 Subject: [PATCH 005/409] qdeleted to qdeleting --- code/datums/components/spawner.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm index dc46603b1e..fe86b60375 100644 --- a/code/datums/components/spawner.dm +++ b/code/datums/components/spawner.dm @@ -19,7 +19,7 @@ if(_max_mobs) max_mobs=_max_mobs - RegisterSignal(parent, list(COMSIG_PARENT_QDELETED), .proc/stop_spawning) + RegisterSignal(parent, list(COMSIG_PARENT_QDELETING), .proc/stop_spawning) START_PROCESSING(SSprocessing, src) /datum/component/spawner/process() From f83d1c4763b251f2d8d52635f8cf13a0428cf1a7 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 7 Dec 2019 10:53:10 +0100 Subject: [PATCH 006/409] Made kevlar and armor padding accessories inconspicious and examine-proof. --- code/__DEFINES/inventory.dm | 1 + code/modules/clothing/under/_under.dm | 3 +++ code/modules/clothing/under/accessories.dm | 3 +++ code/modules/mob/living/carbon/human/examine.dm | 2 +- code/modules/uplink/uplink_items.dm | 6 +++--- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index f5ea8d835f..98ba432e52 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -110,6 +110,7 @@ #define HIDENECK (1<<10) #define HIDETAUR (1<<11) //gotta hide that snowflake #define HIDESNOUT (1<<12) //or do we actually hide our snoots +#define HIDEACCESSORY (1<<13) //hides the jumpsuit accessory. //bitflags for clothing coverage - also used for limbs #define HEAD (1<<0) diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index bb5f909521..508fece53b 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -102,6 +102,9 @@ if(user && notifyAttach) to_chat(user, "You attach [I] to [src].") + if((flags_inv & HIDEACCESSORY) || (A.flags_inv & HIDEACCESSORY)) + return TRUE + var/accessory_color = attached_accessory.item_color if(!accessory_color) accessory_color = attached_accessory.icon_state diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index 0a0499b5f9..50038a03ac 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -373,6 +373,7 @@ icon_state = "padding" item_color = "nothing" armor = list("melee" = 15, "bullet" = 10, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -20, "acid" = 45) + flags_inv = HIDEACCESSORY //hidden from indiscrete mob examines. /obj/item/clothing/accessory/kevlar name = "kevlar sheets" @@ -380,6 +381,7 @@ icon_state = "padding" item_color = "nothing" armor = list("melee" = 10, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 25) + flags_inv = HIDEACCESSORY /obj/item/clothing/accessory/plastics name = "underling plastic sheet" @@ -387,6 +389,7 @@ icon_state = "plastics" item_color = "nothing" armor = list("melee" = 0, "bullet" = 0, "laser" = 20, "energy" = 10, "bomb" = 0, "bio" = 30, "rad" = 0, "fire" = 0, "acid" = -40) + flags_inv = HIDEACCESSORY ///////////////////// //Pokadots On Pants// diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 04ec0454f8..01f452df56 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -34,7 +34,7 @@ var/accessory_msg if(istype(w_uniform, /obj/item/clothing/under)) var/obj/item/clothing/under/U = w_uniform - if(U.attached_accessory) + if(U.attached_accessory && !(U.attached_accessory.flags_inv & HIDEACCESSORY) && !(U.flags_inv & HIDEACCESSORY)) accessory_msg += " with [icon2html(U.attached_accessory, user)] \a [U.attached_accessory]" . += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_msg]." diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index cf663e353f..a6110f3464 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1332,21 +1332,21 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes /datum/uplink_item/suits/padding name = "Soft Padding" - desc = "Padding to add to a jumpsuit to help against melee and bullets." + desc = "Inconspicious padding worn underneath jumpsuits to protect the user against melee and bullets." item = /obj/item/clothing/accessory/padding cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/suits/kevlar name = "Kevlar sheets" - desc = "Kevlar sheets to add to jumpsuit to help against bullets and melee." + desc = "Inconspicious kevlar sheets worn underneath jumpsuits to protect the user against bullets and melee." item = /obj/item/clothing/accessory/kevlar cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/suits/plastic name = "Plastic sheet" - desc = "Plastic body sheet to add to a jumpsuit to help against laser and energy harm." + desc = "Inconspicious plastic body sheet worn underneath jumpsuits to protect the user against laser and energy beams." item = /obj/item/clothing/accessory/plastics cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) From 6df739a0459d7b88caea8b4a2d182fa968709884 Mon Sep 17 00:00:00 2001 From: Seris02 Date: Thu, 19 Dec 2019 00:39:29 +0800 Subject: [PATCH 007/409] changes holofan, adds holofirelock --- code/game/objects/items/holosign_creator.dm | 10 +++++++- code/game/objects/structures/holosign.dm | 28 ++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm index 78881d901e..c241ca50ae 100644 --- a/code/game/objects/items/holosign_creator.dm +++ b/code/game/objects/items/holosign_creator.dm @@ -78,12 +78,20 @@ /obj/item/holosign_creator/atmos name = "ATMOS holofan projector" - desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions." + desc = "A holographic projector that creates holographic fans that prevent changes in atmosphere conditions. Somehow." icon_state = "signmaker_engi" holosign_type = /obj/structure/holosign/barrier/atmos creation_time = 0 max_signs = 3 +/obj/item/holosign_creator/firelock + name = "ATMOS holofirelock projector" + desc = "A holographic projector that creates holographic barriers that prevent changes in temperature conditions." + icon_state = "signmaker_engi" + holosign_type = /obj/structure/holosign/barrier/firelock + creation_time = 0 + max_signs = 3 + /obj/item/holosign_creator/medical name = "\improper PENLITE barrier projector" desc = "A holographic projector that creates PENLITE holobarriers. Useful during quarantines since they halt those with malicious diseases." diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index 1f007b6993..383ddd929f 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -69,9 +69,9 @@ rad_insulation = RAD_LIGHT_INSULATION /obj/structure/holosign/barrier/atmos - name = "holo firelock" - desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects from passing through, gas is kept out." - icon_state = "holo_firelock" + name = "holo fan" + desc = "A holographic barrier resembling a tiny fan. Though it does not prevent solid objects from passing through, gas is kept out. Somehow." + icon_state = "holo_fan" density = FALSE anchored = TRUE CanAtmosPass = ATMOS_PASS_NO @@ -81,6 +81,28 @@ . = ..() air_update_turf(TRUE) +/obj/structure/holosign/barrier/firelock + name = "holo firelock" + desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects or gas from passing through, temperature changes are kept out." + icon_state = "holo_firelock" + density = TRUE + anchored = TRUE + alpha = 150 + +/obj/structure/holosign/barrier/firelock/BlockSuperconductivity() + return TRUE + +/obj/structure/holosign/barrier/firelock/fire_act(exposed_temperature,exposed_volume) + return + +/obj/structure/holosign/barrier/firelock/CanPass(atom/movable/mover, turf/target) + if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE)) + return 1 + if(iscarbon(mover)) + var/mob/living/carbon/C = mover + if(allow_walk && C.m_intent == MOVE_INTENT_WALK) + return 1 + /obj/structure/holosign/barrier/cyborg name = "Energy Field" desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles." From 61ab3685f1c51ba8b164bbb5318dbe81022809c8 Mon Sep 17 00:00:00 2001 From: Seris02 Date: Fri, 20 Dec 2019 14:14:01 +0800 Subject: [PATCH 008/409] atmos firelock, changes to temp blocking --- .../crates_lockers/closets/secure/engineering.dm | 1 + code/game/objects/structures/holosign.dm | 16 +++------------- .../environmental/LINDA_turf_tile.dm | 12 +++++++++--- code/modules/research/designs/misc_designs.dm | 10 ++++++++++ code/modules/research/techweb/all_nodes.dm | 2 +- 5 files changed, 24 insertions(+), 17 deletions(-) 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 8da50d488f..fdc8d03374 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -98,6 +98,7 @@ new /obj/item/tank/internals/emergency_oxygen/engi(src) new /obj/item/analyzer(src) new /obj/item/holosign_creator/atmos(src) + new /obj/item/holosign_creator/firelock(src) new /obj/item/watertank/atmos(src) new /obj/item/clothing/suit/fire/atmos(src) new /obj/item/clothing/head/hardhat/atmos(src) diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index 383ddd929f..69ad9f1567 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -85,24 +85,14 @@ name = "holo firelock" desc = "A holographic barrier resembling a firelock. Though it does not prevent solid objects or gas from passing through, temperature changes are kept out." icon_state = "holo_firelock" - density = TRUE + density = FALSE anchored = TRUE alpha = 150 + resistance_flags = FIRE_PROOF -/obj/structure/holosign/barrier/firelock/BlockSuperconductivity() +/obj/structure/holosign/barrier/firelock/blocksTemperature() return TRUE -/obj/structure/holosign/barrier/firelock/fire_act(exposed_temperature,exposed_volume) - return - -/obj/structure/holosign/barrier/firelock/CanPass(atom/movable/mover, turf/target) - if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE)) - return 1 - if(iscarbon(mover)) - var/mob/living/carbon/C = mover - if(allow_walk && C.m_intent == MOVE_INTENT_WALK) - return 1 - /obj/structure/holosign/barrier/cyborg name = "Energy Field" desc = "A fragile energy field that blocks movement. Excels at blocking lethal projectiles." diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 196bf70fdc..389f1a69f3 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -358,6 +358,9 @@ SSair.excited_groups -= src ////////////////////////SUPERCONDUCTIVITY///////////////////////////// +/atom/movable/proc/blocksTemperature() + return FALSE + /turf/proc/conductivity_directions() if(archived_cycle < SSair.times_fired) archive() @@ -372,6 +375,9 @@ . |= direction /turf/proc/neighbor_conduct_with_src(turf/open/other) + for (var/atom/movable/G in src) + if (G.blocksTemperature()) + return if(!other.blocks_air) //Open but neighbor is solid other.temperature_share_open_to_solid(src) else //Both tiles are solid @@ -382,7 +388,9 @@ if(blocks_air) ..() return - + for (var/atom/movable/G in src) + if (G.blocksTemperature()) + return if(!other.blocks_air) //Both tiles are open var/turf/open/T = other T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT) @@ -401,10 +409,8 @@ if(!neighbor.thermal_conductivity) continue - if(neighbor.archived_cycle < SSair.times_fired) neighbor.archive() - neighbor.neighbor_conduct_with_src(src) neighbor.consider_superconductivity() diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 5f7648b245..302ac345b7 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -364,6 +364,16 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/holosignfirelock + name = "ATMOS Holofirelock Projector" + desc = "A holographic projector that creates holographic barriers that prevent changes in temperature conditions." + id = "holosignfirelock" + build_type = PROTOLATHE + materials = list(MAT_METAL = 5000, MAT_GLASS = 1000, MAT_GOLD = 1000, MAT_SILVER = 1000) + build_path = /obj/item/holosign_creator/firelock + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + /datum/design/forcefield_projector name = "Forcefield Projector" desc = "A device which can project temporary forcefields to seal off an area." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index eed1e4aefd..2df93ca0e8 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -430,7 +430,7 @@ display_name = "Electromagnetic Theory" description = "Study into usage of frequencies in the electromagnetic spectrum." prereq_ids = list("base") - design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "inducer", "tray_goggles", "holopad") + design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "holosignfirelock", "inducer", "tray_goggles", "holopad") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 From ffa013af6eae12be04d8ef6f1d8d71786be2fddb Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 25 Dec 2019 03:59:21 +0100 Subject: [PATCH 009/409] Minor captains closet cleanup. --- .../structures/crates_lockers/closets/secure/security.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 835be8d2fc..058782e1ab 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -19,7 +19,6 @@ new /obj/item/clothing/under/captainparade(src) new /obj/item/clothing/suit/armor/vest/capcarapace/alt(src) new /obj/item/clothing/head/caphat/parade(src) - new /obj/item/clothing/head/caphat/beret(src) new /obj/item/clothing/suit/captunic(src) new /obj/item/clothing/under/rank/captain/femformal(src) //citadel edit new /obj/item/clothing/head/crown/fancy(src) @@ -29,12 +28,14 @@ new /obj/item/radio/headset/heads/captain(src) new /obj/item/clothing/glasses/sunglasses/gar/supergar(src) new /obj/item/clothing/gloves/color/captain(src) - new /obj/item/restraints/handcuffs/cable/zipties(src) new /obj/item/storage/belt/sabre(src) new /obj/item/gun/energy/e_gun(src) new /obj/item/door_remote/captain(src) new /obj/item/storage/photo_album/Captain(src) - new /obj/item/clothing/head/caphat/beret/white(src) + if(prob(50)) + new /obj/item/clothing/head/caphat/beret(src) + else + new /obj/item/clothing/head/caphat/beret/white(src) /obj/structure/closet/secure_closet/hop name = "\proper head of personnel's locker" From 160e8c1ec5863d4d5c6ae0f7fba096bbc18e0163 Mon Sep 17 00:00:00 2001 From: Seris02 Date: Fri, 27 Dec 2019 23:21:40 +0800 Subject: [PATCH 010/409] stunglasses --- code/datums/action.dm | 3 ++ code/modules/clothing/glasses/_glasses.dm | 30 +++++++++++++++++++ .../crafting/recipes/recipes_clothing.dm | 10 +++++++ 3 files changed, 43 insertions(+) diff --git a/code/datums/action.dm b/code/datums/action.dm index 77aa729eb1..44a0e0c7ba 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -533,6 +533,9 @@ cooldown = world.time owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) +/datum/action/item_action/flash + name = "Flash" + //Preset for spells /datum/action/spell_action check_flags = 0 diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 206165a495..db5f79dfaf 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -247,6 +247,36 @@ throwforce = 12 glass_colour_type = /datum/client_colour/glass_colour/red +/obj/item/clothing/glasses/sunglasses/stunglasses + name = "stunglasses" + desc = "Sunglasses with inbuilt flashes. Made for those who prefer to walk around in style, who needs clumsy flashes anyway?" + actions_types = list(/datum/action/item_action/flash) + var/obj/item/assembly/flash/installed + +/obj/item/clothing/glasses/sunglasses/stunglasses/Initialize() + ..() + if (!installed) + installed = new(src) + +/obj/item/clothing/glasses/sunglasses/stunglasses/ui_action_click(mob/user) + if (installed && !installed.crit_fail) + installed.attack_self(user) + else + to_chat(user, "Install a new flash in [src]!") + + +/obj/item/clothing/glasses/sunglasses/stunglasses/attackby(obj/item/W,mob/user) + if (istype(W,/obj/item/screwdriver)) + if (installed) + installed.forceMove(get_turf(src)) + to_chat(user, "You remove [installed] from [src].") + installed = null + if (istype(W,/obj/item/assembly/flash)) + if (!installed) + W.forceMove(src) + to_chat(user, "You install [W] into [src].") + installed = W + /obj/item/clothing/glasses/welding name = "welding goggles" desc = "Protects the eyes from welders; approved by the mad scientist association." diff --git a/code/modules/crafting/recipes/recipes_clothing.dm b/code/modules/crafting/recipes/recipes_clothing.dm index 4f06a44811..088cf30196 100644 --- a/code/modules/crafting/recipes/recipes_clothing.dm +++ b/code/modules/crafting/recipes/recipes_clothing.dm @@ -87,6 +87,16 @@ reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) category = CAT_CLOTHING +/datum/crafting_recipe/stunglasses + name = "Stunglasses" + result = /obj/item/clothing/glasses/sunglasses/stunglasses + time = 60 + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/assembly/flash = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING + /datum/crafting_recipe/ghostsheet name = "Ghost Sheet" result = /obj/item/clothing/suit/ghost_sheet From 1d449fcd129a98a0259821ae372f7268478643e1 Mon Sep 17 00:00:00 2001 From: Seris02 Date: Sun, 29 Dec 2019 19:46:47 +0800 Subject: [PATCH 011/409] changes --- code/modules/clothing/glasses/_glasses.dm | 4 ++-- code/modules/crafting/recipes/recipes_clothing.dm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index db5f79dfaf..330e10db0e 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -254,7 +254,7 @@ var/obj/item/assembly/flash/installed /obj/item/clothing/glasses/sunglasses/stunglasses/Initialize() - ..() + . = ..() if (!installed) installed = new(src) @@ -264,7 +264,6 @@ else to_chat(user, "Install a new flash in [src]!") - /obj/item/clothing/glasses/sunglasses/stunglasses/attackby(obj/item/W,mob/user) if (istype(W,/obj/item/screwdriver)) if (installed) @@ -276,6 +275,7 @@ W.forceMove(src) to_chat(user, "You install [W] into [src].") installed = W + . = ..() /obj/item/clothing/glasses/welding name = "welding goggles" diff --git a/code/modules/crafting/recipes/recipes_clothing.dm b/code/modules/crafting/recipes/recipes_clothing.dm index 088cf30196..83e82654a2 100644 --- a/code/modules/crafting/recipes/recipes_clothing.dm +++ b/code/modules/crafting/recipes/recipes_clothing.dm @@ -86,7 +86,7 @@ tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) category = CAT_CLOTHING - +/* //Kevinz doesn't want it as a recipe for now, leaving it in if anything ever changes to let it in /datum/crafting_recipe/stunglasses name = "Stunglasses" result = /obj/item/clothing/glasses/sunglasses/stunglasses @@ -96,7 +96,7 @@ /obj/item/clothing/glasses/sunglasses = 1, /obj/item/stack/cable_coil = 5) category = CAT_CLOTHING - +*/ /datum/crafting_recipe/ghostsheet name = "Ghost Sheet" result = /obj/item/clothing/suit/ghost_sheet From 9ea99d4c810bf11a158e4f360e14585a1f58909b Mon Sep 17 00:00:00 2001 From: deathride58 Date: Sun, 29 Dec 2019 20:01:21 -0500 Subject: [PATCH 012/409] nerfs limb stamcrit by doubling the base limb stam regen, making limbs regen stam at double the rate when disabled, and adding stam multiplier mechanics to limb stamloss --- code/modules/surgery/bodyparts/bodyparts.dm | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index a1b74942e0..f04cb0c602 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -29,6 +29,7 @@ var/burn_dam = 0 var/stamina_dam = 0 var/max_stamina_damage = 0 + var/incoming_stam_mult = 1 //Multiplier for incoming staminaloss, decreases when taking staminaloss when the limb is disabled, resets back to 1 when limb is no longer disabled. var/max_damage = 0 var/stam_heal_tick = 0 //per Life(). Defaults to 0 due to citadel changes @@ -141,7 +142,7 @@ //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life() if(stam_heal_tick && stamina_dam > DAMAGE_PRECISION) //DO NOT update health here, it'll be done in the carbon's life. - if(heal_damage(brute = 0, burn = 0, stamina = stam_heal_tick, only_robotic = FALSE, only_organic = FALSE, updating_health = FALSE)) + if(heal_damage(brute = 0, burn = 0, stamina = (stam_heal_tick * (disabled ? 2 : 1)), only_robotic = FALSE, only_organic = FALSE, updating_health = FALSE)) . |= BODYPART_LIFE_UPDATE_HEALTH //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. @@ -153,7 +154,7 @@ var/dmg_mlt = CONFIG_GET(number/damage_multiplier) brute = round(max(brute * dmg_mlt, 0),DAMAGE_PRECISION) burn = round(max(burn * dmg_mlt, 0),DAMAGE_PRECISION) - stamina = round(max(stamina * dmg_mlt, 0),DAMAGE_PRECISION) + stamina = round(max((stamina * dmg_mlt) * incoming_stam_mult, 0),DAMAGE_PRECISION) brute = max(0, brute - brute_reduction) burn = max(0, burn - burn_reduction) //No stamina scaling.. for now.. @@ -184,6 +185,9 @@ var/available_damage = max_damage - current_damage stamina_dam += round(CLAMP(stamina, 0, min(max_stamina_damage - stamina_dam, available_damage)), DAMAGE_PRECISION) + if(disabled && stamina > 10) + incoming_stam_mult = max(0.01, incoming_stam_mult/(stamina*0.1)) + if(owner && updating_health) owner.updatehealth() if(stamina > DAMAGE_PRECISION) @@ -253,6 +257,8 @@ owner.update_health_hud() //update the healthdoll owner.update_body() owner.update_canmove() + if(!disabled) + incoming_stam_mult = 1 return TRUE //Updates an organ's brute/burn states for use by update_damage_overlays() @@ -646,7 +652,7 @@ held_index = 1 px_x = -6 px_y = 0 - stam_heal_tick = 2 + stam_heal_tick = 4 /obj/item/bodypart/l_arm/is_disabled() if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) @@ -706,7 +712,7 @@ held_index = 2 px_x = 6 px_y = 0 - stam_heal_tick = 2 + stam_heal_tick = 4 max_stamina_damage = 50 /obj/item/bodypart/r_arm/is_disabled() @@ -766,7 +772,7 @@ body_damage_coeff = 0.75 px_x = -2 px_y = 12 - stam_heal_tick = 2 + stam_heal_tick = 4 max_stamina_damage = 50 var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) @@ -827,7 +833,7 @@ px_x = 2 px_y = 12 max_stamina_damage = 50 - stam_heal_tick = 2 + stam_heal_tick = 4 var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) From 1b6359a1752897a8987f4d7cec5bd488bb650908 Mon Sep 17 00:00:00 2001 From: deathride58 Date: Sun, 29 Dec 2019 20:18:52 -0500 Subject: [PATCH 013/409] [experimental] Buffs the stamina buffer by making it recharge for free. --- code/modules/mob/living/carbon/life.dm | 1 - modular_citadel/code/_onclick/hud/stamina.dm | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 0061c7ed70..f74f6f7cc0 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -516,7 +516,6 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put if(bufferedstam && world.time > stambufferregentime) var/drainrate = max((bufferedstam*(bufferedstam/(5)))*0.1,1) bufferedstam = max(bufferedstam - drainrate, 0) - adjustStaminaLoss(drainrate*0.5) //END OF CIT CHANGES var/restingpwr = 1 + 4 * resting diff --git a/modular_citadel/code/_onclick/hud/stamina.dm b/modular_citadel/code/_onclick/hud/stamina.dm index 184e3add24..0515b9d762 100644 --- a/modular_citadel/code/_onclick/hud/stamina.dm +++ b/modular_citadel/code/_onclick/hud/stamina.dm @@ -11,7 +11,7 @@ /obj/screen/staminas/Click(location,control,params) if(isliving(usr)) var/mob/living/L = usr - to_chat(L, "You have [L.getStaminaLoss()] stamina loss.
Your stamina buffer can take [L.stambuffer] stamina loss, and will use 50% of that stamina loss when recharging.
Your stamina buffer is [(L.stambuffer*(100/L.stambuffer))-(L.bufferedstam*(100/L.stambuffer))]% full.
") + to_chat(L, "You have [L.getStaminaLoss()] stamina loss.
Your stamina buffer can take [L.stambuffer] stamina loss, and recharges at no cost.
Your stamina buffer is [(L.stambuffer*(100/L.stambuffer))-(L.bufferedstam*(100/L.stambuffer))]% full.
") /obj/screen/staminas/update_icon_state() var/mob/living/carbon/user = hud?.mymob From 81a39aa32493ed803b9d5329da41d4fa23920b04 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Tue, 31 Dec 2019 13:25:09 -0500 Subject: [PATCH 014/409] Add the space radsuit and the crate --- code/modules/cargo/packs/engineering.dm | 11 ++++++++ code/modules/clothing/spacesuits/hardsuit.dm | 25 +++++++++++++++++++ icons/mob/suit.dmi | Bin 402995 -> 402260 bytes icons/obj/clothing/suits.dmi | Bin 136453 -> 136390 bytes 4 files changed, 36 insertions(+) diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm index f09c9e429d..1d9e26e9a1 100644 --- a/code/modules/cargo/packs/engineering.dm +++ b/code/modules/cargo/packs/engineering.dm @@ -73,6 +73,17 @@ crate_name = "atmospherics hardsuit" crate_type = /obj/structure/closet/crate/secure/engineering +/datum/supply_pack/engineering/radhardsuit + name = "Radiation Hardsuit" + desc = "The Singulo is loose? Do you need to do a few changes to its containment and don't want to spent the rest of the shift under the shower? Get this Radiation Hardsuit! It protect from radiations and space only. Ask the CE to open." + cost = 5000 + access = ACCESS_ENGINE + contains = list(/obj/item/tank/internals/air, + /obj/item/clothing/mask/gas, + /obj/item/clothing/suit/space/hardsuit/engine/rad) + crate_name = "radiation hardsuit" + crate_type = /obj/structure/closet/crate/secure/engineering + /datum/supply_pack/engineering/industrialrcd name = "Industrial RCD" desc = "An industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Does not contain spare ammo for the industrial RCD or any other RCD models." diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index bf52b26ae9..5b013cbdb2 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -204,6 +204,31 @@ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/atmos tauric = TRUE //Citadel Add for tauric hardsuits + //Radiation +/obj/item/clothing/head/helmet/space/hardsuit/engine/rad + name = "radiation hardsuit helmet" + desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." + icon_state = "cespace_helmet" + item_state = "nothing" + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + item_color = "engineering" + resistance_flags = FIRE_PROOF + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE + actions_types = list() + +/obj/item/clothing/suit/space/hardsuit/engine/rad + name = "radiation hardsuit" + desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." + icon_state = "hardsuit-rad" + item_state = "nothing" + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/rad + resistance_flags = FIRE_PROOF + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE + tauric = FALSE //Citadel Add for tauric hardsuits + +/obj/item/clothing/head/helmet/space/hardsuit/engine/rad/attack_self() + return //Sprites required for flashlight //Chief Engineer's hardsuit /obj/item/clothing/head/helmet/space/hardsuit/engine/elite diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 5b84dad999f378a1a48e2656418721118571b941..fb2694941dc4bce69ff8840460c650d483de65b7 100644 GIT binary patch delta 287786 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%0Dp1 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

9}Mrg6#K*&XE-g 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 delta 289028 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 delta 101814 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ˡ*?%`{9+)o0&q)(FI-v-L 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"B?is;^H?${-O47LOER_;NqZ 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

Wk?QPGcDfEePw!$k_dmFit^|oL7et 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 delta 100976 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�lpd3ZzDw>=pQTMf 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 PLqA@KhI^8E6} From 7b83ee7d8bc18347849afca3e4de3e333b091c09 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Tue, 31 Dec 2019 13:35:30 -0500 Subject: [PATCH 015/409] Update the description. --- code/modules/clothing/spacesuits/hardsuit.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 5b013cbdb2..25b2c18d32 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -207,7 +207,7 @@ //Radiation /obj/item/clothing/head/helmet/space/hardsuit/engine/rad name = "radiation hardsuit helmet" - desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." + desc = "A special helmet that protects against radiation and space. Not much else unfortunately." icon_state = "cespace_helmet" item_state = "nothing" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) @@ -218,7 +218,7 @@ /obj/item/clothing/suit/space/hardsuit/engine/rad name = "radiation hardsuit" - desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." + desc = "A special suit that protects against radiation and space. Not much else unfortunately." icon_state = "hardsuit-rad" item_state = "nothing" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) From be62bbc96d54cb8489dddfcb3af78afa106091d3 Mon Sep 17 00:00:00 2001 From: r4d6 <50276533+r4d6@users.noreply.github.com> Date: Tue, 31 Dec 2019 18:17:07 -0500 Subject: [PATCH 016/409] Lowering price and change description --- code/modules/cargo/packs/engineering.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm index 1d9e26e9a1..ea90255bce 100644 --- a/code/modules/cargo/packs/engineering.dm +++ b/code/modules/cargo/packs/engineering.dm @@ -75,8 +75,8 @@ /datum/supply_pack/engineering/radhardsuit name = "Radiation Hardsuit" - desc = "The Singulo is loose? Do you need to do a few changes to its containment and don't want to spent the rest of the shift under the shower? Get this Radiation Hardsuit! It protect from radiations and space only. Ask the CE to open." - cost = 5000 + desc = "The Singulo is loose? Do you need to do a few changes to its containment and don't want to spent the rest of the shift under the shower? Get this Radiation Hardsuit! It protect from radiations and space only." + cost = 3500 access = ACCESS_ENGINE contains = list(/obj/item/tank/internals/air, /obj/item/clothing/mask/gas, From 6222b41204c1546d339356c3cb40f98c5621560b Mon Sep 17 00:00:00 2001 From: chefferz Date: Wed, 1 Jan 2020 20:44:16 -0500 Subject: [PATCH 017/409] Update forcefieldprojector.dm --- code/game/objects/items/devices/forcefieldprojector.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index 0c73d829ff..dda75ca1ec 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -10,7 +10,7 @@ lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' materials = list(MAT_METAL=250, MAT_GLASS=500) - var/max_shield_integrity = 250 + var/max_shield_integrity = 100 var/shield_integrity = 250 var/max_fields = 3 var/list/current_fields @@ -87,7 +87,7 @@ mouse_opacity = MOUSE_OPACITY_OPAQUE resistance_flags = INDESTRUCTIBLE CanAtmosPass = ATMOS_PASS_DENSITY - armor = list("melee" = 0, "bullet" = 25, "laser" = 50, "energy" = 50, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 0, "bullet" = 25, "laser" = 25, "energy" = 25, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) var/obj/item/forcefield_projector/generator /obj/structure/projected_forcefield/Initialize(mapload, obj/item/forcefield_projector/origin) From 0b02439b08eb459cf77f5fa8dcc951a431bc14b7 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 2 Jan 2020 03:53:04 -0700 Subject: [PATCH 018/409] Puts an end to the Christmas Menace --- code/modules/vending/autodrobe.dm | 6 ++++++ code/modules/vending/clothesmate.dm | 4 ++++ modular_citadel/code/modules/client/loadout/head.dm | 4 +++- modular_citadel/code/modules/client/loadout/uniform.dm | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 8cd7fc8539..0911258692 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -131,6 +131,12 @@ /obj/item/clothing/suit/drfreeze_coat = 1, /obj/item/clothing/suit/gothcoat = 2, /obj/item/clothing/under/draculass = 1, + /obj/item/clothing/under/christmas/christmasmaler = 3, + /obj/item/clothing/under/christmas/christmasmaleg = 3, + /obj/item/clothing/under/christmas/christmasfemaler = 3, + /obj/item/clothing/under/christmas/christmasfemaleg = 3, + /obj/item/clothing/head/christmashat = 3, + /obj/item/clothing/head/christmashatg = 3, /obj/item/clothing/under/drfreeze = 1) //End of Cit Changes refill_canister = /obj/item/vending_refill/autodrobe diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 6144f4c57a..826650db36 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -123,15 +123,19 @@ /obj/item/clothing/ears/headphones = 10, /obj/item/clothing/suit/apron/purple_bartender = 4, /obj/item/clothing/under/rank/bartender/purple = 4, + /* Commenting out until next Christmas or made automatic /obj/item/clothing/under/christmas/christmasmaler = 3, /obj/item/clothing/under/christmas/christmasmaleg = 3, /obj/item/clothing/under/christmas/christmasfemaler = 3, /obj/item/clothing/under/christmas/christmasfemaleg = 3, + */ /obj/item/clothing/suit/hooded/wintercoat/christmascoatr = 3, /obj/item/clothing/suit/hooded/wintercoat/christmascoatg = 3, /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg = 3, + /*Commenting out until next Christmas or made automatic /obj/item/clothing/head/christmashat = 3, /obj/item/clothing/head/christmashatg = 3, + */ /obj/item/clothing/shoes/winterboots/christmasbootsr = 3, /obj/item/clothing/shoes/winterboots/christmasbootsg = 3, /obj/item/clothing/shoes/winterboots/santaboots = 3) diff --git a/modular_citadel/code/modules/client/loadout/head.dm b/modular_citadel/code/modules/client/loadout/head.dm index 3e7eb39823..efe1fb524c 100644 --- a/modular_citadel/code/modules/client/loadout/head.dm +++ b/modular_citadel/code/modules/client/loadout/head.dm @@ -93,6 +93,7 @@ restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +/*Commenting out Until next Christmas or made automatic /datum/gear/santahatr name = "Red Santa Hat" category = SLOT_HEAD @@ -101,4 +102,5 @@ /datum/gear/santahatg name = "Green Santa Hat" category = SLOT_HEAD - path = /obj/item/clothing/head/christmashatg \ No newline at end of file + path = /obj/item/clothing/head/christmashatg +*/ \ No newline at end of file diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm index 64ed0d363d..46692ea7a9 100644 --- a/modular_citadel/code/modules/client/loadout/uniform.dm +++ b/modular_citadel/code/modules/client/loadout/uniform.dm @@ -390,6 +390,7 @@ path = /obj/item/clothing/under/gear_harness //Christmas +/*Commenting out Until next Christmas or made automatic /datum/gear/christmasmaler name = "Red Masculine Christmas Suit" category = SLOT_W_UNIFORM @@ -415,6 +416,7 @@ category = SLOT_W_UNIFORM path = /obj/item/clothing/under/stripper_pink cost = 3 +*/ /datum/gear/greenstripper name = "Green stripper outfit" From b793bceffcd424ed9dbd7ff14346896172782bab Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Thu, 2 Jan 2020 10:51:06 -0800 Subject: [PATCH 019/409] A --- code/modules/admin/IsBanned.dm | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 839292871c..59b207109c 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -7,14 +7,23 @@ #define STICKYBAN_MAX_ADMIN_MATCHES 2 /world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE) + var/static/key_cache = list() + if(!real_bans_only) + if(key_cache[key]) + return list("reason"="concurrent connection attempts", "desc"="You are attempting to connect too fast. Try again.") + key_cache[key] = 1 + if (!key || !address || !computer_id) if(real_bans_only) + key_cache[key] = 0 return FALSE log_access("Failed Login (invalid data): [key] [address]-[computer_id]") + key_cache[key] = 0 return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]'. (If you continue to get this error, please restart byond or contact byond support.)") if (text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire log_access("Failed Login (invalid cid): [key] [address]-[computer_id]") + key_cache[key] = 0 return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.)") var/admin = 0 var/ckey = ckey(key) @@ -30,21 +39,25 @@ addclientmessage(ckey,"You have been allowed to bypass the whitelist") else log_access("Failed Login: [key] - Not on whitelist") + key_cache[key] = 0 return list("reason"="whitelist", "desc" = "\nReason: You are not on the white list for this server") //Guest Checking if(!real_bans_only && IsGuestKey(key)) if (CONFIG_GET(flag/guest_ban)) log_access("Failed Login: [key] - Guests not allowed") + key_cache[key] = 0 return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") if (CONFIG_GET(flag/panic_bunker) && SSdbcore.Connect()) log_access("Failed Login: [key] - Guests not allowed during panic bunker") + key_cache[key] = 0 return list("reason"="guest", "desc"="\nReason: Sorry but the server is currently not accepting connections from never before seen players or guests. If you have played on this server with a byond account before, please log in to the byond account you have played from.") //Population Cap Checking var/extreme_popcap = CONFIG_GET(number/extreme_popcap) if(!real_bans_only && extreme_popcap && living_player_count() >= extreme_popcap && !admin) log_access("Failed Login: [key] - Population cap reached") + key_cache[key] = 0 return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]") if(CONFIG_GET(flag/ban_legacy_system)) @@ -58,6 +71,7 @@ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]]") else log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") + key_cache[key] = 0 return . else @@ -65,6 +79,7 @@ var/msg = "Ban database connection failure. Key [ckey] not checked" log_world(msg) message_admins(msg) + key_cache[key] = 0 return var/ipquery = "" @@ -78,6 +93,7 @@ var/datum/DBQuery/query_ban_check = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), reason, expiration_time, duration, bantime, bantype, id, round_id FROM [format_table_name("ban")] WHERE (ckey = '[ckey]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") if(!query_ban_check.Execute(async = TRUE)) qdel(query_ban_check) + key_cache[key] = 0 return while(query_ban_check.NextRow()) var/pkey = query_ban_check.item[1] @@ -116,6 +132,7 @@ log_access("Failed Login: [key] [computer_id] [address] - Banned (#[banid]) [.["reason"]]") qdel(query_ban_check) + key_cache[key] = 0 return . qdel(query_ban_check) @@ -131,6 +148,7 @@ //rogue ban in the process of being reverted. if (cachedban && cachedban["reverting"]) + key_cache[key] = 0 return null if (cachedban && ckey != bannedckey) @@ -158,6 +176,7 @@ newmatches_admin.len > STICKYBAN_MAX_ADMIN_MATCHES \ ) if (cachedban["reverting"]) + key_cache[key] = 0 return null cachedban["reverting"] = TRUE @@ -175,6 +194,7 @@ cachedban["admin_matches_this_round"] = list() cachedban -= "reverting" world.SetConfig("ban", bannedckey, list2stickyban(cachedban)) + key_cache[key] = 0 return null //byond will not trigger isbanned() for "global" host bans, @@ -184,6 +204,7 @@ log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]") message_admins("The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]") addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban on [bannedckey]") + key_cache[key] = 0 return null if (C) //user is already connected!. @@ -193,6 +214,7 @@ . = list("reason" = "Stickyban", "desc" = desc) log_access("Failed Login: [key] [computer_id] [address] - StickyBanned [ban["message"]] Target Username: [bannedckey] Placed by [ban["admin"]]") + key_cache[key] = 0 return . From 7e7a11a5c88d822f2c995d76c1fbc07127deef62 Mon Sep 17 00:00:00 2001 From: CameronWoof Date: Thu, 2 Jan 2020 13:07:05 -0800 Subject: [PATCH 020/409] lizard tails for humans and anthromorphs --- .../new_player/sprite_accessories/tails.dm | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm index 33b174afa4..dac91b5445 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -370,6 +370,22 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/smooth + name = "Smooth" + icon_state = "smooth" + +/datum/sprite_accessory/tails_animated/human/smooth + name = "Smooth" + icon_state = "smooth" + +/datum/sprite_accessory/tails/human/spikes + name = "Spikes" + icon_state = "spikes" + +/datum/sprite_accessory/tails_animated/human/spikes + name = "Spikes" + icon_state = "spikes" + /datum/sprite_accessory/tails/human/shark name = "Shark" icon_state = "shark" @@ -438,6 +454,22 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + +/datum/sprite_accessory/tails_animated/human/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + +/datum/sprite_accessory/tails/human/ltiger + name = "Light Tiger" + icon_state = "ltiger" + +/datum/sprite_accessory/tails_animated/human/ltiger + name = "Light Tiger" + icon_state = "ltiger" + /datum/sprite_accessory/tails/human/wolf name = "Wolf" icon_state = "wolf" @@ -693,6 +725,30 @@ datum/sprite_accessory/mam_tails/insect name = "Skunk" icon_state = "skunk" +/datum/sprite_accessory/mam_tails/smooth + name = "Smooth" + icon_state = "smooth" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails_animated/smooth + name = "Smooth" + icon_state = "smooth" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails_animated/spikes + name = "Spikes" + icon_state = "spikes" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails/spikes + name = "Spikes" + icon_state = "spikes" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + /datum/sprite_accessory/mam_tails/shark name = "Shark" icon_state = "shark" @@ -741,6 +797,30 @@ datum/sprite_accessory/mam_tails/insect name = "Tiger" icon_state = "tiger" +/datum/sprite_accessory/mam_tails/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails_animated/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails/ltiger + name = "Light Tiger" + icon_state = "ltiger" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/mam_tails_animated/ltiger + name = "Light Tiger" + icon_state = "ltiger" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + /datum/sprite_accessory/mam_tails/wolf name = "Wolf" icon_state = "wolf" From 5e3abec7046ebe5ae1d8b72444a96572d0eef8cd Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 02:06:47 -0500 Subject: [PATCH 021/409] Removing turf with RCD cost mats. Port : https://github.com/tgstation/tgstation/pull/46801 --- code/game/turfs/simulated/floor.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index d14a4c7385..60ac502c52 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -267,7 +267,7 @@ A.autoclose = TRUE return TRUE if(RCD_DECONSTRUCT) - if(ScrapeAway() == src) + if(!ScrapeAway(flags = CHANGETURF_INHERIT_AIR)) return FALSE to_chat(user, "You deconstruct [src].") return TRUE From 37d50e2aafd3c2e041e89d85fb1384660de5d44a Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 02:13:20 -0500 Subject: [PATCH 022/409] Add RCD effects Port : https://github.com/tgstation/tgstation/pull/47894 & https://github.com/tgstation/tgstation/pull/48362/files --- .../temporary_visuals/miscellaneous.dm | 42 +++++++++++++++++- code/game/objects/items/RCD.dm | 6 ++- icons/effects/effects_rcd.dmi | Bin 0 -> 22425 bytes 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 icons/effects/effects_rcd.dmi diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 1b85a41f7c..2f18fa0ecb 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -452,4 +452,44 @@ icon_state = "slugboom" randomdir = FALSE duration = 30 - pixel_x = -24 \ No newline at end of file + pixel_x = -24 + +/obj/effect/constructing_effect + icon = 'icons/effects/effects_rcd.dmi' + icon_state = "" + layer = ABOVE_ALL_MOB_LAYER + anchored = TRUE + var/status = 0 + var/delay = 0 + +/obj/effect/constructing_effect/Initialize(mapload, rcd_delay, rcd_status) + . = ..() + status = rcd_status + delay = rcd_delay + if (status == RCD_DECONSTRUCT) + addtimer(CALLBACK(src, /atom/.proc/update_icon), 11) + delay -= 11 + icon_state = "rcd_end_reverse" + else + update_icon() + +/obj/effect/constructing_effect/update_icon() + icon_state = "rcd" + if (delay < 10) + icon_state += "_shortest" + else if (delay < 20) + icon_state += "_shorter" + else if (delay < 37) + icon_state += "_short" + if (status == RCD_DECONSTRUCT) + icon_state += "_reverse" + +/obj/effect/constructing_effect/proc/end_animation() + if (status == RCD_DECONSTRUCT) + qdel(src) + else + icon_state = "rcd_end" + addtimer(CALLBACK(src, .proc/end), 15) + +/obj/effect/constructing_effect/proc/end() + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 24c241aabc..c21c975f1a 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -439,18 +439,22 @@ RLD var/list/rcd_results = A.rcd_vals(user, src) if(!rcd_results) return FALSE + var/delay = rcd_results["delay"] * delay_mod + var/obj/effect/constructing_effect/rcd_effect = new(get_turf(A), delay, src.mode) var/turf/the_turf = get_turf(A) var/turf_coords = "[COORD(the_turf)]" investigate_log("[user] is attempting to use [src] on [A] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD) - if(do_after(user, rcd_results["delay"] * delay_mod, target = A)) + if(do_after(user, delay, target = A)) if(checkResource(rcd_results["cost"], user)) var/atom/cached = A if(A.rcd_act(user, src, rcd_results["mode"])) + rcd_effect.end_animation() useResource(rcd_results["cost"], user) activate() investigate_log("[user] used [src] on [cached] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD) playsound(src, 'sound/machines/click.ogg', 50, 1) return TRUE + qdel(rcd_effect) /obj/item/construction/rcd/Initialize() . = ..() diff --git a/icons/effects/effects_rcd.dmi b/icons/effects/effects_rcd.dmi new file mode 100644 index 0000000000000000000000000000000000000000..efb13bfb11a15a8d03bb24d5da9c89e3d2f59de2 GIT binary patch literal 22425 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 Rf=gm{eH-9+f5-9c{{u)XGM)ec literal 0 HcmV?d00001 From 15d79d8818fafdbf33b472789ec2679a9f2d5269 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 02:14:41 -0500 Subject: [PATCH 023/409] RCD don't work on R-Doors Port : https://github.com/tgstation/tgstation/pull/43598 --- code/game/machinery/doors/airlock.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 52b52eb288..7f953052f5 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1408,6 +1408,9 @@ /obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) if(RCD_DECONSTRUCT) + if(security_level != AIRLOCK_SECURITY_NONE) + to_chat(user, "[src]'s reinforcement needs to be removed first.") + return FALSE return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 32) return FALSE From 031f485e4dd8b95012d0c79a3907db80e3929761 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Thu, 2 Jan 2020 23:24:47 -0800 Subject: [PATCH 024/409] updates --- code/__DEFINES/callbacks.dm | 3 +- code/__DEFINES/qdel.dm | 10 +- code/__HELPERS/unsorted.dm | 31 ++++ code/controllers/master.dm | 7 +- code/controllers/subsystem/server_maint.dm | 28 +++- code/controllers/subsystem/timer.dm | 51 ++++++- code/datums/callback.dm | 161 +++++++++++++-------- 7 files changed, 213 insertions(+), 78 deletions(-) diff --git a/code/__DEFINES/callbacks.dm b/code/__DEFINES/callbacks.dm index 126ef1ea1c..f25dfdf150 100644 --- a/code/__DEFINES/callbacks.dm +++ b/code/__DEFINES/callbacks.dm @@ -1,4 +1,5 @@ #define GLOBAL_PROC "some_magic_bullshit" - +/// A shorthand for the callback datum, [documented here](datum/callback.html) #define CALLBACK new /datum/callback #define INVOKE_ASYNC world.ImmediateInvokeAsync +#define CALLBACK_NEW(typepath, args) CALLBACK(GLOBAL_PROC, /proc/___callbacknew, typepath, args) diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 71dbf82734..4296e3c2e9 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -11,14 +11,12 @@ #define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails. //defines for the gc_destroyed var -#define GC_QUEUE_PREQUEUE 1 -#define GC_QUEUE_CHECK 2 -#define GC_QUEUE_HARDDELETE 3 -#define GC_QUEUE_COUNT 3 //increase this when adding more steps. +#define GC_QUEUE_CHECK 1 +#define GC_QUEUE_HARDDELETE 2 +#define GC_QUEUE_COUNT 2 //increase this when adding more steps. #define GC_QUEUED_FOR_QUEUING -1 -#define GC_QUEUED_FOR_HARD_DEL -2 -#define GC_CURRENTLY_BEING_QDELETED -3 +#define GC_CURRENTLY_BEING_QDELETED -2 #define QDELING(X) (X.gc_destroyed) #define QDELETED(X) (!X || QDELING(X)) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 74c32dd52f..e64ed8fd55 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1452,6 +1452,37 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) else D.vars[var_name] = var_value +#define TRAIT_CALLBACK_ADD(target, trait, source) CALLBACK(GLOBAL_PROC, /proc/___TraitAdd, ##target, ##trait, ##source) +#define TRAIT_CALLBACK_REMOVE(target, trait, source) CALLBACK(GLOBAL_PROC, /proc/___TraitRemove, ##target, ##trait, ##source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitAdd(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + ADD_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + ADD_TRAIT(the_atom2,trait,source) + +///DO NOT USE ___TraitAdd OR ___TraitRemove as a replacement for ADD_TRAIT / REMOVE_TRAIT defines. To be used explicitly for callback. +/proc/___TraitRemove(target,trait,source) + if(!target || !trait || !source) + return + if(islist(target)) + for(var/i in target) + if(!isatom(i)) + continue + var/atom/the_atom = i + REMOVE_TRAIT(the_atom,trait,source) + else if(isatom(target)) + var/atom/the_atom2 = target + REMOVE_TRAIT(the_atom2,trait,source) + /proc/get_random_food() var/list/blocked = list(/obj/item/reagent_containers/food/snacks, /obj/item/reagent_containers/food/snacks/store/bread, diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 125da84a30..8772fac5af 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -8,6 +8,7 @@ **/ //This is the ABSOLUTE ONLY THING that should init globally like this +//2019 update: the failsafe,config and Global controllers also do it GLOBAL_REAL(Master, /datum/controller/master) = new //THIS IS THE INIT ORDER @@ -54,7 +55,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/static/restart_clear = 0 var/static/restart_timeout = 0 var/static/restart_count = 0 - + var/static/random_seed //current tick limit, assigned before running a subsystem. @@ -69,7 +70,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if(!random_seed) random_seed = (TEST_RUN_PARAMETER in world.params) ? 29051994 : rand(1, 1e9) rand_seed(random_seed) - + var/list/_subsystems = list() subsystems = _subsystems if (Master != src) @@ -614,4 +615,4 @@ GLOBAL_REAL(Master, /datum/controller/master) = new if (client_count < CONFIG_GET(number/mc_tick_rate/disable_high_pop_mc_mode_amount)) processing = CONFIG_GET(number/mc_tick_rate/base_mc_tick_rate) else if (client_count > CONFIG_GET(number/mc_tick_rate/high_pop_mc_mode_amount)) - processing = CONFIG_GET(number/mc_tick_rate/high_pop_mc_tick_rate) \ No newline at end of file + processing = CONFIG_GET(number/mc_tick_rate/high_pop_mc_tick_rate) diff --git a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm index 15d3e17d29..9e926b29a1 100644 --- a/code/controllers/subsystem/server_maint.dm +++ b/code/controllers/subsystem/server_maint.dm @@ -8,6 +8,10 @@ SUBSYSTEM_DEF(server_maint) init_order = INIT_ORDER_SERVER_MAINT runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT var/list/currentrun + var/cleanup_ticker = 0 + +/datum/controller/subsystem/server_maint/PreInit() + world.hub_password = "" //quickly! before the hubbies see us. /datum/controller/subsystem/server_maint/Initialize(timeofday) if (CONFIG_GET(flag/hub)) @@ -18,10 +22,30 @@ SUBSYSTEM_DEF(server_maint) if(!resumed) if(listclearnulls(GLOB.clients)) log_world("Found a null in clients list!") - if(listclearnulls(GLOB.player_list)) - log_world("Found a null in player list!") src.currentrun = GLOB.clients.Copy() + switch (cleanup_ticker) // do only one of these at a time, once per 5 fires + if (0) + if(listclearnulls(GLOB.player_list)) + log_world("Found a null in player_list!") + cleanup_ticker++ + if (5) + if(listclearnulls(GLOB.mob_list)) + log_world("Found a null in mob_list!") + cleanup_ticker++ + if (10) + if(listclearnulls(GLOB.alive_mob_list)) + log_world("Found a null in alive_mob_list!") + cleanup_ticker++ + if (15) + if(listclearnulls(GLOB.dead_mob_list)) + log_world("Found a null in dead_mob_list!") + cleanup_ticker++ + if (20) + cleanup_ticker = 0 + else + cleanup_ticker++ + var/list/currentrun = src.currentrun var/round_started = SSticker.HasRoundStarted() diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index d0eb0b9ce2..bd2fb854af 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -1,5 +1,5 @@ #define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth) -#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN)||BUCKET_LEN) +#define BUCKET_POS(timer) (((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag)+1) % BUCKET_LEN)||BUCKET_LEN) #define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1))) #define TIMER_ID_MAX (2**24) //max float with integer precision @@ -38,15 +38,15 @@ SUBSYSTEM_DEF(timer) /datum/controller/subsystem/timer/fire(resumed = FALSE) var/lit = last_invoke_tick - var/last_check = world.time - TIMER_NO_INVOKE_WARNING + var/last_check = world.time - TICKS2DS(BUCKET_LEN*1.5) var/list/bucket_list = src.bucket_list if(!bucket_count) last_invoke_tick = world.time - if(lit && lit < last_check && last_invoke_warning < last_check) + if(lit && lit < last_check && head_offset < last_check && last_invoke_warning < last_check) last_invoke_warning = world.time - var/msg = "No regular timers processed in the last [TIMER_NO_INVOKE_WARNING] ticks[bucket_auto_reset ? ", resetting buckets" : ""]!" + var/msg = "No regular timers processed in the last [BUCKET_LEN*1.5] ticks[bucket_auto_reset ? ", resetting buckets" : ""]!" message_admins(msg) WARNING(msg) if(bucket_auto_reset) @@ -121,7 +121,7 @@ SUBSYSTEM_DEF(timer) if (!resumed) timer = null - while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time) + while (practical_offset <= BUCKET_LEN && head_offset + ((practical_offset-1)*world.tick_lag) <= world.time) var/datum/timedevent/head = bucket_list[practical_offset] if (!timer || !head || timer == head) head = bucket_list[practical_offset] @@ -159,7 +159,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() @@ -169,9 +169,9 @@ SUBSYSTEM_DEF(timer) qdel(timer) continue - if (timer.timeToRun < head_offset + TICKS2DS(practical_offset)) + 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 @@ -447,6 +447,7 @@ SUBSYSTEM_DEF(timer) next.prev = src prev.next = src +///Returns a string of the type of the callback for this timer /datum/timedevent/proc/getcallingtype() . = "ERROR" if (callBack.object == GLOBAL_PROC) @@ -454,6 +455,14 @@ SUBSYSTEM_DEF(timer) else . = "[callBack.object.type]" +/** + * Create a new timer and insert it in the queue + * + * Arguments: + * * callback the callback to call on timer finish + * * wait deciseconds to run the timer for + * * flags flags for this timer, see: code\__DEFINES\subsystems.dm + */ /proc/addtimer(datum/callback/callback, wait = 0, flags = 0) if (!callback) CRASH("addtimer called without a callback") @@ -498,6 +507,12 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/timer = new(callback, wait, flags, hash) return timer.id +/** + * Delete a timer + * + * Arguments: + * * id a timerid or a /datum/timedevent + */ /proc/deltimer(id) if (!id) return FALSE @@ -514,6 +529,26 @@ SUBSYSTEM_DEF(timer) return TRUE return FALSE +/** + * Get the remaining deciseconds on a timer + * + * Arguments: + * * id a timerid or a /datum/timedevent + */ +/proc/timeleft(id) + if (!id) + return null + if (id == TIMER_ID_NULL) + CRASH("Tried to get timeleft of a null timerid. Use TIMER_STOPPABLE flag") + if (!istext(id)) + if (istype(id, /datum/timedevent)) + var/datum/timedevent/timer = id + return timer.timeToRun - world.time + //id is string + var/datum/timedevent/timer = SStimer.timer_id_dict[id] + if (timer && !timer.spent) + return timer.timeToRun - world.time + return null #undef BUCKET_LEN #undef BUCKET_POS diff --git a/code/datums/callback.dm b/code/datums/callback.dm index 1a26052cc9..62e10922f3 100644 --- a/code/datums/callback.dm +++ b/code/datums/callback.dm @@ -1,55 +1,72 @@ -/* - USAGE: - - var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn) - var/timerid = addtimer(C, time, timertype) - OR - var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype) - - Note: proc strings can only be given for datum proc calls, global procs must be proc paths - Also proc strings are strongly advised against because they don't compile error if the proc stops existing - See the note on proc typepath shortcuts - - INVOKING THE CALLBACK: - var/result = C.Invoke(args, to, add) //additional args are added after the ones given when the callback was created - OR - var/result = C.InvokeAsync(args, to, add) //Sleeps will not block, returns . on the first sleep (then continues on in the "background" after the sleep/block ends), otherwise operates normally. - OR - INVOKE_ASYNC() to immediately create and call InvokeAsync - - PROC TYPEPATH SHORTCUTS (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...) - - global proc while in another global proc: - .procname - Example: - CALLBACK(GLOBAL_PROC, .some_proc_here) - - proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents: - .procname - Example: - CALLBACK(src, .some_proc_here) - - - when the above doesn't apply: - .proc/procname - Example: - CALLBACK(src, .proc/some_proc_here) - - proc defined on a parent of a some type: - /some/type/.proc/some_proc_here - - - - Other wise you will have to do the full typepath of the proc (/type/of/thing/proc/procname) - -*/ - +/** + *# Callback Datums + *A datum that holds a proc to be called on another object, used to track proccalls to other objects + * + * ## USAGE + * + * ``` + * var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn) + * var/timerid = addtimer(C, time, timertype) + * you can also use the compiler define shorthand + * var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype) + * ``` + * + * Note: proc strings can only be given for datum proc calls, global procs must be proc paths + * + * Also proc strings are strongly advised against because they don't compile error if the proc stops existing + * + * In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below + * + * ## INVOKING THE CALLBACK + *`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created + * + * `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background + * after the sleep/block ends, otherwise operates normally. + * + * ## PROC TYPEPATH SHORTCUTS + * (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...) + * + * ### global proc while in another global proc: + * .procname + * + * `CALLBACK(GLOBAL_PROC, .some_proc_here)` + * + * ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents: + * .procname + * + * `CALLBACK(src, .some_proc_here)` + * + * ### when the above doesn't apply: + *.proc/procname + * + * `CALLBACK(src, .proc/some_proc_here)` + * + * + * proc defined on a parent of a some type + * + * `/some/type/.proc/some_proc_here` + * + * Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname) + */ /datum/callback + + ///The object we will be calling the proc on var/datum/object = GLOBAL_PROC + ///The proc we will be calling on the object var/delegate + ///A list of arguments to pass into the proc var/list/arguments + ///A weak reference to the user who triggered this callback var/datum/weakref/user +/** + * Create a new callback datum + * + * Arguments + * * thingtocall the object to call the proc on + * * proctocall the proc to call on the target object + * * ... an optional list of extra arguments to pass to the proc + */ /datum/callback/New(thingtocall, proctocall, ...) if (thingtocall) object = thingtocall @@ -58,7 +75,14 @@ arguments = args.Copy(3) if(usr) user = WEAKREF(usr) - +/** + * Immediately Invoke proctocall on thingtocall, with waitfor set to false + * + * Arguments: + * * thingtocall Object to call on + * * proctocall Proc to call on that object + * * ... optional list of arguments to pass as arguments to the proc being called + */ /world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...) set waitfor = FALSE @@ -72,6 +96,14 @@ else call(thingtocall, proctocall)(arglist(calling_arguments)) +/** + * Invoke this callback + * + * Calls the registered proc on the registered object, if the user ref + * can be resolved it also inclues that as an arg + * + * If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall + */ /datum/callback/proc/Invoke(...) if(!usr) var/datum/weakref/W = user @@ -97,7 +129,14 @@ return call(delegate)(arglist(calling_arguments)) return call(object, delegate)(arglist(calling_arguments)) -//copy and pasted because fuck proc overhead +/** + * Invoke this callback async (waitfor=false) + * + * Calls the registered proc on the registered object, if the user ref + * can be resolved it also inclues that as an arg + * + * If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall + */ /datum/callback/proc/InvokeAsync(...) set waitfor = FALSE @@ -125,7 +164,9 @@ return call(delegate)(arglist(calling_arguments)) return call(object, delegate)(arglist(calling_arguments)) - +/** + Helper datum for the select callbacks proc + */ /datum/callback_select var/list/finished var/pendingcount @@ -150,15 +191,17 @@ if (savereturn) finished[index] = rtn - - - -//runs a list of callbacks asynchronously, returning once all of them return. -//callbacks can be repeated. -//callbacks-args is an optional list of argument lists, in the same order as the callbacks, -// the inner lists will be sent to the callbacks when invoked() as additional args. -//can optionly save and return a list of return values, in the same order as the original list of callbacks -//resolution is the number of byond ticks between checks. +/** + * Runs a list of callbacks asyncronously, returning only when all have finished + * + * Callbacks can be repeated, to call it multiple times + * + * Arguments: + * * list/callbacks the list of callbacks to be called + * * list/callback_args the list of lists of arguments to pass into each callback + * * savereturns Optionally save and return the list of returned values from each of the callbacks + * * resolution The number of byond ticks between each time you check if all callbacks are complete + */ /proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1) if (!callbacks) return @@ -178,3 +221,5 @@ sleep(resolution*world.tick_lag) return CS.finished +/proc/___callbacknew(typepath, arguments) + new typepath(arglist(arguments)) From 5c94e02eac37cd3e5edd027ebb2593ff835c4b29 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 02:32:43 -0500 Subject: [PATCH 025/409] Add simple RCD Circuits Port : https://github.com/tgstation/tgstation/pull/45357 --- code/__DEFINES/construction.dm | 5 +- code/game/machinery/doors/firedoor.dm | 15 ++++++ code/game/machinery/firealarm.dm | 14 ++++++ code/game/objects/items/RCD.dm | 25 +++++++--- .../atmospherics/machinery/airalarm.dm | 15 ++++++ code/modules/power/apc.dm | 46 +++++++++++++++++++ code/modules/research/designs/misc_designs.dm | 18 ++++++-- code/modules/research/techweb/all_nodes.dm | 2 +- 8 files changed, 127 insertions(+), 13 deletions(-) diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm index c394d003d8..c93f1b2435 100644 --- a/code/__DEFINES/construction.dm +++ b/code/__DEFINES/construction.dm @@ -110,4 +110,7 @@ #define RCD_DECONSTRUCT 3 #define RCD_WINDOWGRILLE 4 #define RCD_MACHINE 8 -#define RCD_COMPUTER 16 \ No newline at end of file +#define RCD_COMPUTER 16 + +#define RCD_UPGRADE_FRAMES 1 +#define RCD_UPGRADE_SIMPLE_CIRCUITS 2 \ No newline at end of file diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index dec41b0a59..39b6c8da1d 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -450,6 +450,21 @@ return return ..() +/obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((constructionStep == CONSTRUCTION_NOCIRCUIT) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/structure/firelock_frame/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a firelock circuit and slot it into the assembly.") + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return TRUE + return FALSE + /obj/structure/firelock_frame/heavy name = "heavy firelock frame" reinforced = TRUE diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 71f39608b5..51cd9de2d1 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -256,6 +256,20 @@ return return ..() +/obj/machinery/firealarm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((buildstage == 0) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/machinery/firealarm/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a fire alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return TRUE + return FALSE /obj/machinery/firealarm/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index c21c975f1a..b4f0f1459a 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -85,9 +85,11 @@ RLD to_chat(user, "[src] now holds [matter]/[max_matter] matter-units.") else if(istype(W, /obj/item/rcd_upgrade)) to_chat(user, "You upgrade the RCD with the [W]!") - upgrade = TRUE - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - qdel(W) + var/obj/item/rcd_upgrade/rcd_up = W + if(!(upgrade & rcd_up.upgrade)) + upgrade |= rcd_up.upgrade + playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + qdel(W) else return ..() update_icon() //ensures that ammo counters (if present) get updated @@ -116,10 +118,10 @@ RLD if(matter < amount) if(user) to_chat(user, no_ammo_message) - return 0 + return FALSE matter -= amount update_icon() - return 1 + return TRUE /obj/item/construction/proc/checkResource(amount, mob/user) . = matter >= amount @@ -471,7 +473,7 @@ RLD "Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"), "Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor") ) - if(upgrade) + if(upgrade & RCD_UPGRADE_FRAMES) choices += list( "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"), "Machine Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "machine"), @@ -829,9 +831,18 @@ RLD /obj/item/rcd_upgrade name = "RCD advanced design disk" - desc = "It contains the design for machine frames, computer frames, and deconstruction." + desc = "It seems to be empty." icon = 'icons/obj/module.dmi' icon_state = "datadisk3" + var/upgrade + +/obj/item/rcd_upgrade/frames + desc = "It contains the design for machine frames, computer frames and deconstruction." + upgrade = RCD_UPGRADE_FRAMES + +/obj/item/rcd_upgrade/simple_circuits + desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells." + upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS #undef GLOW_MODE #undef LIGHT_MODE diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index cbbfc05f39..e49368016b 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -822,6 +822,21 @@ return ..() +/obj/machinery/airalarm/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((buildstage == 0) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/machinery/airalarm/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt an air alarm circuit and slot it into the assembly.") + buildstage = 1 + update_icon() + return TRUE + return FALSE + /obj/machinery/airalarm/AltClick(mob/user) . = ..() if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2652026a11..0ad2983b91 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -701,6 +701,52 @@ else return ..() +/obj/machinery/power/apc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if(the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS) + if(!has_electronics) + if(stat & BROKEN) + to_chat(user, "[src]'s frame is too damaged to support a circuit.") + return FALSE + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + else if(!cell) + if(stat & MAINT) + to_chat(user, "There's no connector for a power cell.") + return FALSE + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 50, "cost" = 10) //16 for a wall + else + to_chat(user, "[src] has both electronics and a cell.") + return FALSE + return FALSE + +/obj/machinery/power/apc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + if(!has_electronics) + if(stat & BROKEN) + to_chat(user, "[src]'s frame is too damaged to support a circuit.") + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a power control board and click it into place in [src]'s guts.") + has_electronics = TRUE + locked = TRUE + return TRUE + else if(!cell) + if(stat & MAINT) + to_chat(user, "There's no connector for a power cell.") + return FALSE + var/obj/item/stock_parts/cell/crap/empty/C = new(src) + C.forceMove(src) + cell = C + chargecount = 0 + user.visible_message("[user] fabricates a weak power cell and places it into [src].", \ + "Your [the_rcd.name] whirrs with strain as you create a weak power cell and place it into [src]!") + update_icon() + return TRUE + else + to_chat(user, "[src] has both electronics and a cell.") + return FALSE + return FALSE + /obj/machinery/power/apc/AltClick(mob/user) . = ..() if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 5f7648b245..eeac6a5818 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -379,13 +379,23 @@ ////////////Tools////////////// /////////////////////////////// -/datum/design/rcd_upgrade - name = "Advanced RCD designs upgrade" +/datum/design/rcd_upgrade/frames + name = "RCD frames designs upgrade" desc = "Adds the computer frame and machine frame to the RCD." - id = "rcd_upgrade" + id = "rcd_upgrade_frames" build_type = PROTOLATHE materials = list(MAT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) - build_path = /obj/item/rcd_upgrade + build_path = /obj/item/rcd_upgrade/frames + category = list("Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/rcd_upgrade/simple_circuits + name = "RCD simple circuits designs upgrade" + desc = "Adds the simple circuits to the RCD." + id = "rcd_upgrade_simple_circuits" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 5000, /datum/material/glass = 2500, /datum/material/silver = 1500, /datum/material/titanium = 2000) + build_path = /obj/item/rcd_upgrade/simple_circuits category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 5f3fc0e85e..ce32c467c9 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -200,7 +200,7 @@ display_name = "Advanced Engineering" description = "Pushing the boundaries of physics, one chainsaw-fist at a time." prereq_ids = list("engineering", "emp_basic") - design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade") + design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) export_price = 5000 From 58a986696f6e33c7600c3a9204ad004aa6def2b1 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 02:46:25 -0500 Subject: [PATCH 026/409] Add RCD and RPD to Engie's protolathe Half-port with bonus : https://github.com/tgstation/tgstation/pull/47289 --- code/modules/research/designs/misc_designs.dm | 20 +++++++++++++++++++ code/modules/research/techweb/all_nodes.dm | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index eeac6a5818..5ae33a4752 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -429,6 +429,26 @@ category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING +/datum/design/rcd_loaded + name = "Rapid Construction Device" + desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly." + id = "rcd_loaded" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 60000, /datum/material/glass = 5000) // costs more than what it did in the autolathe, this one comes loaded. + build_path = /obj/item/construction/rcd/loaded + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/rpd + name = "Rapid Pipe Dispenser" + desc = "A tool that can construct and deconstruct pipes on the fly." + id = "rpd" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) // costs more than what it did in the autolathe, this one comes loaded. + build_path = /obj/item/construction/rcd/loaded + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + /datum/design/alienwrench name = "Alien Wrench" desc = "An advanced wrench obtained through Abductor technology." diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index ce32c467c9..1ce28c9ba9 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -200,7 +200,7 @@ display_name = "Advanced Engineering" description = "Pushing the boundaries of physics, one chainsaw-fist at a time." prereq_ids = list("engineering", "emp_basic") - design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits") + design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask" , "rcd_loaded", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade_frames", "rcd_upgrade_simple_circuits") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) export_price = 5000 From 8e1affa1f5c477f9753166ca4f5dc15c84699060 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Thu, 2 Jan 2020 23:56:40 -0800 Subject: [PATCH 027/409] nightshift changes --- code/__DEFINES/misc.dm | 6 + .../configuration/entries/game_options.dm | 9 ++ code/controllers/subsystem/nightshift.dm | 8 +- code/game/area/Space_Station_13_areas.dm | 17 +++ code/game/area/areas.dm | 2 + code/modules/power/apc.dm | 140 ++++++++++-------- config/game_options.txt | 11 +- 7 files changed, 128 insertions(+), 65 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index d89743d2d2..502e1b5edf 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -530,3 +530,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define CRYOMOBS 'icons/obj/cryo_mobs.dmi' #define CANT_REENTER_ROUND -1 + +//Nightshift levels. +#define NIGHTSHIFT_AREA_NONE 0 //default +#define NIGHTSHIFT_AREA_PUBLIC 1 //hallways +#define NIGHTSHIFT_AREA_RECREATION 2 //dorms common areas, etc +#define NIGHTSHIFT_AREA_DEPARTMENT_HALLS 3 //interior hallways, etc diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 61b5788ef8..7ddc9095ee 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -362,6 +362,15 @@ /datum/config_entry/flag/enable_night_shifts +/datum/config_entry/number/night_shift_public_areas_only + config_entry_value = NIGHTSHIFT_AREA_PUBLIC + +/datum/config_entry/flag/nightshift_toggle_requires_auth + config_entry_value = FALSE + +/datum/config_entry/flag/nightshift_toggle_public_requires_auth + config_entry_value = TRUE + /datum/config_entry/flag/randomize_shift_time /datum/config_entry/flag/shift_time_realtime diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm index df406eed3c..6ce8704655 100644 --- a/code/controllers/subsystem/nightshift.dm +++ b/code/controllers/subsystem/nightshift.dm @@ -35,21 +35,21 @@ SUBSYSTEM_DEF(nightshift) if(!emergency) announce("Restoring night lighting configuration to normal operation.") else - announce("Disabling night lighting: Station is in a state of emergency.") + announce("Disabling night lighting: Station is in a state of emergency.") if(emergency) night_time = FALSE if(nightshift_active != night_time) update_nightshift(night_time, announcing) -/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE) +/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE, max_level = (!active? INFINITY : CONFIG_GET(number/night_shift_public_area_only))) nightshift_active = active if(announce) if (active) announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.") else - announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.") + var/public_only = CONFIG_GET(number/night_shift_public_area_only) for(var/A in GLOB.apcs_list) var/obj/machinery/power/apc/APC = A - if (APC.area && (APC.area.type in GLOB.the_station_areas)) + if(APC.area && (!max_level || !APC.area.nightshift_public_area || (APC.area.nightshift_public_area <= max_level)) && (APC.area.type in GLOB.the_station_areas)) APC.set_nightshift(active) CHECK_TICK diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index fa66306302..4cfbc7366f 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -259,6 +259,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station //Hallway +/area/hallway + nightshift_public_area = NIGHTSHIFT_AREA_PUBLIC + /area/hallway/primary/aft name = "Aft Primary Hallway" icon_state = "hallA" @@ -404,14 +407,17 @@ NOTE: there are two lists of areas in the end of this file: centcom and station name = "Dormitories" icon_state = "Sleep" safe = TRUE + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/dorms/male name = "Male Dorm" icon_state = "Sleep" + nightshift_public_area = NIGHTSHIFT_AREA_NONE /area/crew_quarters/dorms/female name = "Female Dorm" icon_state = "Sleep" + nightshift_public_area = NIGHTSHIFT_AREA_NONE /area/crew_quarters/rehab_dome name = "Rehabilitation Dome" @@ -448,26 +454,32 @@ NOTE: there are two lists of areas in the end of this file: centcom and station /area/crew_quarters/locker name = "Locker Room" icon_state = "locker" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/lounge name = "Lounge" icon_state = "yellow" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/fitness name = "Fitness Room" icon_state = "fitness" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/fitness/recreation name = "Recreation Area" icon_state = "fitness" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/cafeteria name = "Cafeteria" icon_state = "cafeteria" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/cafeteria/lunchroom name = "Lunchroom" icon_state = "cafeteria" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/kitchen name = "Kitchen" @@ -480,6 +492,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station /area/crew_quarters/bar name = "Bar" icon_state = "bar" + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/crew_quarters/bar/atrium name = "Atrium" @@ -518,6 +531,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station name = "Library" icon_state = "library" flags_1 = NONE + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/library/lounge name = "Library Lounge" @@ -527,6 +541,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station name = "Abandoned Library" icon_state = "library" flags_1 = NONE + nightshift_public_area = NIGHTSHIFT_AREA_NONE /area/chapel icon_state = "chapel" @@ -534,12 +549,14 @@ NOTE: there are two lists of areas in the end of this file: centcom and station flags_1 = NONE clockwork_warp_allowed = FALSE clockwork_warp_fail = "The consecration here prevents you from warping in." + nightshift_public_area = NIGHTSHIFT_AREA_RECREATION /area/chapel/main name = "Chapel" /area/chapel/main/monastery name = "Monastery" + nightshift_public_area = NIGHTSHIFT_AREA_NONE /area/chapel/office name = "Chapel Office" diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index f65ea98cab..2d256aad27 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -63,6 +63,8 @@ var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default? var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with + var/nightshift_public_area = NIGHTSHIFT_AREA_NONE //considered a public area for nightshift + /*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) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2652026a11..5f51a87f80 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -98,6 +98,7 @@ var/force_update = 0 var/emergency_lights = FALSE var/nightshift_lights = FALSE + var/nightshift_requires_auth = FALSE var/last_nightshift_switch = 0 var/update_state = -1 var/update_overlay = -1 @@ -239,6 +240,7 @@ update_icon() make_terminal() + update_nightshift_auth_requirement() addtimer(CALLBACK(src, .proc/update), 5) @@ -806,6 +808,7 @@ /obj/machinery/power/apc/ui_data(mob/user) var/list/data = list( "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)), + "lock_nightshift" = nightshift_requires_auth, "failTime" = failure_timer, "isOperating" = operating, "externalPower" = main_status, @@ -913,70 +916,73 @@ . = UI_INTERACTIVE /obj/machinery/power/apc/ui_act(action, params) - if(..() || !can_use(usr, 1) || (locked && !usr.has_unlimited_silicon_privilege && !failure_timer && !(integration_cog && (is_servant_of_ratvar(usr))))) + if(..() || !can_use(usr, 1)) return - switch(action) - if("lock") - if(usr.has_unlimited_silicon_privilege) - if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT))) - to_chat(usr, "The APC does not respond to the command.") - else - locked = !locked - update_icon() - . = TRUE - if("cover") - coverlocked = !coverlocked - . = TRUE - if("breaker") - toggle_breaker() - . = TRUE - if("toggle_nightshift") - toggle_nightshift_lights() - . = TRUE - if("charge") - chargemode = !chargemode - if(!chargemode) - charging = APC_NOT_CHARGING - update_icon() - . = TRUE - if("channel") - if(params["eqp"]) - equipment = setsubsystem(text2num(params["eqp"])) - update_icon() - update() - else if(params["lgt"]) - lighting = setsubsystem(text2num(params["lgt"])) - update_icon() - update() - else if(params["env"]) - environ = setsubsystem(text2num(params["env"])) - update_icon() - update() - . = TRUE - if("overload") - if(usr.has_unlimited_silicon_privilege) - overload_lighting() - . = TRUE - if("hack") - if(get_malf_status(usr)) - malfhack(usr) - if("occupy") - if(get_malf_status(usr)) - malfoccupy(usr) - if("deoccupy") - if(get_malf_status(usr)) - malfvacate() - if("reboot") + if(failure_timer) + if(action == "reboot") failure_timer = 0 update_icon() update() - if("emergency_lighting") - emergency_lights = !emergency_lights - for(var/obj/machinery/light/L in area) - if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override - L.no_emergency = emergency_lights - INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) - CHECK_TICK + var/authorized = (!locked || !usr.has_unlimited_silicon_privilege || failure_timer || (integration_cog && (is_servant_of_ratvar(usr)))) + if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized)) + toggle_nightshift_lights() + . = TRUE + if(authorized) + switch(action) + if("lock") + if(usr.has_unlimited_silicon_privilege) + if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT))) + to_chat(usr, "The APC does not respond to the command.") + else + locked = !locked + update_icon() + . = TRUE + if("cover") + coverlocked = !coverlocked + . = TRUE + if("breaker") + toggle_breaker() + . = TRUE + if("charge") + chargemode = !chargemode + if(!chargemode) + charging = APC_NOT_CHARGING + update_icon() + . = TRUE + if("channel") + if(params["eqp"]) + equipment = setsubsystem(text2num(params["eqp"])) + update_icon() + update() + else if(params["lgt"]) + lighting = setsubsystem(text2num(params["lgt"])) + update_icon() + update() + else if(params["env"]) + environ = setsubsystem(text2num(params["env"])) + update_icon() + update() + . = TRUE + if("overload") + if(usr.has_unlimited_silicon_privilege) + overload_lighting() + . = TRUE + if("hack") + if(get_malf_status(usr)) + malfhack(usr) + if("occupy") + if(get_malf_status(usr)) + malfoccupy(usr) + if("deoccupy") + if(get_malf_status(usr)) + malfvacate() + if("emergency_lighting") + emergency_lights = !emergency_lights + for(var/obj/machinery/light/L in area) + if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override + L.no_emergency = emergency_lights + INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) + CHECK_TICK return 1 /obj/machinery/power/apc/proc/toggle_breaker() @@ -1383,6 +1389,8 @@ /obj/machinery/power/apc/proc/set_nightshift(on) set waitfor = FALSE + if(nightshift_lights == on) + return nightshift_lights = on for(var/obj/machinery/light/L in area) if(L.nightshift_allowed) @@ -1390,6 +1398,18 @@ L.update(FALSE) CHECK_TICK +/obj/machinery/power/apc/proc/update_nightshift_auth_requirement() + nightshift_requires_auth = nightshift_toggle_requires_auth() + +/obj/machinery/power/apc/proc/nightshift_toggle_requires_auth() + if(!area) + return FALSE + var/configured_level = CONFIG_GET(number/nightshift_public_areas_only) + var/our_level = area.nightshift_public_area + var/public_requires_auth = CONFIG_GET(flag/nightshift_toggle_public_requires_auth) + var/normal_requires_auth = CONFIG_GET(flag/nightshift_toggle_requires_auth) + return (configured_level && our_level && (our_level <= configured_level))? public_requires_auth : normal_requires_auth) + #undef UPSTATE_CELL_IN #undef UPSTATE_OPENED1 #undef UPSTATE_OPENED2 diff --git a/config/game_options.txt b/config/game_options.txt index 34c8ca48fd..24d3baadd5 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -560,6 +560,15 @@ ROUNDSTART_TRAITS ## Enable night shifts ## #ENABLE_NIGHT_SHIFTS +## Makes night shifts only affect in-code public-flagged areas. Nightshifts hit the level as defined in __DEFINES/misc.dm that this is set to and anything below. ## +NIGHT_SHIFT_PUBLIC_AREAS_ONLY 1 + +## Nightshift toggles REQUIRE APC authorization ## +#NIGHTSHIFT_TOGGLE_REQUIRES_AUTH + +## Nightshift toggles in public areas REQUIRE APC authorization ## +NIGHTSHIFT_TOGGLE_PUBLIC_REQUIRES_AUTH + ## Enable randomized shift start times## #RANDOMIZE_SHIFT_TIME @@ -578,4 +587,4 @@ DYNAMIC_VOTING ## Choose which Engine to start the round with, comment to remove an Engine from the rotation BOX_RANDOM_ENGINE Engine SM BOX_RANDOM_ENGINE Engine Tesla -BOX_RANDOM_ENGINE Engine Singulo \ No newline at end of file +BOX_RANDOM_ENGINE Engine Singulo From aac1b42b8f7112d3cd763641d6b3d4071573cf45 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Fri, 3 Jan 2020 00:01:48 -0800 Subject: [PATCH 028/409] nightshift improvements --- code/controllers/subsystem/nightshift.dm | 10 +++++++-- code/modules/power/apc.dm | 2 +- tgui/assets/tgui.css | 2 +- tgui/assets/tgui.js | 26 ++++++++++++------------ tgui/src/interfaces/apc.ract | 2 +- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm index 6ce8704655..3242afe7bc 100644 --- a/code/controllers/subsystem/nightshift.dm +++ b/code/controllers/subsystem/nightshift.dm @@ -41,13 +41,19 @@ SUBSYSTEM_DEF(nightshift) if(nightshift_active != night_time) update_nightshift(night_time, announcing) -/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE, max_level = (!active? INFINITY : CONFIG_GET(number/night_shift_public_area_only))) +/datum/controller/subsystem/nightshift/proc/update_nightshift(active, announce = TRUE, max_level_override) nightshift_active = active if(announce) if (active) announce("Good evening, crew. To reduce power consumption and stimulate the circadian rhythms of some species, all of the lights aboard the station have been dimmed for the night.") else - var/public_only = CONFIG_GET(number/night_shift_public_area_only) + announce("Good morning, crew. As it is now day time, all of the lights aboard the station have been restored to their former brightness.") + var/max_level + var/configured_level = CONFIG_GET(number/night_shift_public_areas_only) + if(isnull(max_level_override)) + max_level = active? configured_level : INFINITY //by default, deactivating shuts off nightshifts everywhere. + else + max_level = max_level_override for(var/A in GLOB.apcs_list) var/obj/machinery/power/apc/APC = A if(APC.area && (!max_level || !APC.area.nightshift_public_area || (APC.area.nightshift_public_area <= max_level)) && (APC.area.type in GLOB.the_station_areas)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 5f51a87f80..8e6deb4659 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1408,7 +1408,7 @@ var/our_level = area.nightshift_public_area var/public_requires_auth = CONFIG_GET(flag/nightshift_toggle_public_requires_auth) var/normal_requires_auth = CONFIG_GET(flag/nightshift_toggle_requires_auth) - return (configured_level && our_level && (our_level <= configured_level))? public_requires_auth : normal_requires_auth) + return (configured_level && our_level && ((our_level <= configured_level)? public_requires_auth : normal_requires_auth)) #undef UPSTATE_CELL_IN #undef UPSTATE_OPENED1 diff --git a/tgui/assets/tgui.css b/tgui/assets/tgui.css index 896f7d5f2b..b4f5052c2b 100644 --- a/tgui/assets/tgui.css +++ b/tgui/assets/tgui.css @@ -1 +1 @@ -@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffb18b25",endColorstr="#ff5f380e",GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button.gridable.center{text-align:center;width:75px}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display.tabular{padding:0;margin:0}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input.number{width:35px}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .cell,body.clockwork section .compressedcell,body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .cell,body.nanotrasen section .compressedcell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork section .cell:not(:first-child),body.clockwork section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.clockwork section .cell span.button{width:75px}body.clockwork section:not(:last-child){padding-right:4px}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjAiIHZpZXdCb3g9IjAgMCA0MjUgMjAwIiBvcGFjaXR5PSIuMzMiPgogIDxwYXRoIGQ9Im0gMTc4LjAwMzk5LDAuMDM4NjkgLTcxLjIwMzkzLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM0LDYuMDI1NTUgbCAwLDE4Ny44NzE0NyBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgNi43NjEzNCw2LjAyNTU0IGwgNTMuMTA3MiwwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM1LC02LjAyNTU0IGwgMCwtMTAxLjU0NDAxOCA3Mi4yMTYyOCwxMDQuNjk5Mzk4IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA1Ljc2MDE1LDIuODcwMTYgbCA3My41NTQ4NywwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM1LC02LjAyNTU0IGwgMCwtMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNi43NjEzNSwtNi4wMjU1NSBsIC01NC43MTY0NCwwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNi43NjEzMyw2LjAyNTU1IGwgMCwxMDIuNjE5MzUgTCAxODMuNzY0MTMsMi45MDg4NiBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTUuNzYwMTQsLTIuODcwMTcgeiIgLz4KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPgogIDxwYXRoIGQ9Im0gNDIwLjE1NTM1LDE3Ny44OTExOSBhIDEzLjQxMjAzOCwxMi41MDE4NDIgMCAwIDEgLTguNjMyOTUsMjIuMDY5NTEgbCAtNjYuMTE4MzIsMCBhIDUuMzY0ODE1Miw1LjAwMDczNyAwIDAgMSAtNS4zNjQ4MiwtNS4wMDA3NCBsIDAsLTc5Ljg3OTMxIHoiIC8+Cjwvc3ZnPgo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4KPCEtLSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvIC0tPgo=") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button.gridable.center{text-align:center;width:75px}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display.tabular{padding:0;margin:0}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input.number{width:35px}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .cell,body.nanotrasen section .compressedcell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen section .cell:not(:first-child),body.nanotrasen section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.nanotrasen section .cell span.button{width:75px}body.nanotrasen section:not(:last-child){padding-right:4px}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjAiIHZpZXdCb3g9IjAgMCAyMDAgMjg5Ljc0MiIgb3BhY2l0eT0iLjMzIj4KICA8cGF0aCBkPSJtIDkzLjUzNzY3NywwIGMgLTE4LjExMzEyNSwwIC0zNC4yMjAxMzMsMy4xMTE2NCAtNDguMzIzNDg0LDkuMzM0MzcgLTEzLjk2NTA5Miw2LjIyMTY3IC0yNC42MTI0NDIsMTUuMDcxMTQgLTMxLjk0MDY1MSwyNi41NDcxIC03LjE4OTkzOTgsMTEuMzM3ODkgLTEwLjMwMTIyNjYsMjQuNzQ5MTEgLTEwLjMwMTIyNjYsNDAuMjM0NzggMCwxMC42NDY2MiAyLjcyNTAwMjYsMjAuNDY0NjUgOC4xNzUxMTE2LDI5LjQ1MjU4IDUuNjE1Mjc3LDguOTg2ODYgMTQuMDM4Mjc3LDE3LjM1MjA0IDI1LjI2ODgyMSwyNS4wOTQzNiAxMS4yMzA1NDQsNy42MDUzMSAyNi41MDc0MjEsMTUuNDE4MzUgNDUuODMwNTE0LDIzLjQzNzgyIDE5Ljk4Mzc0OCw4LjI5NTU3IDM0Ljg0ODg0OCwxNS41NTQ3MSA0NC41OTI5OTgsMjEuNzc2MzggOS43NDQxNCw2LjIyMjczIDE2Ljc2MTcsMTIuODU4NSAyMS4wNTU3MiwxOS45MDk1MSA0LjI5NDA0LDcuMDUyMDggNi40NDE5MywxNS43NjQwOCA2LjQ0MTkzLDI2LjEzNDU5IDAsMTYuMTc3MDIgLTUuMjAxOTYsMjguNDgyMjIgLTE1LjYwNjczLDM2LjkxNjgyIC0xMC4yMzk2LDguNDM0NyAtMjUuMDIyMDMsMTIuNjUyMyAtNDQuMzQ1MTY5LDEyLjY1MjMgLTE0LjAzODE3MSwwIC0yNS41MTUyNDcsLTEuNjU5NCAtMzQuNDMzNjE4LC00Ljk3NzcgLTguOTE4MzcsLTMuNDU2NiAtMTYuMTg1NTcyLC04LjcxMTMgLTIxLjgwMDgzOSwtMTUuNzYzMyAtNS42MTUyNzcsLTcuMDUyMSAtMTAuMDc0Nzk1LC0xNi42NjA4OCAtMTMuMzc3ODk5LC0yOC44MjgxMiBsIC0yNC43NzMxNjI2MjkzOTQ1LDAgMCw1Ni44MjYzMiBDIDMzLjg1Njc2OSwyODYuMDc2MDEgNjMuNzQ5MDQsMjg5Ljc0MjAxIDg5LjY3ODM4MywyODkuNzQyMDEgYyAxNi4wMjAwMjcsMCAzMC43MTk3ODcsLTEuMzgyNyA0NC4wOTczMzcsLTQuMTQ3OSAxMy41NDI3MiwtMi45MDQzIDI1LjEwNDEsLTcuNDY3NiAzNC42ODMwOSwtMTMuNjg5MyA5Ljc0NDEzLC02LjM1OTcgMTcuMzQwNDIsLTE0LjUxOTUgMjIuNzkwNTIsLTI0LjQ3NDggNS40NTAxLC0xMC4wOTMzMiA4LjE3NTExLC0yMi4zOTk1OSA4LjE3NTExLC0zNi45MTY4MiAwLC0xMi45OTc2NCAtMy4zMDIxLC0yNC4zMzUzOSAtOS45MDgyOSwtMzQuMDE0NiAtNi40NDEwNSwtOS44MTcyNSAtMTUuNTI1NDUsLTE4LjUyNzA3IC0yNy4yNTE0NiwtMjYuMTMxMzMgLTExLjU2MDg1LC03LjYwNDI3IC0yNy45MTA4MywtMTUuODMxNDIgLTQ5LjA1MDY2LC0yNC42ODAyMiAtMTcuNTA2NDQsLTcuMTkwMTIgLTMwLjcxOTY2OCwtMTMuNjg5NDggLTM5LjYzODAzOCwtMTkuNDk3MDEgLTguOTE4MzcxLC01LjgwNzUyIC0xOC42MDc0NzQsLTEyLjQzNDA5IC0yNC4wOTY1MjQsLTE4Ljg3NDE3IC01LjQyNjA0MywtNi4zNjYxNiAtOS42NTg4MjYsLTE1LjA3MDAzIC05LjY1ODgyNiwtMjQuODg3MjkgMCwtOS4yNjQwMSAyLjA3NTQxNCwtMTcuMjEzNDUgNi4yMjM0NTQsLTIzLjg1MDMzIDExLjA5ODI5OCwtMTQuMzk3NDggNDEuMjg2NjM4LC0xLjc5NTA3IDQ1LjA3NTYwOSwyNC4zNDc2MiA0LjgzOTM5Miw2Ljc3NDkxIDguODQ5MzUsMTYuMjQ3MjkgMTIuMDI5NTE1LDI4LjQxNTYgbCAyMC41MzIzNCwwIDAsLTU1Ljk5OTY3IGMgLTQuNDc4MjUsLTUuOTI0NDggLTkuOTU0ODgsLTEwLjYzMjIyIC0xNS45MDgzNywtMTQuMzc0MTEgMS42NDA1NSwwLjQ3OTA1IDMuMTkwMzksMS4wMjM3NiA0LjYzODY1LDEuNjQwMjQgNi40OTg2MSwyLjYyNjA3IDEyLjE2NzkzLDcuMzI3NDcgMTcuMDA3MywxNC4xMDM0NSA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNSwxNi4yNDU2NyAxMi4wMjk1MiwyOC40MTM5NyAwLDAgOC40ODEyOCwtMC4xMjg5NCA4LjQ4OTc4LC0wLjAwMiAwLjQxNzc2LDYuNDE0OTQgLTEuNzUzMzksOS40NTI4NiAtNC4xMjM0MiwxMi41NjEwNCAtMi40MTc0LDMuMTY5NzggLTUuMTQ0ODYsNi43ODk3MyAtNC4wMDI3OCwxMy4wMDI5IDEuNTA3ODYsOC4yMDMxOCAxMC4xODM1NCwxMC41OTY0MiAxNC42MjE5NCw5LjMxMTU0IC0zLjMxODQyLC0wLjQ5OTExIC01LjMxODU1LC0xLjc0OTQ4IC01LjMxODU1LC0xLjc0OTQ4IDAsMCAxLjg3NjQ2LDAuOTk4NjggNS42NTExNywtMS4zNTk4MSAtMy4yNzY5NSwwLjk1NTcxIC0xMC43MDUyOSwtMC43OTczOCAtMTEuODAxMjUsLTYuNzYzMTMgLTAuOTU3NTIsLTUuMjA4NjEgMC45NDY1NCwtNy4yOTUxNCAzLjQwMTEzLC0xMC41MTQ4MiAyLjQ1NDYyLC0zLjIxOTY4IDUuMjg0MjYsLTYuOTU4MzEgNC42ODQzLC0xNC40ODgyNCBsIDAuMDAzLDAuMDAyIDguOTI2NzYsMCAwLC01NS45OTk2NyBjIC0xNS4wNzEyNSwtMy44NzE2OCAtMjcuNjUzMTQsLTYuMzYwNDIgLTM3Ljc0NjcxLC03LjQ2NTg2IC05Ljk1NTMxLC0xLjEwNzU1IC0yMC4xODgyMywtMS42NTk4MSAtMzAuNjk2NjEzLC0xLjY1OTgxIHogbSA3MC4zMjE2MDMsMTcuMzA4OTMgMC4yMzgwNSw0MC4zMDQ5IGMgMS4zMTgwOCwxLjIyNjY2IDIuNDM5NjUsMi4yNzgxNSAzLjM0MDgxLDMuMTA2MDIgNC44MzkzOSw2Ljc3NDkxIDguODQ5MzQsMTYuMjQ1NjYgMTIuMDI5NTEsMjguNDEzOTcgbCAyMC41MzIzNCwwIDAsLTU1Ljk5OTY3IGMgLTYuNjc3MzEsLTQuNTkzODEgLTE5LjgzNjQzLC0xMC40NzMwOSAtMzYuMTQwNzEsLTE1LjgyNTIyIHogbSAtMjguMTIwNDksNS42MDU1MSA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM3LC02LjQ2Njk3IC0xMy44NDY3OCwtOS43MTcyNiAtOC41NjQ3OSwtMTcuNzE2NTUgeiBtIDIyLjc5NzA1LDAgYyAyLjc3MTUsNy45OTkyOSAxLjc4NzQxLDExLjI0OTU4IC00LjQ5MzU0LDE3LjcxNjU1IGwgNC40OTM1NCwtMTcuNzE2NTUgeiBtIDE1LjIyMTk1LDI0LjAwODQ4IDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzgsLTYuNDY2OTcgLTEzLjg0Njc5LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDQsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gLTk5LjExMzg0LDIuMjA3NjQgOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzODIsLTYuNDY2OTcgLTEzLjg0Njc4MiwtOS43MTcyNiAtOC41NjQ3OSwtMTcuNzE2NTUgeiBtIDIyLjc5NTQyLDAgYyAyLjc3MTUsNy45OTkyOSAxLjc4NzQxLDExLjI0OTU4IC00LjQ5MzU0LDE3LjcxNjU1IGwgNC40OTM1NCwtMTcuNzE2NTUgeiIgLz4KPC9zdmc+CjwhLS0gVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIC0tPgo8IS0tIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8gLS0+Cg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff750000",endColorstr="#ff340404",GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button.gridable.center{text-align:center;width:75px}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display.tabular{padding:0;margin:0}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input.number{width:35px}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate section .cell:not(:first-child),body.syndicate section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.syndicate section .cell span.button{width:75px}body.syndicate section:not(:last-child){padding-right:4px}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} \ No newline at end of file +@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffb18b25",endColorstr="#ff5f380e",GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button.gridable.center{text-align:center;width:75px}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display.tabular{padding:0;margin:0}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input.number{width:35px}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .cell,body.clockwork section .compressedcell,body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .cell,body.nanotrasen section .compressedcell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork section .cell:not(:first-child),body.clockwork section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.clockwork section .cell span.button{width:75px}body.clockwork section:not(:last-child){padding-right:4px}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgNDI1IDIwMCIgb3BhY2l0eT0iLjMzIj4NCiAgPHBhdGggZD0ibSAxNzguMDAzOTksMC4wMzg2OSAtNzEuMjAzOTMsMCBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTYuNzYxMzQsNi4wMjU1NSBsIDAsMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM0LDYuMDI1NTQgbCA1My4xMDcyLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xMDEuNTQ0MDE4IDcyLjIxNjI4LDEwNC42OTkzOTggYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDUuNzYwMTUsMi44NzAxNiBsIDczLjU1NDg3LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xODcuODcxNDcgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM1LC02LjAyNTU1IGwgLTU0LjcxNjQ0LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTMzLDYuMDI1NTUgbCAwLDEwMi42MTkzNSBMIDE4My43NjQxMywyLjkwODg2IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNS43NjAxNCwtMi44NzAxNyB6IiAvPg0KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPg0KICA8cGF0aCBkPSJtIDQyMC4xNTUzNSwxNzcuODkxMTkgYSAxMy40MTIwMzgsMTIuNTAxODQyIDAgMCAxIC04LjYzMjk1LDIyLjA2OTUxIGwgLTY2LjExODMyLDAgYSA1LjM2NDgxNTIsNS4wMDA3MzcgMCAwIDEgLTUuMzY0ODIsLTUuMDAwNzQgbCAwLC03OS44NzkzMSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button.gridable.center{text-align:center;width:75px}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display.tabular{padding:0;margin:0}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input.number{width:35px}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .cell,body.nanotrasen section .compressedcell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen section .cell:not(:first-child),body.nanotrasen section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.nanotrasen section .cell span.button{width:75px}body.nanotrasen section:not(:last-child){padding-right:4px}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgMjAwIDI4OS43NDIiIG9wYWNpdHk9Ii4zMyI+DQogIDxwYXRoIGQ9Im0gOTMuNTM3Njc3LDAgYyAtMTguMTEzMTI1LDAgLTM0LjIyMDEzMywzLjExMTY0IC00OC4zMjM0ODQsOS4zMzQzNyAtMTMuOTY1MDkyLDYuMjIxNjcgLTI0LjYxMjQ0MiwxNS4wNzExNCAtMzEuOTQwNjUxLDI2LjU0NzEgLTcuMTg5OTM5OCwxMS4zMzc4OSAtMTAuMzAxMjI2NiwyNC43NDkxMSAtMTAuMzAxMjI2Niw0MC4yMzQ3OCAwLDEwLjY0NjYyIDIuNzI1MDAyNiwyMC40NjQ2NSA4LjE3NTExMTYsMjkuNDUyNTggNS42MTUyNzcsOC45ODY4NiAxNC4wMzgyNzcsMTcuMzUyMDQgMjUuMjY4ODIxLDI1LjA5NDM2IDExLjIzMDU0NCw3LjYwNTMxIDI2LjUwNzQyMSwxNS40MTgzNSA0NS44MzA1MTQsMjMuNDM3ODIgMTkuOTgzNzQ4LDguMjk1NTcgMzQuODQ4ODQ4LDE1LjU1NDcxIDQ0LjU5Mjk5OCwyMS43NzYzOCA5Ljc0NDE0LDYuMjIyNzMgMTYuNzYxNywxMi44NTg1IDIxLjA1NTcyLDE5LjkwOTUxIDQuMjk0MDQsNy4wNTIwOCA2LjQ0MTkzLDE1Ljc2NDA4IDYuNDQxOTMsMjYuMTM0NTkgMCwxNi4xNzcwMiAtNS4yMDE5NiwyOC40ODIyMiAtMTUuNjA2NzMsMzYuOTE2ODIgLTEwLjIzOTYsOC40MzQ3IC0yNS4wMjIwMywxMi42NTIzIC00NC4zNDUxNjksMTIuNjUyMyAtMTQuMDM4MTcxLDAgLTI1LjUxNTI0NywtMS42NTk0IC0zNC40MzM2MTgsLTQuOTc3NyAtOC45MTgzNywtMy40NTY2IC0xNi4xODU1NzIsLTguNzExMyAtMjEuODAwODM5LC0xNS43NjMzIC01LjYxNTI3NywtNy4wNTIxIC0xMC4wNzQ3OTUsLTE2LjY2MDg4IC0xMy4zNzc4OTksLTI4LjgyODEyIGwgLTI0Ljc3MzE2MjYyOTM5NDUsMCAwLDU2LjgyNjMyIEMgMzMuODU2NzY5LDI4Ni4wNzYwMSA2My43NDkwNCwyODkuNzQyMDEgODkuNjc4MzgzLDI4OS43NDIwMSBjIDE2LjAyMDAyNywwIDMwLjcxOTc4NywtMS4zODI3IDQ0LjA5NzMzNywtNC4xNDc5IDEzLjU0MjcyLC0yLjkwNDMgMjUuMTA0MSwtNy40Njc2IDM0LjY4MzA5LC0xMy42ODkzIDkuNzQ0MTMsLTYuMzU5NyAxNy4zNDA0MiwtMTQuNTE5NSAyMi43OTA1MiwtMjQuNDc0OCA1LjQ1MDEsLTEwLjA5MzMyIDguMTc1MTEsLTIyLjM5OTU5IDguMTc1MTEsLTM2LjkxNjgyIDAsLTEyLjk5NzY0IC0zLjMwMjEsLTI0LjMzNTM5IC05LjkwODI5LC0zNC4wMTQ2IC02LjQ0MTA1LC05LjgxNzI1IC0xNS41MjU0NSwtMTguNTI3MDcgLTI3LjI1MTQ2LC0yNi4xMzEzMyAtMTEuNTYwODUsLTcuNjA0MjcgLTI3LjkxMDgzLC0xNS44MzE0MiAtNDkuMDUwNjYsLTI0LjY4MDIyIC0xNy41MDY0NCwtNy4xOTAxMiAtMzAuNzE5NjY4LC0xMy42ODk0OCAtMzkuNjM4MDM4LC0xOS40OTcwMSAtOC45MTgzNzEsLTUuODA3NTIgLTE4LjYwNzQ3NCwtMTIuNDM0MDkgLTI0LjA5NjUyNCwtMTguODc0MTcgLTUuNDI2MDQzLC02LjM2NjE2IC05LjY1ODgyNiwtMTUuMDcwMDMgLTkuNjU4ODI2LC0yNC44ODcyOSAwLC05LjI2NDAxIDIuMDc1NDE0LC0xNy4yMTM0NSA2LjIyMzQ1NCwtMjMuODUwMzMgMTEuMDk4Mjk4LC0xNC4zOTc0OCA0MS4yODY2MzgsLTEuNzk1MDcgNDUuMDc1NjA5LDI0LjM0NzYyIDQuODM5MzkyLDYuNzc0OTEgOC44NDkzNSwxNi4yNDcyOSAxMi4wMjk1MTUsMjguNDE1NiBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNC40NzgyNSwtNS45MjQ0OCAtOS45NTQ4OCwtMTAuNjMyMjIgLTE1LjkwODM3LC0xNC4zNzQxMSAxLjY0MDU1LDAuNDc5MDUgMy4xOTAzOSwxLjAyMzc2IDQuNjM4NjUsMS42NDAyNCA2LjQ5ODYxLDIuNjI2MDcgMTIuMTY3OTMsNy4zMjc0NyAxNy4wMDczLDE0LjEwMzQ1IDQuODM5MzksNi43NzQ5MSA4Ljg0OTM1LDE2LjI0NTY3IDEyLjAyOTUyLDI4LjQxMzk3IDAsMCA4LjQ4MTI4LC0wLjEyODk0IDguNDg5NzgsLTAuMDAyIDAuNDE3NzYsNi40MTQ5NCAtMS43NTMzOSw5LjQ1Mjg2IC00LjEyMzQyLDEyLjU2MTA0IC0yLjQxNzQsMy4xNjk3OCAtNS4xNDQ4Niw2Ljc4OTczIC00LjAwMjc4LDEzLjAwMjkgMS41MDc4Niw4LjIwMzE4IDEwLjE4MzU0LDEwLjU5NjQyIDE0LjYyMTk0LDkuMzExNTQgLTMuMzE4NDIsLTAuNDk5MTEgLTUuMzE4NTUsLTEuNzQ5NDggLTUuMzE4NTUsLTEuNzQ5NDggMCwwIDEuODc2NDYsMC45OTg2OCA1LjY1MTE3LC0xLjM1OTgxIC0zLjI3Njk1LDAuOTU1NzEgLTEwLjcwNTI5LC0wLjc5NzM4IC0xMS44MDEyNSwtNi43NjMxMyAtMC45NTc1MiwtNS4yMDg2MSAwLjk0NjU0LC03LjI5NTE0IDMuNDAxMTMsLTEwLjUxNDgyIDIuNDU0NjIsLTMuMjE5NjggNS4yODQyNiwtNi45NTgzMSA0LjY4NDMsLTE0LjQ4ODI0IGwgMC4wMDMsMC4wMDIgOC45MjY3NiwwIDAsLTU1Ljk5OTY3IGMgLTE1LjA3MTI1LC0zLjg3MTY4IC0yNy42NTMxNCwtNi4zNjA0MiAtMzcuNzQ2NzEsLTcuNDY1ODYgLTkuOTU1MzEsLTEuMTA3NTUgLTIwLjE4ODIzLC0xLjY1OTgxIC0zMC42OTY2MTMsLTEuNjU5ODEgeiBtIDcwLjMyMTYwMywxNy4zMDg5MyAwLjIzODA1LDQwLjMwNDkgYyAxLjMxODA4LDEuMjI2NjYgMi40Mzk2NSwyLjI3ODE1IDMuMzQwODEsMy4xMDYwMiA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNCwxNi4yNDU2NiAxMi4wMjk1MSwyOC40MTM5NyBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNi42NzczMSwtNC41OTM4MSAtMTkuODM2NDMsLTEwLjQ3MzA5IC0zNi4xNDA3MSwtMTUuODI1MjIgeiBtIC0yOC4xMjA0OSw1LjYwNTUxIDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzcsLTYuNDY2OTcgLTEzLjg0Njc4LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDUsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gMTUuMjIxOTUsMjQuMDA4NDggOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzOCwtNi40NjY5NyAtMTMuODQ2NzksLTkuNzE3MjYgLTguNTY0NzksLTE3LjcxNjU1IHogbSAyMi43OTcwNCwwIGMgMi43NzE1LDcuOTk5MjkgMS43ODc0MSwxMS4yNDk1OCAtNC40OTM1NCwxNy43MTY1NSBsIDQuNDkzNTQsLTE3LjcxNjU1IHogbSAtOTkuMTEzODQsMi4yMDc2NCA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM4MiwtNi40NjY5NyAtMTMuODQ2NzgyLC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk1NDIsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff750000",endColorstr="#ff340404",GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button.gridable.center{text-align:center;width:75px}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display.tabular{padding:0;margin:0}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input.number{width:35px}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .cell,body.syndicate section .compressedcell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate section .cell:not(:first-child),body.syndicate section .compressedcell:not(:first-child){text-align:center;padding-top:0}body.syndicate section .cell span.button{width:75px}body.syndicate section:not(:last-child){padding-right:4px}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} \ No newline at end of file diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index cc0b5d198f..b4668af2d0 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -6,16 +6,16 @@ try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n},_=function(t) return t.docFrag.appendChild(e.render())}),this.renderedFragments=this.fragments.slice(),this.fragmentsToRender=[],this.rendered=!0,this.docFrag}function Ze(t){var e,n,a=this;this.updating||(this.updating=!0,this.keypath&&(e=this.root.viewmodel.wrapped[this.keypath.str])&&(t=e.get()),this.fragmentsToCreate.length?(n={template:this.template.f||[],root:this.root,pElement:this.pElement,owner:this},this.fragmentsToCreate.forEach(function(t){var e;n.context=a.keypath.join(t),n.index=t,e=new rg(n),a.fragmentsToRender.push(a.fragments[t]=e)}),this.fragmentsToCreate.length=0):en(this,t)&&(this.bubble(),this.rendered&&bs.addView(this)),this.value=t,this.updating=!1)}function tn(t,e,n){if(e===Bu&&t.indexRefs&&t.indexRefs[0]){var a=t.indexRefs[0];(n&&"i"===a.t||!n&&"k"===a.t)&&(n||(t.length=0,t.fragmentsToUnrender=t.fragments.slice(0),t.fragmentsToUnrender.forEach(function(t){return t.unbind()}))),a.t=n?"k":"i"}t.currentSubtype=e}function en(t,e){var n={template:t.template.f||[],root:t.root,pElement:t.parentFragment.pElement,owner:t};if(t.hasContext=!0,t.subtype)switch(t.subtype){case Fu:return t.hasContext=!1,sn(t,e,!1,n);case Iu:return t.hasContext=!1,sn(t,e,!0,n);case Uu:return on(t,n);case Vu:return rn(t,e,n);case Bu:if(u(e))return tn(t,t.subtype,!0),an(t,e,n)}return t.ordered=!!o(e),t.ordered?(tn(t,Bu,!1),nn(t,e,n)):u(e)||"function"==typeof e?t.template.i?(tn(t,Bu,!0),an(t,e,n)):(tn(t,Uu,!1),on(t,n)):(tn(t,Fu,!1),t.hasContext=!1,sn(t,e,!1,n))}function nn(t,e,n){var a,r,i;if(r=e.length,r===t.length)return!1;if(rt.length)for(a=t.length;r>a;a+=1)n.context=t.keypath.join(a),n.index=a,i=new rg(n),t.fragmentsToRender.push(t.fragments[a]=i);return t.length=r,!0}function an(t,e,n){var a,r,i,o,s,p;for(i=t.hasKey||(t.hasKey={}),r=t.fragments.length;r--;)o=t.fragments[r],o.key in e||(s=!0,o.unbind(),t.fragmentsToUnrender.push(o),t.fragments.splice(r,1),i[o.key]=!1);for(r=t.fragments.length;r--;)o=t.fragments[r],o.index!==r&&(o.index=r,(p=o.registeredIndexRefs)&&p.forEach(cn));r=t.fragments.length;for(a in e)i[a]||(s=!0,n.context=t.keypath.join(a),n.key=a,n.index=r++,o=new rg(n),t.fragmentsToRender.push(o),t.fragments.push(o),i[a]=!0);return t.length=t.fragments.length,s}function rn(t,e,n){return e?on(t,n):pn(t)}function on(t,e){var n;return t.length?void 0:(e.context=t.keypath,e.index=0,n=new rg(e),t.fragmentsToRender.push(t.fragments[0]=n),t.length=1,!0)}function sn(t,e,n,a){var r,i,s,p,c;if(i=o(e)&&0===e.length,s=!1,!o(e)&&u(e)){s=!0;for(c in e){s=!1;break}}return r=n?i||s||!e:e&&!i&&!s,r?t.length?t.length>1?(t.fragmentsToUnrender=t.fragments.splice(1),t.fragmentsToUnrender.forEach(K),!0):void 0:(a.index=0,p=new rg(a),t.fragmentsToRender.push(t.fragments[0]=p),t.length=1,!0):pn(t)}function pn(t){return t.length?(t.fragmentsToUnrender=t.fragments.splice(0,t.fragments.length).filter(un),t.fragmentsToUnrender.forEach(K),t.length=t.fragmentsToRender.length=0,!0):void 0}function un(t){return t.rendered}function cn(t){t.rebind("","")}function ln(t){var e,n,a;for(e="",n=0,a=this.length,n=0;a>n;n+=1)e+=this.fragments[n].toString(t);return e}function dn(){var t=this;this.fragments.forEach(K),this.fragmentsToRender.forEach(function(e){return N(t.fragments,e)}),this.fragmentsToRender=[],_c.call(this),this.length=0,this.unbound=!0}function fn(t){this.fragments.forEach(t?hn:mn),this.renderedFragments=[],this.rendered=!1}function hn(t){t.unrender(!0)}function mn(t){t.unrender(!1)}function gn(){var t,e,n,a,r,i,o;for(n=this.renderedFragments;t=this.fragmentsToUnrender.pop();)t.unrender(!0),n.splice(n.indexOf(t),1);for(;t=this.fragmentsToRender.shift();)t.render();for(this.rendered&&(r=this.parentFragment.getNode()),o=this.fragments.length,i=0;o>i;i+=1)t=this.fragments[i],e=n.indexOf(t,i),e!==i?(this.docFrag.appendChild(t.detach()),-1!==e&&n.splice(e,1),n.splice(i,0,t)):this.docFrag.childNodes.length&&(a=t.firstNode(),r.insertBefore(this.docFrag,a));this.rendered&&this.docFrag.childNodes.length&&(a=this.parentFragment.findNextNode(this),r.insertBefore(this.docFrag,a)),this.renderedFragments=this.fragments.slice()}function vn(){var t,e;if(this.docFrag){for(t=this.nodes.length,e=0;t>e;e+=1)this.docFrag.appendChild(this.nodes[e]);return this.docFrag}}function bn(t){var e,n,a,r;for(n=this.nodes.length,e=0;n>e;e+=1)if(a=this.nodes[e],1===a.nodeType){if(lo(a,t))return a;if(r=a.querySelector(t))return r}return null}function yn(t,e){var n,a,r,i,o,s;for(a=this.nodes.length,n=0;a>n;n+=1)if(r=this.nodes[n],1===r.nodeType&&(lo(r,t)&&e.push(r),i=r.querySelectorAll(t)))for(o=i.length,s=0;o>s;s+=1)e.push(i[s])}function _n(){return this.rendered&&this.nodes[0]?this.nodes[0]:this.parentFragment.findNextNode(this)}function xn(t){return gl[t]||(gl[t]=co(t))}function wn(t){var e,n,a;t&&"select"===t.name&&t.binding&&(e=F(t.node.options).filter(kn),t.getAttribute("multiple")?a=e.map(function(t){return t.value}):(n=e[0])&&(a=n.value),void 0!==a&&t.binding.setValue(a),t.bubble())}function kn(t){return t.selected}function Sn(){if(this.rendered)throw Error("Attempted to render an item that was already rendered");return this.docFrag=document.createDocumentFragment(),this.nodes=vl(this.value,this.parentFragment.getNode(),this.docFrag),bl(this.pElement),this.rendered=!0,this.docFrag}function En(t){var e;(e=this.root.viewmodel.wrapped[this.keypath.str])&&(t=e.get()),t!==this.value&&(this.value=t,this.parentFragment.bubble(),this.rendered&&bs.addView(this))}function Cn(){return void 0!=this.value?we(""+this.value):""}function Pn(t){this.rendered&&t&&(this.nodes.forEach(e),this.rendered=!1)}function An(){var t,e;if(this.rendered){for(;this.nodes&&this.nodes.length;)t=this.nodes.pop(),t.parentNode.removeChild(t);e=this.parentFragment.getNode(),this.nodes=vl(this.value,e,this.docFrag),e.insertBefore(this.docFrag,this.parentFragment.findNextNode(this)),bl(this.pElement)}}function On(){var t,e=this.node;return e?((t=e.parentNode)&&t.removeChild(e),e):void 0}function Tn(){return null}function Rn(){return this.node}function Mn(t){return this.attributes&&this.attributes[t]?this.attributes[t].value:void 0}function Ln(){var t=this.useProperty||!this.rendered?this.fragment.getValue():""+this.fragment;s(t,this.value)||("id"===this.name&&this.value&&delete this.root.nodes[this.value],this.value=t,"value"===this.name&&this.node&&(this.node._ractive.value=t),this.rendered&&bs.addView(this))}function jn(t){var e=t.fragment.items;if(1===e.length)return e[0].type===Su?e[0]:void 0}function Dn(t){return this.type=Tu,this.element=t.element,this.root=t.root,zl(this,t.name),this.isBoolean=rc.test(this.name),t.value&&"string"!=typeof t.value?(this.parentFragment=this.element.parentFragment,this.fragment=new rg({template:t.value,root:this.root,owner:this}),this.value=this.fragment.getValue(),this.interpolator=Wl(this),this.isBindable=!!this.interpolator&&!this.interpolator.isStatic,void(this.ready=!0)):void(this.value=this.isBoolean?!0:t.value||"")}function Nn(t,e){this.fragment&&this.fragment.rebind(t,e)}function Fn(t){var e;this.node=t,t.namespaceURI&&t.namespaceURI!==no.html||(e=Yl[this.name]||this.name,void 0!==t[e]&&(this.propertyName=e),(this.isBoolean||this.isTwoway)&&(this.useProperty=!0),"value"===e&&(t._ractive.value=this.value)),this.rendered=!0,this.update()}function In(){var t=this,e=t.name,n=t.namespacePrefix,a=t.value,r=t.interpolator,i=t.fragment;if(("value"!==e||"select"!==this.element.name&&"textarea"!==this.element.name)&&("value"!==e||void 0===this.element.getAttribute("contenteditable"))){if("name"===e&&"input"===this.element.name&&r)return"name={{"+(r.keypath.str||r.ref)+"}}";if(this.isBoolean)return a?e:"";if(i){if(1===i.items.length&&null==i.items[0].value)return"";a=""+i}return n&&(e=n+":"+e),a?e+'="'+Bn(a)+'"':e}}function Bn(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'")}function Un(){this.fragment&&this.fragment.unbind(),"id"===this.name&&delete this.root.nodes[this.value]}function Vn(){var t,e,n,a,r=this.value;if(!this.locked)for(this.node._ractive.value=r,t=this.node.options,a=t.length;a--;)if(e=t[a],n=e._ractive?e._ractive.value:e.value,n==r){e.selected=!0;break}}function qn(){var t,e,n,a,r=this.value;for(i(r)||(r=[r]),t=this.node.options,e=t.length;e--;)n=t[e],a=n._ractive?n._ractive.value:n.value,n.selected=M(r,a)}function Gn(){var t=this,e=t.node,n=t.value;e.checked=n==e._ractive.value}function zn(){var t,e,n,a,r=this.node;if(t=r.checked,r.value=this.element.getAttribute("value"),r.checked=this.element.getAttribute("value")===this.element.getAttribute("name"),t&&!r.checked&&this.element.binding&&(n=this.element.binding.siblings,a=n.length)){for(;a--;){if(e=n[a],!e.element.node)return;if(e.element.node.checked)return bs.addRactive(e.root),e.handleChange()}this.root.viewmodel.set(e.keypath,void 0)}}function Wn(){var t,e,n=this,a=n.element,r=n.node,o=n.value,s=a.binding;if(t=a.getAttribute("value"),i(o)){for(e=o.length;e--;)if(t==o[e])return void(s.isChecked=r.checked=!0);s.isChecked=r.checked=!1}else s.isChecked=r.checked=o==t}function Hn(){this.node.className=n(this.value)}function Kn(){var t=this,e=t.node,n=t.value;this.root.nodes[n]=e,e.id=n}function Qn(){var t,e;t=this.node,e=this.value,void 0===e&&(e=""),t.style.setAttribute("cssText",e)}function Yn(){var t=this.value;void 0===t&&(t=""),this.locked||(this.node.innerHTML=t)}function $n(){var t=this,e=t.node,n=t.value;e._ractive.value=n,this.locked||(e.value=void 0==n?"":n)}function Jn(){this.locked||(this.node[this.propertyName]=this.value)}function Xn(){var t=this,e=t.node,n=t.namespace,a=t.name,r=t.value,i=t.fragment;n?e.setAttributeNS(n,a,""+(i||r)):this.isBoolean?r?e.setAttribute(a,""):e.removeAttribute(a):null==r?e.removeAttribute(a):e.setAttribute(a,""+(i||r))}function Zn(){var t,e,n=this,a=n.name,r=n.element,i=n.node;"id"===a?e=rd:"value"===a?"select"===r.name&&"value"===a?e=r.getAttribute("multiple")?Zl:Xl:"textarea"===r.name?e=sd:null!=r.getAttribute("contenteditable")?e=od:"input"===r.name&&(t=r.getAttribute("type"),e="file"===t?ko:"radio"===t&&r.binding&&"name"===r.binding.name?ed:sd):this.isTwoway&&"name"===a?"radio"===i.type?e=td:"checkbox"===i.type&&(e=nd):"style"===a&&i.style.setAttribute?e=id:"class"!==a||i.namespaceURI&&i.namespaceURI!==no.html?this.useProperty&&(e=pd):e=ad,e||(e=ud),this.update=e,this.update()}function ta(t,e){var n=e?"svg":"div";return dd.innerHTML="<"+n+" "+t+">",F(dd.childNodes[0].attributes)}function ea(t,e){for(var n=t.length;n--;)if(t[n].name===e.name)return!1;return!0}function na(t){for(;t=t.parent;)if("form"===t.name)return t}function aa(){this._ractive.binding.handleChange()}function ra(){var t;xd.call(this),t=this._ractive.root.viewmodel.get(this._ractive.binding.keypath),this.value=void 0==t?"":t}function ia(){var t=this._ractive.binding,e=this;t._timeout&&clearTimeout(t._timeout),t._timeout=setTimeout(function(){t.rendered&&xd.call(e),t._timeout=void 0},t.element.lazy)}function oa(t,e,n){var a=t+e+n;return Cd[a]||(Cd[a]=[])}function sa(t){return t.isChecked}function pa(t){return t.element.getAttribute("value")}function ua(t){var e,n,a,r,i,o=t.attributes;return t.binding&&(t.binding.teardown(),t.binding=null),(t.getAttribute("contenteditable")||o.contenteditable&&ca(o.contenteditable))&&ca(o.value)?n=Sd:"input"===t.name?(e=t.getAttribute("type"),"radio"===e||"checkbox"===e?(a=ca(o.name),r=ca(o.checked),a&&r&&m("A radio input can have two-way binding on its name attribute, or its checked attribute - not both",{ractive:t.root}),a?n="radio"===e?Td:Md:r&&(n="radio"===e?Ad:jd)):"file"===e&&ca(o.value)?n=Ud:ca(o.value)&&(n="number"===e||"range"===e?Vd:wd)):"select"===t.name&&ca(o.value)?n=t.getAttribute("multiple")?Id:Nd:"textarea"===t.name&&ca(o.value)&&(n=wd),n&&(i=new n(t))&&i.keypath?i:void 0}function ca(t){return t&&t.isBindable}function la(){var t=this.getAction();t&&!this.hasListener?this.listen():!t&&this.hasListener&&this.unrender()}function da(t){zs(this.root,this.getAction(),{event:t})}function fa(){return(""+this.action).trim()}function ha(t,e,n){var a,r,i,o=this;this.element=t,this.root=t.root,this.parentFragment=t.parentFragment,this.name=e,-1!==e.indexOf("*")&&(l('Only component proxy-events may contain "*" wildcards, <%s on-%s="..."/> is not valid',t.name,e),this.invalid=!0),n.m?(r=n.a.r,this.method=n.m,this.keypaths=[],this.fn=Mc(n.a.s,r.length),this.parentFragment=t.parentFragment,i=this.root,this.refResolvers=[],r.forEach(function(t,e){var n=void 0;(n=Kd.exec(t))?o.keypaths[e]={eventObject:!0,refinements:n[1]?n[1].split("."):[]}:o.refResolvers.push(Rc(o,t,function(t){return o.resolve(e,t)}))}),this.fire=ma):(a=n.n||n,"string"!=typeof a&&(a=new rg({template:a,root:this.root,owner:this})),this.action=a,n.d?(this.dynamicParams=new rg({template:n.d,root:this.root,owner:this.element}),this.fire=va):n.a&&(this.params=n.a,this.fire=ga))}function ma(t){var e,n,a;if(e=this.root,"function"!=typeof e[this.method])throw Error('Attempted to call a non-existent method ("'+this.method+'")');n=this.keypaths.map(function(n){var a,r,i;if(void 0!==n){if(n.eventObject){if(a=t,r=n.refinements.length)for(i=0;r>i;i+=1)a=a[n.refinements[i]]}else a=e.viewmodel.get(n);return a}}),Gs.enqueue(e,t),a=this.fn.apply(null,n),e[this.method].apply(e,a),Gs.dequeue(e)}function ga(t){zs(this.root,this.getAction(),{event:t,args:this.params})}function va(t){var e=this.dynamicParams.getArgsList();"string"==typeof e&&(e=e.substr(1,e.length-2)),zs(this.root,this.getAction(),{event:t,args:e})}function ba(t){var e,n,a,r={};e=this._ractive,n=e.events[t.type],(a=Oc(n.element.parentFragment))&&(r=Oc.resolve(a)),n.fire({node:this,original:t,index:r,keypath:e.keypath.str,context:e.root.viewmodel.get(e.keypath)})}function ya(){var t,e=this.name;if(!this.invalid){if(t=v("events",this.root,e))this.custom=t(this.node,_a(e));else{if(!("on"+e in this.node||window&&"on"+e in window||Zi))return void(Jd[e]||g(Io(e,"event"),{node:this.node}));this.node.addEventListener(e,Qd,!1)}this.hasListener=!0}}function _a(t){return $d[t]||($d[t]=function(e){var n=e.node._ractive;e.index=n.index,e.keypath=n.keypath.str,e.context=n.root.viewmodel.get(n.keypath),n.events[t].fire(e)}),$d[t]}function xa(t,e){function n(n){n&&n.rebind(t,e)}var a;return this.method?(a=this.element.parentFragment,void this.refResolvers.forEach(n)):("string"!=typeof this.action&&n(this.action),void(this.dynamicParams&&n(this.dynamicParams)))}function wa(){this.node=this.element.node,this.node._ractive.events[this.name]=this,(this.method||this.getAction())&&this.listen()}function ka(t,e){this.keypaths[t]=e}function Sa(){return this.method?void this.refResolvers.forEach(K):("string"!=typeof this.action&&this.action.unbind(),void(this.dynamicParams&&this.dynamicParams.unbind()))}function Ea(){this.custom?this.custom.teardown():this.node.removeEventListener(this.name,Qd,!1),this.hasListener=!1}function Ca(){var t=this;this.dirty||(this.dirty=!0,bs.scheduleTask(function(){Pa(t),t.dirty=!1})),this.parentFragment.bubble()}function Pa(t){var e,n,a,r,i;e=t.node,e&&(r=F(e.options),n=t.getAttribute("value"),a=t.getAttribute("multiple"),void 0!==n?(r.forEach(function(t){var e,r;e=t._ractive?t._ractive.value:t.value,r=a?Aa(n,e):n==e,r&&(i=!0),t.selected=r}),i||(r[0]&&(r[0].selected=!0),t.binding&&t.binding.forceUpdate())):t.binding&&t.binding.forceUpdate())}function Aa(t,e){for(var n=t.length;n--;)if(t[n]==e)return!0}function Oa(t,e){t.select=Ra(t.parent),t.select&&(t.select.options.push(t),e.a||(e.a={}),void 0!==e.a.value||e.a.hasOwnProperty("disabled")||(e.a.value=e.f),"selected"in e.a&&void 0!==t.select.getAttribute("value")&&delete e.a.selected)}function Ta(t){t.select&&N(t.select.options,t)}function Ra(t){if(t)do if("select"===t.name)return t;while(t=t.parent)}function Ma(t){var e,n,a,r,i,o,s;this.type=Pu,e=this.parentFragment=t.parentFragment,n=this.template=t.template,this.parent=t.pElement||e.pElement,this.root=a=e.root,this.index=t.index,this.key=t.key,this.name=Gl(n.e),"option"===this.name&&Oa(this,n),"select"===this.name&&(this.options=[],this.bubble=Ca),"form"===this.name&&(this.formBindings=[]),s=Vl(this,n),this.attributes=hd(this,n.a),this.conditionalAttributes=vd(this,n.m),n.f&&(this.fragment=new rg({template:n.f,root:a,owner:this,pElement:this,cssIds:null})),o=a.twoway,s.twoway===!1?o=!1:s.twoway===!0&&(o=!0),this.twoway=o,this.lazy=s.lazy,o&&(r=qd(this,n.a))&&(this.binding=r,i=this.root._twowayBindings[r.keypath.str]||(this.root._twowayBindings[r.keypath.str]=[]),i.push(r)),n.v&&(this.eventHandlers=of(this,n.v)),n.o&&(this.decorator=new lf(this,n.o)),this.intro=n.t0||n.t1,this.outro=n.t0||n.t2}function La(t,e){function n(n){n.rebind(t,e)}var a,r,i,o;if(this.attributes&&this.attributes.forEach(n),this.conditionalAttributes&&this.conditionalAttributes.forEach(n),this.eventHandlers&&this.eventHandlers.forEach(n),this.decorator&&n(this.decorator),this.fragment&&n(this.fragment),i=this.liveQueries)for(o=this.root,a=i.length;a--;)i[a]._makeDirty();this.node&&(r=this.node._ractive)&&w(r,"keypath",t,e)}function ja(t){var e;(t.attributes.width||t.attributes.height)&&t.node.addEventListener("load",e=function(){var n=t.getAttribute("width"),a=t.getAttribute("height");void 0!==n&&t.node.setAttribute("width",n),void 0!==a&&t.node.setAttribute("height",a),t.node.removeEventListener("load",e,!1)},!1)}function Da(t){t.node.addEventListener("reset",Fa,!1)}function Na(t){t.node.removeEventListener("reset",Fa,!1)}function Fa(){var t=this._ractive.proxy;bs.start(),t.formBindings.forEach(Ia),bs.end()}function Ia(t){t.root.viewmodel.set(t.keypath,t.resetValue)}function Ba(t,e,n){var a,r,i;this.element=t,this.root=a=t.root,this.isIntro=n,r=e.n||e,("string"==typeof r||(i=new rg({template:r,root:a,owner:t}),r=""+i,i.unbind(),""!==r))&&(this.name=r,e.a?this.params=e.a:e.d&&(i=new rg({template:e.d,root:a,owner:t}),this.params=i.getArgsList(),i.unbind()),this._fn=v("transitions",a,r),this._fn||g(Io(r,"transition"),{ractive:this.root}))}function Ua(t){return t}function Va(){Vf.hidden=document[Ff]}function qa(){Vf.hidden=!0}function Ga(){Vf.hidden=!1}function za(){var t,e,n,a=this;return t=this.node=this.element.node,e=t.getAttribute("style"),this.complete=function(r){n||(!r&&a.isIntro&&Wa(t,e),t._ractive.transition=null,a._manager.remove(a),n=!0)},this._fn?void this._fn.apply(this.root,[this].concat(this.params)):void this.complete()}function Wa(t,e){e?t.setAttribute("style",e):(t.getAttribute("style"),t.removeAttribute("style"))}function Ha(){var t,e,n,a=this,r=this.root;return t=Ka(this),e=this.node=co(this.name,t),this.parentFragment.cssIds&&this.node.setAttribute("data-ractive-css",this.parentFragment.cssIds.map(function(t){return"{"+t+"}"}).join(" ")),Eo(this.node,"_ractive",{value:{proxy:this,keypath:cs(this.parentFragment),events:So(null),root:r}}),this.attributes.forEach(function(t){return t.render(e)}),this.conditionalAttributes.forEach(function(t){return t.render(e)}),this.fragment&&("script"===this.name?(this.bubble=Xf,this.node.text=this.fragment.toString(!1),this.fragment.unrender=ko):"style"===this.name?(this.bubble=Jf,this.bubble(),this.fragment.unrender=ko):this.binding&&this.getAttribute("contenteditable")?this.fragment.unrender=ko:this.node.appendChild(this.fragment.render())),this.binding&&(this.binding.render(),this.node._ractive.binding=this.binding),this.eventHandlers&&this.eventHandlers.forEach(function(t){return t.render()}),"option"===this.name&&Qa(this),"img"===this.name?ja(this):"form"===this.name?Da(this):"input"===this.name||"textarea"===this.name?this.node.defaultValue=this.node.value:"option"===this.name&&(this.node.defaultSelected=this.node.selected),this.decorator&&this.decorator.fn&&bs.scheduleTask(function(){a.decorator.torndown||a.decorator.init()},!0),r.transitionsEnabled&&this.intro&&(n=new Zf(this,this.intro,!0),bs.registerTransition(n),bs.scheduleTask(function(){return n.start()},!0),this.transition=n),this.node.autofocus&&bs.scheduleTask(function(){return a.node.focus()},!0),Ya(this),this.node}function Ka(t){var e,n,a;return e=(n=t.getAttribute("xmlns"))?n:"svg"===t.name?no.svg:(a=t.parent)?"foreignObject"===a.name?no.html:a.node.namespaceURI:t.root.el.namespaceURI}function Qa(t){var e,n,a;if(t.select&&(n=t.select.getAttribute("value"),void 0!==n))if(e=t.getAttribute("value"),t.select.node.multiple&&i(n)){for(a=n.length;a--;)if(e==n[a]){t.node.selected=!0;break}}else t.node.selected=e==n}function Ya(t){var e,n,a,r,i;e=t.root;do for(n=e._liveQueries,a=n.length;a--;)r=n[a],i=n["_"+r],i._test(t)&&(t.liveQueries||(t.liveQueries=[])).push(i);while(e=e.parent)}function $a(t){var e,n,a;if(e=t.getAttribute("value"),void 0===e||!t.select)return!1;if(n=t.select.getAttribute("value"),n==e)return!0;if(t.select.getAttribute("multiple")&&i(n))for(a=n.length;a--;)if(n[a]==e)return!0}function Ja(t){var e,n,a,r;return e=t.attributes,n=e.type,a=e.value,r=e.name,n&&"radio"===n.value&&a&&r.interpolator&&a.value===r.interpolator.value?!0:void 0}function Xa(t){var e=""+t;return e?" "+e:""}function Za(){this.fragment&&this.fragment.unbind(),this.binding&&this.binding.unbind(),this.eventHandlers&&this.eventHandlers.forEach(K),"option"===this.name&&Ta(this),this.attributes.forEach(K),this.conditionalAttributes.forEach(K)}function tr(t){var e,n,a;(a=this.transition)&&a.complete(),"option"===this.name?this.detach():t&&bs.detachWhenReady(this),this.fragment&&this.fragment.unrender(!1),(e=this.binding)&&(this.binding.unrender(),this.node._ractive.binding=null,n=this.root._twowayBindings[e.keypath.str],n.splice(n.indexOf(e),1)),this.eventHandlers&&this.eventHandlers.forEach(Q),this.decorator&&bs.registerDecorator(this.decorator),this.root.transitionsEnabled&&this.outro&&(a=new Zf(this,this.outro,!1),bs.registerTransition(a),bs.scheduleTask(function(){return a.start()})),this.liveQueries&&er(this),"form"===this.name&&Na(this)}function er(t){var e,n,a;for(a=t.liveQueries.length;a--;)e=t.liveQueries[a],n=e.selector,e._remove(t.node)}function nr(t,e){var n=sh.exec(e)[0];return null===t||n.length%s}}) cannot contain nested inline partials",e,{ractive:t});var s=a?i:ir(i,e);s.partials[e]=r=o.t}return a&&(r._fn=a),r.v?r.t:r}}function ir(t,e){return t.partials.hasOwnProperty(e)?t:or(t.constructor,e)}function or(t,e){return t?t.partials.hasOwnProperty(e)?t:or(t._Parent,e):void 0}function sr(t,e){if(e){if(e.template&&e.template.p&&e.template.p[t])return e.template.p[t];if(e.parentFragment&&e.parentFragment.owner)return sr(t,e.parentFragment.owner)}}function pr(t,e){var n,a=b("components",t,e);if(a&&(n=a.components[e],!n._Parent)){var r=n.bind(a);if(r.isOwner=a.components.hasOwnProperty(e),n=r(),!n)return void m(Fo,e,"component","component",{ractive:t});"string"==typeof n&&(n=pr(t,n)),n._fn=r,a.components[e]=n}return n}function ur(){var t=this.instance.fragment.detach();return yh.fire(this.instance),t}function cr(t){return this.instance.fragment.find(t)}function lr(t,e){return this.instance.fragment.findAll(t,e)}function dr(t,e){e._test(this,!0),this.instance.fragment&&this.instance.fragment.findAllComponents(t,e)}function fr(t){return t&&t!==this.name?this.instance.fragment?this.instance.fragment.findComponent(t):null:this.instance}function hr(){return this.parentFragment.findNextNode(this)}function mr(){return this.rendered?this.instance.fragment.firstNode():null}function gr(t,e,n){function a(t){var n,a;t.value=e,t.updating||(a=t.ractive,n=t.keypath,t.updating=!0,bs.start(a),a.viewmodel.mark(n),bs.end(),t.updating=!1)}var r,i,o,s,p,u;if(r=t.obj,i=t.prop,n&&!n.configurable){if("length"===i)return;throw Error('Cannot use magic mode with property "'+i+'" - object is not configurable')}n&&(o=n.get,s=n.set),p=o||function(){return e},u=function(t){s&&s(t),e=o?o():t,u._ractiveWrappers.forEach(a)},u._ractiveWrappers=[t],Object.defineProperty(r,i,{get:p,set:u,enumerable:!0,configurable:!0})}function vr(t,e){var n,a,r,i;if(this.adaptors)for(n=this.adaptors.length,a=0;n>a;a+=1)if(r=this.adaptors[a],r.filter(e,t,this.ractive))return i=this.wrapped[t]=r.wrap(this.ractive,e,t,yr(t)),void(i.value=e)}function br(t,e){var n,a={};if(!e)return t;e+=".";for(n in t)t.hasOwnProperty(n)&&(a[e+n]=t[n]);return a}function yr(t){var e;return Gh[t]||(e=t?t+".":"",Gh[t]=function(n,a){var r;return"string"==typeof n?(r={},r[e+n]=a,r):"object"==typeof n?e?br(n,t):n:void 0}),Gh[t]}function _r(t){var e,n,a=[$o];for(e=t.length;e--;)for(n=t[e].parent;n&&!n.isRoot;)-1===t.indexOf(n)&&R(a,n),n=n.parent;return a}function xr(t,e,n){var a;kr(t,e),n||(a=e.wildcardMatches(),a.forEach(function(n){wr(t,n,e)}))}function wr(t,e,n){var a,r,i;e=e.str||e,a=t.depsMap.patternObservers,r=a&&a[e],r&&r.forEach(function(e){i=n.join(e.lastKey),kr(t,i),wr(t,e,i)})}function kr(t,e){t.patternObservers.forEach(function(t){t.regex.test(e.str)&&t.update(e)})}function Sr(){function t(t){var a=t.key;t.viewmodel===o?(o.clearCache(a.str),t.invalidate(),n.push(a),e(a)):t.viewmodel.mark(a)}function e(n){var a,r;o.noCascade.hasOwnProperty(n.str)||((r=o.deps.computed[n.str])&&r.forEach(t),(a=o.depsMap.computed[n.str])&&a.forEach(e))}var n,a,r,i=this,o=this,s={};return n=this.changes,n.length?(n.slice().forEach(e),a=zh(n),a.forEach(function(e){var a;-1===n.indexOf(e)&&(a=o.deps.computed[e.str])&&a.forEach(t)}),this.changes=[],this.patternObservers.length&&(a.forEach(function(t){return Wh(i,t,!0)}),n.forEach(function(t){return Wh(i,t)})),this.deps.observers&&(a.forEach(function(t){return Er(i,null,t,"observers")}),Pr(this,n,"observers")),this.deps["default"]&&(r=[],a.forEach(function(t){return Er(i,r,t,"default")}),r.length&&Cr(this,r,n),Pr(this,n,"default")),n.forEach(function(t){s[t.str]=i.get(t)}),this.implicitChanges={},this.noCascade={},s):void 0}function Er(t,e,n,a){var r,i;(r=Ar(t,n,a))&&(i=t.get(n),r.forEach(function(t){e&&t.refineValue?e.push(t):t.setValue(i)}))}function Cr(t,e,n){e.forEach(function(e){for(var a=!1,r=0,i=n.length,o=[];i>r;){var s=n[r];if(s===e.keypath){a=!0;break}s.slice(0,e.keypath.length)===e.keypath&&o.push(s),r++}a&&e.setValue(t.get(e.keypath)),o.length&&e.refineValue(o)})}function Pr(t,e,n){function a(t){t.forEach(r),t.forEach(i)}function r(e){var a=Ar(t,e,n);a&&s.push({keypath:e,deps:a})}function i(e){var r;(r=t.depsMap[n][e.str])&&a(r)}function o(e){var n=t.get(e.keypath);e.deps.forEach(function(t){return t.setValue(n)})}var s=[];a(e),s.forEach(o)}function Ar(t,e,n){var a=t.deps[n];return a?a[e.str]:null}function Or(){this.captureGroups.push([])}function Tr(t,e){var n,a;if(e||(a=this.wrapped[t])&&a.teardown()!==!1&&(this.wrapped[t]=null),this.cache[t]=void 0,n=this.cacheMap[t])for(;n.length;)this.clearCache(n.pop())}function Rr(t,e){var n=e.firstKey;return!(n in t.data||n in t.computations||n in t.mappings)}function Mr(t,e){var n=new Xh(t,e);return this.ready&&n.init(this),this.computations[t.str]=n}function Lr(t,e){var n,a,r,i,o,s=this.cache,p=t.str;if(e=e||nm,e.capture&&(i=D(this.captureGroups))&&(~i.indexOf(t)||i.push(t)),Mo.call(this.mappings,t.firstKey))return this.mappings[t.firstKey].get(t,e);if(t.isSpecial)return t.value;if(void 0===s[p]?((a=this.computations[p])&&!a.bypass?(n=a.get(),this.adapt(p,n)):(r=this.wrapped[p])?n=r.value:t.isRoot?(this.adapt("",this.data),n=this.data):n=jr(this,t),s[p]=n):n=s[p],!e.noUnwrap&&(r=this.wrapped[p])&&(n=r.get()),t.isRoot&&e.fullRootGet)for(o in this.mappings)n[o]=this.mappings[o].getValue();return n===tm?void 0:n}function jr(t,e){var n,a,r,i;return n=t.get(e.parent),(i=t.wrapped[e.parent.str])&&(n=i.get()),null!==n&&void 0!==n?((a=t.cacheMap[e.parent.str])?-1===a.indexOf(e.str)&&a.push(e.str):t.cacheMap[e.parent.str]=[e.str],"object"!=typeof n||e.lastKey in n?(r=n[e.lastKey],t.adapt(e.str,r,!1),t.cache[e.str]=r,r):t.cache[e.str]=tm):void 0}function Dr(){var t;for(t in this.computations)this.computations[t].init(this)}function Nr(t,e){var n=this.mappings[t.str]=new im(t,e);return n.initViewmodel(this),n}function Fr(t,e){var n,a=t.str;e&&(e.implicit&&(this.implicitChanges[a]=!0),e.noCascade&&(this.noCascade[a]=!0)),(n=this.computations[a])&&n.invalidate(),-1===this.changes.indexOf(t)&&this.changes.push(t);var r=e?e.keepExistingWrapper:!1;this.clearCache(a,r),this.ready&&this.onchange()}function Ir(t,e,n,a){var r,i,o,s;if(this.mark(t),a&&a.compare){o=Ur(a.compare);try{r=e.map(o),i=n.map(o)}catch(p){m('merge(): "%s" comparison failed. Falling back to identity checking',t),r=e,i=n}}else r=e,i=n;s=sm(r,i),this.smartUpdate(t,n,s,e.length!==n.length)}function Br(t){return JSON.stringify(t)}function Ur(t){if(t===!0)return Br;if("string"==typeof t)return um[t]||(um[t]=function(e){return e[t]}),um[t];if("function"==typeof t)return t;throw Error("The `compare` option must be a function, or a string representing an identifying field (or `true` to use JSON.stringify)")}function Vr(t,e){var n,a,r,i=void 0===arguments[2]?"default":arguments[2];e.isStatic||((n=this.mappings[t.firstKey])?n.register(t,e,i):(a=this.deps[i]||(this.deps[i]={}),r=a[t.str]||(a[t.str]=[]),r.push(e),this.depsMap[i]||(this.depsMap[i]={}),t.isRoot||qr(this,t,i)))}function qr(t,e,n){for(var a,r,i;!e.isRoot;)a=t.depsMap[n],r=a[e.parent.str]||(a[e.parent.str]=[]),i=e.str,void 0===r["_"+i]&&(r["_"+i]=0,r.push(e)),r["_"+i]+=1,e=e.parent}function Gr(){return this.captureGroups.pop()}function zr(t){this.data=t,this.clearCache("")}function Wr(t,e){var n,a,r,i,o=void 0===arguments[2]?{}:arguments[2];if(!o.noMapping&&(n=this.mappings[t.firstKey]))return n.set(t,e);if(a=this.computations[t.str]){if(a.setting)return;a.set(e),e=a.get()}s(this.cache[t.str],e)||(r=this.wrapped[t.str],r&&r.reset&&(i=r.reset(e)!==!1,i&&(e=r.get())),a||i||Hr(this,t,e),o.silent?this.clearCache(t.str):this.mark(t))}function Hr(t,e,n){var a,r,i,o;i=function(){a.set?a.set(e.lastKey,n):(r=a.get(),o())},o=function(){r||(r=Fh(e.lastKey),t.set(e.parent,r,{silent:!0})),r[e.lastKey]=n},a=t.wrapped[e.parent.str],a?i():(r=t.get(e.parent),(a=t.wrapped[e.parent.str])?i():o())}function Kr(t,e,n){var a,r,i,o=this;if(r=n.length,n.forEach(function(e,n){-1===e&&o.mark(t.join(n),gm)}),this.set(t,e,{silent:!0}),(a=this.deps["default"][t.str])&&a.filter(Qr).forEach(function(t){return t.shuffle(n,e)}),r!==e.length){for(this.mark(t.join("length"),mm),i=n.touchedFrom;ii;i+=1)this.mark(t.join(i),gm)}}function Qr(t){return"function"==typeof t.shuffle}function Yr(){var t,e=this;for(Object.keys(this.cache).forEach(function(t){return e.clearCache(t)});t=this.unresolvedImplicitDependencies.pop();)t.teardown()}function $r(t,e){var n,a,r,i=void 0===arguments[2]?"default":arguments[2];if(!e.isStatic){if(n=this.mappings[t.firstKey])return n.unregister(t,e,i);if(a=this.deps[i][t.str],r=a.indexOf(e),-1===r)throw Error("Attempted to remove a dependant that was no longer registered! This should not happen. If you are seeing this bug in development please raise an issue at https://github.com/RactiveJS/Ractive/issues - thanks");a.splice(r,1),t.isRoot||Jr(this,t,i)}}function Jr(t,e,n){for(var a,r;!e.isRoot;)a=t.depsMap[n],r=a[e.parent.str],r["_"+e.str]-=1,r["_"+e.str]||(N(r,e),r["_"+e.str]=void 0),e=e.parent}function Xr(t){this.hook=new is(t),this.inProcess={},this.queue={}}function Zr(t,e){return t[e._guid]||(t[e._guid]=[])}function ti(t,e){var n=Zr(t.queue,e);for(t.hook.fire(e);n.length;)ti(t,n.shift());delete t.queue[e._guid]}function ei(t,e){var n,a={};for(n in e)a[n]=ni(t,n,e[n]);return a}function ni(t,e,n){var a,r;return"function"==typeof n&&(a=ri(n,t)),"string"==typeof n&&(a=ai(t,n)),"object"==typeof n&&("string"==typeof n.get?a=ai(t,n.get):"function"==typeof n.get?a=ri(n.get,t):l("`%s` computation must have a `get()` method",e), "function"==typeof n.set&&(r=ri(n.set,t))),{getter:a,setter:r}}function ai(t,e){var n,a,r;return n="return ("+e.replace(km,function(t,e){return a=!0,'__ractive.get("'+e+'")'})+");",a&&(n="var __ractive = this; "+n),r=Function(n),a?r.bind(t):r}function ri(t,e){return/this/.test(""+t)?t.bind(e):t}function ii(e){var n,r,i=void 0===arguments[1]?{}:arguments[1],o=void 0===arguments[2]?{}:arguments[2];if(Mg.DEBUG&&Ro(),pi(e,o),Eo(e,"data",{get:ui}),Sm.fire(e,i),Am.forEach(function(t){e[t]=a(So(e.constructor[t]||null),i[t])}),r=new _m({adapt:oi(e,e.adapt,i),data:Wp.init(e.constructor,e,i),computed:wm(e,a(So(e.constructor.prototype.computed),i.computed)),mappings:o.mappings,ractive:e,onchange:function(){return bs.addRactive(e)}}),e.viewmodel=r,r.init(),uu.init(e.constructor,e,i),Em.fire(e),Cm.begin(e),e.template){var s=void 0;(o.cssIds||e.cssId)&&(s=o.cssIds?o.cssIds.slice():[],e.cssId&&s.push(e.cssId)),e.fragment=new rg({template:e.template,root:e,owner:e,cssIds:s})}if(Cm.end(e),n=t(e.el)){var p=e.render(n,e.append);Mg.DEBUG_PROMISES&&p["catch"](function(t){throw g("Promise debugging is enabled, to help solve errors that happen asynchronously. Some browsers will log unhandled promise rejections, in which case you can safely disable promise debugging:\n Ractive.DEBUG_PROMISES = false;"),m("An error happened during rendering",{ractive:e}),t.stack&&d(t.stack),t})}}function oi(t,e,n){function a(e){return"string"==typeof e&&(e=v("adaptors",t,e),e||l(Io(e,"adaptor"))),e}var r,i,o;if(e=e.map(a),r=j(n.adapt).map(a),r=si(e,r),i="magic"in n?n.magic:t.magic,o="modifyArrays"in n?n.modifyArrays:t.modifyArrays,i){if(!eo)throw Error("Getters and setters (magic mode) are not supported in this browser");o&&r.push(Vh),r.push(Uh)}return o&&r.push(Dh),r}function si(t,e){for(var n=t.slice(),a=e.length;a--;)~n.indexOf(e[a])||n.push(e[a]);return n}function pi(t,e){t._guid="r-"+Pm++,t._subs=So(null),t._config={},t._twowayBindings=So(null),t._animations=[],t.nodes={},t._liveQueries=[],t._liveComponentQueries=[],t._boundFunctions=[],t._observers=[],e.component?(t.parent=e.parent,t.container=e.container||null,t.root=t.parent.root,t.component=e.component,e.component.instance=t,t._inlinePartials=e.inlinePartials):(t.root=t,t.parent=t.container=null)}function ui(){throw Error("Using `ractive.data` is no longer supported - you must use the `ractive.get()` API instead")}function ci(t,e,n){this.parentFragment=t.parentFragment,this.callback=n,this.fragment=new rg({template:e,root:t.root,owner:this}),this.update()}function li(t,e,n){var a;return e.r?a=Rc(t,e.r,n):e.x?a=new Dc(t,t.parentFragment,e.x,n):e.rx&&(a=new Bc(t,e.rx,n)),a}function di(t){return 1===t.length&&t[0].t===Su}function fi(t,e){var n;for(n in e)e.hasOwnProperty(n)&&hi(t.instance,t.root,n,e[n])}function hi(t,e,n,a){"string"!=typeof a&&l("Components currently only support simple events - you cannot include arguments. Sorry!"),t.on(n,function(){var t,n;return arguments.length&&arguments[0]&&arguments[0].node&&(t=Array.prototype.shift.call(arguments)),n=Array.prototype.slice.call(arguments),zs(e,a,{event:t,args:n}),!1})}function mi(t,e){var n,a;if(!e)throw Error('Component "'+this.name+'" not found');n=this.parentFragment=t.parentFragment,a=n.root,this.root=a,this.type=Ru,this.name=t.template.e,this.index=t.index,this.indexRefBindings={},this.yielders={},this.resolvers=[],Rm(this,e,t.template.a,t.template.f,t.template.p),Mm(this,t.template.v),(t.template.t0||t.template.t1||t.template.t2||t.template.o)&&m('The "intro", "outro" and "decorator" directives have no effect on components',{ractive:this.instance}),Lm(this)}function gi(t,e){function n(n){n.rebind(t,e)}var a;this.resolvers.forEach(n);for(var r in this.yielders)this.yielders[r][0]&&n(this.yielders[r][0]);(a=this.root._liveComponentQueries["_"+this.name])&&a._makeDirty()}function vi(){var t=this.instance;return t.render(this.parentFragment.getNode()),this.rendered=!0,t.fragment.detach()}function bi(){return""+this.instance.fragment}function yi(){var t=this.instance;this.resolvers.forEach(K),_i(this),t._observers.forEach(Y),t.fragment.unbind(),t.viewmodel.teardown(),t.fragment.rendered&&t.el.__ractive_instances__&&N(t.el.__ractive_instances__,t),Bm.fire(t)}function _i(t){var e,n;e=t.root;do(n=e._liveComponentQueries["_"+t.name])&&n._remove(t);while(e=e.parent)}function xi(t){this.shouldDestroy=t,this.instance.unrender()}function wi(t){var e=this;this.owner=t.owner,this.parent=this.owner.parentFragment,this.root=t.root,this.pElement=t.pElement,this.context=t.context,this.index=t.index,this.key=t.key,this.registeredIndexRefs=[],this.cssIds="cssIds"in t?t.cssIds:this.parent?this.parent.cssIds:null,this.items=t.template.map(function(n,a){return ki({parentFragment:e,pElement:t.pElement,template:n,index:a})}),this.value=this.argsList=null,this.dirtyArgs=this.dirtyValue=!0,this.bound=!0}function ki(t){if("string"==typeof t.template)return new yc(t);switch(t.template.t){case Mu:return new Hm(t);case Su:return new Wc(t);case Cu:return new ll(t);case Eu:return new Ol(t);case Pu:var e=void 0;return(e=vh(t.parentFragment.root,t.template.e))?new qm(t,e):new ih(t);case Au:return new gh(t);case Ou:return new zm(t);case Lu:return new Qm(t);default:throw Error("Something very strange happened. Please file an issue at https://github.com/ractivejs/ractive/issues. Thanks!")}}function Si(t,e){(!this.owner||this.owner.hasContext)&&w(this,"context",t,e),this.items.forEach(function(n){n.rebind&&n.rebind(t,e)})}function Ei(){var t;return 1===this.items.length?t=this.items[0].render():(t=document.createDocumentFragment(),this.items.forEach(function(e){t.appendChild(e.render())})),this.rendered=!0,t}function Ci(t){return this.items?this.items.map(t?Ai:Pi).join(""):""}function Pi(t){return""+t}function Ai(t){return t.toString(!0)}function Oi(){this.bound&&(this.items.forEach(Ti),this.bound=!1)}function Ti(t){t.unbind&&t.unbind()}function Ri(t){if(!this.rendered)throw Error("Attempted to unrender a fragment that was not rendered");this.items.forEach(function(e){return e.unrender(t)}),this.rendered=!1}function Mi(t){var e,n,a,r,i;if(t=t||{},"object"!=typeof t)throw Error("The reset method takes either no arguments, or an object containing new data");for((n=this.viewmodel.wrapped[""])&&n.reset?n.reset(t)===!1&&this.viewmodel.reset(t):this.viewmodel.reset(t),a=uu.reset(this),r=a.length;r--;)if(og.indexOf(a[r])>-1){i=!0;break}if(i){var o=void 0;this.viewmodel.mark($o),(o=this.component)&&(o.shouldDestroy=!0),this.unrender(),o&&(o.shouldDestroy=!1),this.fragment.template!==this.template&&(this.fragment.unbind(),this.fragment=new rg({template:this.template,root:this,owner:this})),e=this.render(this.el,this.anchor)}else e=bs.start(this,!0),this.viewmodel.mark($o),bs.end();return sg.fire(this,t),e}function Li(t){var e,n;Jp.init(null,this,{template:t}),e=this.transitionsEnabled,this.transitionsEnabled=!1,(n=this.component)&&(n.shouldDestroy=!0),this.unrender(),n&&(n.shouldDestroy=!1),this.fragment.unbind(),this.fragment=new rg({template:this.template,root:this,owner:this}),this.render(this.el,this.anchor),this.transitionsEnabled=e}function ji(t,e){var n,a;if(a=bs.start(this,!0),u(t)){n=t;for(t in n)n.hasOwnProperty(t)&&(e=n[t],Di(this,t,e))}else Di(this,t,e);return bs.end(),a}function Di(t,e,n){e=S(P(e)),e.isPattern?E(t,e).forEach(function(e){t.viewmodel.set(e,n)}):t.viewmodel.set(e,n)}function Ni(t,e){return Jo(this,t,void 0===e?-1:-e)}function Fi(){var t;return this.fragment.unbind(),this.viewmodel.teardown(),this._observers.forEach(Y),this.fragment.rendered&&this.el.__ractive_instances__&&N(this.el.__ractive_instances__,this),this.shouldDestroy=!0,t=this.fragment.rendered?this.unrender():us.resolve(),vg.fire(this),this._boundFunctions.forEach(Ii),t}function Ii(t){delete t.fn[t.prop]}function Bi(t){var e=this;if("string"!=typeof t)throw new TypeError(No);var n=void 0;return/\*/.test(t)?(n={},E(this,S(P(t))).forEach(function(t){n[t.str]=!e.viewmodel.get(t)}),this.set(n)):this.set(t,!this.get(t))}function Ui(){return this.fragment.toString(!0)}function Vi(){var t,e;if(!this.fragment.rendered)return m("ractive.unrender() was called on a Ractive instance that was not rendered"),us.resolve();for(t=bs.start(this,!0),e=!this.component||this.component.shouldDestroy||this.shouldDestroy;this._animations[0];)this._animations[0].stop();return this.fragment.unrender(e),N(this.el.__ractive_instances__,this),xg.fire(this),bs.end(),t}function qi(t){var e;return t=S(t)||$o,e=bs.start(this,!0),this.viewmodel.mark(t),bs.end(),Sg.fire(this,t),e}function Gi(t,e){var n,a,r;if("string"!=typeof t||e){r=[];for(a in this._twowayBindings)(!t||S(a).equalsOrStartsWith(t))&&r.push.apply(r,this._twowayBindings[a])}else r=this._twowayBindings[t];return n=zi(this,r),this.set(n)}function zi(t,e){var n={},a=[];return e.forEach(function(t){var e,r;if(!t.radioName||t.element.node.checked){if(t.checkboxName)return void(a[t.keypath.str]||t.changed()||(a.push(t.keypath),a[t.keypath.str]=t));e=t.attribute.value,r=t.getValue(),L(e,r)||s(e,r)||(n[t.keypath.str]=r)}}),a.length&&a.forEach(function(t){var e,r,i;e=a[t.str],r=e.attribute.value,i=e.getValue(),L(r,i)||(n[t.str]=i)}),n}function Wi(t,e){return"function"==typeof e&&/_super/.test(t)}function Hi(t){for(var e={};t;)Ki(t,e),Yi(t,e),t=t._Parent!==Mg?t._Parent:!1;return e}function Ki(t,e){ru.forEach(function(n){Qi(n.useDefaults?t.prototype:t,e,n.name)})}function Qi(t,e,n){var a,r=Object.keys(t[n]);r.length&&((a=e[n])||(a=e[n]={}),r.filter(function(t){return!(t in a)}).forEach(function(e){return a[e]=t[n][e]}))}function Yi(t,e){Object.keys(t.prototype).forEach(function(n){if("computed"!==n){var a=t.prototype[n];if(n in e){if("function"==typeof e[n]&&"function"==typeof a&&e[n]._method){var r=void 0,i=a._method;i&&(a=a._method),r=Pg(e[n]._method,a),i&&(r._method=r),e[n]=r}}else e[n]=a._method?a._method:a}})}function $i(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];return e.length?e.reduce(Ji,this):Ji(this)}function Ji(t){var e,n,r=void 0===arguments[1]?{}:arguments[1];return r.prototype instanceof Mg&&(r=Ag(r)),e=function(t){return this instanceof e?void Om(this,t):new e(t)},n=So(t.prototype),n.constructor=e,Co(e,{defaults:{value:n},extend:{value:$i,writable:!0,configurable:!0},_Parent:{value:t}}),uu.extend(t,n,r),Wp.extend(t,n,r),r.computed&&(n.computed=a(So(t.prototype.computed),r.computed)),e.prototype=n,e}var Xi,Zi,to,eo,no,ao,ro,io=3,oo={el:void 0,append:!1,template:{v:io,t:[]},preserveWhitespace:!1,sanitize:!1,stripComments:!0,delimiters:["{{","}}"],tripleDelimiters:["{{{","}}}"],interpolate:!1,data:{},computed:{},magic:!1,modifyArrays:!0,adapt:[],isolated:!1,twoway:!0,lazy:!1,noIntro:!1,transitionsEnabled:!0,complete:void 0,css:null,noCssTransform:!1},so=oo,po={linear:function(t){return t},easeIn:function(t){return Math.pow(t,3)},easeOut:function(t){return Math.pow(t-1,3)+1},easeInOut:function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)}};Xi="object"==typeof document,Zi="undefined"!=typeof navigator&&/jsDom/.test(navigator.appName),to="undefined"!=typeof console&&"function"==typeof console.warn&&"function"==typeof console.warn.apply;try{Object.defineProperty({},"test",{value:0}),eo=!0}catch(uo){eo=!1}no={html:"http://www.w3.org/1999/xhtml",mathml:"http://www.w3.org/1998/Math/MathML",svg:"http://www.w3.org/2000/svg",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},ao="undefined"==typeof document?!1:document&&document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),ro=["o","ms","moz","webkit"];var co,lo,fo,ho,mo,go,vo,bo,yo;if(co=ao?function(t,e){return e&&e!==no.html?document.createElementNS(e,t):document.createElement(t)}:function(t,e){if(e&&e!==no.html)throw"This browser does not support namespaces other than http://www.w3.org/1999/xhtml. The most likely cause of this error is that you're trying to render SVG in an older browser. See http://docs.ractivejs.org/latest/svg-and-older-browsers for more information";return document.createElement(t)},Xi){for(fo=co("div"),ho=["matches","matchesSelector"],yo=function(t){return function(e,n){return e[t](n)}},vo=ho.length;vo--&&!lo;)if(mo=ho[vo],fo[mo])lo=yo(mo);else for(bo=ro.length;bo--;)if(go=ro[vo]+mo.substr(0,1).toUpperCase()+mo.substring(1),fo[go]){lo=yo(go);break}lo||(lo=function(t,e){var n,a,r;for(a=t.parentNode,a||(fo.innerHTML="",a=fo,t=t.cloneNode(),fo.appendChild(t)),n=a.querySelectorAll(e),r=n.length;r--;)if(n[r]===t)return!0;return!1})}else lo=null;var _o,xo,wo,ko=function(){};"undefined"==typeof window?wo=null:(_o=window,xo=_o.document,wo={},xo||(wo=null),Date.now||(Date.now=function(){return+new Date}),String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+/,"").replace(/\s+$/,"")}),Object.keys||(Object.keys=function(){var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],a=n.length;return function(r){if("object"!=typeof r&&"function"!=typeof r||null===r)throw new TypeError("Object.keys called on non-object");var i=[];for(var o in r)t.call(r,o)&&i.push(o);if(e)for(var s=0;a>s;s++)t.call(r,n[s])&&i.push(n[s]);return i}}()),Array.prototype.indexOf||(Array.prototype.indexOf=function(t,e){var n;for(void 0===e&&(e=0),0>e&&(e+=this.length),0>e&&(e=0),n=this.length;n>e;e++)if(this.hasOwnProperty(e)&&this[e]===t)return e;return-1}),Array.prototype.forEach||(Array.prototype.forEach=function(t,e){var n,a;for(n=0,a=this.length;a>n;n+=1)this.hasOwnProperty(n)&&t.call(e,this[n],n,this)}),Array.prototype.map||(Array.prototype.map=function(t,e){var n,a,r,i=this,o=[];for(i instanceof String&&(i=""+i,r=!0),n=0,a=i.length;a>n;n+=1)(i.hasOwnProperty(n)||r)&&(o[n]=t.call(e,i[n],n,i));return o}),"function"!=typeof Array.prototype.reduce&&(Array.prototype.reduce=function(t,e){var n,a,r,i;if("function"!=typeof t)throw new TypeError(t+" is not a function");for(r=this.length,i=!1,arguments.length>1&&(a=e,i=!0),n=0;r>n;n+=1)this.hasOwnProperty(n)?i&&(a=t(a,this[n],n,this)):(a=this[n],i=!0);if(!i)throw new TypeError("Reduce of empty array with no initial value");return a}),Array.prototype.filter||(Array.prototype.filter=function(t,e){var n,a,r=[];for(n=0,a=this.length;a>n;n+=1)this.hasOwnProperty(n)&&t.call(e,this[n],n,this)&&(r[r.length]=this[n]);return r}),Array.prototype.every||(Array.prototype.every=function(t,e){var n,a,r;if(null==this)throw new TypeError;if(n=Object(this),a=n.length>>>0,"function"!=typeof t)throw new TypeError;for(r=0;a>r;r+=1)if(r in n&&!t.call(e,n[r],r,n))return!1;return!0}),"function"!=typeof Function.prototype.bind&&(Function.prototype.bind=function(t){var e,n,a,r,i=[].slice;if("function"!=typeof this)throw new TypeError("Function.prototype.bind called on non-function");return e=i.call(arguments,1),n=this,a=function(){},r=function(){var r=this instanceof a&&t?this:t;return n.apply(r,e.concat(i.call(arguments)))},a.prototype=this.prototype,r.prototype=new a,r}),_o.addEventListener||!function(t,e){var n,a,r,i,o,s;t.appearsToBeIELessEqual8=!0,n=function(t,e){var n,a=this;for(n in t)a[n]=t[n];a.currentTarget=e,a.target=t.srcElement||e,a.timeStamp=+new Date,a.preventDefault=function(){t.returnValue=!1},a.stopPropagation=function(){t.cancelBubble=!0}},a=function(t,e){var a,r,i=this;a=i.listeners||(i.listeners=[]),r=a.length,a[r]=[e,function(t){e.call(i,new n(t,i))}],i.attachEvent("on"+t,a[r][1])},r=function(t,e){var n,a,r=this;if(r.listeners)for(n=r.listeners,a=n.length;a--;)n[a][0]===e&&r.detachEvent("on"+t,n[a][1])},t.addEventListener=e.addEventListener=a,t.removeEventListener=e.removeEventListener=r,"Element"in t?(t.Element.prototype.addEventListener=a,t.Element.prototype.removeEventListener=r):(s=e.createElement,e.createElement=function(t){var e=s(t);return e.addEventListener=a,e.removeEventListener=r,e},i=e.getElementsByTagName("head")[0],o=e.createElement("style"),i.insertBefore(o,i.firstChild))}(_o,xo),_o.getComputedStyle||(wo.getComputedStyle=function(){function t(n,a,r,i){var o,s=a[r],p=parseFloat(s),u=s.split(/\d/)[0];return isNaN(p)&&/^thin|medium|thick$/.test(s)&&(p=e(s),u=""),i=null!=i?i:/%|em/.test(u)&&n.parentElement?t(n.parentElement,n.parentElement.currentStyle,"fontSize",null):16,o="fontSize"==r?i:/width/i.test(r)?n.clientWidth:n.clientHeight,"em"==u?p*i:"in"==u?96*p:"pt"==u?96*p/72:"%"==u?p/100*o:p}function e(t){var e,n;return i[t]||(e=document.createElement("div"),e.style.display="block",e.style.position="fixed",e.style.width=e.style.height="0",e.style.borderRight=t+" solid black",document.getElementsByTagName("body")[0].appendChild(e),n=e.getBoundingClientRect(),i[t]=n.right-n.left),i[t]}function n(t,e){var n="border"==e?"Width":"",a=e+"Top"+n,r=e+"Right"+n,i=e+"Bottom"+n,o=e+"Left"+n;t[e]=(t[a]==t[r]==t[i]==t[o]?[t[a]]:t[a]==t[i]&&t[o]==t[r]?[t[a],t[r]]:t[o]==t[r]?[t[a],t[r],t[i]]:[t[a],t[r],t[i],t[o]]).join(" ")}function a(e){var a,r,i,s;a=e.currentStyle,r=this,i=t(e,a,"fontSize",null);for(s in a)"normal"===a[s]&&o.hasOwnProperty(s)?r[s]=o[s]:/width|height|margin.|padding.|border.+W/.test(s)?"auto"===a[s]?/^width|height/.test(s)?r[s]=("width"===s?e.clientWidth:e.clientHeight)+"px":/(?:padding)?Top|Bottom$/.test(s)&&(r[s]="0px"):r[s]=t(e,a,s,i)+"px":"styleFloat"===s?r["float"]=a[s]:r[s]=a[s];return n(r,"margin"),n(r,"padding"),n(r,"border"),r.fontSize=i+"px",r}function r(t){return new a(t)}var i={},o={fontWeight:400,lineHeight:1.2,letterSpacing:0};return a.prototype={constructor:a,getPropertyPriority:ko,getPropertyValue:function(t){return this[t]||""},item:ko,removeProperty:ko,setProperty:ko,getPropertyCSSValue:ko},r}()));var So,Eo,Co,Po=wo;try{Object.defineProperty({},"test",{value:0}),Xi&&Object.defineProperty(document.createElement("div"),"test",{value:0}),Eo=Object.defineProperty}catch(Ao){Eo=function(t,e,n){t[e]=n.value}}try{try{Object.defineProperties({},{test:{value:0}})}catch(Ao){throw Ao}Xi&&Object.defineProperties(co("div"),{test:{value:0}}),Co=Object.defineProperties}catch(Ao){Co=function(t,e){var n;for(n in e)e.hasOwnProperty(n)&&Eo(t,n,e[n])}}try{Object.create(null),So=Object.create}catch(Ao){So=function(){var t=function(){};return function(e,n){var a;return null===e?{}:(t.prototype=e,a=new t,n&&Object.defineProperties(a,n),a)}}()}var Oo,To,Ro,Mo=Object.prototype.hasOwnProperty,Lo=Object.prototype.toString,jo=/^\[object (?:Array|FileList)\]$/,Do={};to?!function(){var t=["%cRactive.js %c0.7.3 %cin debug mode, %cmore...","color: rgb(114, 157, 52); font-weight: normal;","color: rgb(85, 85, 85); font-weight: normal;","color: rgb(85, 85, 85); font-weight: normal;","color: rgb(82, 140, 224); font-weight: normal; text-decoration: underline;"],e="You're running Ractive 0.7.3 in debug mode - messages will be printed to the console to help you fix problems and optimise your application.\n\nTo disable debug mode, add this line at the start of your app:\n Ractive.DEBUG = false;\n\nTo disable debug mode when your app is minified, add this snippet:\n Ractive.DEBUG = /unminified/.test(function(){/*unminified*/});\n\nGet help and support:\n http://docs.ractivejs.org\n http://stackoverflow.com/questions/tagged/ractivejs\n http://groups.google.com/forum/#!forum/ractive-js\n http://twitter.com/ractivejs\n\nFound a bug? Raise an issue:\n https://github.com/ractivejs/ractive/issues\n\n";Ro=function(){var n=!!console.groupCollapsed;console[n?"groupCollapsed":"log"].apply(console,t),console.log(e),n&&console.groupEnd(t),Ro=ko},To=function(t,e){if(Ro(),"object"==typeof e[e.length-1]){var n=e.pop(),a=n?n.ractive:null;if(a){var r=void 0;a.component&&(r=a.component.name)&&(t="<"+r+"> "+t);var i=void 0;(i=n.node||a.fragment&&a.fragment.rendered&&a.find("*"))&&e.push(i)}}console.warn.apply(console,["%cRactive.js: %c"+t,"color: rgb(114, 157, 52);","color: rgb(85, 85, 85);"].concat(e))},Oo=function(){console.log.apply(console,arguments)}}():To=Oo=Ro=ko;var No="Bad arguments",Fo='A function was specified for "%s" %s, but no %s was returned',Io=function(t,e){return'Missing "'+t+'" '+e+" plugin. You may need to download a plugin via http://docs.ractivejs.org/latest/plugins#"+e+"s"},Bo=function(t,e,n,a){if(t===e)return y(e);if(a){var r=v("interpolators",n,a);if(r)return r(t,e)||y(e);l(Io(a,"interpolator"))}return qo.number(t,e)||qo.array(t,e)||qo.object(t,e)||y(e)},Uo=Bo,Vo={number:function(t,e){var n;return p(t)&&p(e)?(t=+t,e=+e,n=e-t,n?function(e){return t+e*n}:function(){return t}):null},array:function(t,e){var n,a,r,o;if(!i(t)||!i(e))return null;for(n=[],a=[],o=r=Math.min(t.length,e.length);o--;)a[o]=Uo(t[o],e[o]);for(o=r;o=this.duration?(null!==i&&(bs.start(this.root),this.root.viewmodel.set(i,this.to),bs.end()),this.step&&this.step(1,this.to),this.complete(this.to),r=this.root._animations.indexOf(this),-1===r&&m("Animation was not found"),this.root._animations.splice(r,1),this.running=!1,!1):(e=this.easing?this.easing(t/this.duration):t/this.duration,null!==i&&(n=this.interpolator(e),bs.start(this.root),this.root.viewmodel.set(i,n),bs.end()),this.step&&this.step(e,n),!0)):!1},stop:function(){var t;this.running=!1,t=this.root._animations.indexOf(this),-1===t&&m("Animation was not found"),this.root._animations.splice(t,1)}};var ks=ws,Ss=nt,Es={stop:ko},Cs=rt,Ps=new is("detach"),As=it,Os=ot,Ts=function(){var t,e,n;t=this._root[this._isComponentQuery?"liveComponentQueries":"liveQueries"],e=this.selector,n=t.indexOf(e),-1!==n&&(t.splice(n,1),t[e]=null)},Rs=function(t,e){var n,a,r,i,o,s,p,u,c,l;for(n=pt(t.component||t._ractive.proxy),a=pt(e.component||e._ractive.proxy),r=D(n),i=D(a);r&&r===i;)n.pop(),a.pop(),o=r,r=D(n),i=D(a);if(r=r.component||r,i=i.component||i,c=r.parentFragment,l=i.parentFragment,c===l)return s=c.items.indexOf(r),p=l.items.indexOf(i),s-p||n.length-a.length;if(u=o.fragments)return s=u.indexOf(c),p=u.indexOf(l),s-p||n.length-a.length;throw Error("An unexpected condition was met while comparing the position of two components. Please file an issue at https://github.com/RactiveJS/Ractive/issues - thanks!")},Ms=function(t,e){var n;return t.compareDocumentPosition?(n=t.compareDocumentPosition(e),2&n?1:-1):Rs(t,e)},Ls=function(){this.sort(this._isComponentQuery?Rs:Ms),this._dirty=!1},js=function(){var t=this;this._dirty||(this._dirty=!0,bs.scheduleTask(function(){t._sort()}))},Ds=function(t){var e=this.indexOf(this._isComponentQuery?t.instance:t);-1!==e&&this.splice(e,1)},Ns=ut,Fs=ct,Is=lt,Bs=dt,Us=ft,Vs=ht,qs={enqueue:function(t,e){t.event&&(t._eventQueue=t._eventQueue||[],t._eventQueue.push(t.event)),t.event=e},dequeue:function(t){t._eventQueue&&t._eventQueue.length?t.event=t._eventQueue.pop():delete t.event}},Gs=qs,zs=mt,Ws=bt,Hs=yt,Ks={capture:!0,noUnwrap:!0,fullRootGet:!0},Qs=_t,Ys=new is("insert"),$s=wt,Js=function(t,e,n,a){this.root=t,this.keypath=e,this.callback=n,this.defer=a.defer,this.context=a&&a.context?a.context:t};Js.prototype={init:function(t){this.value=this.root.get(this.keypath.str),t!==!1?this.update():this.oldValue=this.value},setValue:function(t){var e=this;s(t,this.value)||(this.value=t,this.defer&&this.ready?bs.scheduleTask(function(){return e.update()}):this.update())},update:function(){this.updating||(this.updating=!0,this.callback.call(this.context,this.value,this.oldValue,this.keypath.str),this.oldValue=this.value,this.updating=!1)}};var Xs,Zs=Js,tp=kt,ep=Array.prototype.slice;Xs=function(t,e,n,a){this.root=t,this.callback=n,this.defer=a.defer,this.keypath=e,this.regex=RegExp("^"+e.str.replace(/\./g,"\\.").replace(/\*/g,"([^\\.]+)")+"$"),this.values={},this.defer&&(this.proxies=[]),this.context=a&&a.context?a.context:t},Xs.prototype={init:function(t){var e,n;if(e=tp(this.root,this.keypath),t!==!1)for(n in e)e.hasOwnProperty(n)&&this.update(S(n));else this.values=e},update:function(t){var e,n=this;if(t.isPattern){e=tp(this.root,t);for(t in e)e.hasOwnProperty(t)&&this.update(S(t))}else if(!this.root.viewmodel.implicitChanges[t.str])return this.defer&&this.ready?void bs.scheduleTask(function(){return n.getProxy(t).update()}):void this.reallyUpdate(t)},reallyUpdate:function(t){var e,n,a,r;return e=t.str,n=this.root.viewmodel.get(t),this.updating?void(this.values[e]=n):(this.updating=!0,s(n,this.values[e])&&this.ready||(a=ep.call(this.regex.exec(e),1),r=[n,this.values[e],e].concat(a),this.values[e]=n,this.callback.apply(this.context,r)),void(this.updating=!1))},getProxy:function(t){var e=this;return this.proxies[t.str]||(this.proxies[t.str]={update:function(){return e.reallyUpdate(t)}}),this.proxies[t.str]}};var np,ap,rp,ip,op,sp,pp=Xs,up=St,cp={},lp=Et,dp=Ct,fp=function(t){return t.trim()},hp=function(t){return""!==t},mp=Pt,gp=At,vp=Ot,bp=Tt,yp=Array.prototype,_p=function(t){return function(e){for(var n=arguments.length,a=Array(n>1?n-1:0),r=1;n>r;r++)a[r-1]=arguments[r];var o,s,p,u,c=[];if(e=S(P(e)),o=this.viewmodel.get(e),s=o.length,!i(o))throw Error("Called ractive."+t+"('"+e.str+"'), but '"+e.str+"' does not refer to an array");return c=bp(o,t,a),u=yp[t].apply(o,a),p=bs.start(this,!0).then(function(){return u}),c?this.viewmodel.smartUpdate(e,o,c):this.viewmodel.mark(e),bs.end(),p}},xp=_p("pop"),wp=_p("push"),kp="/* Ractive.js component styles */\n",Sp=[],Ep=!1;Xi?(rp=document.createElement("style"),rp.type="text/css",ip=document.getElementsByTagName("head")[0],sp=!1,op=rp.styleSheet,ap=function(){var t=kp+Sp.map(function(t){return"\n/* {"+t.id+"} */\n"+t.styles}).join("\n");op?op.cssText=t:rp.innerHTML=t,sp||(ip.appendChild(rp),sp=!0)},np={add:function(t){Sp.push(t),Ep=!0},apply:function(){Ep&&(ap(),Ep=!1)}}):np={add:ko,apply:ko};var Cp,Pp,Ap,Op=np,Tp=Mt,Rp=new is("render"),Mp=new is("complete"),Lp={extend:function(t,e,n){e.adapt=jt(e.adapt,j(n.adapt))},init:function(){}},jp=Lp,Dp=Dt,Np=/(?:^|\})?\s*([^\{\}]+)\s*\{/g,Fp=/\/\*.*?\*\//g,Ip=/((?:(?:\[[^\]+]\])|(?:[^\s\+\>\~:]))+)((?::[^\s\+\>\~\(]+(?:\([^\)]+\))?)?\s*[\s\+\>\~]?)\s*/g,Bp=/^@media/,Up=/\[data-ractive-css~="\{[a-z0-9-]+\}"]/g,Vp=1,qp={ name:"css",extend:function(t,e,n){if(n.css){var a=Vp++,r=n.noCssTransform?n.css:Dp(n.css,a);e.cssId=a,Op.add({id:a,styles:r})}},init:function(){}},Gp=qp,zp={name:"data",extend:function(t,e,n){var a=void 0,r=void 0;if(n.data&&u(n.data))for(a in n.data)r=n.data[a],r&&"object"==typeof r&&(u(r)||i(r))&&m("Passing a `data` option with object and array properties to Ractive.extend() is discouraged, as mutating them is likely to cause bugs. Consider using a data function instead:\n\n // this...\n data: function () {\n return {\n myObject: {}\n };\n })\n\n // instead of this:\n data: {\n myObject: {}\n }");e.data=Bt(e.data,n.data)},init:function(t,e,n){var a=Bt(t.prototype.data,n.data);return"function"==typeof a&&(a=a.call(e)),a||{}},reset:function(t){var e=this.init(t.constructor,t,t.viewmodel);return t.viewmodel.reset(e),!0}},Wp=zp,Hp=null,Kp=["preserveWhitespace","sanitize","stripComments","delimiters","tripleDelimiters","interpolate"],Qp={fromId:zt,isHashedId:Wt,isParsed:Ht,getParseOptions:Kt,createHelper:qt,parse:Gt},Yp=Qp,$p={name:"template",extend:function(t,e,n){var a;"template"in n&&(a=n.template,"function"==typeof a?e.template=a:e.template=Jt(a,e))},init:function(t,e,n){var a,r;a="template"in n?n.template:t.prototype.template,"function"==typeof a&&(r=a,a=Yt(e,r),e._config.template={fn:r,result:a}),a=Jt(a,e),e.template=a.t,a.p&&Xt(e.partials,a.p)},reset:function(t){var e,n=Qt(t);return n?(e=Jt(n,t),t.template=e.t,Xt(t.partials,e.p,!0),!0):void 0}},Jp=$p;Cp=["adaptors","components","computed","decorators","easing","events","interpolators","partials","transitions"],Pp=function(t,e){this.name=t,this.useDefaults=e},Pp.prototype={constructor:Pp,extend:function(t,e,n){this.configure(this.useDefaults?t.defaults:t,this.useDefaults?e:e.constructor,n)},init:function(){},configure:function(t,e,n){var a,r=this.name,i=n[r];a=So(t[r]);for(var o in i)a[o]=i[o];e[r]=a},reset:function(t){var e=t[this.name],n=!1;return Object.keys(e).forEach(function(t){var a=e[t];a._fn&&(a._fn.isOwner?e[t]=a._fn:delete e[t],n=!0)}),n}},Ap=Cp.map(function(t){return new Pp(t,"computed"===t)});var Xp,Zp,tu,eu,nu,au,ru=Ap,iu=Zt,ou=ae;eu={adapt:jp,css:Gp,data:Wp,template:Jp},tu=Object.keys(so),au=oe(tu.filter(function(t){return!eu[t]})),nu=oe(tu.concat(ru.map(function(t){return t.name}))),Zp=[].concat(tu.filter(function(t){return!ru[t]&&!eu[t]}),ru,eu.data,eu.template,eu.css),Xp={extend:function(t,e,n){return re("extend",t,e,n)},init:function(t,e,n){return re("init",t,e,n)},reset:function(t){return Zp.filter(function(e){return e.reset&&e.reset(t)}).map(function(t){return t.name})},order:Zp};var su,pu,uu=Xp,cu=se,lu=pe,du=ue,fu=ce,hu=le,mu=de,gu=fe,vu=he,bu=/^\s+/;pu=function(t){this.name="ParseError",this.message=t;try{throw Error(t)}catch(e){this.stack=e.stack}},pu.prototype=Error.prototype,su=function(t,e){var n,a,r=0;for(this.str=t,this.options=e||{},this.pos=0,this.lines=this.str.split("\n"),this.lineEnds=this.lines.map(function(t){var e=r+t.length+1;return r=e,e},0),this.init&&this.init(t,e),n=[];this.posn;n+=1)if(this.pos=e,r=t[n](this))return r;return null},getLinePos:function(t){for(var e,n=0,a=0;t>=this.lineEnds[n];)a=this.lineEnds[n],n+=1;return e=t-a,[n+1,e+1,t]},error:function(t){var e=this.getLinePos(this.pos),n=e[0],a=e[1],r=this.lines[e[0]-1],i=0,o=r.replace(/\t/g,function(t,n){return n/g,lc=/&/g;var vc=function(){return e(this.node)},bc=function(t){this.type=ku,this.text=t.template};bc.prototype={detach:vc,firstNode:function(){return this.node},render:function(){return this.node||(this.node=document.createTextNode(this.text)),this.node},toString:function(t){return t?Se(this.text):this.text},unrender:function(t){return t?this.detach():void 0}};var yc=bc,_c=Ee,xc=Ce,wc=function(t,e,n){var a;this.ref=e,this.resolved=!1,this.root=t.root,this.parentFragment=t.parentFragment,this.callback=n,a=ls(t.root,e,t.parentFragment),void 0!=a?this.resolve(a):bs.addUnresolved(this)};wc.prototype={resolve:function(t){this.keypath&&!t&&bs.addUnresolved(this),this.resolved=!0,this.keypath=t,this.callback(t)},forceResolution:function(){this.resolve(S(this.ref))},rebind:function(t,e){var n;void 0!=this.keypath&&(n=this.keypath.replace(t,e),void 0!==n&&this.resolve(n))},unbind:function(){this.resolved||bs.removeUnresolved(this)}};var kc=wc,Sc=function(t,e,n){this.parentFragment=t.parentFragment,this.ref=e,this.callback=n,this.rebind()},Ec={"@keypath":{prefix:"c",prop:["context"]},"@index":{prefix:"i",prop:["index"]},"@key":{prefix:"k",prop:["key","index"]}};Sc.prototype={rebind:function(){var t,e=this.ref,n=this.parentFragment,a=Ec[e];if(!a)throw Error('Unknown special reference "'+e+'" - valid references are @index, @key and @keypath');if(this.cached)return this.callback(S("@"+a.prefix+Pe(this.cached,a)));if(-1!==a.prop.indexOf("index")||-1!==a.prop.indexOf("key"))for(;n;){if(n.owner.currentSubtype===Bu&&void 0!==(t=Pe(n,a)))return this.cached=n,n.registerIndexRef(this),this.callback(S("@"+a.prefix+t));n=!n.parent&&n.owner&&n.owner.component&&n.owner.component.parentFragment&&!n.owner.component.instance.isolated?n.owner.component.parentFragment:n.parent}else for(;n;){if(void 0!==(t=Pe(n,a)))return this.callback(S("@"+a.prefix+t.str));n=n.parent}},unbind:function(){this.cached&&this.cached.unregisterIndexRef(this)}};var Cc=Sc,Pc=function(t,e,n){this.parentFragment=t.parentFragment,this.ref=e,this.callback=n,e.ref.fragment.registerIndexRef(this),this.rebind()};Pc.prototype={rebind:function(){var t,e=this.ref.ref;t="k"===e.ref.t?"k"+e.fragment.key:"i"+e.fragment.index,void 0!==t&&this.callback(S("@"+t))},unbind:function(){this.ref.ref.fragment.unregisterIndexRef(this)}};var Ac=Pc,Oc=Ae;Ae.resolve=function(t){var e,n,a={};for(e in t.refs)n=t.refs[e],a[n.ref.n]="k"===n.ref.t?n.fragment.key:n.fragment.index;return a};var Tc,Rc=Oe,Mc=Te,Lc={},jc=Function.prototype.bind;Tc=function(t,e,n,a){var r,i=this;r=t.root,this.root=r,this.parentFragment=e,this.callback=a,this.owner=t,this.str=n.s,this.keypaths=[],this.pending=n.r.length,this.refResolvers=n.r.map(function(t,e){return Rc(i,t,function(t){i.resolve(e,t)})}),this.ready=!0,this.bubble()},Tc.prototype={bubble:function(){this.ready&&(this.uniqueString=Me(this.str,this.keypaths),this.keypath=Le(this.uniqueString),this.createEvaluator(),this.callback(this.keypath))},unbind:function(){for(var t;t=this.refResolvers.pop();)t.unbind()},resolve:function(t,e){this.keypaths[t]=e,this.bubble()},createEvaluator:function(){var t,e,n,a,r,i=this;a=this.keypath,t=this.root.viewmodel.computations[a.str],t?this.root.viewmodel.mark(a):(r=Mc(this.str,this.refResolvers.length),e=this.keypaths.map(function(t){var e;return"undefined"===t?function(){}:t.isSpecial?(e=t.value,function(){return e}):function(){var e=i.root.viewmodel.get(t,{noUnwrap:!0,fullRootGet:!0});return"function"==typeof e&&(e=De(e,i.root)),e}}),n={deps:this.keypaths.filter(je),getter:function(){var t=e.map(Re);return r.apply(null,t)}},t=this.root.viewmodel.compute(a,n))},rebind:function(t,e){this.refResolvers.forEach(function(n){return n.rebind(t,e)})}};var Dc=Tc,Nc=function(t,e,n){var a=this;this.resolver=e,this.root=e.root,this.parentFragment=n,this.viewmodel=e.root.viewmodel,"string"==typeof t?this.value=t:t.t===Nu?this.refResolver=Rc(this,t.n,function(t){a.resolve(t)}):new Dc(e,n,t,function(t){a.resolve(t)})};Nc.prototype={resolve:function(t){this.keypath&&this.viewmodel.unregister(this.keypath,this),this.keypath=t,this.value=this.viewmodel.get(t),this.bind(),this.resolver.bubble()},bind:function(){this.viewmodel.register(this.keypath,this)},rebind:function(t,e){this.refResolver&&this.refResolver.rebind(t,e)},setValue:function(t){this.value=t,this.resolver.bubble()},unbind:function(){this.keypath&&this.viewmodel.unregister(this.keypath,this),this.refResolver&&this.refResolver.unbind()},forceResolution:function(){this.refResolver&&this.refResolver.forceResolution()}};var Fc=Nc,Ic=function(t,e,n){var a,r,i,o,s=this;this.parentFragment=o=t.parentFragment,this.root=a=t.root,this.mustache=t,this.ref=r=e.r,this.callback=n,this.unresolved=[],(i=ls(a,r,o))?this.base=i:this.baseResolver=new kc(this,r,function(t){s.base=t,s.baseResolver=null,s.bubble()}),this.members=e.m.map(function(t){return new Fc(t,s,o)}),this.ready=!0,this.bubble()};Ic.prototype={getKeypath:function(){var t=this.members.map(Ne);return!t.every(Fe)||this.baseResolver?null:this.base.join(t.join("."))},bubble:function(){this.ready&&!this.baseResolver&&this.callback(this.getKeypath())},unbind:function(){this.members.forEach(K)},rebind:function(t,e){var n;if(this.base){var a=this.base.replace(t,e);a&&a!==this.base&&(this.base=a,n=!0)}this.members.forEach(function(a){a.rebind(t,e)&&(n=!0)}),n&&this.bubble()},forceResolution:function(){this.baseResolver&&(this.base=S(this.ref),this.baseResolver.unbind(),this.baseResolver=null),this.members.forEach(Ie),this.bubble()}};var Bc=Ic,Uc=Be,Vc=Ue,qc=Ve,Gc={getValue:xc,init:Uc,resolve:Vc,rebind:qc},zc=function(t){this.type=Su,Gc.init(this,t)};zc.prototype={update:function(){this.node.data=void 0==this.value?"":this.value},resolve:Gc.resolve,rebind:Gc.rebind,detach:vc,unbind:_c,render:function(){return this.node||(this.node=document.createTextNode(n(this.value))),this.node},unrender:function(t){t&&e(this.node)},getValue:Gc.getValue,setValue:function(t){var e;this.keypath&&(e=this.root.viewmodel.wrapped[this.keypath.str])&&(t=e.get()),s(t,this.value)||(this.value=t,this.parentFragment.bubble(),this.node&&bs.addView(this))},firstNode:function(){return this.node},toString:function(t){var e=""+n(this.value);return t?Se(e):e}};var Wc=zc,Hc=qe,Kc=Ge,Qc=ze,Yc=We,$c=He,Jc=Ke,Xc=Qe,Zc=Ye,tl=$e,el=function(t,e){Gc.rebind.call(this,t,e)},nl=Xe,al=Ze,rl=ln,il=dn,ol=fn,sl=gn,pl=function(t){this.type=Cu,this.subtype=this.currentSubtype=t.template.n,this.inverted=this.subtype===Iu,this.pElement=t.pElement,this.fragments=[],this.fragmentsToCreate=[],this.fragmentsToRender=[],this.fragmentsToUnrender=[],t.template.i&&(this.indexRefs=t.template.i.split(",").map(function(t,e){return{n:t,t:0===e?"k":"i"}})),this.renderedFragments=[],this.length=0,Gc.init(this,t)};pl.prototype={bubble:Hc,detach:Kc,find:Qc,findAll:Yc,findAllComponents:$c,findComponent:Jc,findNextNode:Xc,firstNode:Zc,getIndexRef:function(t){if(this.indexRefs)for(var e=this.indexRefs.length;e--;){var n=this.indexRefs[e];if(n.n===t)return n}},getValue:Gc.getValue,shuffle:tl,rebind:el,render:nl,resolve:Gc.resolve,setValue:al,toString:rl,unbind:il,unrender:ol,update:sl};var ul,cl,ll=pl,dl=vn,fl=bn,hl=yn,ml=_n,gl={};try{co("table").innerHTML="foo"}catch(Ao){ul=!0,cl={TABLE:['',"
"],THEAD:['',"
"],TBODY:['',"
"],TR:['',"
"],SELECT:['"]}}var vl=function(t,e,n){var a,r,i,o,s,p=[];if(null!=t&&""!==t){for(ul&&(r=cl[e.tagName])?(a=xn("DIV"),a.innerHTML=r[0]+t+r[1],a=a.querySelector(".x"),"SELECT"===a.tagName&&(i=a.options[a.selectedIndex])):e.namespaceURI===no.svg?(a=xn("DIV"),a.innerHTML=''+t+"",a=a.querySelector(".x")):(a=xn(e.tagName),a.innerHTML=t,"SELECT"===a.tagName&&(i=a.options[a.selectedIndex]));o=a.firstChild;)p.push(o),n.appendChild(o);if("SELECT"===e.tagName)for(s=p.length;s--;)p[s]!==i&&(p[s].selected=!1)}return p},bl=wn,yl=Sn,_l=En,xl=Cn,wl=Pn,kl=An,Sl=function(t){this.type=Eu,Gc.init(this,t)};Sl.prototype={detach:dl,find:fl,findAll:hl,firstNode:ml,getValue:Gc.getValue,rebind:Gc.rebind,render:yl,resolve:Gc.resolve,setValue:_l,toString:xl,unbind:_c,unrender:wl,update:kl};var El,Cl,Pl,Al,Ol=Sl,Tl=function(){this.parentFragment.bubble()},Rl=On,Ml=function(t){return this.node?lo(this.node,t)?this.node:this.fragment&&this.fragment.find?this.fragment.find(t):void 0:null},Ll=function(t,e){e._test(this,!0)&&e.live&&(this.liveQueries||(this.liveQueries=[])).push(e),this.fragment&&this.fragment.findAll(t,e)},jl=function(t,e){this.fragment&&this.fragment.findAllComponents(t,e)},Dl=function(t){return this.fragment?this.fragment.findComponent(t):void 0},Nl=Tn,Fl=Rn,Il=Mn,Bl=/^true|on|yes|1$/i,Ul=/^[0-9]+$/,Vl=function(t,e){var n,a,r;return r=e.a||{},a={},n=r.twoway,void 0!==n&&(a.twoway=0===n||Bl.test(n)),n=r.lazy,void 0!==n&&(0!==n&&Ul.test(n)?a.lazy=parseInt(n):a.lazy=0===n||Bl.test(n)),a},ql=Ln;El="altGlyph altGlyphDef altGlyphItem animateColor animateMotion animateTransform clipPath feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence foreignObject glyphRef linearGradient radialGradient textPath vkern".split(" "),Cl="attributeName attributeType baseFrequency baseProfile calcMode clipPathUnits contentScriptType contentStyleType diffuseConstant edgeMode externalResourcesRequired filterRes filterUnits glyphRef gradientTransform gradientUnits kernelMatrix kernelUnitLength keyPoints keySplines keyTimes lengthAdjust limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits numOctaves pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ preserveAlpha preserveAspectRatio primitiveUnits refX refY repeatCount repeatDur requiredExtensions requiredFeatures specularConstant specularExponent spreadMethod startOffset stdDeviation stitchTiles surfaceScale systemLanguage tableValues targetX targetY textLength viewBox viewTarget xChannelSelector yChannelSelector zoomAndPan".split(" "),Pl=function(t){for(var e={},n=t.length;n--;)e[t[n].toLowerCase()]=t[n];return e},Al=Pl(El.concat(Cl));var Gl=function(t){var e=t.toLowerCase();return Al[e]||e},zl=function(t,e){var n,a;if(n=e.indexOf(":"),-1===n||(a=e.substr(0,n),"xmlns"===a))t.name=t.element.namespace!==no.html?Gl(e):e;else if(e=e.substring(n+1),t.name=Gl(e),t.namespace=no[a.toLowerCase()],t.namespacePrefix=a,!t.namespace)throw'Unknown namespace ("'+a+'")'},Wl=jn,Hl=Dn,Kl=Nn,Ql=Fn,Yl={"accept-charset":"acceptCharset",accesskey:"accessKey",bgcolor:"bgColor","class":"className",codebase:"codeBase",colspan:"colSpan",contenteditable:"contentEditable",datetime:"dateTime",dirname:"dirName","for":"htmlFor","http-equiv":"httpEquiv",ismap:"isMap",maxlength:"maxLength",novalidate:"noValidate",pubdate:"pubDate",readonly:"readOnly",rowspan:"rowSpan",tabindex:"tabIndex",usemap:"useMap"},$l=In,Jl=Un,Xl=Vn,Zl=qn,td=Gn,ed=zn,nd=Wn,ad=Hn,rd=Kn,id=Qn,od=Yn,sd=$n,pd=Jn,ud=Xn,cd=Zn,ld=function(t){this.init(t)};ld.prototype={bubble:ql,init:Hl,rebind:Kl,render:Ql,toString:$l,unbind:Jl,update:cd};var dd,fd=ld,hd=function(t,e){var n,a,r=[];for(n in e)"twoway"!==n&&"lazy"!==n&&e.hasOwnProperty(n)&&(a=new fd({element:t,name:n,value:e[n],root:t.root}),r[n]=a,"value"!==n&&r.push(a));return(a=r.value)&&r.push(a),r};"undefined"!=typeof document&&(dd=co("div"));var md=function(t,e){this.element=t,this.root=t.root,this.parentFragment=t.parentFragment,this.attributes=[],this.fragment=new rg({root:t.root,owner:this,template:[e]})};md.prototype={bubble:function(){this.node&&this.update(),this.element.bubble()},rebind:function(t,e){this.fragment.rebind(t,e)},render:function(t){this.node=t,this.isSvg=t.namespaceURI===no.svg,this.update()},unbind:function(){this.fragment.unbind()},update:function(){var t,e,n=this;t=""+this.fragment,e=ta(t,this.isSvg),this.attributes.filter(function(t){return ea(e,t)}).forEach(function(t){n.node.removeAttribute(t.name)}),e.forEach(function(t){n.node.setAttribute(t.name,t.value)}),this.attributes=e},toString:function(){return""+this.fragment}};var gd=md,vd=function(t,e){return e?e.map(function(e){return new gd(t,e)}):[]},bd=function(t){var e,n,a,r;if(this.element=t,this.root=t.root,this.attribute=t.attributes[this.name||"value"],e=this.attribute.interpolator,e.twowayBinding=this,n=e.keypath){if("}"===n.str.slice(-1))return g("Two-way binding does not work with expressions (`%s` on <%s>)",e.resolver.uniqueString,t.name,{ractive:this.root}),!1;if(n.isSpecial)return g("Two-way binding does not work with %s",e.resolver.ref,{ractive:this.root}),!1}else{var i=e.template.r?"'"+e.template.r+"' reference":"expression";m("The %s being used for two-way binding is ambiguous, and may cause unexpected results. Consider initialising your data to eliminate the ambiguity",i,{ractive:this.root}),e.resolver.forceResolution(),n=e.keypath}this.attribute.isTwoway=!0,this.keypath=n,a=this.root.viewmodel.get(n),void 0===a&&this.getInitialValue&&(a=this.getInitialValue(),void 0!==a&&this.root.viewmodel.set(n,a)),(r=na(t))&&(this.resetValue=a,r.formBindings.push(this))};bd.prototype={handleChange:function(){var t=this;bs.start(this.root),this.attribute.locked=!0,this.root.viewmodel.set(this.keypath,this.getValue()),bs.scheduleTask(function(){return t.attribute.locked=!1}),bs.end()},rebound:function(){var t,e,n;e=this.keypath,n=this.attribute.interpolator.keypath,e!==n&&(N(this.root._twowayBindings[e.str],this),this.keypath=n,t=this.root._twowayBindings[n.str]||(this.root._twowayBindings[n.str]=[]),t.push(this))},unbind:function(){}},bd.extend=function(t){var e,n=this;return e=function(t){bd.call(this,t),this.init&&this.init()},e.prototype=So(n.prototype),a(e.prototype,t),e.extend=bd.extend,e};var yd,_d=bd,xd=aa;yd=_d.extend({getInitialValue:function(){return""},getValue:function(){return this.element.node.value},render:function(){var t,e=this.element.node,n=!1;this.rendered=!0,t=this.root.lazy,this.element.lazy===!0?t=!0:this.element.lazy===!1?t=!1:p(this.element.lazy)?(t=!1,n=+this.element.lazy):p(t||"")&&(n=+t,t=!1,this.element.lazy=n),this.handler=n?ia:xd,e.addEventListener("change",xd,!1),t||(e.addEventListener("input",this.handler,!1),e.attachEvent&&e.addEventListener("keyup",this.handler,!1)),e.addEventListener("blur",ra,!1)},unrender:function(){var t=this.element.node;this.rendered=!1,t.removeEventListener("change",xd,!1),t.removeEventListener("input",this.handler,!1),t.removeEventListener("keyup",this.handler,!1),t.removeEventListener("blur",ra,!1)}});var wd=yd,kd=wd.extend({getInitialValue:function(){return this.element.fragment?""+this.element.fragment:""},getValue:function(){return this.element.node.innerHTML}}),Sd=kd,Ed=oa,Cd={},Pd=_d.extend({name:"checked",init:function(){this.siblings=Ed(this.root._guid,"radio",this.element.getAttribute("name")),this.siblings.push(this)},render:function(){var t=this.element.node;t.addEventListener("change",xd,!1),t.attachEvent&&t.addEventListener("click",xd,!1)},unrender:function(){var t=this.element.node;t.removeEventListener("change",xd,!1),t.removeEventListener("click",xd,!1)},handleChange:function(){bs.start(this.root),this.siblings.forEach(function(t){t.root.viewmodel.set(t.keypath,t.getValue())}),bs.end()},getValue:function(){return this.element.node.checked},unbind:function(){N(this.siblings,this)}}),Ad=Pd,Od=_d.extend({name:"name",init:function(){this.siblings=Ed(this.root._guid,"radioname",this.keypath.str),this.siblings.push(this),this.radioName=!0},getInitialValue:function(){return this.element.getAttribute("checked")?this.element.getAttribute("value"):void 0},render:function(){var t=this.element.node;t.name="{{"+this.keypath.str+"}}",t.checked=this.root.viewmodel.get(this.keypath)==this.element.getAttribute("value"),t.addEventListener("change",xd,!1),t.attachEvent&&t.addEventListener("click",xd,!1)},unrender:function(){var t=this.element.node;t.removeEventListener("change",xd,!1),t.removeEventListener("click",xd,!1)},getValue:function(){var t=this.element.node;return t._ractive?t._ractive.value:t.value},handleChange:function(){this.element.node.checked&&_d.prototype.handleChange.call(this)},rebound:function(t,e){var n;_d.prototype.rebound.call(this,t,e),(n=this.element.node)&&(n.name="{{"+this.keypath.str+"}}")},unbind:function(){N(this.siblings,this)}}),Td=Od,Rd=_d.extend({name:"name",getInitialValue:function(){return this.noInitialValue=!0,[]},init:function(){var t,e;this.checkboxName=!0,this.siblings=Ed(this.root._guid,"checkboxes",this.keypath.str),this.siblings.push(this),this.noInitialValue&&(this.siblings.noInitialValue=!0),this.siblings.noInitialValue&&this.element.getAttribute("checked")&&(t=this.root.viewmodel.get(this.keypath),e=this.element.getAttribute("value"),t.push(e))},unbind:function(){N(this.siblings,this)},render:function(){var t,e,n=this.element.node;t=this.root.viewmodel.get(this.keypath),e=this.element.getAttribute("value"),i(t)?this.isChecked=M(t,e):this.isChecked=t==e,n.name="{{"+this.keypath.str+"}}",n.checked=this.isChecked,n.addEventListener("change",xd,!1),n.attachEvent&&n.addEventListener("click",xd,!1)},unrender:function(){var t=this.element.node;t.removeEventListener("change",xd,!1),t.removeEventListener("click",xd,!1)},changed:function(){var t=!!this.isChecked;return this.isChecked=this.element.node.checked,this.isChecked===t},handleChange:function(){this.isChecked=this.element.node.checked,_d.prototype.handleChange.call(this)},getValue:function(){return this.siblings.filter(sa).map(pa)}}),Md=Rd,Ld=_d.extend({name:"checked",render:function(){var t=this.element.node;t.addEventListener("change",xd,!1),t.attachEvent&&t.addEventListener("click",xd,!1)},unrender:function(){var t=this.element.node;t.removeEventListener("change",xd,!1),t.removeEventListener("click",xd,!1)},getValue:function(){return this.element.node.checked}}),jd=Ld,Dd=_d.extend({getInitialValue:function(){var t,e,n,a,r=this.element.options;if(void 0===this.element.getAttribute("value")&&(e=t=r.length,t)){for(;e--;)if(r[e].getAttribute("selected")){n=r[e].getAttribute("value"),a=!0;break}if(!a)for(;++ee;e+=1)if(a=t[e],t[e].selected)return r=a._ractive?a._ractive.value:a.value},forceUpdate:function(){var t=this,e=this.getValue();void 0!==e&&(this.attribute.locked=!0,bs.scheduleTask(function(){return t.attribute.locked=!1}),this.root.viewmodel.set(this.keypath,e))}}),Nd=Dd,Fd=Nd.extend({getInitialValue:function(){return this.element.options.filter(function(t){return t.getAttribute("selected")}).map(function(t){return t.getAttribute("value")})},render:function(){var t;this.element.node.addEventListener("change",xd,!1),t=this.root.viewmodel.get(this.keypath),void 0===t&&this.handleChange()},unrender:function(){this.element.node.removeEventListener("change",xd,!1)},setValue:function(){throw Error("TODO not implemented yet")},getValue:function(){var t,e,n,a,r,i;for(t=[],e=this.element.node.options,a=e.length,n=0;a>n;n+=1)r=e[n],r.selected&&(i=r._ractive?r._ractive.value:r.value,t.push(i));return t},handleChange:function(){var t,e,n;return t=this.attribute,e=t.value,n=this.getValue(),void 0!==e&&L(n,e)||Nd.prototype.handleChange.call(this),this},forceUpdate:function(){var t=this,e=this.getValue();void 0!==e&&(this.attribute.locked=!0,bs.scheduleTask(function(){return t.attribute.locked=!1}),this.root.viewmodel.set(this.keypath,e))},updateModel:function(){void 0!==this.attribute.value&&this.attribute.value.length||this.root.viewmodel.set(this.keypath,this.initialValue)}}),Id=Fd,Bd=_d.extend({render:function(){this.element.node.addEventListener("change",xd,!1)},unrender:function(){this.element.node.removeEventListener("change",xd,!1)},getValue:function(){return this.element.node.files}}),Ud=Bd,Vd=wd.extend({getInitialValue:function(){},getValue:function(){var t=parseFloat(this.element.node.value);return isNaN(t)?void 0:t}}),qd=ua,Gd=la,zd=da,Wd=fa,Hd=ha,Kd=/^event(?:\.(.+))?/,Qd=ba,Yd=ya,$d={},Jd={touchstart:!0,touchmove:!0,touchend:!0,touchcancel:!0,touchleave:!0},Xd=xa,Zd=wa,tf=ka,ef=Sa,nf=Ea,af=function(t,e,n){this.init(t,e,n)};af.prototype={bubble:Gd,fire:zd,getAction:Wd,init:Hd,listen:Yd,rebind:Xd,render:Zd,resolve:tf,unbind:ef,unrender:nf};var rf=af,of=function(t,e){var n,a,r,i,o=[];for(a in e)if(e.hasOwnProperty(a))for(r=a.split("-"),n=r.length;n--;)i=new rf(t,r[n],e[a]),o.push(i);return o},sf=function(t,e){var n,a,r,i=this;this.element=t,this.root=n=t.root,a=e.n||e,("string"==typeof a||(r=new rg({template:a,root:n,owner:t}),a=""+r,r.unbind(),""!==a))&&(e.a?this.params=e.a:e.d&&(this.fragment=new rg({template:e.d,root:n,owner:t}),this.params=this.fragment.getArgsList(),this.fragment.bubble=function(){this.dirtyArgs=this.dirtyValue=!0,i.params=this.getArgsList(),i.ready&&i.update()}),this.fn=v("decorators",n,a),this.fn||l(Io(a,"decorator")))};sf.prototype={init:function(){var t,e,n;if(t=this.element.node,this.params?(n=[t].concat(this.params),e=this.fn.apply(this.root,n)):e=this.fn.call(this.root,t),!e||!e.teardown)throw Error("Decorator definition must return an object with a teardown method");this.actual=e,this.ready=!0},update:function(){this.actual.update?this.actual.update.apply(this.root,this.params):(this.actual.teardown(!0),this.init())},rebind:function(t,e){this.fragment&&this.fragment.rebind(t,e)},teardown:function(t){this.torndown=!0,this.ready&&this.actual.teardown(),!t&&this.fragment&&this.fragment.unbind()}};var pf,uf,cf,lf=sf,df=Ma,ff=La,hf=Ba,mf=function(t){ -return t.replace(/-([a-zA-Z])/g,function(t,e){return e.toUpperCase()})};Xi?(uf={},cf=co("div").style,pf=function(t){var e,n,a;if(t=mf(t),!uf[t])if(void 0!==cf[t])uf[t]=t;else for(a=t.charAt(0).toUpperCase()+t.substring(1),e=ro.length;e--;)if(n=ro[e],void 0!==cf[n+a]){uf[t]=n+a;break}return uf[t]}):pf=null;var gf,vf,bf=pf;Xi?(vf=window.getComputedStyle||Po.getComputedStyle,gf=function(t){var e,n,a,r,o;if(e=vf(this.node),"string"==typeof t)return o=e[bf(t)],"0px"===o&&(o=0),o;if(!i(t))throw Error("Transition$getStyle must be passed a string, or an array of strings representing CSS properties");for(n={},a=t.length;a--;)r=t[a],o=e[bf(r)],"0px"===o&&(o=0),n[r]=o;return n}):gf=null;var yf=gf,_f=function(t,e){var n;if("string"==typeof t)this.node.style[bf(t)]=e;else for(n in t)t.hasOwnProperty(n)&&(this.node.style[bf(n)]=t[n]);return this},xf=function(t){var e;this.duration=t.duration,this.step=t.step,this.complete=t.complete,"string"==typeof t.easing?(e=t.root.easing[t.easing],e||(g(Io(t.easing,"easing")),e=Ua)):e="function"==typeof t.easing?t.easing:Ua,this.easing=e,this.start=ns(),this.end=this.start+this.duration,this.running=!0,xs.add(this)};xf.prototype={tick:function(t){var e,n;return this.running?t>this.end?(this.step&&this.step(1),this.complete&&this.complete(1),!1):(e=t-this.start,n=this.easing(e/this.duration),this.step&&this.step(n),!0):!1},stop:function(){this.abort&&this.abort(),this.running=!1}};var wf,kf,Sf,Ef,Cf,Pf,Af,Of,Tf=xf,Rf=RegExp("^-(?:"+ro.join("|")+")-"),Mf=function(t){return t.replace(Rf,"")},Lf=RegExp("^(?:"+ro.join("|")+")([A-Z])"),jf=function(t){var e;return t?(Lf.test(t)&&(t="-"+t),e=t.replace(/[A-Z]/g,function(t){return"-"+t.toLowerCase()})):""},Df={},Nf={};Xi?(kf=co("div").style,function(){void 0!==kf.transition?(Sf="transition",Ef="transitionend",Cf=!0):void 0!==kf.webkitTransition?(Sf="webkitTransition",Ef="webkitTransitionEnd",Cf=!0):Cf=!1}(),Sf&&(Pf=Sf+"Duration",Af=Sf+"Property",Of=Sf+"TimingFunction"),wf=function(t,e,n,a,r){setTimeout(function(){var i,o,s,p,u;p=function(){o&&s&&(t.root.fire(t.name+":end",t.node,t.isIntro),r())},i=(t.node.namespaceURI||"")+t.node.tagName,t.node.style[Af]=a.map(bf).map(jf).join(","),t.node.style[Of]=jf(n.easing||"linear"),t.node.style[Pf]=n.duration/1e3+"s",u=function(e){var n;n=a.indexOf(mf(Mf(e.propertyName))),-1!==n&&a.splice(n,1),a.length||(t.node.removeEventListener(Ef,u,!1),s=!0,p())},t.node.addEventListener(Ef,u,!1),setTimeout(function(){for(var r,c,l,d,f,h=a.length,g=[];h--;)d=a[h],r=i+d,Cf&&!Nf[r]&&(t.node.style[bf(d)]=e[d],Df[r]||(c=t.getStyle(d),Df[r]=t.getStyle(d)!=e[d],Nf[r]=!Df[r],Nf[r]&&(t.node.style[bf(d)]=c))),(!Cf||Nf[r])&&(void 0===c&&(c=t.getStyle(d)),l=a.indexOf(d),-1===l?m("Something very strange happened with transitions. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!",{node:t.node}):a.splice(l,1),f=/[^\d]*$/.exec(e[d])[0],g.push({name:bf(d),interpolator:Uo(parseFloat(c),parseFloat(e[d])),suffix:f}));g.length?new Tf({root:t.root,duration:n.duration,easing:mf(n.easing||""),step:function(e){var n,a;for(a=g.length;a--;)n=g[a],t.node.style[n.name]=n.interpolator(e)+n.suffix},complete:function(){o=!0,p()}}):o=!0,a.length||(t.node.removeEventListener(Ef,u,!1),s=!0,p())},0)},n.delay||0)}):wf=null;var Ff,If,Bf,Uf,Vf,qf=wf;if("undefined"!=typeof document){if(Ff="hidden",Vf={},Ff in document)Bf="";else for(Uf=ro.length;Uf--;)If=ro[Uf],Ff=If+"Hidden",Ff in document&&(Bf=If);void 0!==Bf?(document.addEventListener(Bf+"visibilitychange",Va),Va()):("onfocusout"in document?(document.addEventListener("focusout",qa),document.addEventListener("focusin",Ga)):(window.addEventListener("pagehide",qa),window.addEventListener("blur",qa),window.addEventListener("pageshow",Ga),window.addEventListener("focus",Ga)),Vf.hidden=!1)}var Gf,zf,Wf,Hf=Vf;Xi?(zf=window.getComputedStyle||Po.getComputedStyle,Gf=function(t,e,n){var a,r=this;if(4===arguments.length)throw Error("t.animateStyle() returns a promise - use .then() instead of passing a callback");if(Hf.hidden)return this.setStyle(t,e),Wf||(Wf=us.resolve());"string"==typeof t?(a={},a[t]=e):(a=t,n=e),n||(g('The "%s" transition does not supply an options object to `t.animateStyle()`. This will break in a future version of Ractive. For more info see https://github.com/RactiveJS/Ractive/issues/340',this.name),n=this);var i=new us(function(t){var e,i,o,s,p,u,c;if(!n.duration)return r.setStyle(a),void t();for(e=Object.keys(a),i=[],o=zf(r.node),p={},u=e.length;u--;)c=e[u],s=o[bf(c)],"0px"===s&&(s=0),s!=a[c]&&(i.push(c),r.node.style[bf(c)]=s);return i.length?void qf(r,a,n,i,t):void t()});return i}):Gf=null;var Kf=Gf,Qf=function(t,e){return"number"==typeof t?t={duration:t}:"string"==typeof t?t="slow"===t?{duration:600}:"fast"===t?{duration:200}:{duration:400}:t||(t={}),r({},t,e)},Yf=za,$f=function(t,e,n){this.init(t,e,n)};$f.prototype={init:hf,start:Yf,getStyle:yf,setStyle:_f,animateStyle:Kf,processParams:Qf};var Jf,Xf,Zf=$f,th=Ha;Jf=function(){var t=this.node,e=this.fragment.toString(!1);if(window&&window.appearsToBeIELessEqual8&&(t.type="text/css"),t.styleSheet)t.styleSheet.cssText=e;else{for(;t.hasChildNodes();)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}},Xf=function(){this.node.type&&"text/javascript"!==this.node.type||m("Script tag was updated. This does not cause the code to be re-evaluated!",{ractive:this.root}),this.node.text=this.fragment.toString(!1)};var eh=function(){var t,e;return this.template.y?"":(t="<"+this.template.e,t+=this.attributes.map(Xa).join("")+this.conditionalAttributes.map(Xa).join(""),"option"===this.name&&$a(this)&&(t+=" selected"),"input"===this.name&&Ja(this)&&(t+=" checked"),t+=">","textarea"===this.name&&void 0!==this.getAttribute("value")?t+=Se(this.getAttribute("value")):void 0!==this.getAttribute("contenteditable")&&(t+=this.getAttribute("value")||""),this.fragment&&(e="script"!==this.name&&"style"!==this.name,t+=this.fragment.toString(e)),ic.test(this.template.e)||(t+=""),t)},nh=Za,ah=tr,rh=function(t){this.init(t)};rh.prototype={bubble:Tl,detach:Rl,find:Ml,findAll:Ll,findAllComponents:jl,findComponent:Dl,findNextNode:Nl,firstNode:Fl,getAttribute:Il,init:df,rebind:ff,render:th,toString:eh,unbind:nh,unrender:ah};var ih=rh,oh=/^\s*$/,sh=/^\s*/,ph=function(t){var e,n,a,r;return e=t.split("\n"),n=e[0],void 0!==n&&oh.test(n)&&e.shift(),a=D(e),void 0!==a&&oh.test(a)&&e.pop(),r=e.reduce(nr,null),r&&(t=e.map(function(t){return t.replace(r,"")}).join("\n")),t},uh=ar,ch=function(t,e){var n;return e?n=t.split("\n").map(function(t,n){return n?e+t:t}).join("\n"):t},lh='Could not find template for partial "%s"',dh=function(t){var e,n;e=this.parentFragment=t.parentFragment,this.root=e.root,this.type=Au,this.index=t.index,this.name=t.template.r,this.rendered=!1,this.fragment=this.fragmentToRender=this.fragmentToUnrender=null,Gc.init(this,t),this.keypath||((n=uh(this.root,this.name,e))?(_c.call(this),this.isNamed=!0,this.setTemplate(n)):g(lh,this.name))};dh.prototype={bubble:function(){this.parentFragment.bubble()},detach:function(){return this.fragment.detach()},find:function(t){return this.fragment.find(t)},findAll:function(t,e){return this.fragment.findAll(t,e)},findComponent:function(t){return this.fragment.findComponent(t)},findAllComponents:function(t,e){return this.fragment.findAllComponents(t,e)},firstNode:function(){return this.fragment.firstNode()},findNextNode:function(){return this.parentFragment.findNextNode(this)},getPartialName:function(){return this.isNamed&&this.name?this.name:void 0===this.value?this.name:this.value},getValue:function(){return this.fragment.getValue()},rebind:function(t,e){this.isNamed||qc.call(this,t,e),this.fragment&&this.fragment.rebind(t,e)},render:function(){return this.docFrag=document.createDocumentFragment(),this.update(),this.rendered=!0,this.docFrag},resolve:Gc.resolve,setValue:function(t){var e;(void 0===t||t!==this.value)&&(void 0!==t&&(e=uh(this.root,""+t,this.parentFragment)),!e&&this.name&&(e=uh(this.root,this.name,this.parentFragment))&&(_c.call(this),this.isNamed=!0),e||g(lh,this.name,{ractive:this.root}),this.value=t,this.setTemplate(e||[]),this.bubble(),this.rendered&&bs.addView(this))},setTemplate:function(t){this.fragment&&(this.fragment.unbind(),this.rendered&&(this.fragmentToUnrender=this.fragment)),this.fragment=new rg({template:t,root:this.root,owner:this,pElement:this.parentFragment.pElement}),this.fragmentToRender=this.fragment},toString:function(t){var e,n,a,r;return e=this.fragment.toString(t),n=this.parentFragment.items[this.index-1],n&&n.type===ku?(a=n.text.split("\n").pop(),(r=/^\s+$/.exec(a))?ch(e,r[0]):e):e},unbind:function(){this.isNamed||_c.call(this),this.fragment&&this.fragment.unbind()},unrender:function(t){this.rendered&&(this.fragment&&this.fragment.unrender(t),this.rendered=!1)},update:function(){var t,e;this.fragmentToUnrender&&(this.fragmentToUnrender.unrender(!0),this.fragmentToUnrender=null),this.fragmentToRender&&(this.docFrag.appendChild(this.fragmentToRender.render()),this.fragmentToRender=null),this.rendered&&(t=this.parentFragment.getNode(),e=this.parentFragment.findNextNode(this),t.insertBefore(this.docFrag,e))}};var fh,hh,mh,gh=dh,vh=pr,bh=ur,yh=new is("detach"),_h=cr,xh=lr,wh=dr,kh=fr,Sh=hr,Eh=mr,Ch=function(t,e,n,a){var r=t.root,i=t.keypath;a?r.viewmodel.smartUpdate(i,e,a):r.viewmodel.mark(i)},Ph=[],Ah=["pop","push","reverse","shift","sort","splice","unshift"];Ah.forEach(function(t){var e=function(){for(var e=arguments.length,n=Array(e),a=0;e>a;a++)n[a]=arguments[a];var r,i,o,s;for(r=bp(this,t,n),i=Array.prototype[t].apply(this,arguments),bs.start(),this._ractive.setting=!0,s=this._ractive.wrappers.length;s--;)o=this._ractive.wrappers[s],bs.addRactive(o.root),Ch(o,this,t,r);return bs.end(),this._ractive.setting=!1,i};Eo(Ph,t,{value:e})}),fh={},fh.__proto__?(hh=function(t){t.__proto__=Ph},mh=function(t){t.__proto__=Array.prototype}):(hh=function(t){var e,n;for(e=Ah.length;e--;)n=Ah[e],Eo(t,n,{value:Ph[n],configurable:!0})},mh=function(t){var e;for(e=Ah.length;e--;)delete t[Ah[e]]}),hh.unpatch=mh;var Oh,Th,Rh,Mh=hh;Oh={filter:function(t){return i(t)&&(!t._ractive||!t._ractive.setting)},wrap:function(t,e,n){return new Th(t,e,n)}},Th=function(t,e,n){this.root=t,this.value=e,this.keypath=S(n),e._ractive||(Eo(e,"_ractive",{value:{wrappers:[],instances:[],setting:!1},configurable:!0}),Mh(e)),e._ractive.instances[t._guid]||(e._ractive.instances[t._guid]=0,e._ractive.instances.push(t)),e._ractive.instances[t._guid]+=1,e._ractive.wrappers.push(this)},Th.prototype={get:function(){return this.value},teardown:function(){var t,e,n,a,r;if(t=this.value,e=t._ractive,n=e.wrappers,a=e.instances,e.setting)return!1;if(r=n.indexOf(this),-1===r)throw Error(Rh);if(n.splice(r,1),n.length){if(a[this.root._guid]-=1,!a[this.root._guid]){if(r=a.indexOf(this.root),-1===r)throw Error(Rh);a.splice(r,1)}}else delete t._ractive,Mh.unpatch(this.value)}},Rh="Something went wrong in a rather interesting way";var Lh,jh,Dh=Oh,Nh=/^\s*[0-9]+\s*$/,Fh=function(t){return Nh.test(t)?[]:{}};try{Object.defineProperty({},"test",{value:0}),Lh={filter:function(t,e,n){var a,r;return e?(e=S(e),(a=n.viewmodel.wrapped[e.parent.str])&&!a.magic?!1:(r=n.viewmodel.get(e.parent),i(r)&&/^[0-9]+$/.test(e.lastKey)?!1:r&&("object"==typeof r||"function"==typeof r))):!1},wrap:function(t,e,n){return new jh(t,e,n)}},jh=function(t,e,n){var a,r,i;return n=S(n),this.magic=!0,this.ractive=t,this.keypath=n,this.value=e,this.prop=n.lastKey,a=n.parent,this.obj=a.isRoot?t.viewmodel.data:t.viewmodel.get(a),r=this.originalDescriptor=Object.getOwnPropertyDescriptor(this.obj,this.prop),r&&r.set&&(i=r.set._ractiveWrappers)?void(-1===i.indexOf(this)&&i.push(this)):void gr(this,e,r)},jh.prototype={get:function(){return this.value},reset:function(t){return this.updating?void 0:(this.updating=!0,this.obj[this.prop]=t,bs.addRactive(this.ractive),this.ractive.viewmodel.mark(this.keypath,{keepExistingWrapper:!0}),this.updating=!1,!0)},set:function(t,e){this.updating||(this.obj[this.prop]||(this.updating=!0,this.obj[this.prop]=Fh(t),this.updating=!1),this.obj[this.prop][t]=e)},teardown:function(){var t,e,n,a,r;return this.updating?!1:(t=Object.getOwnPropertyDescriptor(this.obj,this.prop),e=t&&t.set,void(e&&(a=e._ractiveWrappers,r=a.indexOf(this),-1!==r&&a.splice(r,1),a.length||(n=this.obj[this.prop],Object.defineProperty(this.obj,this.prop,this.originalDescriptor||{writable:!0,enumerable:!0,configurable:!0}),this.obj[this.prop]=n))))}}}catch(Ao){Lh=!1}var Ih,Bh,Uh=Lh;Uh&&(Ih={filter:function(t,e,n){return Uh.filter(t,e,n)&&Dh.filter(t)},wrap:function(t,e,n){return new Bh(t,e,n)}},Bh=function(t,e,n){this.value=e,this.magic=!0,this.magicWrapper=Uh.wrap(t,e,n),this.arrayWrapper=Dh.wrap(t,e,n)},Bh.prototype={get:function(){return this.value},teardown:function(){this.arrayWrapper.teardown(),this.magicWrapper.teardown()},reset:function(t){return this.magicWrapper.reset(t)}});var Vh=Ih,qh=vr,Gh={},zh=_r,Wh=xr,Hh=Sr,Kh=Or,Qh=Tr,Yh=function(t,e){this.computation=t,this.viewmodel=t.viewmodel,this.ref=e,this.root=this.viewmodel.ractive,this.parentFragment=this.root.component&&this.root.component.parentFragment};Yh.prototype={resolve:function(t){this.computation.softDeps.push(t),this.computation.unresolvedDeps[t.str]=null,this.viewmodel.register(t,this.computation,"computed")}};var $h=Yh,Jh=function(t,e){this.key=t,this.getter=e.getter,this.setter=e.setter,this.hardDeps=e.deps||[],this.softDeps=[],this.unresolvedDeps={},this.depValues={},this._dirty=this._firstRun=!0};Jh.prototype={constructor:Jh,init:function(t){var e,n=this;this.viewmodel=t,this.bypass=!0,e=t.get(this.key),t.clearCache(this.key.str),this.bypass=!1,this.setter&&void 0!==e&&this.set(e),this.hardDeps&&this.hardDeps.forEach(function(e){return t.register(e,n,"computed")})},invalidate:function(){this._dirty=!0},get:function(){var t,e,n=this,a=!1;if(this.getting){var r="The "+this.key.str+" computation indirectly called itself. This probably indicates a bug in the computation. It is commonly caused by `array.sort(...)` - if that's the case, clone the array first with `array.slice().sort(...)`";return h(r),this.value}if(this.getting=!0,this._dirty){if(this._firstRun||!this.hardDeps.length&&!this.softDeps.length?a=!0:[this.hardDeps,this.softDeps].forEach(function(t){var e,r,i;if(!a)for(i=t.length;i--;)if(e=t[i],r=n.viewmodel.get(e),!s(r,n.depValues[e.str]))return n.depValues[e.str]=r,void(a=!0)}),a){this.viewmodel.capture();try{this.value=this.getter()}catch(i){m('Failed to compute "%s"',this.key.str),d(i.stack||i),this.value=void 0}t=this.viewmodel.release(),e=this.updateDependencies(t),e&&[this.hardDeps,this.softDeps].forEach(function(t){t.forEach(function(t){n.depValues[t.str]=n.viewmodel.get(t)})})}this._dirty=!1}return this.getting=this._firstRun=!1,this.value},set:function(t){if(this.setting)return void(this.value=t);if(!this.setter)throw Error("Computed properties without setters are read-only. (This may change in a future version of Ractive!)");this.setter(t)},updateDependencies:function(t){var e,n,a,r,i;for(n=this.softDeps,e=n.length;e--;)a=n[e],-1===t.indexOf(a)&&(r=!0,this.viewmodel.unregister(a,this,"computed"));for(e=t.length;e--;)a=t[e],-1!==n.indexOf(a)||this.hardDeps&&-1!==this.hardDeps.indexOf(a)||(r=!0,Rr(this.viewmodel,a)&&!this.unresolvedDeps[a.str]?(i=new $h(this,a.str),t.splice(e,1),this.unresolvedDeps[a.str]=i,bs.addUnresolved(i)):this.viewmodel.register(a,this,"computed"));return r&&(this.softDeps=t.slice()),r}};var Xh=Jh,Zh=Mr,tm={FAILED_LOOKUP:!0},em=Lr,nm={},am=Dr,rm=Nr,im=function(t,e){this.localKey=t,this.keypath=e.keypath,this.origin=e.origin,this.deps=[],this.unresolved=[],this.resolved=!1};im.prototype={forceResolution:function(){this.keypath=this.localKey,this.setup()},get:function(t,e){return this.resolved?this.origin.get(this.map(t),e):void 0},getValue:function(){return this.keypath?this.origin.get(this.keypath):void 0},initViewmodel:function(t){this.local=t,this.setup()},map:function(t){return void 0===typeof this.keypath?this.localKey:t.replace(this.localKey,this.keypath)},register:function(t,e,n){this.deps.push({keypath:t,dep:e,group:n}),this.resolved&&this.origin.register(this.map(t),e,n)},resolve:function(t){void 0!==this.keypath&&this.unbind(!0),this.keypath=t,this.setup()},set:function(t,e){this.resolved||this.forceResolution(),this.origin.set(this.map(t),e)},setup:function(){var t=this;void 0!==this.keypath&&(this.resolved=!0,this.deps.length&&(this.deps.forEach(function(e){var n=t.map(e.keypath);if(t.origin.register(n,e.dep,e.group),e.dep.setValue)e.dep.setValue(t.origin.get(n));else{if(!e.dep.invalidate)throw Error("An unexpected error occurred. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!");e.dep.invalidate()}}),this.origin.mark(this.keypath)))},setValue:function(t){if(!this.keypath)throw Error("Mapping does not have keypath, cannot set value. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!");this.origin.set(this.keypath,t)},unbind:function(t){var e=this;t||delete this.local.mappings[this.localKey],this.resolved&&(this.deps.forEach(function(t){e.origin.unregister(e.map(t.keypath),t.dep,t.group)}),this.tracker&&this.origin.unregister(this.keypath,this.tracker))},unregister:function(t,e,n){var a,r;if(this.resolved){for(a=this.deps,r=a.length;r--;)if(a[r].dep===e){a.splice(r,1);break}this.origin.unregister(this.map(t),e,n)}}};var om=Fr,sm=function(t,e){var n,a,r,i;return n={},a=0,r=t.map(function(t,r){var o,s,p;s=a,p=e.length;do{if(o=e.indexOf(t,s),-1===o)return i=!0,-1;s=o+1}while(n[o]&&p>s);return o===a&&(a+=1),o!==r&&(i=!0),n[o]=!0,o})},pm=Ir,um={},cm=Vr,lm=Gr,dm=zr,fm=Wr,hm=Kr,mm={implicit:!0},gm={noCascade:!0},vm=Yr,bm=$r,ym=function(t){var e,n,a=t.adapt,r=t.data,i=t.ractive,o=t.computed,s=t.mappings;this.ractive=i,this.adaptors=a,this.onchange=t.onchange,this.cache={},this.cacheMap=So(null),this.deps={computed:So(null),"default":So(null)},this.depsMap={computed:So(null),"default":So(null)},this.patternObservers=[],this.specials=So(null),this.wrapped=So(null),this.computations=So(null),this.captureGroups=[],this.unresolvedImplicitDependencies=[],this.changes=[],this.implicitChanges={},this.noCascade={},this.data=r,this.mappings=So(null);for(e in s)this.map(S(e),s[e]);if(r)for(e in r)(n=this.mappings[e])&&void 0===n.getValue()&&n.setValue(r[e]);for(e in o)s&&e in s&&l("Cannot map to a computed property ('%s')",e),this.compute(S(e),o[e]);this.ready=!0};ym.prototype={adapt:qh,applyChanges:Hh,capture:Kh,clearCache:Qh,compute:Zh,get:em,init:am,map:rm,mark:om,merge:pm,register:cm,release:lm,reset:dm,set:fm,smartUpdate:hm,teardown:vm,unregister:bm};var _m=ym;Xr.prototype={constructor:Xr,begin:function(t){this.inProcess[t._guid]=!0},end:function(t){var e=t.parent;e&&this.inProcess[e._guid]?Zr(this.queue,e).push(t):ti(this,t),delete this.inProcess[t._guid]}};var xm=Xr,wm=ei,km=/\$\{([^\}]+)\}/g,Sm=new is("construct"),Em=new is("config"),Cm=new xm("init"),Pm=0,Am=["adaptors","components","decorators","easing","events","interpolators","partials","transitions"],Om=ii,Tm=ci;ci.prototype={bubble:function(){this.dirty||(this.dirty=!0,bs.addView(this))},update:function(){this.callback(this.fragment.getValue()),this.dirty=!1},rebind:function(t,e){this.fragment.rebind(t,e)},unbind:function(){this.fragment.unbind()}};var Rm=function(t,e,n,r,o){var s,p,u,c,l,d,f={},h={},g={},v=[];for(p=t.parentFragment,u=t.root,o=o||{},a(f,o),o.content=r||[],f[""]=o.content,e.defaults.el&&m("The <%s/> component has a default `el` property; it has been disregarded",t.name),c=p;c;){if(c.owner.type===Mu){l=c.owner.container;break}c=c.parent}return n&&Object.keys(n).forEach(function(e){var a,r,o=n[e];if("string"==typeof o)a=dc(o),h[e]=a?a.value:o;else if(0===o)h[e]=!0;else{if(!i(o))throw Error("erm wut");di(o)?(g[e]={origin:t.root.viewmodel,keypath:void 0},r=li(t,o[0],function(t){t.isSpecial?d?s.set(e,t.value):(h[e]=t.value,delete g[e]):d?s.viewmodel.mappings[e].resolve(t):g[e].keypath=t})):r=new Tm(t,o,function(t){d?s.set(e,t):h[e]=t}),v.push(r)}}),s=So(e.prototype),Om(s,{el:null,append:!0,data:h,partials:o,magic:u.magic||e.defaults.magic,modifyArrays:u.modifyArrays,adapt:u.adapt},{parent:u,component:t,container:l,mappings:g,inlinePartials:f,cssIds:p.cssIds}),d=!0,t.resolvers=v,s},Mm=fi,Lm=function(t){var e,n;for(e=t.root;e;)(n=e._liveComponentQueries["_"+t.name])&&n.push(t.instance),e=e.parent},jm=mi,Dm=gi,Nm=vi,Fm=bi,Im=yi,Bm=new is("teardown"),Um=xi,Vm=function(t,e){this.init(t,e)};Vm.prototype={detach:bh,find:_h,findAll:xh,findAllComponents:wh,findComponent:kh,findNextNode:Sh,firstNode:Eh,init:jm,rebind:Dm,render:Nm,toString:Fm,unbind:Im,unrender:Um};var qm=Vm,Gm=function(t){this.type=Ou,this.value=t.template.c};Gm.prototype={detach:vc,firstNode:function(){return this.node},render:function(){return this.node||(this.node=document.createComment(this.value)),this.node},toString:function(){return""},unrender:function(t){t&&this.node.parentNode.removeChild(this.node)}};var zm=Gm,Wm=function(t){var e,n;this.type=Mu,this.container=e=t.parentFragment.root,this.component=n=e.component,this.container=e,this.containerFragment=t.parentFragment,this.parentFragment=n.parentFragment;var a=this.name=t.template.n||"",r=e._inlinePartials[a];r||(m('Could not find template for partial "'+a+'"',{ractive:t.root}),r=[]),this.fragment=new rg({owner:this,root:e.parent,template:r,pElement:this.containerFragment.pElement}),i(n.yielders[a])?n.yielders[a].push(this):n.yielders[a]=[this],bs.scheduleTask(function(){if(n.yielders[a].length>1)throw Error("A component template can only have one {{yield"+(a?" "+a:"")+"}} declaration at a time")})};Wm.prototype={detach:function(){return this.fragment.detach()},find:function(t){return this.fragment.find(t)},findAll:function(t,e){return this.fragment.findAll(t,e)},findComponent:function(t){return this.fragment.findComponent(t)},findAllComponents:function(t,e){return this.fragment.findAllComponents(t,e)},findNextNode:function(){return this.containerFragment.findNextNode(this)},firstNode:function(){return this.fragment.firstNode()},getValue:function(t){return this.fragment.getValue(t)},render:function(){return this.fragment.render()},unbind:function(){this.fragment.unbind()},unrender:function(t){this.fragment.unrender(t),N(this.component.yielders[this.name],this)},rebind:function(t,e){this.fragment.rebind(t,e)},toString:function(){return""+this.fragment}};var Hm=Wm,Km=function(t){this.declaration=t.template.a};Km.prototype={init:ko,render:ko,unrender:ko,teardown:ko,toString:function(){return""}};var Qm=Km,Ym=wi,$m=Si,Jm=Ei,Xm=Ci,Zm=Oi,tg=Ri,eg=function(t){this.init(t)};eg.prototype={bubble:cu,detach:lu,find:du,findAll:fu,findAllComponents:hu,findComponent:mu,findNextNode:gu,firstNode:vu,getArgsList:hc,getNode:mc,getValue:gc,init:Ym,rebind:$m,registerIndexRef:function(t){var e=this.registeredIndexRefs;-1===e.indexOf(t)&&e.push(t)},render:Jm,toString:Xm,unbind:Zm,unregisterIndexRef:function(t){var e=this.registeredIndexRefs;e.splice(e.indexOf(t),1)},unrender:tg};var ng,ag,rg=eg,ig=Mi,og=["template","partials","components","decorators","events"],sg=new is("reset"),pg=function(t,e){function n(e,a,r){r&&r.partials[t]||e.forEach(function(e){e.type===Au&&e.getPartialName()===t&&a.push(e),e.fragment&&n(e.fragment.items,a,r),i(e.fragments)?n(e.fragments,a,r):i(e.items)?n(e.items,a,r):e.type===Ru&&e.instance&&n(e.instance.fragment.items,a,e.instance),e.type===Pu&&(i(e.attributes)&&n(e.attributes,a,r),i(e.conditionalAttributes)&&n(e.conditionalAttributes,a,r))})}var a,r=[];return n(this.fragment.items,r),this.partials[t]=e,a=bs.start(this,!0),r.forEach(function(e){e.value=void 0,e.setValue(t)}),bs.end(),a},ug=Li,cg=_p("reverse"),lg=ji,dg=_p("shift"),fg=_p("sort"),hg=_p("splice"),mg=Ni,gg=Fi,vg=new is("teardown"),bg=Bi,yg=Ui,_g=Vi,xg=new is("unrender"),wg=_p("unshift"),kg=qi,Sg=new is("update"),Eg=Gi,Cg={add:Zo,animate:Ss,detach:Cs,find:As,findAll:Fs,findAllComponents:Is,findComponent:Bs,findContainer:Us,findParent:Vs,fire:Ws,get:Hs,insert:Qs,merge:$s,observe:lp,observeOnce:dp,off:mp,on:gp,once:vp,pop:xp,push:wp,render:Tp,reset:ig,resetPartial:pg,resetTemplate:ug,reverse:cg,set:lg,shift:dg,sort:fg,splice:hg,subtract:mg,teardown:gg,toggle:bg,toHTML:yg,toHtml:yg,unrender:_g,unshift:wg,update:kg,updateModel:Eg},Pg=function(t,e,n){return n||Wi(t,e)?function(){var n,a="_super"in this,r=this._super;return this._super=e,n=t.apply(this,arguments),a&&(this._super=r),n}:t},Ag=Hi,Og=$i,Tg=function(t){var e,n,a={};return t&&(e=t._ractive)?(a.ractive=e.root,a.keypath=e.keypath.str,a.index={},(n=Oc(e.proxy.parentFragment))&&(a.index=Oc.resolve(n)),a):a};ng=function(t){return this instanceof ng?void Om(this,t):new ng(t)},ag={DEBUG:{writable:!0,value:!0},DEBUG_PROMISES:{writable:!0,value:!0},extend:{value:Og},getNodeInfo:{value:Tg},parse:{value:Hp},Promise:{value:us},svg:{value:ao},magic:{value:eo},VERSION:{value:"0.7.3"},adaptors:{writable:!0,value:{}},components:{writable:!0,value:{}},decorators:{writable:!0,value:{}},easing:{writable:!0,value:po},events:{writable:!0,value:{}},interpolators:{writable:!0,value:qo},partials:{writable:!0,value:{}},transitions:{writable:!0,value:{}}},Co(ng,ag),ng.prototype=a(Cg,so),ng.prototype.constructor=ng,ng.defaults=ng.prototype;var Rg="function";if(typeof Date.now!==Rg||typeof String.prototype.trim!==Rg||typeof Object.keys!==Rg||typeof Array.prototype.indexOf!==Rg||typeof Array.prototype.forEach!==Rg||typeof Array.prototype.map!==Rg||typeof Array.prototype.filter!==Rg||"undefined"!=typeof window&&typeof window.addEventListener!==Rg)throw Error("It looks like you're attempting to use Ractive.js in an older browser. You'll need to use one of the 'legacy builds' in order to continue - see http://docs.ractivejs.org/latest/legacy-builds for more information.");var Mg=ng;return Mg})},{}],342:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.observe("value",function(e,n,a){var r=t.get(),i=r.min,o=r.max,s=Math.clamp(i,o,e);t.animate("percentage",Math.round((s-i)/(o-i)*100))})}}}(r),r.exports.template={v:3,t:[" ",{p:[13,1,293],t:7,e:"div",a:{"class":"bar"},f:[{p:[14,3,313],t:7,e:"div",a:{"class":["barFill ",{t:2,r:"state",p:[14,23,333]}],style:["width: ",{t:2,r:"percentage",p:[14,48,358]},"%"]}}," ",{p:[15,3,384],t:7,e:"span",a:{"class":"barText"},f:[{t:16,p:[15,25,406]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],343:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(481),a=t(480);e.exports={computed:{clickable:function(){return!this.get("enabled")||this.get("state")&&"toggle"!=this.get("state")?!1:!0},enabled:function(){return this.get("config.status")===n.UI_INTERACTIVE?!0:!1},styles:function(){var t="";if(this.get("class")&&(t+=" "+this.get("class")),this.get("tooltip-side")&&(t=" tooltip-"+this.get("tooltip-side")),this.get("grid")&&(t+=" gridable"),this.get("enabled")){var e=this.get("state"),n=this.get("style");return e?"inactive "+e+" "+t:"active normal "+n+" "+t}return"inactive disabled "+t}},oninit:function(){var t=this;this.on("press",function(e){var n=t.get(),r=n.action,i=n.params;(0,a.act)(t.get("config.ref"),r,i),e.node.blur()})},data:{iconStackToHTML:function(t){var e="",n=t.split(",");if(n.length){e+='';for(var a=n,r=Array.isArray(a),i=0,a=r?a:a[Symbol.iterator]();;){var o;if(r){if(i>=a.length)break;o=a[i++]}else{if(i=a.next(),i.done)break;o=i.value}var s=o,p=/([\w\-]+)\s*(\dx)/g,u=p.exec(s),c=u[1],l=u[2];e+=''}}return e&&(e+=""),e}}}}(r),r.exports.template={v:3,t:[" ",{p:[70,1,1950],t:7,e:"span",a:{"class":["button ",{t:2,r:"styles",p:[70,21,1970]}],unselectable:"on","data-tooltip":[{t:2,r:"tooltip",p:[73,17,2052]}]},m:[{t:4,f:["tabindex='0'"],r:"clickable",p:[72,3,2004]}],v:{"mouseover-mousemove":"hover",mouseleave:"unhover","click-enter":{n:[{t:4,f:["press"],r:"clickable",p:[76,19,2142]}],d:[]}},f:[{t:4,f:[{p:[78,5,2188],t:7,e:"i",a:{"class":["fa fa-",{t:2,r:"icon",p:[78,21,2204]}]}}],n:50,r:"icon",p:[77,3,2171]}," ",{t:4,f:[{t:3,x:{r:["iconStackToHTML","icon_stack"],s:"_0(_1)"},p:[81,6,2255]}],n:50,r:"icon_stack",p:[80,3,2231]}," ",{t:16,p:[83,3,2301]}]}]},e.exports=a.extend(r.exports)},{341:341,480:480,481:481}],344:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"display"},f:[{t:4,f:[{p:[3,5,42],t:7,e:"header",f:[{p:[4,7,57],t:7,e:"h3",f:[{t:2,r:"title",p:[4,11,61]}]}," ",{t:4,f:[{p:[6,9,105],t:7,e:"div",a:{"class":"buttonRight"},f:[{t:16,n:"button",p:[6,34,130]}]}],n:50,r:"button",p:[5,7,82]}]}],n:50,r:"title",p:[2,3,24]}," ",{p:[10,3,193],t:7,e:"article",f:[{t:16,p:[11,5,207]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],345:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.on("clear",function(){t.set("value",""),t.find("input").focus()})}}}(r),r.exports.template={v:3,t:[" ",{p:[12,1,159],t:7,e:"input",a:{type:"text",value:[{t:2,r:"value",p:[12,27,185]}],placeholder:[{t:2,r:"placeholder",p:[12,51,209]}]}}," ",{p:[13,1,228],t:7,e:"ui-button",a:{icon:"refresh"},v:{press:"clear"}}]},e.exports=a.extend(r.exports)},{341:341}],346:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";e.exports={data:{graph:t(338),xaccessor:function(t){return t.x},yaccessor:function(t){return t.y}},computed:{size:function(){var t=this.get("points");return t[0].length},scale:function(){var t=this.get("points");return Math.max.apply(Math,Array.map(t,function(t){return Math.max.apply(Math,Array.map(t,function(t){return t.y}))}))},xaxis:function(){var t=this.get("xinc"),e=this.get("size");return Array.from(Array(e).keys()).filter(function(e){return e&&e%t==0})},yaxis:function(){var t=this.get("yinc"),e=this.get("scale");return Array.from(Array(t).keys()).map(function(t){return Math.round(e*(++t/100)*10)})}},oninit:function(){var t=this;this.on({enter:function(t){this.set("selected",t.index.count)},exit:function(t){this.set("selected")}}),window.addEventListener("resize",function(e){t.set("width",t.el.clientWidth)})},onrender:function(){this.set("width",this.el.clientWidth)}}}(r),r.exports.template={v:3,t:[" ",{p:[47,1,1223],t:7,e:"svg",a:{"class":"linegraph",width:"100%",height:[{t:2,x:{r:["height"],s:"_0+10"},p:[47,45,1267]}]},f:[{p:[48,3,1287],t:7,e:"g",a:{transform:"translate(0, 5)"},f:[{t:4,f:[{t:4,f:[{p:[51,9,1454],t:7,e:"line",a:{x1:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[51,19,1464]}],x2:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[51,38,1483]}],y1:"0",y2:[{t:2,r:"height",p:[51,64,1509]}],stroke:"darkgray"}}," ",{t:4,f:[{p:[53,11,1583],t:7,e:"text",a:{x:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[53,20,1592]}],y:[{t:2,x:{r:["height"],s:"_0-5"},p:[53,38,1610]}],"text-anchor":"middle",fill:"white"},f:[{t:2,x:{r:["size",".","xfactor"],s:"(_0-_1)*_2"},p:[53,88,1660]}," ",{t:2,r:"xunit",p:[53,113,1685]}]}],n:50,x:{r:["@index"],s:"_0%2==0"},p:[52,9,1549]}],n:52,r:"xaxis",p:[50,7,1430]}," ",{t:4,f:[{p:[57,9,1764],t:7,e:"line",a:{x1:"0",x2:[{t:2,r:"width",p:[57,26,1781]}],y1:[{t:2,x:{r:["yscale","."],s:"_0(_1)"},p:[57,41,1796]}],y2:[{t:2,x:{r:["yscale","."],s:"_0(_1)"},p:[57,60,1815]}],stroke:"darkgray"}}," ",{p:[58,9,1858],t:7,e:"text",a:{x:"0",y:[{t:2,x:{r:["yscale","."],s:"_0(_1)-5"},p:[58,24,1873]}],"text-anchor":"begin",fill:"white"},f:[{t:2,x:{r:[".","yfactor"],s:"_0*_1"},p:[58,76,1925]}," ",{t:2,r:"yunit",p:[58,92,1941]}]}],n:52,r:"yaxis",p:[56,7,1740]}," ",{t:4,f:[{p:[61,9,2011],t:7,e:"path",a:{d:[{t:2,x:{r:["area.path"],s:"_0.print()"},p:[61,18,2020]}],fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[61,47,2049]}],opacity:"0.1"}}],n:52,i:"curve",r:"curves",p:[60,7,1980]}," ",{t:4,f:[{p:[64,9,2137],t:7,e:"path",a:{d:[{t:2,x:{r:["line.path"],s:"_0.print()"},p:[64,18,2146]}],stroke:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[64,49,2177]}],fill:"none"}}],n:52, -i:"curve",r:"curves",p:[63,7,2106]}," ",{t:4,f:[{t:4,f:[{p:[68,11,2308],t:7,e:"circle",a:{transform:["translate(",{t:2,r:".",p:[68,40,2337]},")"],r:[{t:2,x:{r:["selected","count"],s:"_0==_1?10:4"},p:[68,51,2348]}],fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[68,89,2386]}]},v:{mouseenter:"enter",mouseleave:"exit"}}],n:52,i:"count",x:{r:["line.path"],s:"_0.points()"},p:[67,9,2263]}],n:52,i:"curve",r:"curves",p:[66,7,2232]}," ",{t:4,f:[{t:4,f:[{t:4,f:[{p:[74,13,2605],t:7,e:"text",a:{transform:["translate(",{t:2,r:".",p:[74,40,2632]},") ",{t:2,x:{r:["count","size"],s:'_0<=_1/2?"translate(15, 4)":"translate(-15, 4)"'},p:[74,47,2639]}],"text-anchor":[{t:2,x:{r:["count","size"],s:'_0<=_1/2?"start":"end"'},p:[74,126,2718]}],fill:"white"},f:[{t:2,x:{r:["count","item","yfactor"],s:"_1[_0].y*_2"},p:[75,15,2787]}," ",{t:2,r:"yunit",p:[75,43,2815]}," @ ",{t:2,x:{r:["size","count","item","xfactor"],s:"(_0-_2[_1].x)*_3"},p:[75,55,2827]}," ",{t:2,r:"xunit",p:[75,92,2864]}]}],n:50,x:{r:["selected","count"],s:"_0==_1"},p:[73,11,2566]}],n:52,i:"count",x:{r:["line.path"],s:"_0.points()"},p:[72,9,2521]}],n:52,i:"curve",r:"curves",p:[71,7,2490]}," ",{t:4,f:[{p:[81,9,2983],t:7,e:"g",a:{transform:["translate(",{t:2,x:{r:["width","curves.length","@index"],s:"(_0/(_1+1))*(_2+1)"},p:[81,33,3007]},", 10)"]},f:[{p:[82,11,3073],t:7,e:"circle",a:{r:"4",fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[82,31,3093]}]}}," ",{p:[83,11,3124],t:7,e:"text",a:{x:"8",y:"4",fill:"white"},f:[{t:2,rx:{r:"legend",m:[{t:30,n:"curve"}]},p:[83,42,3155]}]}]}],n:52,i:"curve",r:"curves",p:[80,7,2952]}],x:{r:["graph","points","xaccessor","yaccessor","width","height"],s:"_0({data:_1,xaccessor:_2,yaccessor:_3,width:_4,height:_5})"},p:[49,5,1323]}]}]}]},e.exports=a.extend(r.exports)},{338:338,341:341}],347:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"notice"},f:[{t:16,p:[2,3,23]}]}]},e.exports=a.extend(r.exports)},{341:341}],348:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(480),a=t(482);e.exports={oninit:function(){var t=this,e=a.resize.bind(this),r=function(){return t.set({resize:!1,x:null,y:null})};this.observe("config.fancy",function(a,i,o){(0,n.winset)(t.get("config.window"),"can-resize",!a),a?(document.addEventListener("mousemove",e),document.addEventListener("mouseup",r)):(document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",r))}),this.on("resize",function(){return t.toggle("resize")})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[28,3,739],t:7,e:"div",a:{"class":"resize"},v:{mousedown:"resize"}}],n:50,r:"config.fancy",p:[27,1,716]}]},e.exports=a.extend(r.exports)},{341:341,480:480,482:482}],349:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"section",a:{"class":[{t:4,f:["candystripe"],r:"candystripe",p:[1,17,16]}]},f:[{t:4,f:[{p:[3,5,82],t:7,e:"span",a:{"class":"label",style:[{t:4,f:["color:",{t:2,r:"labelcolor",p:[3,53,130]}],r:"labelcolor",p:[3,32,109]}]},f:[{t:2,r:"label",p:[3,84,161]},":"]}],n:50,r:"label",p:[2,3,64]}," ",{t:4,f:[{t:16,p:[6,5,210]}],n:50,r:"nowrap",p:[5,3,191]},{t:4,n:51,f:[{p:[8,5,235],t:7,e:"div",a:{"class":"content",style:[{t:4,f:["float:right;"],r:"right",p:[8,33,263]}]},f:[{t:16,p:[9,7,304]}]}],r:"nowrap"}]}]},e.exports=a.extend(r.exports)},{341:341}],350:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"subdisplay"},f:[{t:4,f:[{p:[3,5,45],t:7,e:"header",f:[{p:[4,7,60],t:7,e:"h4",f:[{t:2,r:"title",p:[4,11,64]}]}," ",{t:4,f:[{t:16,n:"button",p:[5,21,99]}],n:50,r:"button",p:[5,7,85]}]}],n:50,r:"title",p:[2,3,27]}," ",{p:[8,3,149],t:7,e:"article",f:[{t:16,p:[9,5,163]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],351:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.set("active",this.findComponent("tab").get("name")),this.on("switch",function(e){t.set("active",e.node.textContent.trim())}),this.observe("active",function(e,n,a){for(var r=t.findAllComponents("tab"),i=Array.isArray(r),o=0,r=i?r:r[Symbol.iterator]();;){var s;if(i){if(o>=r.length)break;s=r[o++]}else{if(o=r.next(),o.done)break;s=o.value}var p=s;p.set("shown",p.get("name")===e)}})}}}(r),r.exports.template={v:3,t:[" "," ",{p:[20,1,505],t:7,e:"header",f:[{t:4,f:[{p:[22,5,535],t:7,e:"ui-button",a:{pane:[{t:2,r:".",p:[22,22,552]}]},v:{press:"switch"},f:[{t:2,r:".",p:[22,47,577]}]}],n:52,r:"tabs",p:[21,3,516]}]}," ",{p:[25,1,617],t:7,e:"ui-display",f:[{t:8,r:"content",p:[26,3,632]}]}]},r.exports.components=r.exports.components||{};var i={tab:t(352)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,352:352}],352:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:16,p:[2,3,16]}],n:50,r:"shown",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],353:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(481),a=t(480),r=t(482);e.exports={computed:{visualStatus:function(){switch(this.get("config.status")){case n.UI_INTERACTIVE:return"good";case n.UI_UPDATE:return"average";case n.UI_DISABLED:return"bad";default:return"bad"}}},oninit:function(){var t=this,e=r.drag.bind(this),n=function(e){return t.set({drag:!1,x:null,y:null})};this.observe("config.fancy",function(r,i,o){(0,a.winset)(t.get("config.window"),"titlebar",!r&&t.get("config.titlebar")),r?(document.addEventListener("mousemove",e),document.addEventListener("mouseup",n)):(document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",n))}),this.on({drag:function(){this.toggle("drag")},close:function(){(0,a.winset)(this.get("config.window"),"is-visible",!1),window.location.href=(0,a.href)({command:"uiclose "+this.get("config.ref")},"winset")},minimize:function(){(0,a.winset)(this.get("config.window"),"is-minimized",!0)}})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[50,3,1391],t:7,e:"header",a:{"class":"titlebar"},v:{mousedown:"drag"},f:[{p:[51,5,1441],t:7,e:"i",a:{"class":["statusicon fa fa-eye fa-2x ",{t:2,r:"visualStatus",p:[51,42,1478]}]}}," ",{p:[52,5,1505],t:7,e:"span",a:{"class":"title"},f:[{t:16,p:[52,25,1525]}]}," ",{t:4,f:[{p:[54,7,1573],t:7,e:"i",a:{"class":"minimize fa fa-minus fa-2x"},v:{click:"minimize"}}," ",{p:[55,7,1642],t:7,e:"i",a:{"class":"close fa fa-close fa-2x"},v:{click:"close"}}],n:50,r:"config.fancy",p:[53,5,1546]}]}],n:50,r:"config.titlebar",p:[49,1,1365]}]},e.exports=a.extend(r.exports)},{341:341,480:480,481:481,482:482}],354:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";var e=[11,10,9,8];t.exports={data:{userAgent:navigator.userAgent},computed:{ie:function(){if(document.documentMode)return document.documentMode;for(var t in e){var n=document.createElement("div");if(n.innerHTML="",n.getElementsByTagName("span").length)return t}}},oninit:function(){var t=this;this.on("debug",function(){return t.toggle("debug")})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[27,3,636],t:7,e:"ui-notice",f:[{p:[28,5,652],t:7,e:"span",f:["You have an old (IE",{t:2,r:"ie",p:[28,30,677]},"), end-of-life (click 'EOL Info' for more information) version of Internet Explorer installed."]},{p:[28,137,784],t:7,e:"br"}," ",{p:[29,5,794],t:7,e:"span",f:["To upgrade, click 'Upgrade IE' to download IE11 from Microsoft."]},{p:[29,81,870],t:7,e:"br"}," ",{p:[30,5,880],t:7,e:"span",f:["If you are unable to upgrade directly, click 'IE VMs' to download a VM with IE11 or Edge from Microsoft."]},{p:[30,122,997],t:7,e:"br"}," ",{p:[31,5,1007],t:7,e:"span",f:["Otherwise, click 'No Frills' below to disable potentially incompatible features (and this message)."]}," ",{p:[32,5,1124],t:7,e:"hr"}," ",{p:[33,5,1134],t:7,e:"ui-button",a:{icon:"close",action:"tgui:nofrills"},f:["No Frills"]}," ",{p:[34,5,1207],t:7,e:"ui-button",a:{icon:"internet-explorer",action:"tgui:link",params:'{"url": "http://windows.microsoft.com/en-us/internet-explorer/download-ie"}'},f:["Upgrade IE"]}," ",{p:[36,5,1381],t:7,e:"ui-button",a:{icon:"edge",action:"tgui:link",params:'{"url": "https://dev.windows.com/en-us/microsoft-edge/tools/vms"}'},f:["IE VMs"]}," ",{p:[38,5,1528],t:7,e:"ui-button",a:{icon:"info",action:"tgui:link",params:'{"url": "https://support.microsoft.com/en-us/lifecycle#gp/Microsoft-Internet-Explorer"}'},f:["EOL Info"]}," ",{p:[40,5,1699],t:7,e:"ui-button",a:{icon:"bug"},v:{press:"debug"},f:["Debug Info"]}," ",{t:4,f:[{p:[42,7,1785],t:7,e:"hr"}," ",{p:[43,7,1797],t:7,e:"span",f:["Detected: IE",{t:2,r:"ie",p:[43,25,1815]}]},{p:[43,38,1828],t:7,e:"br"}," ",{p:[44,7,1840],t:7,e:"span",f:["User Agent: ",{t:2,r:"userAgent",p:[44,25,1858]}]}],n:50,r:"debug",p:[41,5,1765]}]}],n:50,x:{r:["config.fancy","ie"],s:"_0&&_1&&_1<11"},p:[26,1,596]}]},e.exports=a.extend(r.exports)},{341:341}],355:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},shockState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[22,1,327],t:7,e:"ui-display",a:{title:"Power Status"},f:[{p:[23,2,362],t:7,e:"ui-section",a:{label:"Main"},f:[{p:[24,3,390],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.power.main"],s:"_0(_1)"},p:[24,16,403]}]},f:[{t:2,x:{r:["data.power.main"],s:'_0?"Online":"Offline"'},p:[24,49,436]}]}," ",{t:4,f:["[ ",{p:[26,6,542],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.main_1","data.wires.main_2"],s:"!_0||!_1"},p:[25,3,488]},{t:4,n:51,f:[{t:4,f:["[ ",{t:2,r:"data.power.main_timeleft",p:[29,7,646]}," seconds left ]"],n:50,x:{r:["data.power.main_timeleft"],s:"_0>0"},p:[28,4,603]}],x:{r:["data.wires.main_1","data.wires.main_2"],s:"!_0||!_1"}}," ",{p:[32,3,713],t:7,e:"div",a:{style:"float:right"},f:[{p:[33,4,742],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"disrupt-main",state:[{t:2,x:{r:["data.power.main"],s:'_0?null:"disabled"'},p:[33,63,801]}]},f:["Disrupt"]}]}]}," ",{p:[36,2,887],t:7,e:"ui-section",a:{label:"Backup"},f:[{p:[37,3,917],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.power.backup"],s:"_0(_1)"},p:[37,16,930]}]},f:[{t:2,x:{r:["data.power.backup"],s:'_0?"Online":"Offline"'},p:[37,51,965]}]}," ",{t:4,f:["[ ",{p:[39,6,1077],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.backup_1","data.wires.backup_2"],s:"!_0||!_1"},p:[38,3,1019]},{t:4,n:51,f:[{t:4,f:["[ ",{t:2,r:"data.power.backup_timeleft",p:[42,7,1183]}," seconds left ]"],n:50,x:{r:["data.power.backup_timeleft"],s:"_0>0"},p:[41,4,1138]}],x:{r:["data.wires.backup_1","data.wires.backup_2"],s:"!_0||!_1"}}," ",{p:[45,3,1252],t:7,e:"div",a:{style:"float:right"},f:[{p:[46,4,1281],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"disrupt-backup",state:[{t:2,x:{r:["data.power.backup"],s:'_0?null:"disabled"'},p:[46,65,1342]}]},f:["Disrupt"]}]}]}," ",{p:[49,2,1430],t:7,e:"ui-section",a:{label:"Electrify"},f:[{p:[50,3,1463],t:7,e:"span",a:{"class":[{t:2,x:{r:["shockState","data.shock"],s:"_0(_1)"},p:[50,16,1476]}]},f:[{t:2,x:{r:["data.shock"],s:'_0==2?"Safe":"Electrified"'},p:[50,44,1504]}]}," ",{t:4,f:["[ ",{p:[52,6,1589],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.shock"],s:"!_0"},p:[51,3,1558]},{t:4,n:51,f:[{t:4,f:["[ ",{p:[55,7,1688],t:7,e:"span",a:{"class":"bad"},f:[{t:2,r:"data.shock_timeleft",p:[55,25,1706]}," seconds left"]}," ]"],n:50,x:{r:["data.shock_timeleft"],s:"_0>0"},p:[54,4,1650]}," ",{t:4,f:["[ ",{p:[58,7,1806],t:7,e:"span",a:{"class":"bad"},f:["Permanent"]}," ]"],n:50,x:{r:["data.shock_timeleft"],s:"_0==-1"},p:[57,4,1766]}],x:{r:["data.wires.shock"],s:"!_0"}}," ",{p:[61,3,1866],t:7,e:"div",a:{style:"float:right"},f:[{p:[62,4,1895],t:7,e:"ui-button",a:{icon:"wrench",action:"shock-restore",state:[{t:2,x:{r:["data.wires.shock","data.shock"],s:'_0&&_1==0?null:"disabled"'},p:[62,59,1950]}]},f:["Restore"]}," ",{p:[63,4,2032],t:7,e:"ui-button",a:{icon:"bolt",action:"shock-temp",state:[{t:2,x:{r:["data.wires.shock"],s:"!_0"},p:[63,54,2082]}]},f:["Set (Temporary)"]}," ",{p:[64,4,2136],t:7,e:"ui-button",a:{icon:"bolt",action:"shock-perm",state:[{t:2,x:{r:["data.wires.shock"],s:"!_0"},p:[64,53,2185]}]},f:["Set (Permanent)"]}]}]}]}," ",{p:[68,1,2274],t:7,e:"ui-display",a:{title:"Access & Door Control"},f:[{p:[69,2,2318],t:7,e:"ui-section",a:{label:"ID Scan"},f:[{t:4,f:["[ ",{p:[71,6,2385],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[70,3,2349]}," ",{p:[73,3,2444],t:7,e:"div",a:{style:"float:right"},f:[{p:[74,4,2473],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[74,22,2491]}],icon:"power-off",action:"idscan-on",style:[{t:2,x:{r:["data.id_scanner"],s:'_0?"selected":""'},p:[74,93,2562]}]},f:["Enabled"]}," ",{p:[75,4,2624],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[75,22,2642]}],icon:"close",action:"idscan-off",style:[{t:2,x:{r:["data.id_scanner"],s:'_0?"":"selected"'},p:[75,90,2710]}]},f:["Disabled"]}]}]}," ",{p:[78,2,2795],t:7,e:"ui-section",a:{label:"Emergency Access"},f:[{p:[79,3,2835],t:7,e:"div",a:{style:"float:right"},f:[{p:[80,4,2864],t:7,e:"ui-button",a:{icon:"power-off",action:"emergency-on",style:[{t:2,x:{r:["data.emergency"],s:'_0?"selected":""'},p:[80,61,2921]}]},f:["Enabled"]}," ",{p:[81,4,2982],t:7,e:"ui-button",a:{icon:"close",action:"emergency-off",style:[{t:2,x:{r:["data.emergency"],s:'_0?"":"selected"'},p:[81,58,3036]}]},f:["Disabled"]}]}]}," ",{p:[84,2,3120],t:7,e:"br"}," ",{p:[85,2,3128],t:7,e:"ui-section",a:{label:"Door bolts"},f:[{t:4,f:["[ ",{p:[87,6,3193],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.bolts"],s:"!_0"},p:[86,3,3162]}," ",{p:[89,3,3252],t:7,e:"div",a:{style:"float:right"},f:[{p:[90,4,3281],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.bolts"],s:"!_0"},p:[90,22,3299]}],icon:"unlock",action:"bolt-raise",style:[{t:2,x:{r:["data.locked"],s:'_0?"":"selected"'},p:[90,85,3362]}]},f:["Raised"]}," ",{p:[91,4,3419],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.bolts"],s:"!_0"},p:[91,22,3437]}],icon:"lock",action:"bolt-drop",style:[{t:2,x:{r:["data.locked"],s:'_0?"selected":""'},p:[91,82,3497]}]},f:["Dropped"]}]}]}," ",{p:[94,2,3577],t:7,e:"ui-section",a:{label:"Door bolt lights"},f:[{t:4,f:["[ ",{p:[96,6,3649],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.lights"],s:"!_0"},p:[95,3,3617]}," ",{p:[98,3,3708],t:7,e:"div",a:{style:"float:right"},f:[{p:[99,4,3737],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.lights"],s:"!_0"},p:[99,22,3755]}],icon:"power-off",action:"light-on",style:[{t:2,x:{r:["data.lights"],s:'_0?"selected":""'},p:[99,88,3821]}]},f:["Enabled"]}," ",{p:[100,4,3879],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.lights"],s:"!_0"},p:[100,22,3897]}],icon:"close",action:"light-off",style:[{t:2,x:{r:["data.lights"],s:'_0?"":"selected"'},p:[100,85,3960]}]},f:["Disabled"]}]}]}," ",{p:[103,2,4041],t:7,e:"ui-section",a:{label:"Door force sensors"},f:[{t:4,f:["[ ",{p:[105,6,4113],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.safe"],s:"!_0"},p:[104,3,4083]}," ",{p:[107,3,4172],t:7,e:"div",a:{style:"float:right"},f:[{p:[108,4,4201],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.safe"],s:"!_0"},p:[108,22,4219]}],icon:"power-off",action:"safe-on",style:[{t:2,x:{r:["data.safe"],s:'_0?"selected":""'},p:[108,85,4282]}]},f:["Enabled"]}," ",{p:[109,4,4338],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.safe"],s:"!_0"},p:[109,22,4356]}],icon:"close",action:"safe-off",style:[{t:2,x:{r:["data.safe"],s:'_0?"":"selected"'},p:[109,82,4416]}]},f:["Disabled"]}]}]}," ",{p:[112,2,4495],t:7,e:"ui-section",a:{label:"Door timing safety"},f:[{t:4,f:["[ ",{p:[114,6,4569],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.timing"],s:"!_0"},p:[113,3,4537]}," ",{p:[116,3,4628],t:7,e:"div",a:{style:"float:right"},f:[{p:[117,4,4657],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.timing"],s:"!_0"},p:[117,22,4675]}],icon:"power-off",action:"speed-on",style:[{t:2,x:{r:["data.speed"],s:'_0?"selected":""'},p:[117,88,4741]}]},f:["Enabled"]}," ",{p:[118,4,4798],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.timing"],s:"!_0"},p:[118,22,4816]}],icon:"close",action:"speed-off",style:[{t:2,x:{r:["data.speed"],s:'_0?"":"selected"'},p:[118,85,4879]}]},f:["Disabled"]}]}]}," ",{p:[121,2,4959],t:7,e:"br"}," ",{p:[122,2,4967],t:7,e:"ui-section",a:{label:"Door control"},f:[{t:4,f:["[ ",{p:[124,6,5043],t:7,e:"span",a:{"class":"bad"},f:["Door is ",{t:2,x:{r:["data.locked","data.welded"],s:'(_0?"bolted":"")+(_0&&_1?" and ":"")+(_1?"welded":"")'},p:[124,32,5069]}]}," ]"],n:50,x:{r:["data.locked","data.welded"],s:"_0||_1"},p:[123,3,5003]}," ",{p:[126,3,5202],t:7,e:"div",a:{style:"float:right"},f:[{p:[127,4,5231],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.locked","data.welded","data.opened"],s:'(_0||_1)||(_2&&"disabled")'},p:[127,22,5249]}],icon:"sign-out",action:"open-close"},f:["Open door"]}," ",{p:[128,4,5375],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.locked","data.welded","data.opened"],s:'(_0||_1)||(!_2&&"disabled")'},p:[128,22,5393]}],icon:"sign-in",action:"open-close"},f:["Close door"]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],356:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," "," "," ",{p:[7,1,261],t:7,e:"ui-notice",f:[{t:4,f:[{p:[9,5,304],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[10,7,346],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[10,24,363]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[10,75,414]}]}]}],n:50,r:"data.siliconUser",p:[8,3,275]},{t:4,n:51,f:[{p:[13,5,502],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[13,31,528]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[16,1,610],t:7,e:"status"}," ",{t:4,f:[{t:4,f:[{p:[19,7,701],t:7,e:"ui-display",a:{title:"Air Controls"},f:[{p:[20,9,743],t:7,e:"ui-section",f:[{p:[21,11,766],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"exclamation-triangle":"exclamation"'},p:[21,28,783]}],style:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"caution":null'},p:[21,98,853]}],action:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"reset":"alarm"'},p:[22,23,916]}]},f:["Area Atmosphere Alarm"]}]}," ",{p:[24,9,1022],t:7,e:"ui-section",f:[{p:[25,11,1045],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0==3?"exclamation-triangle":"exclamation"'},p:[25,28,1062]}],style:[{t:2,x:{r:["data.mode"],s:'_0==3?"danger":null'},p:[25,96,1130]}],action:"mode",params:['{"mode": ',{t:2,x:{r:["data.mode"],s:"_0==3?1:3"},p:[26,44,1211]},"}"]},f:["Panic Siphon"]}]}," ",{p:[28,9,1295],t:7,e:"br"}," ",{p:[29,9,1309],t:7,e:"ui-section",f:[{p:[30,11,1332],t:7,e:"ui-button",a:{icon:"sign-out",action:"tgui:view",params:'{"screen": "vents"}'},f:["Vent Controls"]}]}," ",{p:[32,9,1463],t:7,e:"ui-section",f:[{p:[33,11,1486],t:7,e:"ui-button",a:{icon:"filter",action:"tgui:view",params:'{"screen": "scrubbers"}'},f:["Scrubber Controls"]}]}," ",{p:[35,9,1623],t:7,e:"ui-section",f:[{p:[36,11,1646],t:7,e:"ui-button",a:{icon:"cog",action:"tgui:view",params:'{"screen": "modes"}'},f:["Operating Mode"]}]}," ",{p:[38,9,1773],t:7,e:"ui-section",f:[{p:[39,11,1796],t:7,e:"ui-button",a:{icon:"bar-chart",action:"tgui:view",params:'{"screen": "thresholds"}'},f:["Alarm Thresholds"]}]}]}],n:50,x:{r:["config.screen"],s:'_0=="home"'},p:[18,3,663]},{t:4,n:51,f:[{t:4,n:50,x:{r:["config.screen"],s:'_0=="vents"'},f:[{p:[43,5,1990],t:7,e:"vents"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&(_0=="scrubbers")'},f:[" ",{p:[45,5,2045],t:7,e:"scrubbers"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&((!(_0=="scrubbers"))&&(_0=="modes"))'},f:[" ",{p:[47,5,2100],t:7,e:"modes"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&((!(_0=="scrubbers"))&&((!(_0=="modes"))&&(_0=="thresholds")))'},f:[" ",{p:[49,5,2156],t:7,e:"thresholds"}]}],x:{r:["config.screen"],s:'_0=="home"'}}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[17,1,620]}]},r.exports.components=r.exports.components||{};var i={vents:t(362),modes:t(358),thresholds:t(361),status:t(360),scrubbers:t(359)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,358:358,359:359,360:360,361:361,362:362}],357:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-button",a:{icon:"arrow-left",action:"tgui:view",params:'{"screen": "home"}'},f:["Back"]}]},e.exports=a.extend(r.exports)},{341:341}],358:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,111],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Operating Modes",button:0},f:[" ",{t:4,f:[{p:[8,5,161],t:7,e:"ui-section",f:[{p:[9,7,180],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["selected"],s:'_0?"check-square-o":"square-o"'},p:[9,24,197]}],state:[{t:2,x:{r:["selected","danger"],s:'_0?_1?"danger":"selected":null'},p:[10,16,258]}],action:"mode",params:['{"mode": ',{t:2,r:"mode",p:[11,40,351]},"}"]},f:[{t:2,r:"name",p:[11,51,362]}]}]}],n:52,r:"data.modes",p:[7,3,136]}]}]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],359:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," ",{p:{button:[{p:[6,5,180],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Scrubber Controls",button:0},f:[" ",{t:4,f:[{p:[9,5,234],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"long_name",p:[9,27,256]}]},f:[{p:[10,7,278],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[11,9,313],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["power"],s:'_0?"power-off":"close"'},p:[11,26,330]}],style:[{t:2,x:{r:["power"],s:'_0?"selected":null'},p:[11,68,372]}],action:"power",params:['{"id_tag": "',{t:2,r:"id_tag",p:[12,46,448]},'", "val": ',{t:2,x:{r:["power"],s:"+!_0"},p:[12,66,468]},"}"]},f:[{t:2,x:{r:["power"],s:'_0?"On":"Off"'},p:[12,80,482]}]}]}," ",{p:[14,7,545],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[15,9,579],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["scrubbing"],s:'_0?"filter":"sign-in"'},p:[15,26,596]}],style:[{t:2,x:{r:["scrubbing"],s:'_0?null:"danger"'},p:[15,71,641]}],action:"scrubbing",params:['{"id_tag": "',{t:2,r:"id_tag",p:[16,50,723]},'", "val": ',{t:2,x:{r:["scrubbing"],s:"+!_0"},p:[16,70,743]},"}"]},f:[{t:2,x:{r:["scrubbing"],s:'_0?"Scrubbing":"Siphoning"'},p:[16,88,761]}]}]}," ",{p:[18,7,841],t:7,e:"ui-section",a:{label:"Range"},f:[{p:[19,9,876],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["widenet"],s:'_0?"expand":"compress"'},p:[19,26,893]}],style:[{t:2,x:{r:["widenet"],s:'_0?"selected":null'},p:[19,70,937]}],action:"widenet",params:['{"id_tag": "',{t:2,r:"id_tag",p:[20,48,1017]},'", "val": ',{t:2,x:{r:["widenet"],s:"+!_0"},p:[20,68,1037]},"}"]},f:[{t:2,x:{r:["widenet"],s:'_0?"Expanded":"Normal"'},p:[20,84,1053]}]}]}," ",{p:[22,7,1127],t:7,e:"ui-section",a:{label:"Filters"},f:[{p:[23,9,1164],t:7,e:"filters"}]}]}],n:52,r:"data.scrubbers",p:[8,3,205]},{t:4,n:51,f:[{p:[27,5,1231],t:7,e:"span",a:{"class":"bad"},f:["Error: No scrubbers connected."]}],r:"data.scrubbers"}]}]},r.exports.components=r.exports.components||{};var i={filters:t(456),back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357,456:456}],360:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Air Status"},f:[{t:4,f:[{t:4,f:[{p:[4,7,107],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[4,26,126]}]},f:[{p:[5,6,142],t:7,e:"span",a:{"class":[{t:2,x:{r:["danger_level"],s:'_0==2?"bad":_0==1?"average":"good"'},p:[5,19,155]}]},f:[{t:2,x:{r:["value"],s:"Math.fixed(_0,2)"},p:[6,5,232]},{t:2,r:"unit",p:[6,29,256]}]}]}],n:52,r:"adata.environment_data",p:[3,5,68]}," ",{p:[10,5,313],t:7,e:"ui-section",a:{label:"Local Status"},f:[{p:[11,7,353],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.danger_level"],s:'_0==2?"bad bold":_0==1?"average bold":"good"'},p:[11,20,366]}]},f:[{t:2,x:{r:["data.danger_level"],s:'_0==2?"Danger (Internals Required)":_0==1?"Caution":"Optimal"'},p:[12,6,464]}]}]}," ",{p:[15,5,605],t:7,e:"ui-section",a:{label:"Area Status"},f:[{p:[16,7,644],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.atmos_alarm","data.fire_alarm"],s:'_0||_1?"bad bold":"good"'},p:[16,20,657]}]},f:[{t:2,x:{r:["data.atmos_alarm","fire_alarm"],s:'_0?"Atmosphere Alarm":_1?"Fire Alarm":"Nominal"'},p:[17,8,728]}]}]}],n:50,r:"data.environment_data",p:[2,3,34]},{t:4,n:51,f:[{p:[21,5,856],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[22,7,891],t:7,e:"span",a:{"class":"bad bold"},f:["Cannot obtain air sample for analysis."]}]}],r:"data.environment_data"}," ",{t:4,f:[{p:[26,5,1015],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[27,7,1050],t:7,e:"span",a:{"class":"bad bold"},f:["Safety measures offline. Device may exhibit abnormal behavior."]}]}],n:50,r:"data.emagged",p:[25,3,990]}]}]},e.exports=a.extend(r.exports)},{341:341}],361:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.css=" th, td {\n padding-right: 16px;\n text-align: left;\n }",r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,112],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Alarm Thresholds",button:0},f:[" ",{p:[7,3,137],t:7,e:"table",f:[{p:[8,5,149],t:7,e:"thead",f:[{p:[8,12,156],t:7,e:"tr",f:[{p:[9,7,167],t:7,e:"th"}," ",{p:[10,7,183],t:7,e:"th",f:[{p:[10,11,187],t:7,e:"span",a:{"class":"bad"},f:["min2"]}]}," ",{p:[11,7,228],t:7,e:"th",f:[{p:[11,11,232],t:7,e:"span",a:{"class":"average"},f:["min1"]}]}," ",{p:[12,7,277],t:7,e:"th",f:[{p:[12,11,281],t:7,e:"span",a:{"class":"average"},f:["max1"]}]}," ",{p:[13,7,326],t:7,e:"th",f:[{p:[13,11,330],t:7,e:"span",a:{"class":"bad"},f:["max2"]}]}]}]}," ",{p:[15,5,387],t:7,e:"tbody",f:[{t:4,f:[{p:[16,32,426],t:7,e:"tr",f:[{p:[17,9,439],t:7,e:"th",f:[{t:3,r:"name",p:[17,13,443]}]}," ",{t:4,f:[{p:[18,27,485],t:7,e:"td",f:[{p:[19,11,500],t:7,e:"ui-button",a:{action:"threshold",params:['{"env": "',{t:2,r:"env",p:[19,58,547]},'", "var": "',{t:2,r:"val",p:[19,76,565]},'"}']},f:[{t:2,x:{r:["selected"],s:"Math.fixed(_0,2)"},p:[19,87,576]}]}]}],n:52,r:"settings",p:[18,9,467]}]}],n:52,r:"data.thresholds",p:[16,7,401]}]}," ",{p:[23,3,675],t:7,e:"table",f:[]}]}]}," "]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],362:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,109],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Vent Controls",button:0},f:[" ",{t:4,f:[{p:[8,5,159],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"long_name",p:[8,27,181]}]},f:[{p:[9,7,203],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[10,9,238],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["power"],s:'_0?"power-off":"close"'},p:[10,26,255]}],style:[{t:2,x:{r:["power"],s:'_0?"selected":null'},p:[10,68,297]}],action:"power",params:['{"id_tag": "',{t:2,r:"id_tag",p:[11,46,373]},'", "val": ',{t:2,x:{r:["power"],s:"+!_0"},p:[11,66,393]},"}"]},f:[{t:2,x:{r:["power"],s:'_0?"On":"Off"'},p:[11,80,407]}]}]}," ",{p:[13,7,470],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[14,9,504],t:7,e:"span",f:[{t:2,x:{r:["direction"],s:'_0=="release"?"Pressurizing":"Siphoning"'},p:[14,15,510]}]}]}," ",{p:[16,7,601],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[17,9,649],t:7,e:"ui-button",a:{icon:"sign-in",style:[{t:2,x:{r:["incheck"],s:'_0?"selected":null'},p:[17,42,682]}],action:"incheck",params:['{"id_tag": "',{t:2,r:"id_tag",p:[18,48,762]},'", "val": ',{t:2,r:"checks",p:[18,68,782]},"}"]},f:["Internal"]}," ",{p:[19,9,824],t:7,e:"ui-button",a:{icon:"sign-out",style:[{t:2,x:{r:["excheck"],s:'_0?"selected":null'},p:[19,43,858]}],action:"excheck",params:['{"id_tag": "',{t:2,r:"id_tag",p:[20,48,938]},'", "val": ',{t:2,r:"checks",p:[20,68,958]},"}"]},f:["External"]}]}," ",{t:4,f:[{p:[23,9,1042],t:7,e:"ui-section",a:{label:"Internal Target Pressure"},f:[{p:[24,11,1098],t:7,e:"ui-button",a:{icon:"pencil",action:"set_internal_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[25,33,1186]},'"}']},f:[{t:2,x:{r:["internal"],s:"Math.fixed(_0)"},p:[25,47,1200]}]}," ",{p:[26,11,1247],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["intdefault"],s:'_0?"disabled":null'},p:[26,44,1280]}],action:"reset_internal_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[27,33,1381]},'"}']},f:["Reset"]}]}],n:50,r:"incheck",p:[22,7,1018]}," ",{t:4,f:[{p:[31,11,1481],t:7,e:"ui-section",a:{label:"External Target Pressure"},f:[{p:[32,13,1539],t:7,e:"ui-button",a:{icon:"pencil",action:"set_external_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[33,35,1629]},'"}']},f:[{t:2,x:{r:["external"],s:"Math.fixed(_0)"},p:[33,49,1643]}]}," ",{p:[34,13,1692],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["extdefault"],s:'_0?"disabled":null'},p:[34,46,1725]}],action:"reset_external_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[35,35,1828]},'"}']},f:["Reset"]}]}],n:50,r:"excheck",p:[30,7,1455]}]}],n:52,r:"data.vents",p:[7,3,134]},{t:4,n:51,f:[{p:[40,5,1934],t:7,e:"span",a:{"class":"bad"},f:["Error: No vents connected."]}],r:"data.vents"}]}]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],363:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.css=" table {\n width: 100%;\n border-spacing: 2px;\n }\n th {\n text-align: left;\n }\n td {\n vertical-align: top;\n }\n td .button {\n margin-top: 4px\n }",r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-section",f:[{p:[3,5,32],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.oneAccess"],s:'_0?"unlock":"lock"'},p:[3,22,49]}],action:"one_access"},f:[{t:2,x:{r:["data.oneAccess"],s:'_0?"One":"All"'},p:[3,82,109]}," Required"]}," ",{p:[4,5,169],t:7,e:"ui-button",a:{icon:"refresh",action:"clear"},f:["Clear"]}]}," ",{p:[6,3,246],t:7,e:"hr"}," ",{p:[7,3,254],t:7,e:"table",f:[{p:[8,3,264],t:7,e:"thead",f:[{p:[9,4,275],t:7,e:"tr",f:[{t:4,f:[{p:[10,5,306],t:7,e:"th",f:[{p:[10,9,310],t:7,e:"span",a:{"class":"highlight bold"},f:[{t:2,r:"name",p:[10,38,339]}]}]}],n:52,r:"data.regions",p:[9,8,279]}]}]}," ",{p:[13,3,391],t:7,e:"tbody",f:[{p:[14,4,402],t:7,e:"tr",f:[{t:4,f:[{p:[15,5,433],t:7,e:"td",f:[{t:4,f:[{p:[16,11,466],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["req"],s:'_0?"check-square-o":"square-o"'},p:[16,28,483]}],style:[{t:2,x:{r:["req"],s:'_0?"selected":null'},p:[16,76,531]}],action:"set",params:['{"access": "',{t:2,r:"id",p:[17,46,605]},'"}']},f:[{t:2,r:"name",p:[17,56,615]}]}," ",{p:[18,9,644],t:7,e:"br"}],n:52,r:"accesses",p:[15,9,437]}]}],n:52,r:"data.regions",p:[14,8,406]}]}]}]}," ",{p:[23,2,709],t:7,e:"hr"}," ",{p:[24,2,716],t:7,e:"span",a:{"class":"highlight bold"},f:["Unrestricted Access:"]}," ",{p:[25,2,774],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&1?"check-square-o":"square-o"'},p:[25,19,791]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&1?"selected":null'},p:[25,88,860]}],action:"direc_set",params:'{"unres_direction": "1"}'},f:["North"]}," ",{p:[26,2,982],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&4?"check-square-o":"square-o"'},p:[26,19,999]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&4?"selected":null'},p:[26,88,1068]}],action:"direc_set",params:'{"unres_direction": "4"}'},f:["East"]}," ",{p:[27,2,1189],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&2?"check-square-o":"square-o"'},p:[27,19,1206]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&2?"selected":null' -},p:[27,88,1275]}],action:"direc_set",params:'{"unres_direction": "2"}'},f:["South"]}," ",{p:[28,2,1397],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&8?"check-square-o":"square-o"'},p:[28,19,1414]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&8?"selected":null'},p:[28,88,1483]}],action:"direc_set",params:'{"unres_direction": "8"}'},f:["West"]}]}," "]},e.exports=a.extend(r.exports)},{341:341}],364:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}}},computed:{malfAction:function(){switch(this.get("data.malfStatus")){case 1:return"hack";case 2:return"occupy";case 3:return"deoccupy"}},malfButton:function(){switch(this.get("data.malfStatus")){case 1:return"Override Programming";case 2:case 4:return"Shunt Core Process";case 3:return"Return to Main Core"}},malfIcon:function(){switch(this.get("data.malfStatus")){case 1:return"terminal";case 2:case 4:return"caret-square-o-down";case 3:return"caret-square-o-left"}},powerCellStatusState:function(){var t=this.get("data.powerCellStatus");return t>50?"good":t>25?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[46,2,1161],t:7,e:"ui-notice",f:[{p:[47,3,1175],t:7,e:"b",f:[{p:[47,6,1178],t:7,e:"h3",f:["SYSTEM FAILURE"]}]}," ",{p:[48,3,1208],t:7,e:"i",f:["I/O regulators malfunction detected! Waiting for system reboot..."]},{p:[48,75,1280],t:7,e:"br"}," Automatic reboot in ",{t:2,r:"data.failTime",p:[49,23,1307]}," seconds... ",{p:[50,3,1338],t:7,e:"ui-button",a:{icon:"refresh",action:"reboot"},f:["Reboot Now"]},{p:[50,67,1402],t:7,e:"br"},{p:[50,71,1406],t:7,e:"br"},{p:[50,75,1410],t:7,e:"br"}]}],n:50,r:"data.failTime",p:[45,1,1138]},{t:4,n:51,f:[{p:[53,2,1439],t:7,e:"ui-notice",f:[{t:4,f:[{p:[55,3,1481],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[56,5,1521],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[56,22,1538]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[56,73,1589]}]}]}],n:50,r:"data.siliconUser",p:[54,4,1454]},{t:4,n:51,f:[{p:[59,3,1674],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[59,29,1700]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[62,2,1785],t:7,e:"ui-display",a:{title:"Power Status"},f:[{p:[63,4,1822],t:7,e:"ui-section",a:{label:"Main Breaker"},f:[{t:4,f:[{p:[65,5,1903],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.isOperating"],s:'_0?"good":"bad"'},p:[65,18,1916]}]},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[65,57,1955]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[64,3,1858]},{t:4,n:51,f:[{p:[67,5,2013],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOperating"],s:'_0?"power-off":"close"'},p:[67,22,2030]}],style:[{t:2,x:{r:["data.isOperating"],s:'_0?"selected":null'},p:[67,75,2083]}],action:"breaker"},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[68,21,2145]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}," ",{p:[71,4,2223],t:7,e:"ui-section",a:{label:"External Power"},f:[{p:[72,3,2261],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.externalPower"],s:"_0(_1)"},p:[72,16,2274]}]},f:[{t:2,x:{r:["data.externalPower"],s:'_0==2?"Good":_0==1?"Low":"None"'},p:[72,52,2310]}]}]}," ",{p:[74,4,2417],t:7,e:"ui-section",a:{label:"Power Cell"},f:[{t:4,f:[{p:[76,5,2492],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.powerCellStatus",p:[76,38,2525]}],state:[{t:2,r:"powerCellStatusState",p:[76,71,2558]}]},f:[{t:2,x:{r:["adata.powerCellStatus"],s:"Math.fixed(_0)"},p:[76,97,2584]},"%"]}],n:50,x:{r:["data.powerCellStatus"],s:"_0!=null"},p:[75,3,2451]},{t:4,n:51,f:[{p:[78,5,2647],t:7,e:"span",a:{"class":"bad"},f:["Removed"]}],x:{r:["data.powerCellStatus"],s:"_0!=null"}}]}," ",{t:4,f:[{p:[82,3,2749],t:7,e:"ui-section",a:{label:"Charge Mode"},f:[{t:4,f:[{p:[84,4,2830],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.chargeMode"],s:'_0?"good":"bad"'},p:[84,17,2843]}]},f:[{t:2,x:{r:["data.chargeMode"],s:'_0?"Auto":"Off"'},p:[84,55,2881]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[83,5,2786]},{t:4,n:51,f:[{p:[86,4,2941],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.chargeMode"],s:'_0?"refresh":"close"'},p:[86,21,2958]}],style:[{t:2,x:{r:["data.chargeMode"],s:'_0?"selected":null'},p:[86,71,3008]}],action:"charge"},f:[{t:2,x:{r:["data.chargeMode"],s:'_0?"Auto":"Off"'},p:[87,22,3070]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}," [",{p:[90,6,3147],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.chargingStatus"],s:"_0(_1)"},p:[90,19,3160]}]},f:[{t:2,x:{r:["data.chargingStatus"],s:'_0==2?"Fully Charged":_0==1?"Charging":"Not Charging"'},p:[90,56,3197]}]},"]"]}],n:50,x:{r:["data.powerCellStatus"],s:"_0!=null"},p:[81,4,2710]}]}," ",{p:[94,2,3352],t:7,e:"ui-display",a:{title:"Power Channels"},f:[{t:4,f:[{p:[96,3,3422],t:7,e:"ui-section",a:{label:[{t:2,r:"title",p:[96,22,3441]}],nowrap:0},f:[{p:[97,5,3464],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.powerChannels",m:[{t:30,n:"@index"},"powerLoad"]},p:[97,26,3485]}]}," ",{p:[98,5,3537],t:7,e:"div",a:{"class":"content"},f:[{p:[98,26,3558],t:7,e:"span",a:{"class":[{t:2,x:{r:["status"],s:'_0>=2?"good":"bad"'},p:[98,39,3571]}]},f:[{t:2,x:{r:["status"],s:'_0>=2?"On":"Off"'},p:[98,73,3605]}]}]}," ",{p:[99,5,3653],t:7,e:"div",a:{"class":"content"},f:["[",{p:[99,27,3675],t:7,e:"span",f:[{t:2,x:{r:["status"],s:'_0==1||_0==3?"Auto":"Manual"'},p:[99,33,3681]}]},"]"]}," ",{p:[100,5,3750],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{t:4,f:[{p:[102,6,3841],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["status"],s:'_0==1||_0==3?"selected":null'},p:[102,39,3874]}],action:"channel",params:[{t:2,r:"topicParams.auto",p:[103,30,3955]}]},f:["Auto"]}," ",{p:[104,6,3999],t:7,e:"ui-button",a:{icon:"power-off",state:[{t:2,x:{r:["status"],s:'_0==2?"selected":null'},p:[104,41,4034]}],action:"channel",params:[{t:2,r:"topicParams.on",p:[105,13,4100]}]},f:["On"]}," ",{p:[106,6,4140],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["status"],s:'_0==0?"selected":null'},p:[106,37,4171]}],action:"channel",params:[{t:2,r:"topicParams.off",p:[107,13,4237]}]},f:["Off"]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[101,4,3795]}]}]}],n:52,r:"data.powerChannels",p:[95,4,3391]}," ",{p:[112,4,4328],t:7,e:"ui-section",a:{label:"Total Load"},f:[{p:[113,3,4362],t:7,e:"span",a:{"class":"bold"},f:[{t:2,r:"adata.totalLoad",p:[113,22,4381]}]}]}]}," ",{t:4,f:[{p:[117,4,4469],t:7,e:"ui-display",a:{title:"System Overrides"},f:[{p:[118,3,4509],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"overload"},f:["Overload"]}," ",{t:4,f:[{p:[120,5,4608],t:7,e:"ui-button",a:{icon:[{t:2,r:"malfIcon",p:[120,22,4625]}],state:[{t:2,x:{r:["data.malfStatus"],s:'_0==4?"disabled":null'},p:[120,43,4646]}],action:[{t:2,r:"malfAction",p:[120,97,4700]}]},f:[{t:2,r:"malfButton",p:[120,113,4716]}]}],n:50,r:"data.malfStatus",p:[119,3,4580]}]}],n:50,r:"data.siliconUser",p:[116,2,4441]}," ",{p:[124,2,4780],t:7,e:"ui-notice",f:[{p:[125,4,4795],t:7,e:"ui-section",a:{label:"Emergency Light Fallback"},f:[{t:4,f:[{p:[127,8,4894],t:7,e:"span",f:[{t:2,x:{r:["data.emergencyLights"],s:'_0?"Enabled":"Disabled"'},p:[127,14,4900]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[126,6,4846]},{t:4,n:51,f:[{p:[129,8,4978],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"emergency_lighting"},f:[{t:2,x:{r:["data.emergencyLights"],s:'_0?"Enabled":"Disabled"'},p:[129,66,5036]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}]}," ",{p:[133,2,5143],t:7,e:"ui-notice",f:[{p:[134,4,5158],t:7,e:"ui-section",a:{label:"Night Shift Lighting"},f:[{t:4,f:[{p:[136,8,5253],t:7,e:"span",f:[{t:2,x:{r:["data.nightshiftLights"],s:'_0?"Enabled":"Disabled"'},p:[136,14,5259]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[135,6,5205]},{t:4,n:51,f:[{p:[138,8,5338],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"toggle_nightshift"},f:[{t:2,x:{r:["data.nightshiftLights"],s:'_0?"Enabled":"Disabled"'},p:[138,65,5395]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}]}," ",{p:[142,2,5503],t:7,e:"ui-notice",f:[{p:[143,4,5518],t:7,e:"ui-section",a:{label:"Cover Lock"},f:[{t:4,f:[{p:[145,5,5597],t:7,e:"span",f:[{t:2,x:{r:["data.coverLocked"],s:'_0?"Engaged":"Disengaged"'},p:[145,11,5603]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[144,3,5552]},{t:4,n:51,f:[{p:[147,5,5673],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.coverLocked"],s:'_0?"lock":"unlock"'},p:[147,22,5690]}],action:"cover"},f:[{t:2,x:{r:["data.coverLocked"],s:'_0?"Engaged":"Disengaged"'},p:[147,79,5747]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}]}],r:"data.failTime"}]},e.exports=a.extend(r.exports)},{341:341}],365:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Alarms"},f:[{p:[2,3,30],t:7,e:"ul",f:[{t:4,f:[{p:[4,7,69],t:7,e:"li",f:[{p:[4,11,73],t:7,e:"ui-button",a:{icon:"close",style:"danger",action:"clear",params:['{"zone": "',{t:2,r:".",p:[4,83,145]},'"}']},f:[{t:2,r:".",p:[4,92,154]}]}]}],n:52,r:"data.priority",p:[3,5,39]},{t:4,n:51,f:[{p:[6,7,196],t:7,e:"li",f:[{p:[6,11,200],t:7,e:"span",a:{"class":"good"},f:["No Priority Alerts"]}]}],r:"data.priority"}," ",{t:4,f:[{p:[9,7,295],t:7,e:"li",f:[{p:[9,11,299],t:7,e:"ui-button",a:{icon:"close",style:"caution",action:"clear",params:['{"zone": "',{t:2,r:".",p:[9,84,372]},'"}']},f:[{t:2,r:".",p:[9,93,381]}]}]}],n:52,r:"data.minor",p:[8,5,268]},{t:4,n:51,f:[{p:[11,7,423],t:7,e:"li",f:[{p:[11,11,427],t:7,e:"span",a:{"class":"good"},f:["No Minor Alerts"]}]}],r:"data.minor"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],366:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:[{t:2,x:{r:["data.tank","data.sensors.0.long_name"],s:"_0?_1:null"},p:[1,20,19]}]},f:[{t:4,f:[{p:[3,5,100],t:7,e:"ui-subdisplay",a:{title:[{t:2,x:{r:["data.tank","long_name"],s:"!_0?_1:null"},p:[3,27,122]}]},f:[{p:[4,7,164],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[5,3,196],t:7,e:"span",f:[{t:2,x:{r:["pressure"],s:"Math.fixed(_0,2)"},p:[5,9,202]}," kPa"]}]}," ",{t:4,f:[{p:[8,9,295],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[9,11,338],t:7,e:"span",f:[{t:2,x:{r:["temperature"],s:"Math.fixed(_0,2)"},p:[9,17,344]}," K"]}]}],n:50,r:"temperature",p:[7,7,267]}," ",{t:4,f:[{p:[13,9,450],t:7,e:"ui-section",a:{label:[{t:2,r:"id",p:[13,28,469]}]},f:[{p:[14,5,482],t:7,e:"span",f:[{t:2,x:{r:["."],s:"Math.fixed(_0,2)"},p:[14,11,488]},"%"]}]}],n:52,i:"id",r:"gases",p:[12,4,423]}]}],n:52,r:"adata.sensors",p:[2,3,72]}]}," ",{t:4,f:[{p:{button:[{p:[23,5,682],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}]},t:7,e:"ui-display",a:{title:"Controls",button:0},f:[" ",{p:[25,5,768],t:7,e:"ui-section",a:{label:"Input Injector"},f:[{p:[26,7,810],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.inputting"],s:'_0?"power-off":"close"'},p:[26,24,827]}],style:[{t:2,x:{r:["data.inputting"],s:'_0?"selected":null'},p:[26,75,878]}],action:"input"},f:[{t:2,x:{r:["data.inputting"],s:'_0?"Injecting":"Off"'},p:[27,9,942]}]}]}," ",{p:[29,5,1016],t:7,e:"ui-section",a:{label:"Input Rate"},f:[{p:[30,7,1054],t:7,e:"span",f:[{t:2,x:{r:["adata.inputRate"],s:"Math.fixed(_0)"},p:[30,13,1060]}," L/s"]}]}," ",{p:[32,5,1125],t:7,e:"ui-section",a:{label:"Output Regulator"},f:[{p:[33,7,1169],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.outputting"],s:'_0?"power-off":"close"'},p:[33,24,1186]}],style:[{t:2,x:{r:["data.outputting"],s:'_0?"selected":null'},p:[33,76,1238]}],action:"output"},f:[{t:2,x:{r:["data.outputting"],s:'_0?"Open":"Closed"'},p:[34,9,1304]}]}]}," ",{p:[36,5,1377],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[37,7,1420],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure"},f:[{t:2,x:{r:["adata.outputPressure"],s:"Math.round(_0)"},p:[37,50,1463]}," kPa"]}]}]}],n:50,r:"data.tank",p:[20,1,599]}]},e.exports=a.extend(r.exports)},{341:341}],367:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,48],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,65]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,109]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,164]}]}]}," ",{p:[6,3,223],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{p:[7,5,263],t:7,e:"ui-button",a:{icon:"pencil",action:"rate",params:'{"rate": "input"}'},f:["Set"]}," ",{p:[8,5,350],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.rate","data.max_rate"],s:'_0==_1?"disabled":null'},p:[8,35,380]}],action:"rate",params:'{"rate": "max"}'},f:["Max"]}," ",{p:[9,5,492],t:7,e:"span",f:[{t:2,x:{r:["adata.rate"],s:"Math.round(_0)"},p:[9,11,498]}," L/s"]}]}," ",{p:[11,3,556],t:7,e:"ui-section",a:{label:"Filter"},f:[{t:4,f:[{p:[13,7,624],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[13,25,642]}],action:"filter",params:['{"mode": ',{t:2,r:"id",p:[14,42,718]},"}"]},f:[{t:2,r:"name",p:[14,51,727]}]}],n:52,r:"data.filter_types",p:[12,5,589]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],368:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,46],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,63]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,107]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,161]}]}]}," ",{p:[6,3,218],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[7,5,259],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[8,5,353],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.set_pressure","data.max_pressure"],s:'_0==_1?"disabled":null'},p:[8,35,383]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}," ",{p:[9,5,514],t:7,e:"span",f:[{t:2,x:{r:["adata.set_pressure"],s:"Math.round(_0)"},p:[9,11,520]}," kPa"]}]}," ",{p:[11,3,584],t:7,e:"ui-section",a:{label:"Node 1"},f:[{p:[12,5,616],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==0?"disabled":null'},p:[12,44,655]}],action:"node1",params:'{"concentration": -0.1}'}}," ",{p:[14,5,770],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==0?"disabled":null'},p:[14,39,804]}],action:"node1",params:'{"concentration": -0.01}'}}," ",{p:[16,5,920],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==100?"disabled":null'},p:[16,38,953]}],action:"node1",params:'{"concentration": 0.01}'}}," ",{p:[18,5,1070],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==100?"disabled":null'},p:[18,43,1108]}],action:"node1",params:'{"concentration": 0.1}'}}," ",{p:[20,5,1224],t:7,e:"span",f:[{t:2,x:{r:["adata.node1_concentration"],s:"Math.round(_0)"},p:[20,11,1230]},"%"]}]}," ",{p:[22,3,1298],t:7,e:"ui-section",a:{label:"Node 2"},f:[{p:[23,5,1330],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==0?"disabled":null'},p:[23,44,1369]}],action:"node2",params:'{"concentration": -0.1}'}}," ",{p:[25,5,1484],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==0?"disabled":null'},p:[25,39,1518]}],action:"node2",params:'{"concentration": -0.01}'}}," ",{p:[27,5,1634],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==100?"disabled":null'},p:[27,38,1667]}],action:"node2",params:'{"concentration": 0.01}'}}," ",{p:[29,5,1784],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==100?"disabled":null'},p:[29,43,1822]}],action:"node2",params:'{"concentration": 0.1}'}}," ",{p:[31,5,1938],t:7,e:"span",f:[{t:2,x:{r:["adata.node2_concentration"],s:"Math.round(_0)"},p:[31,11,1944]},"%"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],369:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,46],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,63]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,107]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,161]}]}]}," ",{t:4,f:[{p:[7,5,244],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{p:[8,7,285],t:7,e:"ui-button",a:{icon:"pencil",action:"rate",params:'{"rate": "input"}'},f:["Set"]}," ",{p:[9,7,373],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.rate","data.max_rate"],s:'_0==_1?"disabled":null'},p:[9,37,403]}],action:"rate",params:'{"rate": "max"}'},f:["Max"]}," ",{p:[10,7,516],t:7,e:"span",f:[{t:2,x:{r:["adata.rate"],s:"Math.round(_0)"},p:[10,13,522]}," L/s"]}]}],n:50,r:"data.max_rate",p:[6,3,218]},{t:4,n:51,f:[{p:[13,5,593],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[14,7,636],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[15,7,732],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.pressure","data.max_pressure"],s:'_0==_1?"disabled":null'},p:[15,37,762]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}," ",{p:[16,7,891],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[16,13,897]}," kPa"]}]}],r:"data.max_rate"}]}]},e.exports=a.extend(r.exports)},{341:341}],370:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,3,70],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:["Rename"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"data.borg.name",p:[1,20,19]}],button:0},f:[" ",{p:[5,2,145],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[6,4,176],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.emagged"],s:'_0?"check-square-o":"square-o"'},p:[6,21,193]}],style:[{t:2,x:{r:["data.borg.emagged"],s:'_0?"selected":null'},p:[6,83,255]}],action:"toggle_emagged"},f:["Emagged"]}," ",{p:[7,4,345],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.lockdown"],s:'_0?"check-square-o":"square-o"'},p:[7,21,362]}],style:[{t:2,x:{r:["data.borg.lockdown"],s:'_0?"selected":null'},p:[7,84,425]}],action:"toggle_lockdown"},f:["Locked down"]}," ",{p:[8,4,521],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.scrambledcodes"],s:'_0?"check-square-o":"square-o"'},p:[8,21,538]}],style:[{t:2,x:{r:["data.borg.scrambledcodes"],s:'_0?"selected":null'},p:[8,90,607]}],action:"toggle_scrambledcodes"},f:["Scrambled codes"]}]}," ",{p:[10,2,732],t:7,e:"ui-section",a:{label:"Charge"},f:[{t:4,f:[{p:[12,4,792],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.cell.maxcharge",p:[12,25,813]}],value:[{t:2,r:"data.cell.charge",p:[12,57,845]}]},f:[{t:2,x:{r:["data.cell.charge"],s:"Math.round(_0)"},p:[12,79,867]}," / ",{t:2,x:{r:["data.cell.maxcharge"],s:"Math.round(_0)"},p:[12,114,902]}]}],n:50,x:{r:["data.cell.missing"],s:"!_0"},p:[11,3,762]},{t:4,n:51,f:[{p:[14,4,961],t:7,e:"span",a:{"class":"warning"},f:["Cell missing"]},{p:[14,45,1002],t:7,e:"br"}],x:{r:["data.cell.missing"],s:"!_0"}}," ",{p:[16,3,1020],t:7,e:"ui-button",a:{icon:"pencil",action:"set_charge"},f:["Set"]},{p:[16,63,1080],t:7,e:"ui-button",a:{icon:"eject",action:"change_cell"},f:["Change"]},{p:[16,126,1143],t:7,e:"ui-button",a:{icon:"trash","class":"bad",action:"remove_cell"},f:["Remove"]}]}," ",{p:[18,2,1235],t:7,e:"ui-section",a:{label:"Radio channels"},f:[{t:4,f:[{p:[20,4,1300],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["installed"],s:'_0?"check-square-o":"square-o"'},p:[20,21,1317]}],style:[{t:2,x:{r:["installed"],s:'_0?"selected":null'},p:[20,75,1371]}],action:"toggle_radio",params:['{"channel": "',{t:2,r:"name",p:[20,154,1450]},'"}']},f:[{t:2,r:"name",p:[20,166,1462]}]}],n:52,r:"data.channels",p:[19,3,1273]}]}," ",{p:[23,2,1511],t:7,e:"ui-section",a:{label:"Module"},f:[{t:4,f:[{p:[25,4,1567],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.active_module","type"],s:'_0==_1?"check-square-o":"square-o"'},p:[25,21,1584]}],style:[{t:2,x:{r:["data.borg.active_module","type"],s:'_0==_1?"selected":null'},p:[25,97,1660]}],action:"setmodule",params:['{"module": "',{t:2,r:"type",p:[25,193,1756]},'"}']},f:[{t:2,r:"name",p:[25,205,1768]}]}],n:52,r:"data.modules",p:[24,3,1541]}]}," ",{p:[28,2,1817],t:7,e:"ui-section",a:{label:"Upgrades"},f:[{t:4,f:[{p:[30,4,1876],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["installed"],s:'_0?"check-square-o":"square-o"'},p:[30,21,1893]}],style:[{t:2,x:{r:["installed"],s:'_0?"selected":null'},p:[30,75,1947]}],action:"toggle_upgrade",params:['{"upgrade": "',{t:2,r:"type",p:[30,155,2027]},'"}']},f:[{t:2,r:"name",p:[30,167,2039]}]}],n:52,r:"data.upgrades",p:[29,3,1849]}]}," ",{p:[33,2,2088],t:7,e:"ui-section",a:{label:"Master AI"},f:[{t:4,f:[{p:[35,4,2143],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["connected"],s:'_0?"check-square-o":"square-o"'},p:[35,21,2160]}],style:[{t:2,x:{r:["connected"],s:'_0?"selected":null'},p:[35,75,2214]}],action:"slavetoai",params:['{"slavetoai": "',{t:2,r:"ref",p:[35,152,2291]},'"}']},f:[{t:2,r:"name",p:[35,163,2302]}]}],n:52,r:"data.ais",p:[34,3,2121]}]}]}," ",{p:{button:[{p:[41,3,2420],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.lawupdate"],s:'_0?"check-square-o":"square-o"'},p:[41,20,2437]}],style:[{t:2,x:{r:["data.borg.lawupdate"],s:'_0?"selected":null'},p:[41,84,2501]}],action:"toggle_lawupdate"},f:["Lawsync"]}]},t:7,e:"ui-display",a:{title:"Laws",button:0},f:[" ",{t:4,f:[{p:[44,3,2629],t:7,e:"p",f:[{t:2,r:".",p:[44,6,2632]}]}],n:52,r:"data.laws",p:[43,2,2607]}]}]},e.exports=a.extend(r.exports)},{341:341}],371:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,5,65],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"selected":null'},p:[3,38,98]}],action:[{t:2,x:{r:["data.timing"],s:'_0?"stop":"start"'},p:[3,83,143]}]},f:[{t:2,x:{r:["data.timing"],s:'_0?"Stop":"Start"'},p:[3,119,179]}]}," ",{p:[4,5,230],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"flash",style:[{t:2,x:{r:["data.flash_charging"],s:'_0?"disabled":null'},p:[4,57,282]}]},f:[{t:2,x:{r:["data.flash_charging"],s:'_0?"Recharging":"Flash"'},p:[4,102,327]}]}]},t:7,e:"ui-display",a:{title:"Cell Timer",button:0},f:[" ",{p:[6,3,405],t:7,e:"ui-section",f:[{p:[7,5,422],t:7,e:"ui-button",a:{icon:"fast-backward",action:"time",params:'{"adjust": -600}'}}," ",{p:[8,5,511],t:7,e:"ui-button",a:{icon:"backward",action:"time",params:'{"adjust": -100}'}}," ",{p:[9,5,595],t:7,e:"span",f:[{t:2,x:{r:["text","data.minutes"],s:"_0.zeroPad(_1,2)"},p:[9,11,601]},":",{t:2,x:{r:["text","data.seconds"],s:"_0.zeroPad(_1,2)"},p:[9,45,635]}]}," ",{p:[10,5,680],t:7,e:"ui-button",a:{icon:"forward",action:"time",params:'{"adjust": 100}'}}," ",{p:[11,5,762],t:7,e:"ui-button",a:{icon:"fast-forward",action:"time",params:'{"adjust": 600}'}}]}," ",{p:[13,3,863],t:7,e:"ui-section",f:[{p:[14,7,882],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "short"}'},f:["Short"]}," ",{p:[15,7,985],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "medium"}'},f:["Medium"]}," ",{p:[16,7,1090],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "long"}'},f:["Long"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],372:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,22],t:7,e:"ui-notice",f:[{t:2,r:"data.notice",p:[3,5,38]}]}],n:50,r:"data.notice",p:[1,1,0]},{p:[6,1,77],t:7,e:"ui-display",a:{title:"Bluespace Artillery Control",button:0},f:[{t:4,f:[{p:[8,3,160],t:7,e:"ui-section",a:{label:"Target"},f:[{p:[9,5,192],t:7,e:"ui-button",a:{icon:"crosshairs",action:"recalibrate"},f:[{t:2,r:"data.target",p:[9,55,242]}]}]}," ",{p:[11,3,288],t:7,e:"ui-section",a:{label:"Controls"},f:[{t:4,f:[{p:[13,3,344],t:7,e:"ui-notice",f:[{p:[14,4,359],t:7,e:"span",f:["Bluespace Artillery firing protocols must be globally unlocked from two keycard authentication devices first!"]}]}],n:50,x:{r:["data.unlocked"],s:"!_0"},p:[12,2,319]},{t:4,n:51,f:[{p:[17,3,509],t:7,e:"ui-button",a:{icon:"warning",state:[{t:2,x:{r:["data.ready"],s:'_0?null:"disabled"'},p:[17,36,542]}],action:"fire"},f:["FIRE!"]}],x:{r:["data.unlocked"],s:"!_0"}}]}],n:50,r:"data.connected",p:[7,3,135]}," ",{t:4,f:[{p:[22,3,673],t:7,e:"ui-section",a:{label:"Maintenance"},f:[{p:[23,7,712],t:7,e:"ui-button",a:{icon:"wrench",action:"build"},f:["Complete Deployment."]}]}],n:50,x:{r:["data.connected"],s:"!_0"},p:[21,3,647]}]}]},e.exports=a.extend(r.exports)},{341:341}],373:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,14],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.hasHoldingTank"],s:'_0?"is":"is not"'},p:[2,23,34]}," connected to a tank."]}]}," ",{p:{button:[{p:[6,5,180],t:7,e:"ui-button",a:{icon:"pencil",action:"relabel"},f:["Relabel"]}]},t:7,e:"ui-display",a:{title:"Canister",button:0},f:[" ",{p:[8,3,259],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[9,5,293],t:7,e:"span",f:[{t:2,x:{r:["adata.tankPressure"],s:"Math.round(_0)"},p:[9,11,299]}," kPa"]}]}," ",{p:[11,3,363],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[12,5,393],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.portConnected"],s:'_0?"good":"average"'},p:[12,18,406]}]},f:[{t:2,x:{r:["data.portConnected"],s:'_0?"Connected":"Not Connected"'},p:[12,63,451]}]}]}," ",{t:4,f:[{p:[15,3,559],t:7,e:"ui-section",a:{label:"Access"},f:[{p:[16,7,593],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.restricted"],s:'_0?"lock":"unlock"'},p:[16,24,610]}],style:[{t:2,x:{r:[],s:'"caution"'},p:[17,14,664]}],action:"restricted"},f:[{t:2,x:{r:["data.restricted"],s:'_0?"Restricted to Engineering":"Public"'},p:[18,27,705]}]}]}],n:50,r:"data.isPrototype",p:[14,3,531]}]}," ",{p:[22,1,818],t:7,e:"ui-display",a:{title:"Valve"},f:[{p:[23,3,847],t:7,e:"ui-section",a:{label:"Release Pressure"},f:[{p:[24,5,889],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.minReleasePressure",p:[24,18,902]}],max:[{t:2,r:"data.maxReleasePressure",p:[24,52,936]}],value:[{t:2,r:"data.releasePressure",p:[25,14,978]}]},f:[{t:2,x:{r:["adata.releasePressure"],s:"Math.round(_0)"},p:[25,40,1004]}," kPa"]}]}," ",{p:[27,3,1073],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[28,5,1117],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.releasePressure","data.defaultReleasePressure"],s:'_0!=_1?null:"disabled"'},p:[28,38,1150]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[30,5,1304],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.releasePressure","data.minReleasePressure"],s:'_0>_1?null:"disabled"'},p:[30,36,1335]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[32,5,1480],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[33,5,1574],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.releasePressure","data.maxReleasePressure"],s:'_0<_1?null:"disabled"'},p:[33,35,1604]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}," ",{p:[36,3,1763],t:7,e:"ui-section",a:{label:"Valve"},f:[{p:[37,5,1794],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.valveOpen"],s:'_0?"unlock":"lock"'},p:[37,22,1811]}],style:[{t:2,x:{r:["data.valveOpen","data.hasHoldingTank"],s:'_0?_1?"caution":"danger":null'},p:[38,14,1864]}],action:"valve"},f:[{t:2,x:{r:["data.valveOpen"],s:'_0?"Open":"Closed"'},p:[39,22,1957]}]}]}]}," ",{t:4,f:[{p:[42,1,2049],t:7,e:"ui-display",a:{title:"Valve Toggle Timer"},f:[{t:4,f:[{p:[44,5,2112],t:7,e:"ui-section",a:{label:"Adjust Timer"},f:[{p:[45,7,2152],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.timer_is_not_default"],s:'_0?null:"disabled"'},p:[45,40,2185]}],action:"timer",params:'{"change": "reset"}'},f:["Reset"]}," ",{p:[47,7,2312],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.timer_is_not_min"],s:'_0?null:"disabled"'},p:[47,38,2343]}],action:"timer",params:'{"change": "decrease"}'},f:["Decrease"]}," ",{p:[49,7,2472],t:7,e:"ui-button",a:{icon:"pencil",state:[{t:2,x:{r:[],s:'"disabled"'},p:[49,39,2504]}],action:"timer",params:'{"change": "input"}'},f:["Set"]}," ",{p:[51,7,2587],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.timer_is_not_max"],s:'_0?null:"disabled"'},p:[51,37,2617]}],action:"timer",params:'{"change": "increase"}'},f:["Increase"]}]}],n:51,r:"data.timing",p:[43,3,2091]}," ",{p:[55,3,2779],t:7,e:"ui-section",a:{label:"Timer"},f:[{p:[56,6,2811],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"danger":"caution"'},p:[56,39,2844]}],action:"toggle_timer"},f:[{t:2,x:{r:["data.timing"],s:'_0?"On":"Off"'},p:[57,30,2913]}]}," ",{p:[59,2,2959],t:7,e:"ui-section",a:{label:"Time until Valve Toggle"},f:[{p:[60,2,3005],t:7,e:"span",f:[{t:2,x:{r:["data.timing","data.time_left","data.timer_set"],s:"_0?_1:_2"},p:[60,8,3011]}]}]}]}]}],n:50,r:"data.isPrototype",p:[41,1,2022]},{p:{button:[{t:4,f:[{p:[69,7,3209],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.valveOpen"],s:'_0?"danger":null'},p:[69,38,3240]}],action:"eject"},f:["Eject"]}],n:50,r:"data.hasHoldingTank",p:[68,5,3175]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[73,3,3370],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holdingTank.name",p:[74,4,3400]}]}," ",{p:[76,3,3444],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holdingTank.tankPressure"],s:"Math.round(_0)"},p:[77,4,3477]}," kPa"]}],n:50,r:"data.hasHoldingTank",p:[72,3,3340]},{t:4,n:51,f:[{p:[80,3,3556],t:7,e:"ui-section",f:[{p:[81,4,3572],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.hasHoldingTank"}]}]},e.exports=a.extend(r.exports)},{341:341}],374:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tabs:function(){return Object.keys(this.get("data.supplies"))}}}}(r),r.exports.template={v:3,t:[" ",{p:[11,1,158],t:7,e:"ui-display",a:{title:"Cargo"},f:[{p:[12,3,188],t:7,e:"ui-section",a:{label:"Shuttle"},f:[{t:4,f:[{p:[14,7,270],t:7,e:"ui-button",a:{action:"send"},f:[{t:2,r:"data.location",p:[14,32,295]}]}],n:50,x:{r:["data.docked","data.requestonly"],s:"_0&&!_1"},p:[13,5,222]},{t:4,n:51,f:[{p:[16,7,346],t:7,e:"span",f:[{t:2,r:"data.location",p:[16,13,352]}]}],x:{r:["data.docked","data.requestonly"],s:"_0&&!_1"}}]}," ",{p:[19,3,410],t:7,e:"ui-section",a:{label:"Credits"},f:[{p:[20,5,444],t:7,e:"span",f:[{t:2,x:{r:["adata.points"],s:"Math.floor(_0)"},p:[20,11,450]}]}]}," ",{p:[22,3,506],t:7,e:"ui-section",a:{label:"CentCom Message"},f:[{p:[23,7,550],t:7,e:"span",f:[{t:2,r:"data.message",p:[23,13,556]}]}]}," ",{t:4,f:[{p:[26,5,644],t:7,e:"ui-section",a:{label:"Loan"},f:[{t:4,f:[{p:[28,9,716],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.away","data.docked"],s:'_0&&_1?null:"disabled"'},p:[29,17,744]}],action:"loan"},f:["Loan Shuttle"]}],n:50,x:{r:["data.loan_dispatched"],s:"!_0"},p:[27,7,677]},{t:4,n:51,f:[{p:[32,9,868],t:7,e:"span",a:{"class":"bad"},f:["Loaned to CentCom"]}],x:{r:["data.loan_dispatched"],s:"!_0"}}]}],n:50,x:{r:["data.loan","data.requestonly"],s:"_0&&!_1"},p:[25,3,600]}]}," ",{t:4,f:[{p:{button:[{p:[40,7,1066],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.cart.length"],s:'_0?null:"disabled"'},p:[40,38,1097]}],action:"clear"},f:["Clear"]}]},t:7,e:"ui-display",a:{title:"Cart",button:0},f:[" ",{t:4,f:[{p:[43,7,1222],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[44,9,1263],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[44,31,1285]}]}," ",{p:[45,9,1307],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"object",p:[45,30,1328]}]}," ",{p:[46,9,1354],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"cost",p:[46,30,1375]}," Credits"]}," ",{p:[47,9,1407],t:7,e:"div",a:{"class":"content"},f:[{p:[48,11,1440],t:7,e:"ui-button",a:{icon:"minus",action:"remove",params:['{"id": "',{t:2,r:"id",p:[48,67,1496]},'"}']}}]}] -}],n:52,r:"data.cart",p:[42,5,1195]},{t:4,n:51,f:[{p:[52,7,1566],t:7,e:"span",f:["Nothing in Cart"]}],r:"data.cart"}]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[37,1,972]},{p:{button:[{t:4,f:[{p:[59,7,1735],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.requests.length"],s:'_0?null:"disabled"'},p:[59,38,1766]}],action:"denyall"},f:["Clear"]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[58,5,1702]}]},t:7,e:"ui-display",a:{title:"Requests",button:0},f:[" ",{t:4,f:[{p:[63,5,1908],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[64,7,1947],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[64,29,1969]}]}," ",{p:[65,7,1989],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"object",p:[65,28,2010]}]}," ",{p:[66,7,2034],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"cost",p:[66,28,2055]}," Credits"]}," ",{p:[67,7,2085],t:7,e:"div",a:{"class":"content"},f:["By ",{t:2,r:"orderer",p:[67,31,2109]}]}," ",{p:[68,7,2134],t:7,e:"div",a:{"class":"content"},f:["Comment: ",{t:2,r:"reason",p:[68,37,2164]}]}," ",{t:4,f:[{p:[70,9,2223],t:7,e:"div",a:{"class":"content"},f:[{p:[71,11,2256],t:7,e:"ui-button",a:{icon:"check",action:"approve",params:['{"id": "',{t:2,r:"id",p:[71,68,2313]},'"}']}}," ",{p:[72,11,2336],t:7,e:"ui-button",a:{icon:"close",action:"deny",params:['{"id": "',{t:2,r:"id",p:[72,65,2390]},'"}']}}]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[69,7,2188]}]}],n:52,r:"data.requests",p:[62,3,1879]},{t:4,n:51,f:[{p:[77,7,2473],t:7,e:"span",f:["No Requests"]}],r:"data.requests"}]}," ",{p:[80,1,2529],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"tabs",p:[80,16,2544]}]},f:[{t:4,f:[{p:[82,5,2587],t:7,e:"tab",a:{name:[{t:2,r:"name",p:[82,16,2598]}]},f:[{t:4,f:[{p:[84,9,2641],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[84,28,2660]}],candystripe:0,right:0},f:[{p:[85,11,2700],t:7,e:"ui-button",a:{tooltip:[{t:2,r:"desc",p:[85,31,2720]}],"tooltip-side":"left",action:"add",params:['{"id": "',{t:2,r:"id",p:[85,90,2779]},'"}']},f:[{t:2,r:"cost",p:[85,100,2789]}," Credits"]}]}],n:52,r:"packs",p:[83,7,2616]}]}],n:52,r:"data.supplies",p:[81,3,2558]}]}]},e.exports=a.extend(r.exports)},{341:341}],375:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tabs:function(){return Object.keys(this.get("data.supplies"))}}}}(r),r.exports.template={v:3,t:[" ",{p:[12,1,163],t:7,e:"ui-notice",f:[{t:4,f:[{p:[14,5,207],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[15,7,249],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[15,24,266]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[15,75,317]}]}]}],n:50,r:"data.siliconUser",p:[13,3,177]},{t:4,n:51,f:[{p:[18,5,405],t:7,e:"span",f:["Swipe a QM-Level ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[18,39,439]}," this interface."]}],r:"data.siliconUser"}]}," ",{t:4,f:[{p:[23,3,546],t:7,e:"ui-display",a:{title:"Express Cargo Console"},f:[{p:[25,5,594],t:7,e:"ui-section",a:{label:"Landing Location"},f:[{p:[26,7,638],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.usingBeacon"],s:'_0?null:"selected"'},p:[26,25,656]}],action:"LZCargo"},f:["Cargo Bay"]}," ",{p:[27,7,744],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.hasBeacon","data.usingBeacon"],s:'_0?_1?"selected":null:"disabled"'},p:[27,25,762]}],action:"LZBeacon"},f:[{t:2,r:"data.beaconzone",p:[27,116,853]}," (",{t:2,r:"data.beaconName",p:[27,137,874]},")"]}," ",{p:[28,7,913],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.canBuyBeacon"],s:'_0?null:"disabled"'},p:[28,25,931]}],action:"printBeacon"},f:[{t:2,r:"data.printMsg",p:[28,90,996]}]}]}," ",{p:[31,5,1049],t:7,e:"ui-section",a:{label:"Credits"},f:[{p:[32,7,1084],t:7,e:"span",f:[{t:2,x:{r:["adata.points"],s:"Math.floor(_0)"},p:[32,13,1090]}]}]}," ",{p:[35,5,1149],t:7,e:"ui-section",a:{label:"Notice"},f:[{p:[36,7,1183],t:7,e:"span",f:[{t:2,r:"data.message",p:[36,13,1189]}]}]}]}," ",{p:[39,3,1249],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"tabs",p:[39,18,1264]}]},f:[{t:4,f:[{p:[41,7,1309],t:7,e:"tab",a:{name:[{t:2,r:"name",p:[41,18,1320]}]},f:[{t:4,f:[{p:[43,11,1365],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[43,30,1384]}],candystripe:0,right:0},f:[{p:[44,13,1425],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.canBeacon"],s:'_0?null:"disabled"'},p:[44,31,1443]}],tooltip:[{t:2,r:"desc",p:[44,80,1492]}],"tooltip-side":"left",action:"add",params:['{"id": "',{t:2,r:"id",p:[44,139,1551]},'"}']},f:[{t:2,r:"cost",p:[44,149,1561]}," Credits ",{t:2,r:"data.beaconError",p:[44,166,1578]}]}]}],n:52,r:"packs",p:[42,9,1339]}]}],n:52,r:"data.supplies",p:[40,5,1279]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[22,1,522]}]},e.exports=a.extend(r.exports)},{341:341}],376:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Cellular Emporium",button:0},f:[{p:[2,3,48],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.can_readapt"],s:'_0?null:"disabled"'},p:[2,36,81]}],action:"readapt"},f:["Readapt"]}," ",{p:[4,3,166],t:7,e:"ui-section",a:{label:"Genetic Points Remaining",right:0},f:[{t:2,r:"data.genetic_points_remaining",p:[5,5,222]}]}]}," ",{p:[8,1,286],t:7,e:"ui-display",f:[{t:4,f:[{p:[10,3,326],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[10,22,345]}],candystripe:0,right:0},f:[{p:[11,5,378],t:7,e:"span",f:[{t:2,r:"desc",p:[11,11,384]}]}," ",{p:[12,5,404],t:7,e:"span",f:[{t:2,r:"helptext",p:[12,11,410]}]}," ",{p:[13,5,434],t:7,e:"span",f:["Cost: ",{t:2,r:"dna_cost",p:[13,17,446]}]}," ",{p:[14,5,470],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["owned","can_purchase"],s:'_0?"selected":_1?null:"disabled"'},p:[15,14,494]}],action:"evolve",params:['{"name": "',{t:2,r:"name",p:[17,25,599]},'"}']},f:[{t:2,x:{r:["owned"],s:'_0?"Evolved":"Evolve"'},p:[18,7,618]}]}]}],n:52,r:"data.abilities",p:[9,1,299]},{t:4,f:[{p:[23,3,716],t:7,e:"span",a:{"class":"warning"},f:["No abilities available."]}],n:51,r:"data.abilities",p:[22,1,694]}]}]},e.exports=a.extend(r.exports)},{341:341}],377:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,5,17],t:7,e:"span",f:["To use this, simply spawn the atoms you want in one of the five Centcom Supplypod Bays. Items in the bay will then be launched inside your supplypod, one turf-full at a time! You can optionally use the following buttons to configure how the supplypod acts."]}]}," ",{p:[5,1,304],t:7,e:"ui-display",a:{title:"Centcom Pod Customization (to be used against helen weinstein)"},f:[{p:[8,5,397],t:7,e:"ui-section",a:{label:"Which supplypod bay will you use?"},f:[{p:[9,6,458],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==1?"selected":null'},p:[9,24,476]}],action:"bay1"},f:["Bay #1"]}," ",{p:[10,6,561],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==2?"selected":null'},p:[10,24,579]}],action:"bay2"},f:["Bay #2"]}," ",{p:[11,6,664],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==3?"selected":null'},p:[11,24,682]}],action:"bay3"},f:["Bay #3"]}," ",{p:[12,6,766],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==4?"selected":null'},p:[12,24,784]}],action:"bay4"},f:["Bay #4"]}," ",{p:[13,6,868],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==5?"selected":null'},p:[13,24,886]}],action:"bay5","tooltip-side":"left",tooltip:"This bay is located on the western edge of CentCom. Its the glass room directly west of where ERT spawn, and south of the CentCom ferry. Useful for launching ERT/Deathsquads/etc. onto the station via drop pods."},f:["ERT Bay"]}]}," ",{p:[18,5,1236],t:7,e:"ui-section",a:{label:"Teleport to:"},f:[{p:[19,9,1279],t:7,e:"ui-button",a:{action:"teleportCentcom"},f:[{t:2,r:"data.bay",p:[19,45,1315]}]}," ",{p:[20,9,1349],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.oldArea"],s:'_0?null:"disabled"'},p:[20,27,1367]}],action:"teleportBack"},f:[{t:2,x:{r:["data.oldArea"],s:'_0?_0:"where you were"'},p:[20,86,1426]}]}]}," ",{p:[25,5,1519],t:7,e:"ui-section",a:{label:"Launch the real atoms?"},f:[{p:[26,6,1570],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchClone"],s:'_0?"selected":null'},p:[26,24,1588]}],action:"launchClone","tooltip-side":"left",tooltip:"Choosing this will create a duplicate of the item to be launched in Centcom, allowing you to send one type of item multiple times. Either way, the atoms are forceMoved into the supplypod after it lands (but before it opens)."},f:["Launch Clones"]}]}," ",{p:[29,5,1958],t:7,e:"ui-section",a:{label:"Launch all at once?"},f:[{p:[30,9,2008],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchChoice"],s:'_0==1?"selected":null'},p:[30,27,2026]}],action:"launchOrdered","tooltip-side":"left",tooltip:'Instead of launching everything in the bay at once, this will "scan" things (one turf-full at a time) in order, left to right and top to bottom. Refreshing will reset the "scanner" to the top-leftmost position.'},f:["Ordered"]}," ",{p:[32,9,2376],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchChoice"],s:'_0==2?"selected":null'},p:[32,27,2394]}],action:"launchRandom","tooltip-side":"left",tooltip:"Instead of launching everything in the bay at once, this will launch one random turf of items at a time."},f:["Random"]}]}," ",{p:[38,5,2656],t:7,e:"ui-section",a:{label:"Add an explosion?"},f:[{p:[39,5,2700],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.explosionChoice"],s:'_0==1?"selected":null'},p:[39,23,2718]}],action:"explosionCustom","tooltip-side":"left",tooltip:"This will cause an explosion of whatever size you like (including flame range) to occur as soon as the supplypod lands. Dont worry, supply-pods are explosion-proof!"},f:["Custom Size"]}," ",{p:[41,5,3023],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.explosionChoice"],s:'_0==2?"selected":null'},p:[41,23,3041]}],action:"explosionBus","tooltip-side":"left",tooltip:"This will cause a maxcap explosion (dependent on server config) to occur as soon as the supplypod lands. Dont worry, supply-pods are explosion-proof!"},f:["Adminbus"]}]}," ",{p:[46,5,3344],t:7,e:"ui-section",a:{label:"Extra damage?","(default":"None)"},f:[{p:[47,5,3401],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.damageChoice"],s:'_0==1?"selected":null'},p:[47,23,3419]}],action:"damageCustom","tooltip-side":"left",tooltip:"Anyone caught under the pod when it lands will be dealt this amount of brute damage. Sucks to be them!"},f:["Custom Damage"]}," ",{p:[49,5,3659],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.damageChoice"],s:'_0==2?"selected":null'},p:[49,23,3677]}],action:"damageGib","tooltip-side":"left",tooltip:"This will attempt to gib any mob caught under the pod when it lands, as well as dealing a nice 5000 brute damage. Ya know, just to be sure!"},f:["Gib"]}]}," ",{p:[54,5,3960],t:7,e:"ui-section",a:{label:"Damaging effects?"},f:[{p:[55,5,4004],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectStun"],s:'_0?"selected":null'},p:[55,23,4022]}],action:"effectStun","tooltip-side":"left",tooltip:"Anyone who is on the turf when the supplypod is launched will be stunned until the supplypod lands. They cant get away that easy!"},f:["Stun"]}," ",{p:[57,5,4271],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectLimb"],s:'_0?"selected":null'},p:[57,23,4289]}],action:"effectLimb","tooltip-side":"left",tooltip:"This will cause anyone caught under the pod to lose a limb, excluding their head."},f:["Delimb"]}," ",{p:[59,5,4492],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectOrgans"],s:'_0?"selected":null'},p:[59,23,4510]}],action:"effectOrgans","tooltip-side":"left",tooltip:"This will cause anyone caught under the pod to lose all their limbs and organs in a spectacular fashion."},f:["Yeet Organs"]}]}," ",{p:[64,5,4764],t:7,e:"ui-section",a:{label:"Movement effects?"},f:[{p:[65,5,4808],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectBluespace"],s:'_0?"selected":null'},p:[65,23,4826]}],action:"effectBluespace","tooltip-side":"left",tooltip:"Gives the supplypod an advanced Bluespace Recyling Device. After opening, the supplypod will be warped directly to the surface of a nearby NT-designated trash planet (/r/ss13)."},f:["Bluespace"]}," ",{p:[67,5,5137],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectStealth"],s:'_0?"selected":null'},p:[67,23,5155]}],action:"effectStealth","tooltip-side":"left",tooltip:'This hides the red target icon from appearing when you launch the supplypod. Combos well with the "Invisible" style. Sneak attack, go!'},f:["Stealth"]}," ",{p:[69,5,5418],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectQuiet"],s:'_0?"selected":null'},p:[69,23,5436]}],action:"effectQuiet","tooltip-side":"left",tooltip:"This will keep the supplypod from making any sounds, except for those specifically set by admins in the Sound section."},f:["Quiet Landing"]}," ",{p:[71,5,5685],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectReverse"],s:'_0?"selected":null'},p:[71,23,5703]}],action:"effectReverse","tooltip-side":"left",tooltip:"This pod will not send any items. Instead, after landing, the supplypod will close (similar to a normal closet closing), and then launch back to the right centcom bay to drop off any new contents."},f:["Reverse Mode"]}," ",{p:[73,5,6033],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectMissile"],s:'_0?"selected":null'},p:[73,23,6051]}],action:"effectMissile","tooltip-side":"left",tooltip:"This pod will not send any items. Instead, it will immediatley delete after landing (Similar visually to setting openDelay & departDelay to 0, but this looks nicer). Useful if you just wanna fuck some shit up. Combos well with the Missile style."},f:["Missile Mode"]}," ",{p:[75,5,6430],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectCircle"],s:'_0?"selected":null'},p:[75,23,6448]}],action:"effectCircle","tooltip-side":"left",tooltip:"This will make the supplypod come in from any angle. Im not sure why this feature exists, but here it is."},f:["Any Descent Angle"]}," ",{p:[77,5,6690],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectBurst"],s:'_0?"selected":null'},p:[77,23,6708]}],action:"effectBurst","tooltip-side":"left",tooltip:"This will make each click launch 5 supplypods inaccuratly around the target turf (a 3x3 area). Combos well with the Missle Mode if you dont want shit lying everywhere after."},f:["Machine Gun Mode"]}," ",{p:[79,5,7015],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectTarget"],s:'_0?"selected":null'},p:[79,23,7033]}],action:"effectTarget","tooltip-side":"left",tooltip:"This will make the supplypod target a specific atom, instead of the mouses position. Smiting does this automatically!"},f:["Specific Target"]}]}," ",{p:[84,5,7304],t:7,e:"ui-section",a:{label:"Change Name/Desc?"},f:[{p:[85,5,7348],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectName"],s:'_0?"selected":null'},p:[85,23,7366]}],action:"effectName","tooltip-side":"left",tooltip:"Allows you to add a custom name and description."},f:["Custom Name/Desc"]}," ",{p:[87,5,7546],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectAnnounce"],s:'_0?"selected":null'},p:[87,23,7564]}],action:"effectAnnounce","tooltip-side":"left",tooltip:"Alerts ghosts when a pod is launched. Useful if some dumb shit is aboutta come outta the pod."},f:["Alert Ghosts"]}]}," ",{p:[92,5,7812],t:7,e:"ui-section",a:{label:"Sound?"},f:[{p:[93,5,7845],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.fallingSound"],s:'_0?"selected":null'},p:[93,23,7863]}],action:"fallingSound","tooltip-side":"left",tooltip:"Choose a sound to play as the pod falls. Note that for this to work right you should know the exact length of the sound, in seconds."},f:["Custom Falling Sound"]}," ",{p:[95,5,8135],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.landingSound"],s:'_0?"selected":null'},p:[95,23,8153]}],action:"landingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod lands."},f:["Custom Landing Sound"]}," ",{p:[97,5,8335],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.openingSound"],s:'_0?"selected":null'},p:[97,23,8353]}],action:"openingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod opens."},f:["Custom Opening Sound"]}," ",{p:[99,5,8535],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.leavingSound"],s:'_0?"selected":null'},p:[99,23,8553]}],action:"leavingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod departs (whether that be delection in the case of a bluespace pod, or leaving for centcom for a reversing pod)."},f:["Custom Leaving Sound"]}," ",{p:[101,5,8840],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.soundVolume"],s:'_0?"selected":null'},p:[101,23,8858]}],action:"soundVolume","tooltip-side":"left",tooltip:"Choose the volume for the sound to play at. Default values are between 1 and 100, but hey, do whatever. Im a tooltip, not a cop."},f:["Admin Sound Volume"]}]}," ",{p:[106,5,9141],t:7,e:"ui-section",a:{label:"Delay timers?"},f:[{p:[107,5,9181],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.fallDuration"],s:'_0!=4?"selected":null'},p:[107,23,9199]}],action:"fallDuration","tooltip-side":"left",tooltip:"Set how long the animation for the pod falling lasts. Create dramatic, slow falling pods!"},f:["Custom Falling Duration"]}," ",{p:[109,5,9436],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.landingDelay"],s:'_0!=20?"selected":null'},p:[109,23,9454]}],action:"landingDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to hit the station. By default this value is 0.5 seconds."},f:["Custom Landing Time"]}," ",{p:[111,9,9713],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.openingDelay"],s:'_0!=30?"selected":null'},p:[111,27,9731]}],action:"openingDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to open after landing. Useful for giving whatevers inside the pod a nice dramatic entrance! By default this value is 3 seconds."},f:["Custom Opening Time"]}," ",{p:[113,5,10056],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.departureDelay"],s:'_0!=30?"selected":null'},p:[113,23,10074]}],action:"departureDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to leave after landing. By default this value is 3 seconds."},f:["Custom Leaving Time"]}]}," ",{p:[118,5,10354],t:7,e:"ui-section",a:{label:"Style?"},f:[{p:[119,5,10387],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==1?"selected":null'},p:[119,23,10405]}],action:"styleStandard","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to your standard Nanotrasen black and orange. Same color scheme as the normal station-used supplypods."},f:["Standard"]}," ",{p:[121,5,10701],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==2?"selected":null'},p:[121,23,10719]}],action:"styleBluespace","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to the same as the stations upgraded blue-and-white Bluespace Supplypods."},f:["Advanced"]}," ",{p:[123,5,10987],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==4?"selected":null'},p:[123,23,11005]}],action:"styleSyndie","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a menacing black and blood-red. Great for sending meme-ops in style!"},f:["Syndicate"]}," ",{p:[125,5,11269],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==5?"selected":null'},p:[125,23,11287]}],action:"styleBlue","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a menacing black and dark blue. Great for sending deathsquads in style!"},f:["Deathsquad"]}," ",{p:[127,5,11553],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==6?"selected":null'},p:[127,23,11571]}],action:"styleCult","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a blood and rune covered cult pod!"},f:["Cult Pod"]}," ",{p:[129,5,11791],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==7?"selected":null'},p:[129,23,11809]}],action:"styleMissile","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large missile. Combos well with a missile mode, so the missile doesnt stick around after landing."},f:["Missile"]}," ",{p:[131,5,12096],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==8?"selected":null'},p:[131,23,12114]}],action:"styleSMissile","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large blood-red missile. Combos well with missile mode, so the missile doesnt stick around after landing."},f:["Syndicate Missile"]}," ",{p:[133,5,12420],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==9?"selected":null'},p:[133,23,12438]}],action:"styleBox","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large, dark-green military supply crate."},f:["Supply Crate"]}," ",{p:[135,5,12669],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==10?"selected":null'},p:[135,23,12687]}],action:"styleHONK","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a colorful, clown inspired look."},f:["HONK"]}," ",{p:[137,5,12909],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==11?"selected":null'},p:[137,23,12927]}],action:"styleFruit","tooltip-side":"left",tooltip:"for when an orange is angry"},f:["Fruit~"]}," ",{p:[139,5,13083],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==12?"selected":null'},p:[139,23,13101]}],action:"styleInvisible","tooltip-side":"left",tooltip:'Makes the supplypod invisible! Useful for when you want to use this feature with a gateway or something. Combos well with the "Stealth" and "Quiet Landing" effects.'},f:["Invisible"]}," ",{p:[141,5,13400],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==13?"selected":null'},p:[141,23,13418]}],action:"styleGondola","tooltip-side":"left",tooltip:"this gondola can control when he wants to deliver his supplies if he has a smart enough mind, so offer up his body to ghosts for maximum enjoyment. (Make sure to turn off bluespace and set a arbitrarily high open-time if you do!)"},f:["Gondola (alive)"]}," ",{p:[143,5,13787],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==14?"selected":null'},p:[143,23,13805]}],action:"styleSeeThrough","tooltip-side":"left",tooltip:"By selecting this, the pod will instead look like whatevers inside it (as if it were the contents falling by themselves, without a pod). Useful for launching mechs at the station and standing tall as they soar in from the heavens."},f:["Show Contents (See-Through Pod)!"]}]}]}," ",{p:[148,1,14223],t:7,e:"ui-display",f:[{p:[149,5,14241],t:7,e:"ui-section",a:{label:[{t:2,r:"data.numObjects",p:[149,24,14260]}," turfs in ",{t:2,r:"data.bay",p:[149,53,14289]}],candystripe:0,right:0},f:[{p:[150,9,14331],t:7,e:"ui-button",a:{action:"refresh","tooltip-side":"left",tooltip:"Manually refreshes the possible things to launch in the pod bay."},f:["Refresh Pod Bay"]}," ",{p:[152,9,14500],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.giveLauncher"],s:'_0?"selected":null'},p:[152,27,14518]}],action:"giveLauncher","tooltip-side":"left",tooltip:"THE CODEX ASTARTES CALLS THIS MANEUVER: STEEL RAIN"},f:["Enter Launch Mode"]}," ",{p:[154,9,14712],t:7,e:"ui-button",a:{style:"danger",action:"clearBay","tooltip-side":"left",tooltip:"This will delete all objs and mobs from the selected bay."},f:["Clear Selected Bay"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],378:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,3,31],t:7,e:"ui-section",a:{label:"Energy"},f:[{p:[3,5,64],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.maxEnergy",p:[3,26,85]}],value:[{t:2,r:"data.energy",p:[3,53,112]}]},f:[{t:2,x:{r:["adata.energy"],s:"Math.fixed(_0)"},p:[3,70,129]}," Units"]}]}]}," ",{p:[6,1,206],t:7,e:"ui-display",a:{title:"Saved Recipes",button:0},f:[{p:[7,3,251],t:7,e:"ui-section",f:[{p:[8,5,269],t:7,e:"ui-button",a:{icon:"plus",action:"add_recipe"},f:["Add Recipe"]}," ",{p:[9,2,337],t:7,e:"ui-button",a:{icon:"minus",action:"clear_recipes"},f:["Clear Recipes"]}," ",{t:4,f:[{p:[11,7,445],t:7,e:"ui-button",a:{grid:0,icon:"tint",action:"dispense_recipe",params:['{"recipe": "',{t:2,r:"contents",p:[11,80,518]},'"}']},f:[{t:2,r:"recipe_name",p:[11,96,534]}]}],n:52,r:"data.recipes",p:[10,5,415]}]}]}," ",{p:{button:[{t:4,f:[{p:[18,7,719],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.amount","."],s:'_0==_1?"selected":null'},p:[18,37,749]}],action:"amount",params:['{"target": ',{t:2,r:".",p:[18,114,826]},"}"]},f:[{t:2,r:".",p:[18,122,834]}]}],n:52,r:"data.beakerTransferAmounts",p:[17,5,675]}]},t:7,e:"ui-display",a:{title:"Dispense",button:0},f:[" ",{p:[21,3,886],t:7,e:"ui-section",f:[{t:4,f:[{p:[23,7,936],t:7,e:"ui-button",a:{grid:0,icon:"tint",action:"dispense",params:['{"reagent": "',{t:2,r:"id",p:[23,74,1003]},'"}']},f:[{t:2,r:"title",p:[23,84,1013]}]}],n:52,r:"data.chemicals",p:[22,5,904]}]}]}," ",{p:{button:[{t:4,f:[{p:[30,7,1190],t:7,e:"ui-button",a:{icon:"minus",action:"remove",params:['{"amount": ',{t:2,r:".",p:[30,66,1249]},"}"]},f:[{t:2,r:".",p:[30,74,1257]}]}],n:52,r:"data.beakerTransferAmounts",p:[29,5,1146]}," ",{p:[32,5,1295],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[32,36,1326]}],action:"eject"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[34,3,1423],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[36,7,1493],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[36,13,1499]},"/",{t:2,r:"data.beakerMaxVolume",p:[36,55,1541]}," Units"]}," ",{p:[37,4,1583],t:7,e:"span",f:["pH: ",{t:2,x:{r:["adata.beakerCurrentpH","adata.partRating"],s:"Math.round(_0*_1)/_1"},p:[37,14,1593]}]}," ",{p:[38,7,1679],t:7,e:"br"}," ",{t:4,f:[{p:[40,9,1732],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[40,52,1775]}," units of ",{t:2,r:"name",p:[40,87,1810]}]},{p:[40,102,1825],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[39,7,1692]},{t:4,n:51,f:[{p:[42,9,1856],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[35,5,1458]},{t:4,n:51,f:[{p:[45,7,1932],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],379:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Thermostat"},f:[{p:[2,3,35],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,67],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isActive"],s:'_0?"power-off":"close"'},p:[3,22,84]}],style:[{t:2,x:{r:["data.isActive"],s:'_0?"selected":null'},p:[4,10,137]}],state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,10,186]}],action:"power"},f:[{t:2,x:{r:["data.isActive"],s:'_0?"On":"Off"'},p:[6,18,249]}]}]}," ",{p:[8,3,314],t:7,e:"ui-section",a:{label:"Target"},f:[{p:[9,4,346],t:7,e:"ui-button",a:{icon:"pencil",action:"temperature",params:'{"target": "input"}'},f:[{t:2,x:{r:["adata.targetTemp"],s:"Math.round(_0)"},p:[9,79,421]}," K"]}]}]}," ",{p:{button:[{p:[14,5,564],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[14,36,595]}],action:"eject"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[16,3,692],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[18,7,762],t:7,e:"span",f:["Temperature: ",{t:2,x:{r:["adata.currentTemp"],s:"Math.round(_0)"},p:[18,26,781]}," K"]}," ",{p:[19,4,828],t:7,e:"br"}," ",{p:[20,7,842],t:7,e:"span",f:["pH: ",{t:2,x:{r:["adata.currentpH","adata.partRating"],s:"Math.round(_0*_1)/_1"},p:[20,17,852]}]}," ",{p:[21,7,932],t:7,e:"br"}," ",{t:4,f:[{p:[23,3,980],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[23,46,1023]}," units of ",{t:2,r:"name",p:[23,81,1058]}]},{p:[23,96,1073],t:7,e:"br"}," ",{t:4,f:[{p:[25,4,1111],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:["Purity: ",{t:2,x:{r:["purity"],s:"Math.fixed(_0,2)"},p:[25,55,1162]}]},{p:[25,87,1194],t:7,e:"br"}],n:50,r:"data.showPurity",p:[24,3,1083]}],n:52,r:"adata.beakerContents",p:[22,7,946]},{t:4,n:51,f:[{p:[28,9,1237],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[17,5,727]},{t:4,n:51,f:[{p:[31,7,1313],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],380:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:["\ufeff",{t:4,f:[" ",{p:[2,2,33],t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[{p:[3,3,71],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"Eject":"close"'},p:[3,20,88]}],style:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"selected":null'},p:[4,11,144]}],state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,11,200]}],action:"eject"},f:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"Eject":"No beaker"'},p:[7,5,269]}]}," ",{p:[10,3,341],t:7,e:"ui-section",f:[{t:4,f:[{t:4,f:[{p:[13,6,427],t:7,e:"ui-section",a:{label:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[13,25,446]}," units of ",{t:2,r:"name",p:[13,60,481]}],nowrap:0},f:[{p:[14,7,506],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{p:[15,8,556],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[15,61,609]},'", "amount": 1}']},f:["1"]}," ",{p:[16,8,654],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[16,61,707]},'", "amount": 5}']},f:["5"]}," ",{p:[17,8,752],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[17,61,805]},'", "amount": 10}']},f:["10"]}," ",{p:[18,8,852],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[18,61,905]},'", "amount": 1000}']},f:["All"]}," ",{p:[19,8,955],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[19,61,1008]},'", "amount": -1}']},f:["Custom"]}," ",{p:[20,8,1059],t:7,e:"ui-button",a:{action:"analyzeBeak",params:['{"id": "',{t:2,r:"id",p:[20,56,1107]},'"}']},f:["Analyze"]}]}]}],n:52,r:"data.beakerContents",p:[12,5,391]},{t:4,n:51,f:[{p:[24,5,1189],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"data.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[11,4,358]},{t:4,n:51,f:[{p:[27,5,1260],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}," ",{p:[32,2,1348],t:7,e:"ui-display",a:{title:"Buffer"},f:[{p:[33,3,1379],t:7,e:"ui-button",a:{action:"toggleMode",state:[{t:2,x:{r:["data.mode"],s:'_0?null:"selected"'},p:[33,41,1417]}]},f:["Destroy"]}," ",{p:[34,3,1475],t:7,e:"ui-button",a:{action:"toggleMode",state:[{t:2,x:{r:["data.mode"],s:'_0?"selected":null'},p:[34,41,1513]}]},f:["Transfer to Beaker"]}," ",{p:[35,3,1582],t:7,e:"ui-section",f:[{t:4,f:[{p:[37,5,1634],t:7,e:"ui-section",a:{label:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[37,24,1653]}," units of ",{t:2,r:"name",p:[37,59,1688]}],nowrap:0},f:[{p:[38,6,1712],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{p:[39,7,1761],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[39,62,1816]},'", "amount": 1}']},f:["1"]}," ",{p:[40,7,1860],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[40,62,1915]},'", "amount": 5}']},f:["5"]}," ",{p:[41,7,1959],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[41,62,2014]},'", "amount": 10}']},f:["10"]}," ",{p:[42,7,2060],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[42,62,2115]},'", "amount": 1000}']},f:["All"]}," ",{p:[43,7,2164],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[43,62,2219]},'", "amount": -1}']},f:["Custom"]}," ",{p:[44,7,2269],t:7,e:"ui-button",a:{action:"analyzeBuff",params:['{"id": "',{t:2,r:"id",p:[44,55,2317]},'"}']},f:["Analyze"] -}]}]}],n:52,r:"data.bufferContents",p:[36,4,1599]}]}]}," ",{t:4,f:[{p:[52,3,2453],t:7,e:"ui-display",a:{title:"Pills, Bottles and Patches"},f:[{t:4,f:[{p:[54,5,2537],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["id","data.chosenPillStyle"],s:'_0==_1?"selected":null'},p:[54,23,2555]}],action:"pillStyle",params:['{"id": "',{t:2,r:"id",p:[54,108,2640]},'"}']},f:[{t:3,r:"htmltag",p:[54,118,2650]}]}],n:52,r:"data.pillStyles",p:[53,4,2506]}," ",{p:[56,4,2694],t:7,e:"br"}," ",{t:4,f:[{p:[58,5,2740],t:7,e:"ui-button",a:{action:"ejectp",state:[{t:2,x:{r:["data.isPillBottleLoaded"],s:'_0?null:"disabled"'},p:[58,39,2774]}]},f:[{t:2,x:{r:["data.isPillBottleLoaded"],s:'_0?"Eject":"No Pill bottle loaded"'},p:[58,88,2823]}]}," ",{p:[59,5,2904],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.pillBotContent",p:[59,27,2926]},"/",{t:2,r:"data.pillBotMaxContent",p:[59,51,2950]}]}],n:50,r:"data.isPillBottleLoaded",p:[57,4,2703]},{t:4,n:51,f:[{p:[61,5,3002],t:7,e:"span",a:{"class":"average"},f:["No Pillbottle"]}],r:"data.isPillBottleLoaded"}," ",{p:[64,4,3063],t:7,e:"br"}," ",{p:[65,4,3073],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[65,63,3132]}]},f:["Create Pill (max 50µ)"]}," ",{p:[66,4,3216],t:7,e:"br"}," ",{p:[67,4,3226],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[67,63,3285]}]},f:["Create Multiple Pills"]}," ",{p:[68,4,3369],t:7,e:"br"}," ",{p:[69,4,3379],t:7,e:"br"}," ",{p:[70,4,3389],t:7,e:"ui-button",a:{action:"createPatch",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[70,64,3449]}]},f:["Create Patch (max 40µ)"]}," ",{p:[71,4,3534],t:7,e:"br"}," ",{p:[72,4,3544],t:7,e:"ui-button",a:{action:"createPatch",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[72,64,3604]}]},f:["Create Multiple Patches"]}," ",{p:[73,4,3690],t:7,e:"br"}," ",{p:[74,4,3700],t:7,e:"br"}," ",{p:[75,4,3710],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[75,65,3771]}]},f:["Create Bottle (max 30µ)"]}," ",{p:[76,4,3857],t:7,e:"br"}," ",{p:[77,4,3867],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[77,65,3928]}]},f:["Dispense Buffer to Bottles"]}," ",{p:[78,4,4017],t:7,e:"br"}," ",{p:[79,4,4027],t:7,e:"br"}," ",{p:[80,4,4037],t:7,e:"ui-button",a:{action:"createVial",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[80,63,4096]}]},f:["Create Hypo Vial (max 60µ)"]}," ",{p:[81,4,4185],t:7,e:"br"}," ",{p:[82,4,4195],t:7,e:"ui-button",a:{action:"createVial",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[82,63,4254]}]},f:["Dispense Buffer to Hypo vials"]}," ",{p:[83,4,4347],t:7,e:"br"}," ",{p:[84,4,4357],t:7,e:"br"}," ",{p:[85,4,4367],t:7,e:"ui-button",a:{action:"createDart",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[85,63,4426]}]},f:["Create SmartDart (max 20µ)"]}," ",{p:[86,4,4515],t:7,e:"br"}," ",{p:[87,4,4525],t:7,e:"ui-button",a:{action:"createDart",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[87,63,4584]}]},f:["Create Multiple SmartDarts"]}," ",{p:[88,4,4674],t:7,e:"br"}]}],n:50,x:{r:["data.condi"],s:"!_0"},p:[51,2,2430]},{t:4,n:51,f:[{p:[93,3,4717],t:7,e:"ui-display",a:{title:"Condiments bottles and packs"},f:[{p:[94,4,4772],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[94,63,4831]}]},f:["Create Pack (max 10µ)"]}," ",{p:[95,4,4915],t:7,e:"br"}," ",{p:[96,4,4925],t:7,e:"br"}," ",{p:[97,4,4935],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[97,65,4996]}]},f:["Create Bottle (max 50µ)"]}]}],x:{r:["data.condi"],s:"!_0"}}],n:50,x:{r:["data.screen"],s:'_0=="home"'},p:[1,2,1]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.screen"],s:'_0=="analyze"'},f:[{p:[101,2,5144],t:7,e:"ui-display",a:{title:[{t:2,r:"data.analyzeVars.name",p:[101,20,5162]}]},f:[{p:[102,3,5193],t:7,e:"span",a:{"class":"highlight"},f:["Description:"]}," ",{p:[103,3,5241],t:7,e:"span",a:{"class":"content",style:"float:center"},f:[{t:2,r:"data.analyzeVars.description",p:[103,46,5284]}]}," ",{p:[104,3,5327],t:7,e:"br"}," ",{p:[105,3,5336],t:7,e:"span",a:{"class":"highlight"},f:["Color:"]}," ",{p:[106,3,5378],t:7,e:"span",a:{style:["color: ",{t:2,r:"data.analyzeVars.color",p:[106,23,5398]},"; background-color: ",{t:2,r:"data.analyzeVars.color",p:[106,69,5444]}]},f:[{t:2,r:"data.analyzeVars.color",p:[106,97,5472]}]}," ",{p:[107,3,5509],t:7,e:"br"}," ",{p:[108,3,5518],t:7,e:"span",a:{"class":"highlight"},f:["State:"]}," ",{p:[109,3,5560],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.state",p:[109,25,5582]}]}," ",{p:[110,3,5619],t:7,e:"br"}," ",{p:[111,3,5628],t:7,e:"span",a:{"class":"highlight"},f:["Metabolization Rate:"]}," ",{p:[112,3,5684],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.metaRate",p:[112,25,5706]},"µ/minute"]}," ",{p:[113,3,5754],t:7,e:"br"}," ",{p:[114,3,5763],t:7,e:"span",a:{"class":"highlight"},f:["Overdose Threshold:"]}," ",{p:[115,3,5818],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.overD",p:[115,25,5840]}]}," ",{p:[116,3,5877],t:7,e:"br"}," ",{p:[117,3,5886],t:7,e:"span",a:{"class":"highlight"},f:["Addiction Threshold:"]}," ",{p:[118,3,5942],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.addicD",p:[118,25,5964]}]}," ",{p:[119,3,6002],t:7,e:"br"}," ",{t:4,f:[{p:[121,4,6041],t:7,e:"span",a:{"class":"highlight"},f:["Minumum Reaction Temperature:"]}," ",{p:[122,4,6107],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.minTemp",p:[122,26,6129]},"K"]}," ",{p:[123,4,6170],t:7,e:"br"}," ",{p:[124,4,6180],t:7,e:"span",a:{"class":"highlight"},f:["Optimal Reaction Temperature:"]}," ",{p:[125,4,6246],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.maxTemp",p:[125,26,6268]},"K"]}," ",{p:[126,4,6309],t:7,e:"br"}," ",{p:[127,4,6319],t:7,e:"span",a:{"class":"highlight"},f:["Explosion Reaction Temperature:"]}," ",{p:[128,4,6387],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.eTemp",p:[128,26,6409]},"K"]}," ",{p:[129,4,6448],t:7,e:"br"}," ",{p:[130,4,6458],t:7,e:"span",a:{"class":"highlight"},f:["Optimal reaction pH:"]}," ",{p:[131,4,6515],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.pHpeak",p:[131,26,6537]}]}," ",{p:[132,4,6576],t:7,e:"br"}," ",{p:[133,4,6586],t:7,e:"span",a:{"class":"highlight"},f:["Current Purity:"]}," ",{p:[134,4,6638],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.purityF",p:[134,26,6660]}]}," ",{p:[135,4,6700],t:7,e:"br"}," ",{p:[136,4,6710],t:7,e:"span",a:{"class":"highlight"},f:["Inverse Purity Threshold:"]}," ",{p:[137,4,6772],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.inverseRatioF",p:[137,26,6794]}]}," ",{p:[138,4,6840],t:7,e:"br"}," ",{p:[139,4,6850],t:7,e:"span",a:{"class":"highlight"},f:["Explosion Purity Threshold:"]}," ",{p:[140,4,6914],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.purityE",p:[140,26,6936]}]}," ",{p:[141,4,6976],t:7,e:"br"}],n:50,r:"data.fermianalyze",p:[120,3,6011]}," ",{p:[143,3,6996],t:7,e:"br"}," ",{p:[144,3,7005],t:7,e:"ui-button",a:{action:"goScreen",params:'{"screen": "home"}'},f:["Back"]}]}]}],x:{r:["data.screen"],s:'_0=="home"'}}]},e.exports=a.extend(r.exports)},{341:341}],381:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Recipient Contents"},f:[{p:[2,2,41],t:7,e:"ui-section",f:[{p:[3,3,56],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[3,34,87]}],action:"ejectBeaker"},f:["Eject"]}," ",{p:[4,3,173],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[4,35,205]}],action:"input"},f:["Input"]}," ",{p:[5,3,285],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,35,317]}],action:"amount"},f:[{t:2,r:"data.amount",p:[5,96,378]},"U"]}," ",{p:[6,3,409],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"disabled":null'},p:[6,33,439]}],action:"makecup"},f:["Create Beaker"]}]}]}," ",{p:[9,1,556],t:7,e:"ui-display",a:{title:"Recipient"},f:[{p:[10,2,588],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[12,4,651],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[12,10,657]},"/",{t:2,r:"data.beakerMaxVolume",p:[12,52,699]}," Units"]}," ",{t:4,f:[{p:[14,5,775],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[14,48,818]}," units of ",{t:2,r:"name",p:[14,83,853]}]},{p:[14,98,868],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[13,4,740]},{t:4,n:51,f:[{p:[16,5,890],t:7,e:"span",a:{"class":"bad"},f:["Recipient Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[11,3,620]},{t:4,n:51,f:[{p:[19,4,958],t:7,e:"span",a:{"class":"average"},f:["No Recipient"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],382:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-button",a:{action:"toggle"},f:[{t:2,x:{r:["data.recollection"],s:'_0?"Recital":"Recollection"'},p:[2,30,42]}]}]}," ",{t:4,f:[{p:[5,3,145],t:7,e:"ui-display",f:[{t:3,r:"data.rec_text",p:[6,3,160]}," ",{t:4,f:[{p:[8,4,224],t:7,e:"br"},{p:[8,8,228],t:7,e:"ui-button",a:{action:"rec_category",params:['{"category": "',{t:2,r:"name",p:[8,63,283]},'"}']},f:[{t:3,r:"name",p:[8,75,295]}," - ",{t:3,r:"desc",p:[8,88,308]}]}],n:52,r:"data.recollection_categories",p:[7,3,182]}," ",{t:3,r:"data.rec_section",p:[10,3,345]}," ",{t:3,r:"data.rec_binds",p:[11,3,370]}]}],n:50,r:"data.recollection",p:[4,1,117]},{t:4,n:51,f:[{p:[14,2,418],t:7,e:"ui-display",a:{title:"Power",button:0},f:[{p:[15,4,455],t:7,e:"ui-section",f:[{t:3,r:"data.power",p:[16,6,473]}]}]}," ",{p:[19,2,523],t:7,e:"ui-display",f:[{p:[20,3,538],t:7,e:"ui-section",f:[{p:[21,4,554],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Driver"?"selected":null'},p:[21,22,572]}],action:"select",params:'{"category": "Driver"}'},f:["Driver"]}," ",{p:[22,4,694],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Script"?"selected":null'},p:[22,22,712]}],action:"select",params:'{"category": "Script"}'},f:["Scripts"]}," ",{p:[23,4,835],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Application"?"selected":null'},p:[23,22,853]}],action:"select",params:'{"category": "Application"}'},f:["Applications"]}," ",{p:[24,4,991],t:7,e:"br"},{t:3,r:"data.tier_info",p:[24,8,995]}]}," ",{p:[26,3,1034],t:7,e:"ui-section",f:[{t:3,r:"data.scripturecolors",p:[27,4,1050]}]},{p:[28,16,1092],t:7,e:"hr"}," ",{p:[29,3,1099],t:7,e:"ui-section",f:[{t:4,f:[{p:[31,4,1142],t:7,e:"div",f:[{p:[31,9,1147],t:7,e:"ui-button",a:{tooltip:[{t:3,r:"tip",p:[31,29,1167]}],"tooltip-side":"right",action:"recite",params:['{"category": "',{t:2,r:"type",p:[31,99,1237]},'"}']},f:["Recite ",{t:3,r:"required",p:[31,118,1256]}]}," ",{t:4,f:[{t:4,f:[{p:[34,6,1329],t:7,e:"ui-button",a:{action:"bind",params:['{"category": "',{t:2,r:"type",p:[34,53,1376]},'"}']},f:["Unbind ",{t:3,r:"bound",p:[34,72,1395]}]}],n:50,r:"bound",p:[33,5,1310]},{t:4,n:51,f:[{p:[36,6,1437],t:7,e:"ui-button",a:{action:"bind",params:['{"category": "',{t:2,r:"type",p:[36,53,1484]},'"}']},f:["Quickbind"]}],r:"bound"}],n:50,r:"quickbind",p:[32,6,1288]}," ",{t:3,r:"name",p:[39,6,1548]}," ",{t:3,r:"descname",p:[39,17,1559]}," ",{t:3,r:"invokers",p:[39,32,1574]}]}],n:52,r:"data.scripture",p:[30,3,1114]}]}]}],r:"data.recollection"}]},e.exports=a.extend(r.exports)},{341:341}],383:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Codex Gigas"},f:[{p:[2,2,34],t:7,e:"ui-section",f:[{t:2,r:"data.name",p:[3,3,49]}]}," ",{p:[5,5,82],t:7,e:"ui-section",a:{label:"Prefix"},f:[{p:[6,3,112],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[6,22,131]}],action:"Dark "},f:["Dark"]}," ",{p:[7,3,215],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[7,22,234]}],action:"Hellish "},f:["Hellish"]}," ",{p:[8,3,324],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[8,22,343]}],action:"Fallen "},f:["Fallen"]}," ",{p:[9,3,431],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[9,22,450]}],action:"Fiery "},f:["Fiery"]}," ",{p:[10,3,536],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[10,22,555]}],action:"Sinful "},f:["Sinful"]}," ",{p:[11,3,643],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[11,22,662]}],action:"Blood "},f:["Blood"]}," ",{p:[12,3,748],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[12,22,767]}],action:"Fluffy "},f:["Fluffy"]}]}," ",{p:[14,5,875],t:7,e:"ui-section",a:{label:"Title"},f:[{p:[15,3,904],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[15,22,923]}],action:"Lord "},f:["Lord"]}," ",{p:[16,3,1007],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[16,22,1026]}],action:"Prelate "},f:["Prelate"]}," ",{p:[17,3,1116],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[17,22,1135]}],action:"Count "},f:["Count"]}," ",{p:[18,3,1221],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[18,22,1240]}],action:"Viscount "},f:["Viscount"]}," ",{p:[19,3,1332],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[19,22,1351]}],action:"Vizier "},f:["Vizier"]}," ",{p:[20,3,1439],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[20,22,1458]}],action:"Elder "},f:["Elder"]}," ",{p:[21,3,1544],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[21,22,1563]}],action:"Adept "},f:["Adept"]}]}," ",{p:[23,5,1669],t:7,e:"ui-section",a:{label:"Name"},f:[{p:[24,3,1697],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[24,22,1716]}],action:"hal"},f:["hal"]}," ",{p:[25,3,1797],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[25,22,1816]}],action:"ve"},f:["ve"]}," ",{p:[26,3,1895],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[26,22,1914]}],action:"odr"},f:["odr"]}," ",{p:[27,3,1995],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[27,22,2014]}],action:"neit"},f:["neit"]}," ",{p:[28,3,2097],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[28,22,2116]}],action:"ci"},f:["ci"]}," ",{p:[29,3,2195],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[29,22,2214]}],action:"quon"},f:["quon"]}," ",{p:[30,3,2297],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[30,22,2316]}],action:"mya"},f:["mya"]}," ",{p:[31,3,2397],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[31,22,2416]}],action:"folth"},f:["folth"]}," ",{p:[32,3,2501],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[32,22,2520]}],action:"wren"},f:["wren"]}," ",{p:[33,3,2603],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[33,22,2622]}],action:"geyr"},f:["geyr"]}," ",{p:[34,3,2705],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[34,22,2724]}],action:"hil"},f:["hil"]}," ",{p:[35,3,2805],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[35,22,2824]}],action:"niet"},f:["niet"]}," ",{p:[36,3,2907],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[36,22,2926]}],action:"twou"},f:["twou"]}," ",{p:[37,3,3009],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[37,22,3028]}],action:"phi"},f:["phi"]}," ",{p:[38,3,3109],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[38,22,3128]}],action:"coa"},f:["coa"]}]}," ",{p:[40,5,3229],t:7,e:"ui-section",a:{label:"suffix"},f:[{p:[41,3,3259],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[41,22,3278]}],action:" the Red"},f:["the Red"]}," ",{p:[42,3,3368],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[42,22,3387]}],action:" the Soulless"},f:["the Soulless"]}," ",{p:[43,3,3487],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[43,22,3506]}],action:" the Master"},f:["the Master"]}," ",{p:[44,3,3602],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[44,22,3621]}],action:", the Lord of all things"},f:["the Lord of all things"]}," ",{p:[45,3,3742],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[45,22,3761]}],action:", Jr."},f:["jr"]}]}," ",{p:[47,5,3863],t:7,e:"ui-section",a:{label:"submit"},f:[{p:[48,3,3894],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0>=4?null:"disabled"'},p:[48,21,3912]}],action:"search"},f:["search"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],384:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[2,1,1],t:7,e:"ui-button",a:{icon:"circle",action:"clean_order"},f:["Clear Order"]},{p:[2,70,70],t:7,e:"br"},{p:[2,74,74],t:7,e:"br"}," ",{p:[3,1,79],t:7,e:"i",f:["Your new computer device you always dreamed of is just four steps away..."]},{p:[3,81,159],t:7,e:"hr"}," ",{t:4,f:[" ",{p:[5,1,219],t:7,e:"div",a:{"class":"item"},f:[{p:[6,2,239],t:7,e:"h2",f:["Step 1: Select your device type"]}," ",{p:[7,2,281],t:7,e:"ui-button",a:{icon:"calc",action:"pick_device",params:'{"pick" : "1"}'},f:["Laptop"]}," ",{p:[8,2,370],t:7,e:"ui-button",a:{icon:"calc",action:"pick_device",params:'{"pick" : "2"}'},f:["LTablet"]}]}],n:50,x:{r:["data.state"],s:"_0==0"},p:[4,1,164]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.state"],s:"_0==1"},f:[{p:[11,1,492],t:7,e:"div",a:{"class":"item"},f:[{p:[12,2,512],t:7,e:"h2",f:["Step 2: Personalise your device"]}," ",{p:[13,2,554],t:7,e:"table",f:[{p:[14,3,564],t:7,e:"tr",f:[{p:[15,4,572],t:7,e:"td",f:[{p:[15,8,576],t:7,e:"b",f:["Current Price:"]}]},{p:[16,4,601],t:7,e:"td",f:[{t:2,r:"data.totalprice",p:[16,8,605]},"C"]}]}," ",{p:[18,3,636],t:7,e:"tr",f:[{p:[19,4,645],t:7,e:"td",f:[{p:[19,8,649],t:7,e:"b",f:["Battery:"]}]},{p:[20,4,668],t:7,e:"td",f:[{p:[20,8,672],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "1"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==1?"selected":null'},p:[20,73,737]}]},f:["Standard"]}]},{p:[21,4,807],t:7,e:"td",f:[{p:[21,8,811],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "2"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==2?"selected":null'},p:[21,73,876]}]},f:["Upgraded"]}]},{p:[22,4,946],t:7,e:"td",f:[{p:[22,8,950],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "3"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==3?"selected":null'},p:[22,73,1015]}]},f:["Advanced"]}]}]}," ",{p:[24,3,1092],t:7,e:"tr",f:[{p:[25,4,1100],t:7,e:"td",f:[{p:[25,8,1104],t:7,e:"b",f:["Hard Drive:"]}]},{p:[26,4,1126],t:7,e:"td",f:[{p:[26,8,1130],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "1"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==1?"selected":null'},p:[26,67,1189]}]},f:["Standard"]}]},{p:[27,4,1256],t:7,e:"td",f:[{p:[27,8,1260],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "2"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==2?"selected":null'},p:[27,67,1319]}]},f:["Upgraded"]}]},{p:[28,4,1386],t:7,e:"td",f:[{p:[28,8,1390],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "3"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==3?"selected":null'},p:[28,67,1449]}]},f:["Advanced"]}]}]}," ",{p:[30,3,1523],t:7,e:"tr",f:[{p:[31,4,1531],t:7,e:"td",f:[{p:[31,8,1535],t:7,e:"b",f:["Network Card:"]}]},{p:[32,4,1559],t:7,e:"td",f:[{p:[32,8,1563],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "0"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==0?"selected":null'},p:[32,73,1628]}]},f:["None"]}]},{p:[33,4,1694],t:7,e:"td",f:[{p:[33,8,1698],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "1"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==1?"selected":null'},p:[33,73,1763]}]},f:["Standard"]}]},{p:[34,4,1833],t:7,e:"td",f:[{p:[34,8,1837],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "2"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==2?"selected":null'},p:[34,73,1902]}]},f:["Advanced"]}]}]}," ",{p:[36,3,1979],t:7,e:"tr",f:[{p:[37,4,1987],t:7,e:"td",f:[{p:[37,8,1991],t:7,e:"b",f:["Nano Printer:"]}]},{p:[38,4,2015],t:7,e:"td",f:[{p:[38,8,2019],t:7,e:"ui-button",a:{action:"hw_nanoprint",params:'{"print" : "0"}',state:[{t:2,x:{r:["data.hw_nanoprint"],s:'_0==0?"selected":null'},p:[38,73,2084]}]},f:["None"]}]},{p:[39,4,2152],t:7,e:"td",f:[{p:[39,8,2156],t:7,e:"ui-button",a:{action:"hw_nanoprint",params:'{"print" : "1"}',state:[{t:2,x:{r:["data.hw_nanoprint"],s:'_0==1?"selected":null'},p:[39,73,2221]}]},f:["Standard"]}]}]}," ",{p:[41,3,2300],t:7,e:"tr",f:[{p:[42,4,2308],t:7,e:"td",f:[{p:[42,8,2312],t:7,e:"b",f:["Card Reader:"]}]},{p:[43,4,2335],t:7,e:"td",f:[{p:[43,8,2339],t:7,e:"ui-button",a:{action:"hw_card",params:'{"card" : "0"}',state:[{t:2,x:{r:["data.hw_card"],s:'_0==0?"selected":null'},p:[43,67,2398]}]},f:["None"]}]},{p:[44,4,2461],t:7,e:"td",f:[{p:[44,8,2465],t:7,e:"ui-button",a:{action:"hw_card",params:'{"card" : "1"}',state:[{t:2,x:{r:["data.hw_card"],s:'_0==1?"selected":null'},p:[44,67,2524]}]},f:["Standard"]}]}]}]}," ",{t:4,f:[" ",{p:[49,4,2658],t:7,e:"table",f:[{p:[50,5,2670],t:7,e:"tr",f:[{p:[51,6,2680],t:7,e:"td",f:[{p:[51,10,2684],t:7,e:"b",f:["Processor Unit:"]}]},{p:[52,6,2712],t:7,e:"td",f:[{p:[52,10,2716],t:7,e:"ui-button",a:{action:"hw_cpu",params:'{"cpu" : "1"}',state:[{t:2,x:{r:["data.hw_cpu"],s:'_0==1?"selected":null'},p:[52,67,2773]}]},f:["Standard"]}]},{p:[53,6,2841],t:7,e:"td",f:[{p:[53,10,2845],t:7,e:"ui-button",a:{action:"hw_cpu",params:'{"cpu" : "2"}',state:[{t:2,x:{r:["data.hw_cpu"],s:'_0==2?"selected":null'},p:[53,67,2902]}]},f:["Advanced"]}]}]}," ",{p:[55,5,2979],t:7,e:"tr",f:[{p:[56,6,2989],t:7,e:"td",f:[{p:[56,10,2993],t:7,e:"b",f:["Tesla Relay:"]}]},{p:[57,6,3018],t:7,e:"td",f:[{p:[57,10,3022],t:7,e:"ui-button",a:{action:"hw_tesla",params:'{"tesla" : "0"}',state:[{t:2,x:{r:["data.hw_tesla"],s:'_0==0?"selected":null'},p:[57,71,3083]}]},f:["None"]}]},{p:[58,6,3149],t:7,e:"td",f:[{p:[58,10,3153],t:7,e:"ui-button",a:{action:"hw_tesla",params:'{"tesla" : "1"}',state:[{t:2,x:{r:["data.hw_tesla"],s:'_0==1?"selected":null'},p:[58,71,3214]}]},f:["Standard"]}]}]}]}],n:50,x:{r:["data.devtype"],s:"_0!=2"},p:[48,3,2612]}," ",{p:[62,3,3313],t:7,e:"table",f:[{p:[63,4,3324],t:7,e:"tr",f:[{p:[64,5,3333],t:7,e:"td",f:[{p:[64,9,3337],t:7,e:"b",f:["Confirm Order:"]}]},{p:[65,5,3363],t:7,e:"td",f:[{p:[65,9,3367],t:7,e:"ui-button",a:{action:"confirm_order"},f:["CONFIRM"]}]}]}]}," ",{p:[69,2,3444],t:7,e:"hr"}," ",{p:[70,2,3450],t:7,e:"b",f:["Battery"]}," allows your device to operate without external utility power source. Advanced batteries increase battery life.",{p:[70,127,3575],t:7,e:"br"}," ",{p:[71,2,3581],t:7,e:"b",f:["Hard Drive"]}," stores file on your device. Advanced drives can store more files, but use more power, shortening battery life.",{p:[71,130,3709],t:7,e:"br"}," ",{p:[72,2,3715],t:7,e:"b",f:["Network Card"]}," allows your device to wirelessly connect to stationwide NTNet network. Basic cards are limited to on-station use, while advanced cards can operate anywhere near the station, which includes the asteroid outposts.",{p:[72,233,3946],t:7,e:"br"}," ",{p:[73,2,3952],t:7,e:"b",f:["Processor Unit"]}," is critical for your device's functionality. It allows you to run programs from your hard drive. Advanced CPUs use more power, but allow you to run more programs on background at once.",{p:[73,208,4158],t:7,e:"br"}," ",{p:[74,2,4164],t:7,e:"b",f:["Tesla Relay"]}," is an advanced wireless power relay that allows your device to connect to nearby area power controller to provide alternative power source. This component is currently unavailable on tablet computers due to size restrictions.",{p:[74,246,4408],t:7,e:"br"}," ",{p:[75,2,4414],t:7,e:"b",f:["Nano Printer"]}," is device that allows for various paperwork manipulations, such as, scanning of documents or printing new ones. This device was certified EcoFriendlyPlus and is capable of recycling existing paper for printing purposes.",{p:[75,241,4653],t:7,e:"br"}," ",{p:[76,2,4659],t:7,e:"b",f:["Card Reader"]}," adds a slot that allows you to manipulate RFID cards. Please note that this is not necessary to allow the device to read your identification, it is just necessary to manipulate other cards."]}]},{t:4,n:50,x:{r:["data.state"],s:"(!(_0==1))&&(_0==2)"},f:[" ",{p:[79,2,4903],t:7,e:"h2",f:["Step 3: Payment"]}," ",{p:[80,2,4929],t:7,e:"b",f:["Your device is now ready for fabrication.."]},{p:[80,51,4978],t:7,e:"br"}," ",{p:[81,2,4984],t:7,e:"i",f:["Please ensure the required amount of credits are in the machine, then press purchase."]},{p:[81,94,5076],t:7,e:"br"}," ",{p:[82,2,5082],t:7,e:"i",f:["Current credits: ",{p:[82,22,5102],t:7,e:"b",f:[{t:2,r:"data.credits",p:[82,25,5105]},"C"]}]},{p:[82,50,5130],t:7,e:"br"}," ",{p:[83,2,5136],t:7,e:"i",f:["Total price: ",{p:[83,18,5152],t:7,e:"b",f:[{t:2,r:"data.totalprice",p:[83,21,5155]},"C"]}]},{p:[83,49,5183],t:7,e:"br"},{p:[83,53,5187],t:7,e:"br"}," ",{p:[84,2,5193],t:7,e:"ui-button",a:{action:"purchase",state:[{t:2,x:{r:["data.credits","data.totalprice"],s:'_0>=_1?null:"disabled"'},p:[84,38,5229]}]},f:["PURCHASE"]}]},{t:4,n:50,x:{r:["data.state"],s:"(!(_0==1))&&((!(_0==2))&&(_0==3))"},f:[" ",{p:[87,2,5337],t:7,e:"h2",f:["Step 4: Thank you for your purchase"]},{p:[87,46,5381],t:7,e:"br"}," ",{p:[88,2,5387],t:7,e:"b",f:["Should you experience any issues with your new device, contact your local network admin for assistance."]}]}],x:{r:["data.state"],s:"_0==0"}}]},e.exports=a.extend(r.exports)},{341:341}],385:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,1,22],t:7,e:"ui-display",f:[{p:[3,2,37],t:7,e:"ui-section",a:{label:"Cap"},f:[{p:[4,3,65],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.is_capped"],s:'_0?"power-off":"close"'},p:[4,20,82]}],style:[{t:2,x:{r:["data.is_capped"],s:'_0?null:"selected"'},p:[4,71,133]}],action:"toggle_cap"},f:[{t:2,x:{r:["data.is_capped"],s:'_0?"On":"Off"'},p:[6,4,202]}]}]}]}],n:50,r:"data.has_cap",p:[1,1,0]},{p:[10,1,288],t:7,e:"ui-display",f:[{t:4,f:[{p:[14,2,419],t:7,e:"ui-section",f:[{p:[15,3,435],t:7,e:"ui-button",a:{action:"select_colour"},f:["Select New Colour"]}]}],n:50,r:"data.can_change_colour",p:[13,1,386]}]}," ",{p:[19,1,540],t:7,e:"ui-display",a:{title:"Stencil"},f:[{t:4,f:[{p:[21,2,599],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[21,21,618]}]},f:[{t:4,f:[{p:[23,7,655],t:7,e:"ui-button",a:{action:"select_stencil",params:['{"item":"',{t:2,r:"item",p:[23,59,707]},'"}'],style:[{t:2,x:{r:["item","data.selected_stencil"],s:'_0==_1?"selected":null'},p:[24,12,731]}]},f:[{t:2,r:"item",p:[25,4,791]}]}],n:52,r:"items",p:[22,3,632]}]}],n:52,r:"data.drawables",p:[20,3,572]}]}," ",{p:[31,1,874],t:7,e:"ui-display",a:{title:"Text Mode"},f:[{p:[32,2,907],t:7,e:"ui-section",a:{label:"Current Buffer"},f:[{t:2,r:"data.text_buffer",p:[32,37,942]}]}," ",{p:[34,2,981],t:7,e:"ui-section",f:[{p:[34,14,993],t:7,e:"ui-button",a:{action:"enter_text"},f:["New Text"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],386:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{isHead:function(t){return t%10==0},dept_class:function(t){return 0==t?"dept-cap":t>=10&&20>t?"dept-sec":t>=20&&30>t?"dept-med":t>=30&&40>t?"dept-sci":t>=40&&50>t?"dept-eng":t>=50&&60>t?"dept-cargo":t>=200&&230>t?"dept-cent":"dept-other"},health_state:function(t,e,n,a){var r=t+e+n+a;return 0>=r?"health-5":25>=r?"health-4":50>=r?"health-3":75>=r?"health-2":"health-0"}}}}(r),r.exports.css=" .health {\n width: 16px;\n height: 16px;\n background-color: #FFF;\n border: 1px solid #434343;\n position: relative;\n top: 2px;\n display: inline-block;\n }\n .health-5 { background-color: #17d568; }\n .health-4 { background-color: #2ecc71; }\n .health-3 { background-color: #e67e22; }\n .health-2 { background-color: #ed5100; }\n .health-1 { background-color: #e74c3c; }\n .health-0 { background-color: #ed2814; }\n\n .dept-cap {color : #C06616;}\n .dept-sec {color : #E74C3C;}\n .dept-med {color : #3498DB;}\n .dept-sci {color : #9B59B6;}\n .dept-eng {color : #F1C40F;}\n .dept-cargo {color : #F39C12;}\n .dept-cent {color : #00C100;}\n .dept-other {color: #C38312;}\n\n .oxy { color : #3498db; }\n .toxin { color : #2ecc71; }\n .burn { color : #e67e22; }\n .brute { color : #e74c3c; }\n\n table.crew{\n border-collapse: collapse;\n }\n\n table.crew td {\n padding : 0px 10px;\n }",r.exports.template={v:3,t:[" ",{p:[27,1,1004],t:7,e:"ui-display",f:[{p:[28,2,1018],t:7,e:"ui-section",f:[{p:[29,3,1033],t:7,e:"table",a:{"class":"crew"},f:[{p:[30,3,1056],t:7,e:"thead",f:[{p:[31,3,1066],t:7,e:"tr",f:[{p:[32,4,1074],t:7,e:"th",f:["Name"]}," ",{p:[33,4,1091],t:7,e:"th",f:["Status"]}," ",{p:[34,4,1110],t:7,e:"th",f:["Vitals"]}," ",{p:[35,4,1129],t:7,e:"th",f:["Position"]}," ",{t:4,f:[{p:[37,5,1180],t:7,e:"th",f:["Tracking"]}],n:50,r:"data.link_allowed",p:[36,4,1150]}]}]}," ",{p:[41,3,1230],t:7,e:"tbody",f:[{t:4,f:[{p:[43,4,1266],t:7,e:"tr",f:[{p:[44,5,1275],t:7,e:"td",f:[{p:[45,6,1285],t:7,e:"span",a:{"class":[{t:2,x:{r:["isHead","ijob"],s:'_0(_1)?"bold ":""'},p:[45,19,1298]},{t:2,x:{r:["dept_class","ijob"],s:"_0(_1)"},p:[45,49,1328]}]},f:[{t:2,r:"name",p:[46,7,1357]}," (",{t:2,r:"assignment",p:[46,17,1367]},") ",{p:[47,6,1388],t:7,e:"span",f:[]}]}]}," ",{p:[49,5,1409],t:7,e:"td",f:[{t:4,f:[{p:[51,7,1448],t:7,e:"span",a:{"class":["health ",{t:2,x:{r:["health_state","oxydam","toxdam","burndam","brutedam"],s:"_0(_1,_2,_3,_4)"},p:[51,27,1468]}]}}],n:50,x:{r:["oxydam"],s:"_0!=null"},p:[50,6,1419]},{t:4,n:51,f:[{t:4,f:[{p:[54,8,1573],t:7,e:"span",a:{"class":"health health-5"}}],n:50,r:"life_status",p:[53,7,1546]},{t:4,n:51,f:[{p:[56,8,1633],t:7,e:"span",a:{"class":"health health-0"}}],r:"life_status"}],x:{r:["oxydam"],s:"_0!=null"}}]}," ",{p:[60,5,1712],t:7,e:"td",f:[{t:4,f:[{p:[62,7,1751],t:7,e:"span",f:["( ",{p:[64,8,1773],t:7,e:"span",a:{"class":"oxy"},f:[{t:2,r:"oxydam",p:[64,26,1791]}]}," / ",{p:[66,8,1825],t:7,e:"span",a:{"class":"toxin"},f:[{t:2,r:"toxdam",p:[66,28,1845]}]}," / ",{p:[68,8,1879],t:7,e:"span",a:{"class":"burn"},f:[{t:2,r:"burndam",p:[68,27,1898]}]}," / ",{p:[70,8,1933],t:7,e:"span",a:{"class":"brute"},f:[{t:2,r:"brutedam",p:[70,28,1953]}]}," )"]}],n:50,x:{r:["oxydam"],s:"_0!=null"},p:[61,6,1722]},{t:4,n:51,f:[{t:4,f:[{p:[75,8,2042],t:7,e:"span",f:["Alive"]}],n:50,r:"life_status",p:[74,7,2015]},{t:4,n:51,f:[{p:[77,8,2083],t:7,e:"span",f:["Dead"]}],r:"life_status"}],x:{r:["oxydam"],s:"_0!=null"}}]}," ",{p:[81,5,2142],t:7,e:"td",f:[{t:4,f:[{p:[83,6,2178],t:7,e:"span",f:[{t:2,r:"area",p:[83,12,2184]}]}],n:50,x:{r:["pos_x"],s:"_0!=null"},p:[82,5,2151]},{t:4,n:51,f:[{p:[85,6,2218],t:7,e:"span",f:["N/A"]}], -x:{r:["pos_x"],s:"_0!=null"}}]}," ",{t:4,f:[{p:[89,6,2293],t:7,e:"td",f:[{p:[90,7,2304],t:7,e:"ui-button",a:{action:"select_person",state:[{t:2,x:{r:["can_track"],s:'_0?null:"disabled"'},p:[90,48,2345]}],params:['{"name":"',{t:2,r:"name",p:[90,100,2397]},'"}']},f:["Track"]}]}],n:50,r:"data.link_allowed",p:[88,5,2261]}]}],n:52,r:"data.sensors",p:[42,3,1240]}]}]}]}]}," "]},e.exports=a.extend(r.exports)},{341:341}],387:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,32],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,64],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,70]}]}]}," ",{t:4,f:[{p:[6,5,184],t:7,e:"ui-section",a:{label:"State"},f:[{p:[7,7,217],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[7,20,230]}]},f:[{t:2,r:"data.occupant.stat",p:[7,49,259]}]}]}," ",{p:[9,4,309],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[10,6,347],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.temperaturestatus",p:[10,19,360]}]},f:[{t:2,r:"data.occupant.bodyTemperature",p:[10,56,397]}," K"]}]}," ",{p:[12,5,461],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[13,7,495],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[13,20,508]}],max:[{t:2,r:"data.occupant.maxHealth",p:[13,54,542]}],value:[{t:2,r:"data.occupant.health",p:[13,90,578]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[14,16,619]}]},f:[{t:2,r:"data.occupant.health",p:[14,68,671]}]}]}," ",{t:4,f:[{p:[17,7,892],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[17,26,911]}]},f:[{p:[18,9,931],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[18,30,952]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[18,66,988]}],state:"bad"},f:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[18,103,1025]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[16,5,727]}],n:50,r:"data.hasOccupant",p:[5,3,155]}]}," ",{p:[23,1,1116],t:7,e:"ui-display",a:{title:"Cell"},f:[{p:[24,3,1144],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[25,5,1175],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOperating"],s:'_0?"power-off":"close"'},p:[25,22,1192]}],style:[{t:2,x:{r:["data.isOperating"],s:'_0?"selected":null'},p:[26,14,1251]}],state:[{t:2,x:{r:["data.isOpen"],s:'_0?"disabled":null'},p:[27,14,1306]}],action:"power"},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[28,22,1364]}]}]}," ",{p:[30,3,1430],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[31,3,1465],t:7,e:"span",a:{"class":[{t:2,r:"data.temperaturestatus",p:[31,16,1478]}]},f:[{t:2,r:"data.cellTemperature",p:[31,44,1506]}," K"]}]}," ",{p:[33,2,1556],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[34,5,1586],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOpen"],s:'_0?"unlock":"lock"'},p:[34,22,1603]}],action:"door"},f:[{t:2,x:{r:["data.isOpen"],s:'_0?"Open":"Closed"'},p:[34,73,1654]}]}," ",{p:[35,5,1706],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoEject"],s:'_0?"sign-out":"sign-in"'},p:[35,22,1723]}],action:"autoeject"},f:[{t:2,x:{r:["data.autoEject"],s:'_0?"Auto":"Manual"'},p:[35,86,1787]}]}]}]}," ",{p:{button:[{p:[40,5,1928],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[40,36,1959]}],action:"ejectbeaker"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[42,3,2060],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{t:4,f:[{p:[45,9,2167],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,r:"volume",p:[45,52,2210]}," units of ",{t:2,r:"name",p:[45,72,2230]}]},{p:[45,87,2245],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[44,7,2128]},{t:4,n:51,f:[{p:[47,9,2274],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[43,5,2094]},{t:4,n:51,f:[{p:[50,7,2347],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],388:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,2,14],t:7,e:"ui-section",a:{label:"State"},f:[{t:4,f:[{p:[4,4,73],t:7,e:"span",a:{"class":"good"},f:["Ready"]}],n:50,r:"data.full_pressure",p:[3,3,43]},{t:4,n:51,f:[{t:4,f:[{p:[7,5,147],t:7,e:"span",a:{"class":"bad"},f:["Power Disabled"]}],n:50,r:"data.panel_open",p:[6,4,119]},{t:4,n:51,f:[{t:4,f:[{p:[10,6,239],t:7,e:"span",a:{"class":"average"},f:["Pressurizing"]}],n:50,r:"data.pressure_charging",p:[9,5,203]},{t:4,n:51,f:[{p:[12,6,299],t:7,e:"span",a:{"class":"bad"},f:["Off"]}],r:"data.pressure_charging"}],r:"data.panel_open"}],r:"data.full_pressure"}]}," ",{p:[17,2,377],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[18,3,409],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.per",p:[18,36,442]}],state:"good"},f:[{t:2,r:"data.per",p:[18,63,469]},"%"]}]}," ",{p:[20,5,511],t:7,e:"ui-section",a:{label:"Handle"},f:[{p:[21,9,547],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.flush"],s:'_0?"toggle-on":"toggle-off"'},p:[22,10,568]}],state:[{t:2,x:{r:["data.isai","data.panel_open"],s:'_0||_1?"disabled":null'},p:[23,11,625]}],action:[{t:2,x:{r:["data.flush"],s:'_0?"handle-0":"handle-1"'},p:[24,12,691]}]},f:[{t:2,x:{r:["data.flush"],s:'_0?"Disengage":"Engage"'},p:[25,5,739]}]}]}," ",{p:[27,2,811],t:7,e:"ui-section",a:{label:"Eject"},f:[{p:[28,3,840],t:7,e:"ui-button",a:{icon:"sign-out",state:[{t:2,x:{r:["data.isai"],s:'_0?"disabled":null'},p:[28,37,874]}],action:"eject"},f:["Eject Contents"]},{p:[28,114,951],t:7,e:"br"}]}," ",{p:[30,2,973],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[31,3,1002],t:7,e:"ui-button",a:{icon:"power-off",state:[{t:2,x:{r:["data.panel_open"],s:'_0?"disabled":null'},p:[31,38,1037]}],action:[{t:2,x:{r:["data.pressure_charging"],s:'_0?"pump-0":"pump-1"'},p:[31,87,1086]}],style:[{t:2,x:{r:["data.pressure_charging"],s:'_0?"selected":null'},p:[31,145,1144]}]}},{p:[31,206,1205],t:7,e:"br"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],389:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"DNA Vault Database"},f:[{p:[2,3,42],t:7,e:"ui-section",a:{label:"Human DNA"},f:[{p:[3,7,79],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.dna_max",p:[3,28,100]}],value:[{t:2,r:"data.dna",p:[3,53,125]}]},f:[{t:2,r:"data.dna",p:[3,67,139]},"/",{t:2,r:"data.dna_max",p:[3,80,152]}," Samples"]}]}," ",{p:[5,3,204],t:7,e:"ui-section",a:{label:"Plant Data"},f:[{p:[6,5,240],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.plants_max",p:[6,26,261]}],value:[{t:2,r:"data.plants",p:[6,54,289]}]},f:[{t:2,r:"data.plants",p:[6,71,306]},"/",{t:2,r:"data.plants_max",p:[6,87,322]}," Samples"]}]}," ",{p:[8,3,377],t:7,e:"ui-section",a:{label:"Animal Data"},f:[{p:[9,5,414],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.animals_max",p:[9,26,435]}],value:[{t:2,r:"data.animals",p:[9,55,464]}]},f:[{t:2,r:"data.animals",p:[9,73,482]},"/",{t:2,r:"data.animals_max",p:[9,90,499]}," Samples"]}]}]}," ",{t:4,f:[{p:[13,1,604],t:7,e:"ui-display",a:{title:"Personal Gene Therapy"},f:[{p:[14,3,650],t:7,e:"ui-section",f:[{p:[15,2,664],t:7,e:"span",f:["Applicable gene therapy treatments:"]}]}," ",{p:[17,3,731],t:7,e:"ui-section",f:[{p:[18,2,745],t:7,e:"ui-button",a:{action:"gene",params:['{"choice": "',{t:2,r:"data.choiceA",p:[18,47,790]},'"}']},f:[{t:2,r:"data.choiceA",p:[18,67,810]}]}," ",{p:[19,2,840],t:7,e:"ui-button",a:{action:"gene",params:['{"choice": "',{t:2,r:"data.choiceB",p:[19,47,885]},'"}']},f:[{t:2,r:"data.choiceB",p:[19,67,905]}]}]}]}],n:50,x:{r:["data.completed","data.used"],s:"_0&&!_1"},p:[12,1,567]}]},e.exports=a.extend(r.exports)},{341:341}],390:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,32],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,64],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,70]}]}]}," ",{t:4,f:[{p:[6,5,178],t:7,e:"ui-section",a:{label:"Items in storage"},f:[{p:[7,4,219],t:7,e:"span",f:[{t:2,r:"data.items",p:[7,10,225]}]}]}],n:50,r:"data.items",p:[5,3,155]}," ",{t:4,f:[{p:[11,5,300],t:7,e:"ui-section",a:{label:"State"},f:[{p:[12,7,333],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[12,20,346]}]},f:[{t:2,r:"data.occupant.stat",p:[12,49,375]}]}]}," ",{p:[14,5,426],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[15,7,460],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[15,20,473]}],max:[{t:2,r:"data.occupant.maxHealth",p:[15,54,507]}],value:[{t:2,r:"data.occupant.health",p:[15,90,543]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[16,16,584]}]},f:[{t:2,x:{r:["adata.occupant.health"],s:"Math.round(_0)"},p:[16,68,636]}]}]}," ",{t:4,f:[{p:[19,7,870],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[19,26,889]}]},f:[{p:[20,9,909],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[20,30,930]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[20,66,966]}],state:"bad"},f:[{t:2,x:{r:["type","adata.occupant"],s:"Math.round(_1[_0])"},p:[20,103,1003]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[18,5,705]}," ",{p:[23,5,1087],t:7,e:"ui-section",a:{label:"Cells"},f:[{p:[24,9,1122],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"bad":"good"'},p:[24,22,1135]}]},f:[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"Damaged":"Healthy"'},p:[24,68,1181]}]}]}," ",{p:[26,5,1262],t:7,e:"ui-section",a:{label:"Brain"},f:[{p:[27,9,1297],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"bad":"good"'},p:[27,22,1310]}]},f:[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"Abnormal":"Healthy"'},p:[27,68,1356]}]}]}," ",{p:[29,5,1438],t:7,e:"ui-section",a:{label:"Bloodstream"},f:[{t:4,f:[{p:[31,11,1523],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,1)"},p:[31,54,1566]}," units of ",{t:2,r:"name",p:[31,89,1601]}]},{p:[31,104,1616],t:7,e:"br"}],n:52,r:"adata.occupant.reagents",p:[30,9,1479]},{t:4,n:51,f:[{p:[33,11,1649],t:7,e:"span",a:{"class":"good"},f:["Pure"]}],r:"adata.occupant.reagents"}]}],n:50,r:"data.occupied",p:[10,3,274]}]}," ",{p:[38,1,1740],t:7,e:"ui-display",a:{title:"Operations"},f:[{p:[39,3,1774],t:7,e:"ui-section",a:{label:"Inject"},f:[{t:4,f:[{p:[41,7,1832],t:7,e:"ui-button",a:{icon:"flask",state:[{t:2,x:{r:["data.occupied"],s:'_0?null:"disabled"'},p:[41,38,1863]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[41,111,1936]},'"}']},f:[{t:2,r:"name",p:[41,121,1946]}]},{p:[41,141,1966],t:7,e:"br"}],n:52,r:"data.chem",p:[40,5,1806]}]}," ",{p:[44,2,2003],t:7,e:"ui-section",a:{label:"Eject"},f:[{p:[45,6,2035],t:7,e:"ui-button",a:{icon:"sign-out",action:"eject"},f:["Eject Contents"]}]}," ",{p:[47,2,2120],t:7,e:"ui-section",a:{label:"Self Cleaning"},f:[{p:[48,3,2157],t:7,e:"ui-button",a:{icon:"recycle",action:"cleaning"},f:["Self-Clean Cycle"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],391:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,23],t:7,e:"ui-display",a:{title:[{t:2,r:"data.question",p:[2,21,41]}]},f:[{p:[3,5,64],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,9,114],t:7,e:"ui-button",a:{action:"vote",params:['{"answer": "',{t:2,r:"answer",p:[6,45,169]},'"}'],style:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[7,18,200]}]},f:[{t:2,r:"answer",p:[7,53,235]}," (",{t:2,r:"amount",p:[7,65,247]},")"]}],n:52,r:"data.answers",p:[4,7,83]}]}]}],n:50,r:"data.shaking",p:[1,1,0]},{t:4,n:51,f:[{p:[13,3,341],t:7,e:"ui-notice",f:["The eightball is not currently being shaken."]}],r:"data.shaking"}]},e.exports=a.extend(r.exports)},{341:341}],392:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,5,16],t:7,e:"span",f:["Time Until Launch: ",{t:2,r:"data.timer_str",p:[2,30,41]}]}]}," ",{p:[4,1,80],t:7,e:"ui-notice",f:[{p:[5,3,94],t:7,e:"span",f:["Engines: ",{t:2,x:{r:["data.engines_started"],s:'_0?"Online":"Idle"'},p:[5,18,109]}]}]}," ",{p:[7,1,174],t:7,e:"ui-display",a:{title:"Early Launch"},f:[{p:[8,2,209],t:7,e:"span",f:["Authorizations Remaining: ",{t:2,x:{r:["data.emagged","data.authorizations_remaining"],s:'_0?"ERROR":_1'},p:[9,2,242]}]}," ",{p:[10,2,309],t:7,e:"ui-button",a:{icon:"exclamation-triangle",action:"authorize",style:"danger",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[12,10,393]}]},f:["AUTHORIZE"]}," ",{p:[15,2,459],t:7,e:"ui-button",a:{icon:"minus",action:"repeal",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[16,10,508]}]},f:["Repeal"]}," ",{p:[19,2,571],t:7,e:"ui-button",a:{icon:"close",action:"abort",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[20,10,619]}]},f:["Repeal All"]}]}," ",{p:[24,1,699],t:7,e:"ui-display",a:{title:"Authorizations"},f:[{t:4,f:[{p:[26,3,768],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{t:2,r:"name",p:[26,34,799]}," (",{t:2,r:"job",p:[26,44,809]},")"]}],n:52,r:"data.authorizations",p:[25,2,736]},{t:4,n:51,f:[{p:[28,3,843],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:["No authorizations."]}],r:"data.authorizations"}]}]},e.exports=a.extend(r.exports)},{341:341}],393:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-section",a:{label:"Message"},f:[{t:2,r:"data.hidden_message",p:[3,5,48]}]}," ",{p:[5,3,90],t:7,e:"ui-section",a:{label:"Created On"},f:[{t:2,r:"data.realdate",p:[6,5,126]}]}," ",{p:[8,3,162],t:7,e:"ui-section",a:{label:"Approval"},f:[{p:[9,5,196],t:7,e:"ui-button",a:{icon:"arrow-up",state:[{t:2,x:{r:["data.is_creator","data.has_liked"],s:'_0?"disabled":_1?"selected":null'},p:[11,14,242]}],action:"like"},f:[{t:2,r:"data.num_likes",p:[12,21,333]}]}," ",{p:[13,5,368],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.is_creator","data.has_liked","data.has_disliked"],s:'_0?"disabled":!_1&&!_2?"selected":null'},p:[15,14,412]}],action:"neutral"}}," ",{p:[17,5,546],t:7,e:"ui-button",a:{icon:"arrow-down",state:[{t:2,x:{r:["data.is_creator","data.has_disliked"],s:'_0?"disabled":_1?"selected":null'},p:[19,14,594]}],action:"dislike"},f:[{t:2,r:"data.num_dislikes",p:[20,24,691]}]}]}]}," ",{t:4,f:[{p:[24,3,782],t:7,e:"ui-display",a:{title:"Admin Panel"},f:[{p:[25,5,819],t:7,e:"ui-section",a:{label:"Creator Ckey"},f:[{t:2,r:"data.creator_key",p:[25,38,852]}]}," ",{p:[26,5,890],t:7,e:"ui-section",a:{label:"Creator Character Name"},f:[{t:2,r:"data.creator_name",p:[26,48,933]}]}," ",{p:[27,5,972],t:7,e:"ui-button",a:{icon:"remove",action:"delete",style:"danger"},f:["Delete"]}]}],n:50,r:"data.admin_mode",p:[23,1,756]}]},e.exports=a.extend(r.exports)},{341:341}],394:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,14],t:7,e:"span",f:["The requested interface (",{t:2,r:"config.interface",p:[2,34,45]},") was not found. Does it exist?"]}]}]},e.exports=a.extend(r.exports)},{341:341}],395:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,19],t:7,e:"ui-notice",f:["Currently syncing with the database"]}],n:50,r:"data.sync",p:[1,1,0]},{t:4,n:51,f:[{p:{button:[{p:[8,4,156],t:7,e:"ui-button",a:{icon:"eject",action:"eject_all"},f:["Eject all"]}," ",{p:[9,4,224],t:7,e:"ui-button",a:{icon:["toggle-",{t:2,x:{r:["data.show_materials"],s:'_0?"off":"on"'},p:[9,28,248]}],action:"toggle_materials_visibility"},f:[{t:2,x:{r:["data.show_materials"],s:'_0?"Hide":"Show"'},p:[10,5,330]}]}]},t:7,e:"ui-display",a:{title:"Materials",button:0},f:[" ",{t:4,f:[{p:[14,4,436],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[15,5,470],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[16,6,505],t:7,e:"section",a:{"class":"cell"}}," ",{p:[17,6,543],t:7,e:"section",a:{"class":"cell"},f:["Mineral"]}," ",{p:[20,6,601],t:7,e:"section",a:{"class":"cell"},f:["Amount"]}," ",{p:[23,6,658],t:7,e:"section",a:{"class":"cell"}}," ",{p:[24,6,696],t:7,e:"section",a:{"class":"cell"}}]}," ",{t:4,f:[{p:[27,6,782],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[28,7,818],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[29,8,848]}]}," ",{p:[31,7,880],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"amount",p:[32,8,910]}]}," ",{p:[34,7,944],t:7,e:"section",a:{"class":"cell"},f:[{p:[35,8,974],t:7,e:"ui-button",a:{icon:"eject"},f:["Release amount"]}]}," ",{p:[37,7,1048],t:7,e:"section",a:{"class":"cell",style:"width: 40px;"},f:[{p:[38,8,1099],t:7,e:"ui-button",a:{icon:"eject"},f:["Release all"]}]}]}],n:52,r:"data.all_materials",p:[26,5,748]}]}],n:50,r:"data.show_materials",p:[13,3,405]}]}," ",{p:[45,2,1230],t:7,e:"ui-display",a:{title:"Categories"},f:[{t:4,f:[{p:[47,4,1288],t:7,e:"ui-button",f:[{t:2,r:".",p:[47,15,1299]}]}],r:"data.categories",p:[46,3,1264]}]}],r:"data.sync"}]},e.exports=a.extend(r.exports)},{341:341}],396:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,15],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[3,5,47],t:7,e:"ui-button",a:{action:"toggle_power",style:[{t:2,x:{r:["data.toggle"],s:'_0?"selected":null'},p:[5,18,107]}]},f:["Turn ",{t:2,x:{r:["data.toggle"],s:'_0?"off":"on"'},p:[6,16,161]}]}]}," ",{p:[9,3,227],t:7,e:"ui-display",a:{title:"Logging"},f:[{t:4,f:[{p:[11,3,282],t:7,e:"ui-section",a:{label:">"},f:[{t:2,r:".",p:[11,25,304]},{p:[11,30,309],t:7,e:"ui-section",f:[]}]}],n:52,r:"data.logs",p:[10,5,260]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],397:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[2,1,30],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,2,58],t:7,e:"ui-button",a:{icon:"power-off",style:[{t:2,x:{r:["data.power"],s:'_0?"selected":"danger"'},p:[3,37,93]}],action:"power"},f:[{t:2,x:{r:["data.power"],s:'_0?"Enabled":"Disabled"'},p:[3,92,148]}]}]}," ",{p:[5,1,214],t:7,e:"ui-section",a:{label:"Tag"},f:[{p:[6,2,240],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:[{t:2,r:"data.tag",p:[6,43,281]}]}]}," ",{p:[8,1,320],t:7,e:"ui-section",a:{label:"Scanning mode"},f:[{p:[9,2,356],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.updating"],s:'_0?"unlock":"lock"'},p:[9,18,372]}],style:[{t:2,x:{r:["data.updating"],s:'_0?null:"danger"'},p:[9,63,417]}],action:"updating",tooltip:"Toggle between automatic scanning or scan only when a button is pressed.","tooltip-side":"right"},f:[{t:2,x:{r:["data.updating"],s:'_0?"AUTO":"MANUAL"'},p:[9,221,575]}]}]}," ",{p:[11,1,639],t:7,e:"ui-section",a:{label:"Detection range"},f:[{p:[12,2,677],t:7,e:"ui-button",a:{icon:"refresh",style:[{t:2,x:{r:["data.globalmode"],s:'_0?null:"selected"'},p:[12,35,710]}],action:"globalmode",tooltip:"Local sector or whole region scanning.","tooltip-side":"right"},f:[{t:2,x:{r:["data.globalmode"],s:'_0?"MAXIMUM":"LOCAL"'},p:[12,165,840]}]}]}]}," ",{t:4,f:[{p:[16,2,942],t:7,e:"ui-display",a:{title:"Current Location"},f:[{p:[17,3,982],t:7,e:"span",f:[{t:2,r:"data.current",p:[17,9,988]}]}]}," ",{p:[20,2,1029],t:7,e:"ui-display",a:{title:"Detected Signals"},f:[{t:4,f:[{p:[22,3,1093],t:7,e:"ui-section",a:{label:[{t:2,r:"entrytag",p:[22,21,1111]}]},f:[{p:[23,3,1127],t:7,e:"span",f:[{t:2,r:"area",p:[23,9,1133]}," (",{t:2,r:"coord",p:[23,19,1143]},")"]}," ",{t:4,f:[{p:[25,4,1185],t:7,e:"span",f:["Dist: ",{t:2,r:"dist",p:[25,16,1197]},"m Dir: ",{t:2,r:"degrees",p:[25,31,1212]},"° (",{t:2,r:"direction",p:[25,45,1226]},")"]}],n:50,r:"direction",p:[24,3,1164]}]}],n:52,r:"data.signals",p:[21,2,1068]}]}],n:50,r:"data.power",p:[15,1,922]}]},e.exports=a.extend(r.exports)},{341:341}],398:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Labor Camp Teleporter"},f:[{p:[2,2,44],t:7,e:"ui-section",a:{label:"Teleporter Status"},f:[{p:[3,3,85],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.teleporter"],s:'_0?"good":"bad"'},p:[3,16,98]}]},f:[{t:2,x:{r:["data.teleporter"],s:'_0?"Connected":"Not connected"'},p:[3,54,136]}]}]}," ",{t:4,f:[{p:[6,4,239],t:7,e:"ui-section",a:{label:"Location"},f:[{p:[7,5,273],t:7,e:"span",f:[{t:2,r:"data.teleporter_location",p:[7,11,279]}]}]}," ",{p:[9,4,335],t:7,e:"ui-section",a:{label:"Locked status"},f:[{p:[10,5,374],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.teleporter_lock"],s:'_0?"lock":"unlock"'},p:[10,22,391]}],action:"teleporter_lock"},f:[{t:2,x:{r:["data.teleporter_lock"],s:'_0?"Locked":"Unlocked"'},p:[10,93,462]}]}," ",{p:[11,5,527],t:7,e:"ui-button",a:{action:"toggle_open"},f:[{t:2,x:{r:["data.teleporter_state_open"],s:'_0?"Open":"Closed"'},p:[11,37,559]}]}]}],n:50,r:"data.teleporter",p:[5,3,212]},{t:4,n:51,f:[{p:[14,4,653],t:7,e:"span",f:[{p:[14,10,659],t:7,e:"ui-button",a:{action:"scan_teleporter"},f:["Scan Teleporter"]}]}],r:"data.teleporter"}]}," ",{p:[17,1,754],t:7,e:"ui-display",a:{title:"Labor Camp Beacon"},f:[{p:[18,2,794],t:7,e:"ui-section",a:{label:"Beacon Status"},f:[{p:[19,3,831],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.beacon"],s:'_0?"good":"bad"'},p:[19,16,844]}]},f:[{t:2,x:{r:["data.beacon"],s:'_0?"Connected":"Not connected"'},p:[19,50,878]}]}]}," ",{t:4,f:[{p:[22,3,971],t:7,e:"ui-section",a:{label:"Location"},f:[{p:[23,4,1004],t:7,e:"span",f:[{t:2,r:"data.beacon_location",p:[23,10,1010]}]}]}],n:50,r:"data.beacon",p:[21,2,949]},{t:4,n:51,f:[{p:[26,4,1072],t:7,e:"span",f:[{p:[26,10,1078],t:7,e:"ui-button",a:{action:"scan_beacon"},f:["Scan Beacon"]}]}],r:"data.beacon"}]}," ",{p:[29,1,1165],t:7,e:"ui-display",a:{title:"Prisoner details"},f:[{p:[30,2,1204],t:7,e:"ui-section",a:{label:"Prisoner ID"},f:[{p:[31,3,1239],t:7,e:"ui-button",a:{action:"handle_id"},f:[{t:2,x:{r:["data.id","data.id_name"],s:'_0?_1:"-------------"'},p:[31,33,1269]}]}]}," ",{t:4,f:[{p:[34,2,1359],t:7,e:"ui-section",a:{label:"Set ID goal"},f:[{p:[35,4,1395],t:7,e:"ui-button",a:{action:"set_goal"},f:[{t:2,r:"data.goal",p:[35,33,1424]}]}]}],n:50,r:"data.id",p:[33,2,1342]}," ",{p:[38,2,1475],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[39,3,1507],t:7,e:"span",f:[{t:2,x:{r:["data.prisoner.name"],s:'_0?_0:"No Occupant"'},p:[39,9,1513]}]}]}," ",{t:4,f:[{p:[42,3,1620],t:7,e:"ui-section",a:{label:"Criminal Status"},f:[{p:[43,4,1660],t:7,e:"span",f:[{t:2,r:"data.prisoner.crimstat",p:[43,10,1666]}]}]}],n:50,r:"data.prisoner",p:[41,2,1596]}]}," ",{p:[47,1,1739],t:7,e:"ui-display",f:[{p:[48,2,1753],t:7,e:"center",f:[{p:[48,10,1761],t:7,e:"ui-button",a:{action:"teleport",state:[{t:2,x:{r:["data.can_teleport"],s:'_0?null:"disabled"'},p:[48,45,1796]}]},f:["Process Prisoner"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],399:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Stored Items"},f:[{t:4,f:[{p:[3,3,59],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[3,22,78]}]},f:[{p:[4,4,93],t:7,e:"ui-button",a:{action:"release_items",params:['{"mobref":',{t:2,r:"mob",p:[4,56,145]},"}"],state:[{t:2,x:{r:["data.can_reclaim"],s:'_0?null:"disabled"'},p:[4,72,161]}]},f:["Drop Items"]}]}],n:52,r:"data.mobs",p:[2,2,36]}]}]},e.exports=a.extend(r.exports)},{341:341}],400:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,3,68],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.emagged"],s:'_0?"un":null'},p:[3,20,85]},"lock"],state:[{t:2,x:{r:["data.can_toggle_safety"],s:'_0?null:"disabled"'},p:[3,63,128]}],action:"safety"},f:["Safeties: ",{p:[4,14,206],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.emagged"],s:'_0?"bad":"good"'},p:[4,27,219]}]},f:[{t:2,x:{r:["data.emagged"],s:'_0?"OFF":"ON"'},p:[4,62,254]}]}]}]},t:7,e:"ui-display",a:{title:"Default Programs",button:0},f:[" ",{t:4,f:[{p:[8,2,356],t:7,e:"ui-button",a:{action:"load_program",params:['{"type": ',{t:2,r:"type",p:[8,52,406]},"}"],style:[{t:2,x:{r:["data.program","type"],s:'_0==_1?"selected":null'},p:[8,70,424]}]},f:[{t:2,r:"name",p:[9,5,475]}," "]},{p:[10,14,497],t:7,e:"br"}],n:52,r:"data.default_programs",p:[7,2,323]}]}," ",{t:4,f:[{p:[14,2,549],t:7,e:"ui-display",a:{title:"Dangerous Programs"},f:[{t:4,f:[{p:[16,4,623],t:7,e:"ui-button",a:{icon:"warning",action:"load_program",params:['{"type": ',{t:2,r:"type",p:[16,69,688]},"}"],style:[{t:2,x:{r:["data.program","type"],s:'_0==_1?"selected":null'},p:[16,87,706]}]},f:[{t:2,r:"name",p:[17,5,757]}," "]},{p:[18,16,781],t:7,e:"br"}],n:52,r:"data.emag_programs",p:[15,3,591]}]}],n:50,r:"data.emagged",p:[13,1,527]}]},e.exports=a.extend(r.exports)},{341:341}],401:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{occupantStatState:function(){switch(this.get("data.occupant.stat")){case 0:return"good";case 1:return"average";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[15,1,266],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[16,3,298],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[17,3,330],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[17,9,336]}]}]}," ",{t:4,f:[{p:[20,5,447],t:7,e:"ui-section",a:{label:"State"},f:[{p:[21,7,480],t:7,e:"span",a:{"class":[{t:2,r:"occupantStatState",p:[21,20,493]}]},f:[{t:2,x:{r:["data.occupant.stat"],s:'_0==0?"Conscious":_0==1?"Unconcious":"Dead"'},p:[21,43,516]}]}]}],n:50,r:"data.occupied",p:[19,3,421]}]}," ",{p:[25,1,656],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[26,2,687],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[27,5,717],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"unlock":"lock"'},p:[27,22,734]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Open":"Closed"'},p:[27,71,783]}]}]}," ",{p:[29,3,846],t:7,e:"ui-section",a:{label:"Uses"},f:[{t:2,r:"data.ready_implants",p:[30,5,876]}," ",{t:4,f:[{p:[32,7,938],t:7,e:"span",a:{"class":"fa fa-cog fa-spin"}}],n:50,r:"data.replenishing",p:[31,5,906]}]}," ",{p:[35,3,1002],t:7,e:"ui-section",a:{label:"Activate"},f:[{p:[36,7,1038],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","data.ready_implants","data.ready"],s:'_0&&_1>0&&_2?null:"disabled"'},p:[36,25,1056]}],action:"implant"},f:[{t:2,x:{r:["data.ready","data.special_name"],s:'_0?(_1?_1:"Implant"):"Recharging"'},p:[37,9,1162]}," "]},{p:[38,19,1265],t:7,e:"br"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],402:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{healthState:function(){var t=this.get("data.health");return t>70?"good":t>50?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[15,3,282],t:7,e:"ui-notice",f:[{p:[16,5,298],t:7,e:"span",f:["Wipe in progress!"]}]}],n:50,r:"data.wiping",p:[14,1,260]},{p:{button:[{t:4,f:[{p:[22,7,458],t:7,e:"ui-button",a:{icon:"trash",state:[{t:2,x:{r:["data.isDead"],s:'_0?"disabled":null'},p:[22,38,489]}],action:"wipe"},f:[{t:2,x:{r:["data.wiping"],s:'_0?"Stop Wiping":"Wipe"'},p:[22,89,540]}," AI"]}],n:50,r:"data.name",p:[21,5,434]}]},t:7,e:"ui-display",a:{title:[{t:2,x:{r:["data.name"],s:'_0||"Empty Card"'},p:[19,19,370]}],button:0},f:[" ",{t:4,f:[{p:[26,5,647],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[27,9,683],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.isDead","data.isBraindead"],s:'_0||_1?"bad":"good"'},p:[27,22,696]}]},f:[{t:2,x:{r:["data.isDead","data.isBraindead"],s:'_0||_1?"Offline":"Operational"'},p:[27,76,750]}]}]}," ",{p:[29,5,843],t:7,e:"ui-section",a:{label:"Software Integrity"},f:[{p:[30,7,889],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.health",p:[30,40,922]}],state:[{t:2,r:"healthState",p:[30,64,946]}]},f:[{t:2,x:{r:["adata.health"],s:"Math.round(_0)"},p:[30,81,963]},"%"]}]}," ",{p:[32,5,1024],t:7,e:"ui-section",a:{label:"Laws"},f:[{t:4,f:[{p:[34,9,1084],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:".",p:[34,33,1108]}]},{p:[34,45,1120],t:7,e:"br"}],n:52,r:"data.laws",p:[33,7,1056]}]}," ",{p:[37,5,1164],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[38,7,1200],t:7,e:"ui-button",a:{icon:"signal",style:[{t:2,x:{r:["data.wireless"],s:'_0?"selected":null'},p:[38,39,1232]}],action:"wireless"},f:["Wireless Activity"]}," ",{p:[39,7,1325],t:7,e:"ui-button",a:{icon:"microphone",style:[{t:2,x:{r:["data.radio"],s:'_0?"selected":null'},p:[39,43,1361]}],action:"radio"},f:["Subspace Radio"]}]}],n:50,r:"data.name",p:[25,3,625]}]}]},e.exports=a.extend(r.exports)},{341:341}],403:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,22],t:7,e:"ui-notice",f:[{p:[3,3,36],t:7,e:"span",f:["Waiting for another device to confirm your request..."]}]}],n:50,r:"data.waiting",p:[1,1,0]},{t:4,n:51,f:[{p:[6,2,127],t:7,e:"ui-display",f:[{p:[7,3,142],t:7,e:"ui-section",f:[{t:4,f:[{p:[9,5,189],t:7,e:"ui-button",a:{icon:"check",action:"auth_swipe"},f:["Authorize ",{t:2,r:"data.auth_required",p:[9,59,243]}]}],n:50,r:"data.auth_required",p:[8,4,158]},{t:4,n:51,f:[{p:[11,5,294],t:7,e:"ui-button",a:{icon:"warning",state:[{t:2,x:{r:["data.red_alert"],s:'_0?"disabled":null'},p:[11,38,327]}],action:"red_alert"},f:["Red Alert"]}," ",{p:[12,5,412],t:7,e:"ui-button",a:{icon:"wrench",state:[{t:2,x:{r:["data.emergency_maint"],s:'_0?"disabled":null'},p:[12,37,444]}],action:"emergency_maint"},f:["Emergency Maintenance Access"]}," ",{p:[13,5,560],t:7,e:"ui-button",a:{icon:"warning",state:"null",action:"bsa_unlock"},f:["Bluespace Artillery Unlock"]}],r:"data.auth_required"}]}]}],r:"data.waiting"}]},e.exports=a.extend(r.exports)},{341:341}],404:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Ore values"},f:[{t:4,f:[{p:[3,3,57],t:7,e:"ui-section",a:{label:[{t:2,r:"ore",p:[3,22,76]}]},f:[{p:[4,4,90],t:7,e:"span",f:[{t:2,r:"value",p:[4,10,96]}]}]}],n:52,r:"data.ores",p:[2,2,34]}]}," ",{p:[8,1,158],t:7,e:"ui-display",a:{title:"Points"},f:[{p:[9,2,188],t:7,e:"ui-section",a:{label:"Unclaimed points"},f:[{p:[10,3,229],t:7,e:"span",f:[{t:2,r:"data.unclaimed_points",p:[10,9,235]}]}," ",{p:[11,3,271],t:7,e:"ui-button",a:{action:"claim_points",state:[{t:2,x:{r:["data.unclaimed_points"],s:'_0?null:"disabled"'},p:[11,42,310]}]},f:["Claim points"]}]}]}," ",{p:[14,1,413],t:7,e:"ui-display",f:[{p:[15,2,428],t:7,e:"span",f:["Points: ",{t:2,r:"data.id_points",p:[15,16,442]}]}," ",{p:[16,2,470],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[17,3,501],t:7,e:"span",f:[{t:2,r:"data.status_info",p:[17,9,507]}]}," ",{p:[18,3,538],t:7,e:"ui-button",a:{action:"move_shuttle",state:[{t:2,x:{r:["data.can_go_home"],s:'_0?null:"disabled"'},p:[18,42,577]}]},f:["Move shuttle"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],405:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Known Languages"},f:[{t:4,f:[{p:[3,5,68],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[3,23,86]}]},f:[{p:[4,7,102],t:7,e:"span",f:[{t:2,r:"desc",p:[4,13,108]}]}," ",{p:[5,7,130],t:7,e:"span",f:["Key: ,",{t:2,r:"key",p:[5,19,142]}]}," ",{t:4,f:[{p:[7,9,186],t:7,e:"span",f:["(gained from mob)"]}],n:50,r:"shadow",p:[6,7,163]}," ",{p:[9,7,237],t:7,e:"span",f:[{t:2,x:{r:["can_speak"],s:'_0?"Can Speak":"Cannot Speak"'},p:[9,13,243]}]}," ",{t:4,f:[{p:[11,9,332],t:7,e:"ui-button",a:{action:"select_default",params:['{"language_name":"',{t:2,r:"name",p:[13,37,413]},'"}'],style:[{t:2,x:{r:["is_default","can_speak"],s:'_0?"selected":_1?null:"disabled"'},p:[14,18,442]}]},f:[{t:2,x:{r:["is_default"],s:'_0?"Default Language":"Select as Default"'},p:[15,10,512]}]}],n:50,r:"data.is_living",p:[10,7,301]}," ",{t:4,f:[{t:4,f:[{p:[20,11,666],t:7,e:"ui-button",a:{action:"grant_language",params:['{"language_name":"',{t:2,r:"name",p:[20,72,727]},'"}']},f:["Grant"]}],n:50,r:"shadow",p:[19,9,641]},{t:4,n:51,f:[{p:[22,11,784],t:7,e:"ui-button",a:{action:"remove_language",params:['{"language_name":"',{t:2,r:"name",p:[22,73,846]},'"}']},f:["Remove"]}],r:"shadow"}],n:50,r:"data.admin_mode",p:[18,7,609]}]}],n:52,r:"data.languages",p:[2,3,39]}]}," ",{t:4,f:[{t:4,f:[{p:[30,5,1004],t:7,e:"ui-button",a:{action:"toggle_omnitongue",style:[{t:2,x:{r:["data.omnitongue"],s:'_0?"selected":null'},p:[32,14,1061]}]},f:["Omnitongue ",{t:2,x:{r:["data.omnitongue"],s:'_0?"Enabled":"Disabled"' -},p:[33,19,1120]}]}],n:50,r:"data.is_living",p:[29,3,977]}," ",{p:[36,3,1196],t:7,e:"ui-display",a:{title:"Unknown Languages"},f:[{t:4,f:[{p:[38,7,1278],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[38,25,1296]}]},f:[{p:[39,9,1314],t:7,e:"span",f:[{t:2,r:"desc",p:[39,15,1320]}]}," ",{p:[40,9,1344],t:7,e:"span",f:["Key: ,",{t:2,r:"key",p:[40,21,1356]}]}," ",{p:[41,9,1379],t:7,e:"ui-button",a:{action:"grant_language",params:['{"language_name":"',{t:2,r:"name",p:[43,37,1460]},'"}']},f:["Grant"]}]}],n:52,r:"data.unknown_languages",p:[37,5,1239]}]}],n:50,r:"data.admin_mode",p:[28,1,951]}]},e.exports=a.extend(r.exports)},{341:341}],406:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Controls"},f:[{t:4,f:[{t:4,f:[{p:[4,4,81],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[5,5,114],t:7,e:"span",f:["Launchpad closed."]}]}],n:50,r:"data.pad_closed",p:[3,3,54]},{t:4,n:51,f:[{p:[8,4,176],t:7,e:"ui-section",a:{label:"Launchpad"},f:[{p:[9,4,210],t:7,e:"span",f:[{p:[9,10,216],t:7,e:"b",f:[{t:2,r:"data.pad_name",p:[9,13,219]}]}]},{p:[9,41,247],t:7,e:"br"}," ",{p:[10,4,255],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:["Rename"]}," ",{p:[11,4,318],t:7,e:"ui-button",a:{icon:"remove",style:"danger",action:"remove"},f:["Remove"]}]}," ",{p:[14,4,414],t:7,e:"ui-section",a:{label:"Set Target"},f:[{p:[15,4,449],t:7,e:"table",f:[{p:[16,4,460],t:7,e:"tr",f:[{p:[17,5,469],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[17,38,502],t:7,e:"ui-button",a:{action:"up-left"},f:["↖"]}]}," ",{p:[18,5,553],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[18,57,605],t:7,e:"ui-button",a:{action:"up"},f:["↑"]}]}," ",{p:[19,5,651],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[19,56,702],t:7,e:"ui-button",a:{action:"up-right"},f:["↗"]}]}]}," ",{p:[21,4,762],t:7,e:"tr",f:[{p:[22,5,771],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[22,38,804],t:7,e:"ui-button",a:{action:"left",style:"width:35px!important"},f:["â†"]}]}," ",{p:[23,5,881],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[23,57,933],t:7,e:"ui-button",a:{action:"reset"},f:["R"]}]}," ",{p:[24,5,982],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[24,56,1033],t:7,e:"ui-button",a:{action:"right"},f:["→"]}]}]}," ",{p:[26,4,1090],t:7,e:"tr",f:[{p:[27,5,1099],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[27,38,1132],t:7,e:"ui-button",a:{action:"down-left"},f:["↙"]}]}," ",{p:[28,5,1185],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[28,57,1237],t:7,e:"ui-button",a:{action:"down"},f:["↓"]}]}," ",{p:[29,5,1285],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[29,56,1336],t:7,e:"ui-button",a:{action:"down-right"},f:["↘"]}]}]}]}]}," ",{p:[33,4,1427],t:7,e:"ui-section",a:{label:"Current Target"},f:[{p:[34,5,1467],t:7,e:"span",f:[{t:2,r:"data.abs_y",p:[34,11,1473]}," ",{t:2,r:"data.north_south",p:[34,26,1488]}]},{p:[34,53,1515],t:7,e:"br"}," ",{p:[35,5,1524],t:7,e:"span",f:[{t:2,r:"data.abs_x",p:[35,11,1530]}," ",{t:2,r:"data.east_west",p:[35,26,1545]}]}]}," ",{p:[37,4,1591],t:7,e:"ui-section",a:{label:"Activate"},f:[{p:[38,5,1625],t:7,e:"ui-button",a:{action:"launch",tooltip:"Teleport everything on the pad to the target.","tooltip-side":"down"},f:["Launch"]}," ",{p:[39,5,1751],t:7,e:"ui-button",a:{action:"pull",tooltip:"Teleport everything from the target to the pad.","tooltip-side":"down"},f:["Pull"]}]}],r:"data.pad_closed"}],n:50,r:"data.has_pad",p:[2,2,31]},{t:4,n:51,f:[{p:[45,3,1912],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[46,4,1944],t:7,e:"span",f:["No launchpad found. Link the remote to a launchpad."]}]}],r:"data.has_pad"}]}]},e.exports=a.extend(r.exports)},{341:341}],407:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{mechChargeState:function(t){var e=this.get("data.recharge_port.mech.cell.maxcharge");return t>=e/1.5?"good":t>=e/3?"average":"bad"},mechHealthState:function(t){var e=this.get("data.recharge_port.mech.maxhealth");return t>e/1.5?"good":t>e/3?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[20,1,526],t:7,e:"ui-display",a:{title:"Mech Status"},f:[{t:4,f:[{t:4,f:[{p:[23,4,624],t:7,e:"ui-section",a:{label:"Integrity"},f:[{p:[24,6,660],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.recharge_port.mech.maxhealth",p:[24,27,681]}],value:[{t:2,r:"adata.recharge_port.mech.health",p:[24,74,728]}],state:[{t:2,x:{r:["mechHealthState","adata.recharge_port.mech.health"],s:"_0(_1)"},p:[24,117,771]}]},f:[{t:2,x:{r:["adata.recharge_port.mech.health"],s:"Math.round(_0)"},p:[24,171,825]},"/",{t:2,r:"adata.recharge_port.mech.maxhealth",p:[24,219,873]}]}]}," ",{t:4,f:[{t:4,f:[{p:[28,5,1034],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[28,31,1060],t:7,e:"span",a:{"class":"bad"},f:["Cell Critical Failure"]}]}],n:50,r:"data.recharge_port.mech.cell.critfail",p:[27,3,984]},{t:4,n:51,f:[{p:[30,11,1141],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[31,13,1180],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.recharge_port.mech.cell.maxcharge",p:[31,34,1201]}],value:[{t:2,r:"adata.recharge_port.mech.cell.charge",p:[31,86,1253]}],state:[{t:2,x:{r:["mechChargeState","adata.recharge_port.mech.cell.charge"],s:"_0(_1)"},p:[31,134,1301]}]},f:[{t:2,x:{r:["adata.recharge_port.mech.cell.charge"],s:"Math.round(_0)"},p:[31,193,1360]},"/",{t:2,x:{r:["adata.recharge_port.mech.cell.maxcharge"],s:"Math.round(_0)"},p:[31,246,1413]}]}]}],r:"data.recharge_port.mech.cell.critfail"}],n:50,r:"data.recharge_port.mech.cell",p:[26,4,945]},{t:4,n:51,f:[{p:[35,3,1524],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[35,29,1550],t:7,e:"span",a:{"class":"bad"},f:["Cell Missing"]}]}],r:"data.recharge_port.mech.cell"}],n:50,r:"data.recharge_port.mech",p:[22,2,589]},{t:4,n:51,f:[{p:[38,4,1625],t:7,e:"ui-section",f:["Mech Not Found"]}],r:"data.recharge_port.mech"}],n:50,r:"data.recharge_port",p:[21,3,561]},{t:4,n:51,f:[{p:[41,5,1689],t:7,e:"ui-section",f:["Recharging Port Not Found"]}," ",{p:[42,2,1741],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}],r:"data.recharge_port"}]}]},e.exports=a.extend(r.exports)},{341:341}],408:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{t:4,f:[{p:[3,5,43],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[4,7,85],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[4,24,102]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[4,75,153]}]}]}],n:50,r:"data.siliconUser",p:[2,3,14]},{t:4,n:51,f:[{p:[7,5,241],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[7,31,267]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[10,1,349],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[11,3,379],t:7,e:"ui-section",a:{label:"Power"},f:[{t:4,f:[{p:[13,7,458],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[13,24,475]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[13,68,519]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[13,116,567]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[12,5,410]},{t:4,n:51,f:[{p:[15,7,625],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.on"],s:'_0?"good":"bad"'},p:[15,20,638]}],state:[{t:2,x:{r:["data.cell"],s:'_0?null:"disabled"'},p:[15,57,675]}]},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[15,92,710]}]}],x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"}}]}," ",{p:[18,3,774],t:7,e:"ui-section",a:{label:"Cell"},f:[{p:[19,5,804],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.cell"],s:'_0?null:"bad"'},p:[19,18,817]}]},f:[{t:2,x:{r:["data.cell","data.cellPercent"],s:'_0?_1+"%":"No Cell"'},p:[19,48,847]}]}]}," ",{p:[21,3,923],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[22,5,953],t:7,e:"span",a:{"class":[{t:2,r:"data.modeStatus",p:[22,18,966]}]},f:[{t:2,r:"data.mode",p:[22,39,987]}]}]}," ",{p:[24,3,1026],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[25,5,1056],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.load"],s:'_0?"good":"average"'},p:[25,18,1069]}]},f:[{t:2,x:{r:["data.load"],s:'_0?_0:"None"'},p:[25,54,1105]}]}]}," ",{p:[27,3,1165],t:7,e:"ui-section",a:{label:"Destination"},f:[{p:[28,5,1202],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.destination"],s:'_0?"good":"average"'},p:[28,18,1215]}]},f:[{t:2,x:{r:["data.destination"],s:'_0?_0:"None"'},p:[28,60,1257]}]}]}]}," ",{t:4,f:[{p:{button:[{t:4,f:[{p:[35,9,1479],t:7,e:"ui-button",a:{icon:"eject",action:"unload"},f:["Unload"]}],n:50,r:"data.load",p:[34,7,1453]}," ",{t:4,f:[{p:[38,9,1586],t:7,e:"ui-button",a:{icon:"eject",action:"ejectpai"},f:["Eject PAI"]}],n:50,r:"data.haspai",p:[37,7,1558]}," ",{p:[40,7,1670],t:7,e:"ui-button",a:{icon:"pencil",action:"setid"},f:["Set ID"]}]},t:7,e:"ui-display",a:{title:"Controls",button:0},f:[" ",{p:[42,5,1750],t:7,e:"ui-section",a:{label:"Destination"},f:[{p:[43,7,1789],t:7,e:"ui-button",a:{icon:"pencil",action:"destination"},f:["Set Destination"]}," ",{p:[44,7,1869],t:7,e:"ui-button",a:{icon:"stop",action:"stop"},f:["Stop"]}," ",{p:[45,7,1929],t:7,e:"ui-button",a:{icon:"play",action:"go"},f:["Go"]}]}," ",{p:[47,5,2001],t:7,e:"ui-section",a:{label:"Home"},f:[{p:[48,7,2033],t:7,e:"ui-button",a:{icon:"home",action:"home"},f:["Go Home"]}," ",{p:[49,7,2096],t:7,e:"ui-button",a:{icon:"pencil",action:"sethome"},f:["Set Home"]}]}," ",{p:[51,5,2181],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[52,7,2217],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoReturn"],s:'_0?"check-square-o":"square-o"'},p:[52,24,2234]}],style:[{t:2,x:{r:["data.autoReturn"],s:'_0?"selected":null'},p:[52,84,2294]}],action:"autoret"},f:["Auto-Return Home"]}," ",{p:[54,7,2396],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoPickup"],s:'_0?"check-square-o":"square-o"'},p:[54,24,2413]}],style:[{t:2,x:{r:["data.autoPickup"],s:'_0?"selected":null'},p:[54,84,2473]}],action:"autopick"},f:["Auto-Pickup Crate"]}," ",{p:[56,7,2577],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.reportDelivery"],s:'_0?"check-square-o":"square-o"'},p:[56,24,2594]}],style:[{t:2,x:{r:["data.reportDelivery"],s:'_0?"selected":null'},p:[56,88,2658]}],action:"report"},f:["Report Deliveries"]}]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[31,1,1343]}]},e.exports=a.extend(r.exports)},{341:341}],409:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Chamber Console"},f:[{p:[2,1,44],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{t:4,f:[{p:[4,2,101],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]},{p:[4,63,162],t:7,e:"br"}," ",{t:4,f:[{p:[6,3,195],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[6,36,228]}]}," ",{p:[7,3,262],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[7,35,294]}]}," ",{p:[8,3,328],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["data.disk.activated"],s:'_0?"Active":"Inactive"'},p:[8,41,366]}]}," ",{t:4,f:[{p:[10,4,468],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"data.disk.activation_delay",p:[10,41,505]}]}],n:50,r:"data.disk.activation_delay",p:[9,3,430]}," ",{t:4,f:[{p:[13,4,588],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"data.disk.timer",p:[13,30,614]}]}," ",{p:[14,4,650],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"data.disk.timer_type",p:[14,36,682]}]}],n:50,r:"data.disk.timer",p:[12,3,561]}," ",{t:4,f:[{p:[17,4,769],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"data.disk.activation_code",p:[17,40,805]}]}],n:50,r:"data.disk.activation_code",p:[16,3,732]}," ",{t:4,f:[{p:[20,4,899],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"data.disk.deactivation_code",p:[20,42,937]}]}],n:50,r:"data.disk.deactivation_code",p:[19,3,860]}," ",{t:4,f:[{p:[23,4,1025],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"data.disk.kill_code",p:[23,34,1055]}]}],n:50,r:"data.disk.kill_code",p:[22,3,994]}," ",{t:4,f:[{p:[26,4,1138],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"data.disk.trigger_code",p:[26,37,1171]}]}],n:50,r:"data.disk.trigger_code",p:[25,3,1104]}," ",{t:4,f:[{t:4,f:[{p:[30,6,1303],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[30,25,1322]}]},f:[{t:2,r:"value",p:[30,35,1332]}]}],n:52,r:"data.disk.extra_settings",p:[29,4,1263]}],n:50,r:"data.disk.has_extra_settings",p:[28,3,1223]}],n:50,r:"data.has_program",p:[5,2,168]},{t:4,n:51,f:[{p:[34,3,1390],t:7,e:"ui-notice",f:["No program detected."]}],r:"data.has_program"}],n:50,r:"data.has_disk",p:[3,1,78]},{t:4,n:51,f:[{p:[37,2,1453],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"}]}," ",{p:[40,1,1511],t:7,e:"br"}," ",{t:4,f:[{p:[42,2,1541],t:7,e:"ui-notice",f:[{t:2,r:"data.status_msg",p:[42,13,1552]}]}],n:50,r:"data.status_msg",p:[41,1,1516]},{t:4,n:51,f:[{p:[44,2,1594],t:7,e:"ui-display",a:{title:"Chamber"},f:[{p:[45,2,1624],t:7,e:"ui-section",f:[{p:[45,14,1636],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock-open":"lock"'},p:[45,30,1652]}],action:"toggle_lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Unlock":"Lock"'},p:[45,90,1712]}," Chamber"]},{p:[45,146,1768],t:7,e:"br"}]}," ",{p:[46,2,1787],t:7,e:"ui-section",f:[{p:[46,14,1799],t:7,e:"b",f:["Occupant:"]}," ",{t:2,r:"data.occupant_name",p:[46,31,1816]}]}," ",{t:4,f:[{p:[48,4,1882],t:7,e:"ui-section",f:[{p:[48,16,1894],t:7,e:"ui-notice",f:["No nanites detected."]}]}," ",{p:[49,4,1954],t:7,e:"ui-section",f:[{p:[49,16,1966],t:7,e:"ui-button",a:{icon:"syringe",action:"nanite_injection"},f:["Implant Nanites"]}]}],n:50,x:{r:["data.has_nanites"],s:"!_0"},p:[47,2,1853]},{t:4,n:51,f:[{p:[51,3,2071],t:7,e:"ui-display",a:{title:"Nanites"},f:[{t:4,f:[{p:[53,5,2129],t:7,e:"ui-button",a:{icon:"download",action:"add_program"},f:["Install Program From Disk"]},{p:[53,90,2214],t:7,e:"br"}," ",{p:[54,5,2223],t:7,e:"br"}],n:50,r:"data.has_disk",p:[52,4,2103]}," ",{p:[56,4,2242],t:7,e:"ui-section",f:[{p:[57,5,2259],t:7,e:"ui-section",a:{label:"Nanite Volume"},f:[{t:2,r:"data.nanite_volume",p:[57,39,2293]}]}," ",{p:[58,5,2333],t:7,e:"ui-section",a:{label:"Growth Rate"},f:[{t:2,r:"data.regen_rate",p:[58,37,2365]}]}," ",{p:[59,5,2402],t:7,e:"ui-section",a:{label:"Safety Threshold"},f:[{t:2,r:"data.safety_threshold",p:[59,42,2439]}," ",{p:[59,68,2465],t:7,e:"ui-button",a:{icon:"pencil",action:"set_safety"},f:["Set"]}]}," ",{p:[60,5,2544],t:7,e:"ui-section",a:{label:"Cloud ID"},f:[{t:2,x:{r:["data.cloud_id"],s:'_0?_0:"No Cloud"'},p:[60,34,2573]}," ",{p:[60,82,2621],t:7,e:"ui-button",a:{icon:"pencil",action:"set_cloud"},f:["Set"]}]}]}," ",{p:[62,4,2715],t:7,e:"ui-display",a:{title:"Programs"},f:[{t:4,f:[{p:[64,6,2782],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[64,25,2801]}],button:0},f:[{p:[65,6,2824],t:7,e:"ui-button",a:{icon:"minus",action:"remove_program",params:['{"program_id": "',{t:2,r:"id",p:[65,78,2896]},'"}']},f:["Uninstall"]}," ",{p:[66,6,2933],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"desc",p:[66,38,2965]}]}," ",{t:4,f:[{p:[68,7,3027],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["activated"],s:'_0?"Active":"Inactive"'},p:[68,45,3065]}]}," ",{p:[69,7,3123],t:7,e:"ui-section",a:{label:"Nanites Consumed"},f:[{t:2,r:"use_rate",p:[69,44,3160]},"/s"]}," ",{t:4,f:[{p:[71,8,3221],t:7,e:"ui-section",a:{label:"Trigger Cost"},f:[{t:2,r:"trigger_cost",p:[71,41,3254]}]}," ",{p:[72,8,3291],t:7,e:"ui-section",a:{label:"Trigger Cooldown"},f:[{t:2,r:"trigger_cooldown",p:[72,45,3328]}," seconds"]}],n:50,r:"can_trigger",p:[70,7,3194]}," ",{t:4,f:[{t:4,f:[{p:[76,9,3459],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"activation_delay",p:[76,46,3496]}]}],n:50,r:"activation_delay",p:[75,8,3426]}," ",{t:4,f:[{p:[79,9,3574],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"timer",p:[79,35,3600]}]}," ",{p:[80,9,3631],t:7,e:"ui-section",a:{label:"Timer Type"},f:[{t:2,r:"timer_type",p:[80,40,3662]}]}],n:50,r:"timer",p:[78,8,3552]}," ",{t:4,f:[{t:4,f:[{p:[84,11,3782],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[84,30,3801]}]},f:[{t:2,r:"value",p:[84,40,3811]}]}],n:52,r:"extra_settings",p:[83,9,3747]}],n:50,r:"has_extra_settings",p:[82,8,3712]}," ",{t:4,f:[{t:4,f:[{p:[89,10,3944],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"activation_code",p:[89,46,3980]}]}],n:50,r:"activation_code",p:[88,9,3911]}," ",{t:4,f:[{p:[92,10,4072],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"deactivation_code",p:[92,48,4110]}]}],n:50,r:"deactivation_code",p:[91,9,4037]}," ",{t:4,f:[{p:[95,10,4196],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"kill_code",p:[95,40,4226]}]}],n:50,r:"kill_code",p:[94,9,4169]}," ",{t:4,f:[{p:[98,10,4307],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"trigger_code",p:[98,43,4340]}]}],n:50,r:"trigger_code",p:[97,9,4277]}],n:50,x:{r:["data.scan_level"],s:"_0>=4"},p:[87,8,3874]}],n:50,x:{r:["data.scan_level"],s:"_0>=3"},p:[74,7,3390]}],n:50,x:{r:["data.scan_level"],s:"_0>=2"},p:[67,6,2992]}]}],n:52,r:"data.mob_programs",p:[63,5,2749]}]}]}],x:{r:["data.has_nanites"],s:"!_0"}}]}],r:"data.status_msg"}]}]},e.exports=a.extend(r.exports)},{341:341}],410:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Cloud Console"},f:[{p:[2,1,42],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{t:4,f:[{p:[4,3,101],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]},{p:[4,64,162],t:7,e:"br"}," ",{t:4,f:[{p:[6,4,197],t:7,e:"ui-section",f:[{p:[7,5,214],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[7,38,247]}]}," ",{p:[8,5,283],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[8,37,315]}]}," ",{p:[9,5,351],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["data.disk.activated"],s:'_0?"Active":"Inactive"'},p:[9,43,389]}]}," ",{t:4,f:[{p:[11,6,495],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"data.disk.activation_delay",p:[11,43,532]}]}],n:50,r:"data.disk.activation_delay",p:[10,5,455]}," ",{t:4,f:[{p:[14,6,621],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"data.disk.timer",p:[14,32,647]}]}," ",{p:[15,6,685],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"data.disk.timer_type",p:[15,38,717]}]}],n:50,r:"data.disk.timer",p:[13,5,592]}," ",{t:4,f:[{p:[18,6,810],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"data.disk.activation_code",p:[18,42,846]}]}],n:50,r:"data.disk.activation_code",p:[17,5,771]}," ",{t:4,f:[{p:[21,6,946],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"data.disk.deactivation_code",p:[21,44,984]}]}],n:50,r:"data.disk.deactivation_code",p:[20,5,905]}," ",{t:4,f:[{p:[24,6,1078],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"data.disk.kill_code",p:[24,36,1108]}]}],n:50,r:"data.disk.kill_code",p:[23,5,1045]}," ",{t:4,f:[{p:[27,6,1197],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"data.disk.trigger_code",p:[27,39,1230]}]}],n:50,r:"data.disk.trigger_code",p:[26,5,1161]}," ",{t:4,f:[{t:4,f:[{p:[31,8,1370],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[31,27,1389]}]},f:[{t:2,r:"value",p:[31,37,1399]}]}],n:52,r:"data.disk.extra_settings",p:[30,6,1328]}],n:50,r:"data.disk.has_extra_settings",p:[29,5,1286]}]}],n:50,r:"data.has_program",p:[5,3,169]},{t:4,n:51,f:[{p:[36,4,1480],t:7,e:"ui-notice",f:["No program detected."]}],r:"data.has_program"}],n:50,r:"data.has_disk",p:[3,2,77]},{t:4,n:51,f:[{p:[39,3,1546],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"}]}," ",{p:[42,1,1605],t:7,e:"ui-display",a:{title:"Cloud Storage"},f:[{t:4,f:[{p:[44,3,1670],t:7,e:"ui-button",a:{icon:"plus-circle",action:"create_backup"},f:["Create New Backup"]}," ",{p:[45,3,1755],t:7,e:"ui-display",a:{title:"Active Backups"},f:[{t:4,f:[{p:[47,5,1827],t:7,e:"ui-button",a:{action:"set_view",params:['{"view": "',{t:2,r:"cloud_id",p:[47,52,1874]},'"}']},f:["Backup #",{t:2,r:"cloud_id",p:[47,76,1898]}]}],n:52,r:"data.cloud_backups",p:[46,4,1794]}]}],n:50,x:{r:["data.current_view"],s:"!_0"},p:[43,2,1641]},{t:4,n:51,f:[{p:[51,3,1964],t:7,e:"ui-button",a:{icon:"undo",action:"set_view",params:'{"view": "0"}'},f:["Return"]}," ",{t:4,f:[{p:[53,4,2079],t:7,e:"ui-notice",f:["ERROR: Backup not found."]}],n:50,x:{r:["data.cloud_backup"],s:"!_0"},p:[52,3,2049]},{t:4,n:51,f:[{p:[55,4,2141],t:7,e:"ui-display",a:{title:["Backup #",{t:2,r:"data.current_view",p:[55,31,2168]}]},f:[{t:4,f:[{p:[57,6,2226],t:7,e:"ui-button",a:{icon:"upload",action:"upload_program",style:"selected"},f:["Upload Program From Disk"]},{p:[57,108,2328],t:7,e:"br"}],n:50,r:"data.has_program",p:[56,5,2196]}," ",{t:4,f:[{p:[60,6,2384],t:7,e:"hr"}," ",{p:[61,6,2394],t:7,e:"ui-section",f:[{p:[62,7,2413],t:7,e:"h3",f:[{t:2,r:"name",p:[62,11,2417]}]}," ",{p:[63,7,2437],t:7,e:"div",a:{style:"float:right"},f:[{p:[64,8,2470],t:7,e:"ui-button",a:{icon:"minus-circle",action:"remove_program",style:"danger",params:['{"program_id": "',{t:2,r:"id",p:[64,102,2564]},'"}']},f:["Uninstall"]}]}]}," ",{p:[67,6,2633],t:7,e:"ui-section",f:[{p:[68,7,2652],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"desc",p:[68,39,2684]}]}," ",{p:[69,7,2712],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["activated"],s:'_0?"Active":"Inactive"'},p:[69,45,2750]}]}," ",{p:[70,7,2808],t:7,e:"ui-section",a:{label:"Nanites Consumed"},f:[{t:2,r:"use_rate",p:[70,44,2845]},"/s"]}," ",{t:4,f:[{p:[72,8,2906],t:7,e:"ui-section",a:{label:"Trigger Cost"},f:[{t:2,r:"trigger_cost",p:[72,41,2939]},"/s"]}," ",{p:[73,8,2978],t:7,e:"ui-section",a:{label:"Trigger Cooldown"},f:[{t:2,r:"trigger_cooldown",p:[73,45,3015]},"/s"]}],n:50,r:"can_trigger",p:[71,7,2879]}," ",{t:4,f:[{p:[76,8,3103],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"activation_delay",p:[76,45,3140]}]}],n:50,r:"activation_delay",p:[75,7,3071]}," ",{t:4,f:[{p:[79,8,3215],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"timer",p:[79,34,3241]}]}," ",{p:[80,8,3271],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"timer_type",p:[80,40,3303]}]}],n:50,r:"timer",p:[78,7,3194]}," ",{t:4,f:[{p:[83,8,3382],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"activation_code",p:[83,44,3418]}]}],n:50,r:"activation_code",p:[82,7,3351]}," ",{t:4,f:[{p:[86,8,3504],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"deactivation_code",p:[86,46,3542]}]}],n:50,r:"deactivation_code",p:[85,7,3471]}," ",{t:4,f:[{p:[89,8,3622],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"kill_code",p:[89,38,3652]}]}],n:50,r:"kill_code",p:[88,7,3597]}," ",{t:4,f:[{p:[92,8,3727],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"trigger_code",p:[92,41,3760]}]}],n:50,r:"trigger_code",p:[91,7,3699]}," ",{t:4,f:[{t:4,f:[{p:[96,10,3878],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[96,29,3897]}]},f:[{t:2,r:"value",p:[96,39,3907]}]}],n:52,r:"extra_settings",p:[95,8,3844]}],n:50,r:"has_extra_settings",p:[94,7,3810]}]}],n:52,r:"data.cloud_programs",p:[59,5,2349]}]}],x:{r:["data.cloud_backup"],s:"!_0"}}],x:{r:["data.current_view"],s:"!_0"}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],411:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Program Hub"},f:[{t:4,f:[{p:[3,2,63],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{p:[4,3,99],t:7,e:"ui-section",f:[{p:[5,4,115],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]}," ",{p:[6,4,180],t:7,e:"ui-button",a:{icon:"minus-circle",action:"clear"},f:["Delete Program"]}]}," ",{t:4,f:[{p:[9,4,299],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[9,37,332]}]}," ",{p:[10,4,367],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[10,36,399]}]}],n:50,r:"data.has_program",p:[8,3,271]},{t:4,n:51,f:[{p:[12,4,445],t:7,e:"ui-notice",f:["No program installed."]}],r:"data.has_program"}]}],n:50,r:"data.has_disk",p:[2,1,40]},{t:4,n:51,f:[{p:[16,2,525],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"},{p:[18,1,569],t:7,e:"br"}," ",{p:[19,1,574],t:7,e:"ui-display",a:{title:"Programs"},f:[{p:[20,2,605],t:7,e:"ui-section",f:[{p:[21,3,620],t:7,e:"ui-button",a:{icon:"undo",action:"set_category",params:'{"category": "Main"}'},f:["Return"]}," ",{p:[22,3,716],t:7,e:"ui-button",a:{icon:"align-justify ",action:"toggle_details"},f:[{t:2,x:{r:["data.detail_view"],s:'_0?"Compact View":"Detailed View"'},p:[22,60,773]}]}]}," ",{t:4,f:[{p:[25,3,892],t:7,e:"ui-display",f:[{t:4,f:[{p:[27,5,938],t:7,e:"ui-section",f:[{p:[27,17,950],t:7,e:"ui-button",a:{action:"set_category",params:['{"category": "',{t:2,r:"name",p:[27,72,1005]},'"}']},f:[{t:2,r:"name",p:[27,84,1017]}]}]}],n:52,r:"data.categories",p:[26,4,908]}]}],n:50,x:{r:["data.category"],s:'_0=="Main"'},p:[24,2,858]},{t:4,n:51,f:[{p:[31,3,1092],t:7,e:"ui-display",a:{title:[{t:2,r:"data.category",p:[31,22,1111]}]},f:[{t:4,f:[{t:4,f:[{p:[34,6,1196],t:7,e:"ui-display",f:[{p:[35,7,1215],t:7,e:"ui-section",f:[{p:[35,19,1227],t:7,e:"b",f:[{t:2,r:"name",p:[35,22,1230]}]}]}," ",{p:[36,7,1262],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[36,19,1274]}]}," ",{p:[37,7,1302],t:7,e:"ui-section",f:[{p:[38,8,1322],t:7,e:"ui-button",a:{icon:"download",action:"download",params:['{"program_id": "',{t:2,r:"id",p:[38,77,1391]},'"}'],state:[{t:2,x:{r:["data.has_disk"],s:'_0?null:"disabled"'},p:[38,94,1408]}]},f:["Download"]}]}]}],n:50,r:"data.detail_view",p:[33,5,1166]},{t:4,n:51,f:[{p:[44,6,1542],t:7,e:"ui-section",f:[{p:[44,18,1554],t:7,e:"ui-button",a:{action:"download",params:['{"program_id": "',{t:2,r:"id",p:[44,71,1607]},'"}']},f:[{t:2,r:"name",p:[44,81,1617]}]}]}],r:"data.detail_view"}],n:52,r:"data.program_list",p:[32,4,1134]}]}],x:{r:["data.category"],s:'_0=="Main"'}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],412:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Programming"},f:[{t:4,f:[{p:[3,3,65],t:7,e:"ui-notice",f:["Insert a nanite program disk."]}],n:50,x:{r:["data.has_disk"],s:"!_0"},p:[2,1,40]},{t:4,n:51,f:[{p:[5,3,129],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]}," ",{t:4,f:[{p:[7,5,223],t:7,e:"ui-notice",f:["No program detected."]}],n:50,x:{r:["data.has_program"],s:"!_0"},p:[6,3,193]},{t:4,n:51,f:[{p:[9,5,282],t:7,e:"ui-section",f:[{p:[10,7,301],t:7,e:"ui-display",a:{title:[{t:2,r:"data.name",p:[10,26,320]}]},f:[{t:2,r:"data.desc",p:[11,9,344]}]}]}," ",{p:[14,5,400],t:7,e:"ui-section",f:[{p:[15,7,419],t:7,e:"ui-section",a:{label:"Program Info"},f:["Nanites Consumed: ",{t:2,r:"data.use_rate",p:[16,26,478]},{p:[16,43,495],t:7,e:"br"}," ",{t:4,f:["Trigger Cost: ",{t:2,r:"data.trigger_cost",p:[18,25,557]},"u",{p:[18,47,579],t:7,e:"br"}],n:50,r:"data.can_trigger",p:[17,9,508]}]}," ",{p:[22,7,627],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[23,9,663],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.activated"],s:'_0?"toggle-on":"toggle-off"'},p:[24,17,690]}],action:"toggle_active"},f:[{t:2,x:{r:["data.activated"],s:'_0?"Active":"Inactive"'},p:[26,11,784]}]}]}," ",{p:[30,7,876],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[31,9,914],t:7,e:"ui-button",a:{icon:"pencil",action:"set_activation_delay"}}," Activation Delay: ",{t:2,r:"data.activation_delay",p:[31,95,1e3]}," ",{p:[31,121,1026],t:7,e:"br"}," ",{p:[32,9,1039],t:7,e:"ui-button",a:{icon:"pencil",action:"set_timer"}}," Timer: ",{t:2,r:"data.timer",p:[32,73,1103]}," ",{p:[32,88,1118],t:7,e:"br"}," ",{p:[33,9,1131],t:7,e:"ui-button",a:{icon:"pencil",action:"set_timer_type"}}," Timer Type: ",{t:2,r:"data.timer_type",p:[33,83,1205]}," ",{p:[33,103,1225],t:7,e:"br"}]}," ",{p:[36,7,1257],t:7,e:"ui-section",a:{label:"Codes"},f:[{p:[37,9,1292],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "activation"}'}}," Activation Code: ",{t:2,r:"data.activation_code",p:[37,121,1404]}," ",{p:[37,146,1429],t:7,e:"br"}," ",{p:[38,9,1442],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "deactivation"}'}}," Deactivation Code: ",{t:2,r:"data.deactivation_code",p:[38,125,1558]}," ",{p:[38,152,1585],t:7,e:"br"}," ",{p:[39,9,1598],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "kill"}'}}," Kill Code: ",{t:2,r:"data.kill_code",p:[39,109,1698]}," ",{p:[39,128,1717],t:7,e:"br"}," ",{t:4,f:[{p:[41,11,1765],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "trigger"}'}}," Trigger Code: ",{t:2,r:"data.trigger_code",p:[41,117,1871]}," ",{p:[41,139,1893],t:7,e:"br"}],n:50,r:"data.can_trigger",p:[40,9,1730]}]}," ",{t:4,f:[{p:[46,9,1981],t:7,e:"ui-section",a:{label:"Special"},f:[{t:4,f:[{p:[48,13,2062],t:7,e:"ui-button",a:{icon:"pencil",action:"set_extra_setting",params:['{"target_setting": "',{t:2,r:"name",p:[48,93,2142]},'"}']}}," ",{t:2,r:"name",p:[48,118,2167]},": ",{t:2,r:"value",p:[48,128,2177]}," ",{p:[48,138,2187],t:7,e:"br"}],n:52,r:"data.extra_settings",p:[47,11,2020]}]}],n:50,r:"data.has_extra_settings",p:[45,7,1941]}]}],x:{r:["data.has_program"],s:"!_0"}}],x:{r:["data.has_disk"],s:"!_0"}}]}]},e.exports=a.extend(r.exports)},{341:341}],413:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Control"},f:[{t:4,f:[{p:[3,3,58],t:7,e:"ui-notice",f:["The interface is locked."]}],n:50,r:"data.locked",p:[2,1,36]},{t:4,n:51,f:[{p:[5,3,117],t:7,e:"ui-button",a:{icon:"lock",action:"lock"},f:["Lock Interface"]}," ",{p:[6,3,183],t:7,e:"ui-button",a:{icon:"save",action:"save"},f:["Save Current Setting"]}," ",{p:[7,3,255],t:7,e:"ui-section",a:{label:"Signal Code"},f:[{p:[8,5,292],t:7,e:"span",f:[{t:2,r:"data.code",p:[8,11,298]}]}," ",{p:[9,4,322],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code"},f:["Set"]}]}," ",{t:4,f:[{p:[12,5,432],t:7,e:"ui-section",a:{label:"Relay Code"},f:[{p:[13,7,470],t:7,e:"span",f:[{t:2,r:"data.relay_code",p:[13,13,476]}]}," ",{p:[14,5,507],t:7,e:"ui-button",a:{icon:"pencil",action:"set_relay_code"},f:["Set"]}]}],n:50,x:{r:["data.mode"],s:'_0=="Relay"'},p:[11,3,399]}," ",{p:[17,3,602],t:7,e:"ui-section",a:{label:"Signal Mode"},f:[{p:[18,5,639],t:7,e:"span",f:[{t:2,r:"data.mode",p:[18,11,645]}]}," ",{p:[19,5,670],t:7,e:"br"}," ",{p:[20,4,678],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Off"}'},f:["Off"]}," ",{p:[21,5,755],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Local"}'},f:["Local"]}," ",{p:[22,5,836],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Targeted"}'},f:["Targeted"]}," ",{p:[23,5,923],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Area"}'},f:["Area"]}," ",{p:[24,5,1002],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Relay"}'},f:["Relay"]}]}],r:"data.locked"}]}," ",{p:[28,1,1117],t:7,e:"ui-display",a:{title:"Saved Settings"},f:[{t:4,f:[{p:[30,3,1186],t:7,e:"ui-button",a:{icon:"load",action:"load",params:['{"save_id": "',{t:2,r:"id",p:[30,61,1244]},'"}']},f:[{t:2,r:"name",p:[30,71,1254]}]}," ",{t:4,f:[{p:[32,4,1301],t:7,e:"ui-button",a:{icon:"remove",action:"remove_save",params:['{"save_id": "',{t:2,r:"id",p:[32,71,1368]},'"}']},f:["Remove"]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[31,3,1277]}," ",{p:[34,3,1409],t:7,e:"br"}],n:52,r:"data.saved_settings",p:[29,2,1154]}]}]},e.exports=a.extend(r.exports)},{341:341}],414:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Ghost roles"},f:[{p:[2,2,34],t:7,e:"ui-section",a:{label:"Ignored roles"},f:[{t:4,f:[{p:[4,4,96],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["enabled"],s:'_0?"check-square-o":"square-o"'},p:[4,21,113]}],style:[{t:2,x:{r:["enabled"],s:'_0?"danger":null'},p:[4,73,165]}],action:"toggle_ignore",params:['{"key": "',{t:2,r:"key",p:[4,144,236]},'"}']},f:[{t:2,r:"desc",p:[4,155,247]}]}],n:52,r:"data.ignore",p:[3,3,71]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],415:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Relay"},f:[{t:4,f:[{p:[3,3,55],t:7,e:"h2",f:["NETWORK BUFFERS OVERLOADED"]}," ",{p:[4,3,93],t:7,e:"h3",f:["Overload Recovery Mode"]}," ",{p:[5,3,127],t:7,e:"i",f:["This system is suffering temporary outage due to overflow of traffic buffers. Until buffered traffic is processed, all further requests will be dropped. Frequent occurences of this error may indicate insufficient hardware capacity of your network. Please contact your network planning department for instructions on how to resolve this issue."] -}," ",{p:[6,3,479],t:7,e:"h3",f:["ADMINISTRATIVE OVERRIDE"]}," ",{p:[7,3,514],t:7,e:"b",f:["CAUTION - Data loss may occur"]}," ",{p:[8,3,555],t:7,e:"ui-button",a:{icon:"signal",action:"restart"},f:["Purge buffered traffic"]}],n:50,r:"data.dos_crashed",p:[2,2,28]},{t:4,n:51,f:[{p:[12,3,652],t:7,e:"ui-section",a:{label:"Relay status"},f:[{p:[13,4,689],t:7,e:"ui-button",a:{icon:"power-off",action:"toggle"},f:[{t:2,x:{r:["data.enabled"],s:'_0?"ENABLED":"DISABLED"'},p:[14,6,739]}]}]}," ",{p:[18,3,819],t:7,e:"ui-section",a:{label:"Network buffer status"},f:[{t:2,r:"data.dos_overload",p:[19,4,865]}," / ",{t:2,r:"data.dos_capacity",p:[19,28,889]}," GQ"]}],r:"data.dos_crashed"}]}]},e.exports=a.extend(r.exports)},{341:341}],416:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{healthState:function(){var t=this.get("data.health");return t>70?"good":t>50?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[15,1,306],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[18,3,346],t:7,e:"ui-notice",f:[{p:[19,5,362],t:7,e:"span",f:["Reconstruction in progress!"]}]}],n:50,r:"data.restoring",p:[17,1,321]},{p:[24,1,428],t:7,e:"ui-display",f:[{p:[26,1,442],t:7,e:"div",a:{"class":"item"},f:[{p:[27,3,463],t:7,e:"div",a:{"class":"itemLabel"},f:["Inserted AI:"]}," ",{p:[30,3,512],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[31,2,539],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",state:[{t:2,x:{r:["data.nocard"],s:'_0?"disabled":null'},p:[31,52,589]}]},f:[{t:2,x:{r:["data.name"],s:'_0?_0:"---"'},p:[31,89,626]}]}]}]}," ",{t:4,f:[{p:[36,2,709],t:7,e:"b",f:["ERROR: ",{t:2,r:"data.error",p:[36,12,719]}]}],n:50,r:"data.error",p:[35,1,689]},{t:4,n:51,f:[{p:[38,2,748],t:7,e:"h2",f:["System Status"]}," ",{p:[39,2,772],t:7,e:"div",a:{"class":"item"},f:[{p:[40,3,793],t:7,e:"div",a:{"class":"itemLabel"},f:["Current AI:"]}," ",{p:[43,3,843],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.name",p:[44,4,872]}]}," ",{p:[46,3,897],t:7,e:"div",a:{"class":"itemLabel"},f:["Status:"]}," ",{p:[49,3,943],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["Nonfunctional"],n:50,r:"data.isDead",p:[50,4,972]},{t:4,n:51,f:["Functional"],r:"data.isDead"}]}," ",{p:[56,3,1059],t:7,e:"div",a:{"class":"itemLabel"},f:["System Integrity:"]}," ",{p:[59,3,1115],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[60,4,1144],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.health",p:[60,37,1177]}],state:[{t:2,r:"healthState",p:[61,11,1204]}]},f:[{t:2,x:{r:["adata.health"],s:"Math.round(_0)"},p:[61,28,1221]},"%"]}]}," ",{p:[63,3,1274],t:7,e:"div",a:{"class":"itemLabel"},f:["Active Laws:"]}," ",{p:[66,3,1325],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[67,4,1354],t:7,e:"table",f:[{t:4,f:[{p:[69,6,1394],t:7,e:"tr",f:[{p:[69,10,1398],t:7,e:"td",f:[{p:[69,14,1402],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:".",p:[69,38,1426]}]}]}]}],n:52,r:"data.ai_laws",p:[68,5,1366]}]}]}," ",{p:[73,2,1475],t:7,e:"ui-section",a:{label:"Operations"},f:[{p:[74,3,1509],t:7,e:"ui-button",a:{icon:"plus",style:[{t:2,x:{r:["data.restoring"],s:'_0?"disabled":null'},p:[74,33,1539]}],action:"PRG_beginReconstruction"},f:["Begin Reconstruction"]}]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],417:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[5,1,87],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"home",params:'{"target" : "mod"}',state:[{t:2,x:{r:["data.mmode"],s:'_0==1?"disabled":null'},p:[5,80,166]}]},f:["Access Modification"]}],n:50,r:"data.have_id_slot",p:[4,1,61]},{p:[7,1,247],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"folder-open",params:'{"target" : "manage"}',state:[{t:2,x:{r:["data.mmode"],s:'_0==2?"disabled":null'},p:[7,90,336]}]},f:["Job Management"]}," ",{p:[8,1,404],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"folder-open",params:'{"target" : "manifest"}',state:[{t:2,x:{r:["data.mmode"],s:'!_0?"disabled":null'},p:[8,92,495]}]},f:["Crew Manifest"]}," ",{t:4,f:[{p:[10,1,584],t:7,e:"ui-button",a:{action:"PRG_print",icon:"print",state:[{t:2,x:{r:["data.has_id","data.mmode"],s:'!_1||_0&&_1==1?null:"disabled"'},p:[10,51,634]}]},f:["Print"]}],n:50,r:"data.have_printer",p:[9,1,558]},{t:4,f:[{p:[14,1,753],t:7,e:"div",a:{"class":"item"},f:[{p:[15,3,774],t:7,e:"h2",f:["Crew Manifest"]}," ",{p:[16,3,799],t:7,e:"br"},"Please use security record computer to modify entries.",{p:[16,61,857],t:7,e:"br"},{p:[16,65,861],t:7,e:"br"}]}," ",{t:4,f:[{p:[19,2,898],t:7,e:"div",a:{"class":"item"},f:[{t:2,r:"name",p:[20,2,918]}," - ",{t:2,r:"rank",p:[20,13,929]}]}],n:52,r:"data.manifest",p:[18,1,873]}],n:50,x:{r:["data.mmode"],s:"!_0"},p:[13,1,733]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.mmode"],s:"_0==2"},f:[{p:[25,1,984],t:7,e:"div",a:{"class":"item"},f:[{p:[26,3,1005],t:7,e:"h2",f:["Job Management"]}]}," ",{p:[28,1,1036],t:7,e:"table",f:[{p:[29,1,1044],t:7,e:"tr",f:[{p:[29,5,1048],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,27,1070],t:7,e:"b",f:["Job"]}]},{p:[29,42,1085],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,64,1107],t:7,e:"b",f:["Slots"]}]},{p:[29,81,1124],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,103,1146],t:7,e:"b",f:["Open job"]}]},{p:[29,123,1166],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,145,1188],t:7,e:"b",f:["Close job"]}]}]}," ",{t:4,f:[{p:[32,2,1238],t:7,e:"tr",f:[{p:[32,6,1242],t:7,e:"td",f:[{t:2,r:"title",p:[32,10,1246]}]},{p:[32,24,1260],t:7,e:"td",f:[{t:2,r:"current",p:[32,28,1264]},"/",{t:2,r:"total",p:[32,40,1276]}]},{p:[32,54,1290],t:7,e:"td",f:[{p:[32,58,1294],t:7,e:"ui-button",a:{action:"PRG_open_job",params:['{"target" : "',{t:2,r:"title",p:[32,112,1348]},'"}'],state:[{t:2,x:{r:["status_open"],s:'_0?null:"disabled"'},p:[32,132,1368]}]},f:[{t:2,r:"desc_open",p:[32,169,1405]}]},{p:[32,194,1430],t:7,e:"br"}]},{p:[32,203,1439],t:7,e:"td",f:[{p:[32,207,1443],t:7,e:"ui-button",a:{action:"PRG_close_job",params:['{"target" : "',{t:2,r:"title",p:[32,262,1498]},'"}'],state:[{t:2,x:{r:["status_close"],s:'_0?null:"disabled"'},p:[32,282,1518]}]},f:[{t:2,r:"desc_close",p:[32,320,1556]}]}]}]}],n:52,r:"data.slots",p:[30,1,1215]}]}]},{t:4,n:50,x:{r:["data.mmode"],s:"!(_0==2)"},f:[" ",{p:[40,1,1626],t:7,e:"div",a:{"class":"item"},f:[{p:[41,3,1647],t:7,e:"h2",f:["Access Modification"]}]}," ",{t:4,f:[{p:[45,3,1707],t:7,e:"span",a:{"class":"alert"},f:[{p:[45,23,1727],t:7,e:"i",f:["Please insert the ID into the terminal to proceed."]}]},{p:[45,87,1791],t:7,e:"br"}],n:50,x:{r:["data.has_id"],s:"!_0"},p:[44,1,1684]},{p:[48,1,1805],t:7,e:"div",a:{"class":"item"},f:[{p:[49,3,1826],t:7,e:"div",a:{"class":"itemLabel"},f:["Target Identity:"]}," ",{p:[52,3,1879],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[53,2,1906],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",params:'{"target" : "id"}'},f:[{t:2,r:"data.id_name",p:[53,72,1976]}]}]}]}," ",{p:[56,1,2021],t:7,e:"div",a:{"class":"item"},f:[{p:[57,3,2042],t:7,e:"div",a:{"class":"itemLabel"},f:["Auth Identity:"]}," ",{p:[60,3,2093],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[61,2,2120],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",params:'{"target" : "auth"}'},f:[{t:2,r:"data.auth_name",p:[61,74,2192]}]}]}]}," ",{p:[64,1,2239],t:7,e:"hr"}," ",{t:4,f:[{t:4,f:[{p:[68,2,2295],t:7,e:"div",a:{"class":"item"},f:[{p:[69,4,2317],t:7,e:"h2",f:["Details"]}]}," ",{t:4,f:[{p:[73,2,2364],t:7,e:"div",a:{"class":"item"},f:[{p:[74,4,2386],t:7,e:"div",a:{"class":"itemLabel"},f:["Registered Name:"]}," ",{p:[77,4,2442],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.id_owner",p:[78,3,2470]}]}]}," ",{p:[81,2,2507],t:7,e:"div",a:{"class":"item"},f:[{p:[82,4,2529],t:7,e:"div",a:{"class":"itemLabel"},f:["Rank:"]}," ",{p:[85,4,2574],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.id_rank",p:[86,3,2602]}]}]}," ",{p:[89,2,2638],t:7,e:"div",a:{"class":"item"},f:[{p:[90,4,2660],t:7,e:"div",a:{"class":"itemLabel"},f:["Demote:"]}," ",{p:[93,4,2707],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[94,3,2735],t:7,e:"ui-button",a:{action:"PRG_terminate",icon:"gear",state:[{t:2,x:{r:["data.id_rank"],s:'_0=="Unassigned"?"disabled":null'},p:[94,56,2788]}]},f:["Demote ",{t:2,r:"data.id_owner",p:[94,117,2849]}]}]}]}],n:50,r:"data.minor",p:[72,2,2344]},{t:4,n:51,f:[{p:[99,2,2909],t:7,e:"div",a:{"class":"item"},f:[{p:[100,4,2931],t:7,e:"div",a:{"class":"itemLabel"},f:["Registered Name:"]}," ",{p:[103,4,2987],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[104,3,3015],t:7,e:"ui-button",a:{action:"PRG_edit",icon:"pencil",params:'{"name" : "1"}'},f:[{t:2,r:"data.id_owner",p:[104,70,3082]}]}]}]}," ",{p:[108,2,3132],t:7,e:"div",a:{"class":"item"},f:[{p:[109,4,3154],t:7,e:"h2",f:["Assignment"]}]}," ",{p:[111,3,3184],t:7,e:"ui-button",a:{action:"PRG_togglea",icon:"gear"},f:[{t:2,x:{r:["data.assignments"],s:'_0?"Hide assignments":"Show assignments"'},p:[111,47,3228]}]}," ",{p:[112,2,3304],t:7,e:"div",a:{"class":"item"},f:[{p:[113,4,3326],t:7,e:"span",a:{id:"allvalue.jobsslot"},f:[]}]}," ",{p:[117,2,3379],t:7,e:"div",a:{"class":"item"},f:[{t:4,f:[{p:[119,4,3429],t:7,e:"div",a:{id:"all-value.jobs"},f:[{p:[120,3,3457],t:7,e:"table",f:[{p:[121,5,3469],t:7,e:"tr",f:[{p:[122,4,3477],t:7,e:"th",f:["Command"]}," ",{p:[123,4,3497],t:7,e:"td",f:[{p:[124,6,3507],t:7,e:"ui-button",a:{action:"PRG_assign",params:'{"assign_target" : "Captain"}',state:[{t:2,x:{r:["data.id_rank"],s:'_0=="Captain"?"selected":null'},p:[124,83,3584]}]},f:["Captain"]}]}]}," ",{p:[127,5,3678],t:7,e:"tr",f:[{p:[128,4,3686],t:7,e:"th",f:["Special"]}," ",{p:[129,4,3706],t:7,e:"td",f:[{p:[130,6,3716],t:7,e:"ui-button",a:{action:"PRG_assign",params:'{"assign_target" : "Custom"}'},f:["Custom"]}]}]}," ",{p:[133,5,3827],t:7,e:"tr",f:[{p:[134,4,3835],t:7,e:"th",a:{style:"color: '#FFA500';"},f:["Engineering"]}," ",{p:[135,4,3885],t:7,e:"td",f:[{t:4,f:[{p:[137,5,3931],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[137,64,3990]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[137,82,4008]}]},f:[{t:2,r:"display_name",p:[137,127,4053]}]}],n:52,r:"data.engineering_jobs",p:[136,6,3895]}]}]}," ",{p:[141,5,4120],t:7,e:"tr",f:[{p:[142,4,4128],t:7,e:"th",a:{style:"color: '#008000';"},f:["Medical"]}," ",{p:[143,4,4174],t:7,e:"td",f:[{t:4,f:[{p:[145,5,4216],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[145,64,4275]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[145,82,4293]}]},f:[{t:2,r:"display_name",p:[145,127,4338]}]}],n:52,r:"data.medical_jobs",p:[144,6,4184]}]}]}," ",{p:[149,5,4405],t:7,e:"tr",f:[{p:[150,4,4413],t:7,e:"th",a:{style:"color: '#800080';"},f:["Science"]}," ",{p:[151,4,4459],t:7,e:"td",f:[{t:4,f:[{p:[153,5,4501],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[153,64,4560]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[153,82,4578]}]},f:[{t:2,r:"display_name",p:[153,127,4623]}]}],n:52,r:"data.science_jobs",p:[152,6,4469]}]}]}," ",{p:[157,5,4690],t:7,e:"tr",f:[{p:[158,4,4698],t:7,e:"th",a:{style:"color: '#DD0000';"},f:["Security"]}," ",{p:[159,4,4745],t:7,e:"td",f:[{t:4,f:[{p:[161,5,4788],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[161,64,4847]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[161,82,4865]}]},f:[{t:2,r:"display_name",p:[161,127,4910]}]}],n:52,r:"data.security_jobs",p:[160,6,4755]}]}]}," ",{p:[165,5,4977],t:7,e:"tr",f:[{p:[166,4,4985],t:7,e:"th",a:{style:"color: '#cc6600';"},f:["Cargo"]}," ",{p:[167,4,5029],t:7,e:"td",f:[{t:4,f:[{p:[169,5,5069],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[169,64,5128]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[169,82,5146]}]},f:[{t:2,r:"display_name",p:[169,127,5191]}]}],n:52,r:"data.cargo_jobs",p:[168,6,5039]}]}]}," ",{p:[173,5,5258],t:7,e:"tr",f:[{p:[174,4,5266],t:7,e:"th",a:{style:"color: '#808080';"},f:["Civilian"]}," ",{p:[175,4,5313],t:7,e:"td",f:[{t:4,f:[{p:[177,5,5356],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[177,64,5415]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[177,82,5433]}]},f:[{t:2,r:"display_name",p:[177,127,5478]}]}],n:52,r:"data.civilian_jobs",p:[176,6,5323]}]}]}," ",{t:4,f:[{p:[182,4,5576],t:7,e:"tr",f:[{p:[183,6,5586],t:7,e:"th",a:{style:"color: '#A52A2A';"},f:["CentCom"]}," ",{p:[184,6,5634],t:7,e:"td",f:[{t:4,f:[{p:[186,7,5677],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[186,66,5736]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[186,84,5754]}]},f:[{t:2,r:"display_name",p:[186,129,5799]}]}],n:52,r:"data.centcom_jobs",p:[185,5,5643]}]}]}],n:50,r:"data.centcom_access",p:[181,5,5545]}]}]}],n:50,r:"data.assignments",p:[118,4,3401]}]}],r:"data.minor"}," ",{t:4,f:[{p:[198,4,5956],t:7,e:"div",a:{"class":"item"},f:[{p:[199,3,5977],t:7,e:"h2",f:["Central Command"]}]}," ",{p:[201,4,6015],t:7,e:"div",a:{"class":"item",style:"width: 100%"},f:[{t:4,f:[{p:[203,5,6094],t:7,e:"div",a:{"class":"itemContentWide"},f:[{p:[204,5,6128],t:7,e:"ui-button",a:{action:"PRG_access",params:['{"access_target" : "',{t:2,r:"ref",p:[204,64,6187]},'", "allowed" : "',{t:2,r:"allowed",p:[204,87,6210]},'"}'],state:[{t:2,x:{r:["allowed"],s:'_0?"toggle":null'},p:[204,109,6232]}]},f:[{t:2,r:"desc",p:[204,140,6263]}]}]}],n:52,r:"data.all_centcom_access",p:[202,3,6056]}]}],n:50,r:"data.centcom_access",p:[197,2,5925]},{t:4,n:51,f:[{p:[209,4,6330],t:7,e:"div",a:{"class":"item"},f:[{p:[210,3,6351],t:7,e:"h2",f:[{t:2,r:"data.station_name",p:[210,7,6355]}]}]}," ",{p:[212,4,6395],t:7,e:"div",a:{"class":"item",style:"width: 100%"},f:[{t:4,f:[{p:[214,5,6463],t:7,e:"div",a:{style:"float: left; width: 175px; min-height: 250px"},f:[{p:[215,4,6525],t:7,e:"div",a:{"class":"average"},f:[{p:[215,25,6546],t:7,e:"ui-button",a:{action:"PRG_regsel",state:[{t:2,x:{r:["selected"],s:'_0?"toggle":null'},p:[215,63,6584]}],params:['{"region" : "',{t:2,r:"regid",p:[215,116,6637]},'"}']},f:[{p:[215,129,6650],t:7,e:"b",f:[{t:2,r:"name",p:[215,132,6653]}]}]}]}," ",{p:[216,4,6687],t:7,e:"br"}," ",{t:4,f:[{p:[218,6,6721],t:7,e:"div",a:{"class":"itemContentWide"},f:[{p:[219,5,6755],t:7,e:"ui-button",a:{action:"PRG_access",params:['{"access_target" : "',{t:2,r:"ref",p:[219,64,6814]},'", "allowed" : "',{t:2,r:"allowed",p:[219,87,6837]},'"}'],state:[{t:2,x:{r:["allowed"],s:'_0?"toggle":null'},p:[219,109,6859]}]},f:[{t:2,r:"desc",p:[219,140,6890]}]}]}],n:52,r:"accesses",p:[217,6,6697]}]}],n:52,r:"data.regions",p:[213,3,6436]}]}],r:"data.centcom_access"}],n:50,r:"data.has_id",p:[67,3,2274]}],n:50,r:"data.authenticated",p:[66,1,2245]}]}],x:{r:["data.mmode"],s:"!_0"}}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],418:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargeState:function(t){var e=this.get("data.battery.max");return t>e/2?"good":t>e/4?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[15,1,297],t:7,e:"ntosheader"}," ",{p:[17,1,312],t:7,e:"ui-display",f:[{p:[18,2,326],t:7,e:"i",f:["Welcome to computer configuration utility. Please consult your system administrator if you have any questions about your device."]},{p:[18,137,461],t:7,e:"hr"}," ",{p:[19,2,467],t:7,e:"ui-display",a:{title:"Power Supply"},f:[{p:[20,3,503],t:7,e:"ui-section",a:{label:"Power Usage"},f:[{t:2,r:"data.power_usage",p:[21,4,539]},"W"]}," ",{t:4,f:[{p:[25,4,606],t:7,e:"ui-section",a:{label:"Battery Status"},f:["Active"]}," ",{p:[28,4,674],t:7,e:"ui-section",a:{label:"Battery Rating"},f:[{t:2,r:"data.battery.max",p:[29,5,714]}]}," ",{p:[31,4,755],t:7,e:"ui-section",a:{label:"Battery Charge"},f:[{p:[32,5,795],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.battery.max",p:[32,26,816]}],value:[{t:2,r:"adata.battery.charge",p:[32,56,846]}],state:[{t:2,x:{r:["chargeState","adata.battery.charge"],s:"_0(_1)"},p:[32,89,879]}]},f:[{t:2,x:{r:["adata.battery.charge"],s:"Math.round(_0)"},p:[32,128,918]},"/",{t:2,r:"adata.battery.max",p:[32,165,955]}]}]}],n:50,r:"data.battery",p:[24,3,582]},{t:4,n:51,f:[{p:[35,4,1017],t:7,e:"ui-section",a:{label:"Battery Status"},f:["Not Available"]}],r:"data.battery"}]}," ",{p:[41,2,1116],t:7,e:"ui-display",a:{title:"File System"},f:[{p:[42,3,1151],t:7,e:"ui-section",a:{label:"Used Capacity"},f:[{p:[43,4,1189],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.disk_size",p:[43,25,1210]}],value:[{t:2,r:"adata.disk_used",p:[43,53,1238]}],state:"good"},f:[{t:2,x:{r:["adata.disk_used"],s:"Math.round(_0)"},p:[43,87,1272]},"GQ / ",{t:2,r:"adata.disk_size",p:[43,123,1308]},"GQ"]}]}]}," ",{p:[47,2,1373],t:7,e:"ui-display",a:{title:"Computer Components"},f:[{t:4,f:[{p:[49,4,1443],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"name",p:[49,26,1465]}]},f:[{p:[50,5,1480],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"desc",p:[50,59,1534]}]}," ",{p:[52,5,1554],t:7,e:"ui-section",a:{label:"State"},f:[{p:[53,6,1586],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["critical"],s:'_0?"disabled":null'},p:[53,24,1604]}],action:"PC_toggle_component",params:['{"name": "',{t:2,r:"name",p:[53,105,1685]},'"}']},f:[{t:2,x:{r:["enabled"],s:'_0?"Enabled":"Disabled"'},p:[54,7,1704]}]}]}," ",{t:4,f:[{p:[59,6,1810],t:7,e:"ui-section",a:{label:"Power Usage"},f:[{t:2,r:"powerusage",p:[60,7,1849]},"W"]}],n:50,r:"powerusage",p:[58,5,1786]}]}," ",{p:[64,4,1922],t:7,e:"br"}],n:52,r:"data.hardware",p:[48,3,1416]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],419:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{t:4,f:[{p:[7,3,97],t:7,e:"h2",f:["An error has occurred and this program can not continue."]}," Additional information: ",{t:2,r:"data.error",p:[8,27,189]},{p:[8,41,203],t:7,e:"br"}," ",{p:[9,3,210],t:7,e:"i",f:["Please try again. If the problem persists contact your system administrator for assistance."]}," ",{p:[10,3,311],t:7,e:"ui-button",a:{action:"PRG_closefile"},f:["Restart program"]}],n:50,r:"data.error",p:[6,2,76]},{t:4,n:51,f:[{t:4,f:[{p:[13,4,410],t:7,e:"h2",f:["Viewing file ",{t:2,r:"data.filename",p:[13,21,427]}]}," ",{p:[14,4,453],t:7,e:"div",a:{"class":"item"},f:[{p:[15,4,475],t:7,e:"ui-button",a:{action:"PRG_closefile"},f:["CLOSE"]}," ",{p:[16,4,530],t:7,e:"ui-button",a:{action:"PRG_edit"},f:["EDIT"]}," ",{p:[17,4,579],t:7,e:"ui-button",a:{action:"PRG_printfile"},f:["PRINT"]}," "]},{p:[18,10,640],t:7,e:"hr"}," ",{t:3,r:"data.filedata",p:[19,4,648]}],n:50,r:"data.filename",p:[12,3,385]},{t:4,n:51,f:[{p:[21,4,682],t:7,e:"h2",f:["Available files (local):"]}," ",{p:[22,4,719],t:7,e:"table",f:[{p:[23,5,731],t:7,e:"tr",f:[{p:[24,6,741],t:7,e:"th",f:["File name"]}," ",{p:[25,6,765],t:7,e:"th",f:["File type"]}," ",{p:[26,6,789],t:7,e:"th",f:["File size (GQ)"]}," ",{p:[27,6,818],t:7,e:"th",f:["Operations"]}]}," ",{t:4,f:[{p:[30,6,878],t:7,e:"tr",f:[{p:[31,7,889],t:7,e:"td",f:[{t:2,r:"name",p:[31,11,893]}]}," ",{p:[32,7,913],t:7,e:"td",f:[".",{t:2,r:"type",p:[32,12,918]}]}," ",{p:[33,7,938],t:7,e:"td",f:[{t:2,r:"size",p:[33,11,942]},"GQ"]}," ",{p:[34,7,964],t:7,e:"td",f:[{p:[35,8,976],t:7,e:"ui-button",a:{action:"PRG_openfile",params:['{"name": "',{t:2,r:"name",p:[35,59,1027]},'"}']},f:["VIEW"]}," ",{p:[36,8,1063],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[36,26,1081]}],action:"PRG_deletefile",params:['{"name": "',{t:2,r:"name",p:[36,105,1160]},'"}']},f:["DELETE"]}," ",{p:[37,8,1198],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[37,26,1216]}],action:"PRG_rename",params:['{"name": "',{t:2,r:"name",p:[37,101,1291]},'"}']},f:["RENAME"]}," ",{p:[38,8,1329],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[38,26,1347]}],action:"PRG_clone",params:['{"name": "',{t:2,r:"name",p:[38,100,1421]},'"}']},f:["CLONE"]}," ",{t:4,f:[{p:[40,9,1492],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[40,27,1510]}],action:"PRG_copytousb",params:['{"name": "',{t:2,r:"name",p:[40,105,1588]},'"}']},f:["EXPORT"]}],n:50,r:"data.usbconnected",p:[39,8,1458]}]}]}],n:52,r:"data.files",p:[29,5,852]}]}," ",{t:4,f:[{p:[47,4,1715],t:7,e:"h2",f:["Available files (portable device):"]}," ",{p:[48,4,1762],t:7,e:"table",f:[{p:[49,5,1774],t:7,e:"tr",f:[{p:[50,6,1784],t:7,e:"th",f:["File name"]}," ",{p:[51,6,1808],t:7,e:"th",f:["File type"]}," ",{p:[52,6,1832],t:7,e:"th",f:["File size (GQ)"]}," ",{p:[53,6,1861],t:7,e:"th",f:["Operations"]}]}," ",{t:4,f:[{p:[56,6,1924],t:7,e:"tr",f:[{p:[57,7,1935],t:7,e:"td",f:[{t:2,r:"name",p:[57,11,1939]}]}," ",{p:[58,7,1959],t:7,e:"td",f:[".",{t:2,r:"type",p:[58,12,1964]}]}," ",{p:[59,7,1984],t:7,e:"td",f:[{t:2,r:"size",p:[59,11,1988]},"GQ"]}," ",{p:[60,7,2010],t:7,e:"td",f:[{p:[61,8,2022],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[61,26,2040]}],action:"PRG_usbdeletefile",params:['{"name": "',{t:2,r:"name",p:[61,108,2122]},'"}']},f:["DELETE"]}," ",{t:4,f:[{p:[63,9,2194],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[63,27,2212]}],action:"PRG_copyfromusb",params:['{"name": "',{t:2,r:"name",p:[63,107,2292]},'"}']},f:["IMPORT"]}],n:50,r:"data.usbconnected",p:[62,8,2160]}]}]}],n:52,r:"data.usbfiles",p:[55,5,1895]}]}],n:50,r:"data.usbconnected",p:[46,4,1686]}," ",{p:[70,4,2401],t:7,e:"ui-button",a:{action:"PRG_newtextfile"},f:["NEW DATA FILE"]}],r:"data.filename"}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],420:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{p:[5,2,75],t:7,e:"i",f:["No program loaded. Please select program from list below."]}," ",{p:[6,2,141],t:7,e:"table",f:[{t:4,f:[{p:[8,4,178],t:7,e:"tr",f:[{p:[8,8,182],t:7,e:"td",f:[{p:[8,12,186],t:7,e:"ui-button",a:{action:"PC_runprogram",params:['{"name": "',{t:2,r:"name",p:[8,64,238]},'"}']},f:[{t:2,r:"desc",p:[9,5,255]}]}]},{p:[11,4,283],t:7,e:"td",f:[{p:[11,8,287],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["running"],s:'_0?null:"disabled"'},p:[11,26,305]}],icon:"close",action:"PC_killprogram",params:['{"name": "',{t:2,r:"name",p:[11,114,393]},'"}']}}]}]}],n:52,r:"data.programs",p:[7,3,151]}]}," ",{p:[14,2,441],t:7,e:"br"},{p:[14,6,445],t:7,e:"br"}," ",{t:4,f:[{p:[16,3,476],t:7,e:"ui-button",a:{action:"PC_toggle_light",style:[{t:2,x:{r:["data.light_on"],s:'_0?"selected":null'},p:[16,46,519]}]},f:["Toggle Flashlight"]},{p:[16,114,587],t:7,e:"br"}," ",{p:[17,3,594],t:7,e:"ui-button",a:{action:"PC_light_color"},f:["Change Flashlight Color ",{p:[17,62,653],t:7,e:"span",a:{style:["border:1px solid #161616; background-color: ",{t:2,r:"data.comp_light_color",p:[17,119,710]},";"]},f:["   "]}]}],n:50,r:"data.has_light",p:[15,2,451]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],421:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{t:4,f:[{p:[6,3,100],t:7,e:"h1",f:["ADMINISTRATIVE MODE"]}],n:50,r:"data.adminmode",p:[5,2,75]}," ",{t:4,f:[{p:[10,3,161],t:7,e:"div",a:{"class":"itemLabel"},f:["Current channel:"]}," ",{p:[13,3,217],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.title",p:[14,4,246]}]}," ",{p:[16,3,272],t:7,e:"div",a:{"class":"itemLabel"},f:["Operator access:"]}," ",{p:[19,3,328],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:[{p:[21,5,386],t:7,e:"b",f:["Enabled"]}],n:50,r:"data.is_operator",p:[20,4,357]},{t:4,n:51,f:[{p:[23,5,417],t:7,e:"b",f:["Disabled"]}],r:"data.is_operator"}]}," ",{p:[26,3,455],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[29,3,504],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[30,4,533],t:7,e:"table",f:[{p:[31,5,545],t:7,e:"tr",f:[{p:[31,9,549],t:7,e:"td",f:[{p:[31,13,553],t:7,e:"ui-button",a:{action:"PRG_speak"},f:["Send message"]}]}]},{p:[32,5,612],t:7,e:"tr",f:[{p:[32,9,616],t:7,e:"td",f:[{p:[32,13,620],t:7,e:"ui-button",a:{action:"PRG_changename"},f:["Change nickname"]}]}]},{p:[33,5,687],t:7,e:"tr",f:[{p:[33,9,691],t:7,e:"td",f:[{p:[33,13,695],t:7,e:"ui-button",a:{action:"PRG_toggleadmin"},f:["Toggle administration mode"]}]}]},{p:[34,5,774],t:7,e:"tr",f:[{p:[34,9,778],t:7,e:"td",f:[{p:[34,13,782],t:7,e:"ui-button",a:{action:"PRG_leavechannel"},f:["Leave channel"]}]}]},{p:[35,5,849],t:7,e:"tr",f:[{p:[35,9,853],t:7,e:"td",f:[{p:[35,13,857],t:7,e:"ui-button",a:{action:"PRG_savelog"},f:["Save log to local drive"]}," ",{t:4,f:[{p:[37,6,959],t:7,e:"tr",f:[{p:[37,10,963],t:7,e:"td",f:[{p:[37,14,967],t:7,e:"ui-button",a:{action:"PRG_renamechannel"},f:["Rename channel"]}]}]},{p:[38,6,1037],t:7,e:"tr",f:[{p:[38,10,1041],t:7,e:"td",f:[{p:[38,14,1045],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}]}]},{p:[39,6,1111],t:7,e:"tr",f:[{p:[39,10,1115],t:7,e:"td",f:[{p:[39,14,1119],t:7,e:"ui-button",a:{action:"PRG_deletechannel"},f:["Delete channel"]}]}]}],n:50,r:"data.is_operator",p:[36,5,929]}]}]}]}]}," ",{p:[43,3,1221],t:7,e:"b",f:["Chat Window"]}," ",{p:[44,4,1243],t:7,e:"div",a:{"class":"statusDisplay",style:"overflow: auto;"},f:[{p:[45,4,1298],t:7,e:"div",a:{"class":"item"},f:[{p:[46,5,1321],t:7,e:"div",a:{"class":"itemContent",style:"width: 100%;"},f:[{t:4,f:[{t:2,r:"msg",p:[48,7,1403]},{p:[48,14,1410],t:7,e:"br"}],n:52,r:"data.messages",p:[47,6,1373]}]}]}]}," ",{p:[53,3,1464],t:7,e:"b",f:["Connected Users"]},{p:[53,25,1486],t:7,e:"br"}," ",{t:4,f:[{t:2,r:"name",p:[55,4,1519]},{p:[55,12,1527],t:7,e:"br"}],n:52,r:"data.clients",p:[54,3,1493]}],n:50,r:"data.title",p:[9,2,140]},{t:4,n:51,f:[{p:[58,3,1556],t:7,e:"b",f:["Controls:"]}," ",{p:[59,3,1575],t:7,e:"table",f:[{p:[60,4,1586],t:7,e:"tr",f:[{p:[60,8,1590],t:7,e:"td",f:[{p:[60,12,1594],t:7,e:"ui-button",a:{action:"PRG_changename"},f:["Change nickname"]}]}]},{p:[61,4,1660],t:7,e:"tr",f:[{p:[61,8,1664],t:7,e:"td",f:[{p:[61,12,1668],t:7,e:"ui-button",a:{action:"PRG_newchannel"},f:["New Channel"]}]}]},{p:[62,4,1730],t:7,e:"tr",f:[{p:[62,8,1734],t:7,e:"td",f:[{p:[62,12,1738],t:7,e:"ui-button",a:{action:"PRG_toggleadmin"},f:["Toggle administration mode"]}]}]}]}," ",{p:[64,3,1826],t:7,e:"b",f:["Available channels:"]}," ",{p:[65,3,1855],t:7,e:"table",f:[{t:4,f:[{p:[67,4,1898],t:7,e:"tr",f:[{p:[67,8,1902],t:7,e:"td",f:[{p:[67,12,1906],t:7,e:"ui-button",a:{action:"PRG_joinchannel",params:['{"id": "',{t:2,r:"id",p:[67,64,1958]},'"}']},f:[{t:2,r:"chan",p:[67,74,1968]}]},{p:[67,94,1988],t:7,e:"br"}]}]}],n:52,r:"data.all_channels",p:[66,3,1865]}]}],r:"data.title"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],422:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{t:4,f:["##SYSTEM ERROR: ",{t:2,r:"data.error",p:[6,19,112]},{p:[6,33,126],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["RESET"]}],n:50,r:"data.error",p:[5,2,75]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.target"],s:"_0"},f:["##DoS traffic generator active. Tx: ",{t:2,r:"data.speed",p:[8,39,236]},"GQ/s",{p:[8,57,254],t:7,e:"br"}," ",{t:4,f:[{t:2,r:"nums",p:[10,4,291]},{p:[10,12,299],t:7,e:"br"}],n:52,r:"data.dos_strings",p:[9,3,261]}," ",{p:[12,3,318],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["ABORT"]}]},{t:4,n:50,x:{r:["data.target"],s:"!(_0)"},f:[" ##DoS traffic generator ready. Select target device.",{p:[14,55,430],t:7,e:"br"}," ",{t:4,f:["Targeted device ID: ",{t:2,r:"data.focus",p:[16,24,479]}],n:50,r:"data.focus",p:[15,3,437]},{t:4,n:51,f:["Targeted device ID: None"],r:"data.focus"}," ",{p:[20,3,545],t:7,e:"ui-button",a:{action:"PRG_execute"},f:["EXECUTE"]},{p:[20,54,596],t:7,e:"div",a:{style:"clear:both"}}," Detected devices on network:",{p:[21,31,657],t:7,e:"br"}," ",{t:4,f:[{p:[23,4,689],t:7,e:"ui-button",a:{action:"PRG_target_relay",params:['{"targid": "',{t:2,r:"id",p:[23,61,746]},'"}']},f:[{t:2,r:"id",p:[23,71,756]}]}],n:52,r:"data.relays",p:[22,3,664]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],423:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{p:[5,2,75],t:7,e:"i",f:["Welcome to software download utility. Please select which software you wish to download."]},{p:[5,97,170],t:7,e:"hr"}," ",{t:4,f:[{p:[7,3,197],t:7,e:"ui-display",a:{title:"Download Error"},f:[{p:[8,4,236],t:7,e:"ui-section",a:{label:"Information"},f:[{t:2,r:"data.error",p:[9,5,273]}]}," ",{p:[11,4,308],t:7,e:"ui-section",a:{label:"Reset Program"},f:[{p:[12,5,347],t:7,e:"ui-button",a:{icon:"times",action:"PRG_reseterror"},f:["RESET"]}]}]}],n:50,r:"data.error",p:[6,2,176]},{t:4,n:51,f:[{t:4,f:[{p:[19,4,498],t:7,e:"ui-display",a:{title:"Download Running"},f:[{p:[20,5,540],t:7,e:"i",f:["Please wait..."]}," ",{p:[21,5,566],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"data.downloadname",p:[22,6,602]}]}," ",{p:[24,5,646],t:7,e:"ui-section",a:{label:"File description"},f:[{t:2,r:"data.downloaddesc",p:[25,6,689]}]}," ",{p:[27,5,733],t:7,e:"ui-section",a:{label:"File size"},f:[{t:2,r:"data.downloadsize",p:[28,6,769]},"GQ"]}," ",{p:[30,5,815],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{t:2,r:"data.downloadspeed",p:[31,6,855]}," GQ/s"]}," ",{p:[33,5,905],t:7,e:"ui-section",a:{label:"Download progress"},f:[{p:[34,6,949],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.downloadsize",p:[34,27,970]}],value:[{t:2,r:"adata.downloadcompletion",p:[34,58,1001]}],state:"good"},f:[{t:2,x:{r:["adata.downloadcompletion"],s:"Math.round(_0)"},p:[34,101,1044]},"GQ / ",{t:2,r:"adata.downloadsize",p:[34,146,1089]},"GQ"]}]}]}],n:50,r:"data.downloadname",p:[18,3,469]}],r:"data.error"}," ",{t:4,f:[{t:4,f:[{p:[41,4,1230],t:7,e:"ui-display",a:{title:"File System"},f:[{p:[42,5,1267],t:7,e:"ui-section",a:{label:"Used Capacity"},f:[{p:[43,6,1307],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.disk_size",p:[43,27,1328]}],value:[{t:2,r:"adata.disk_used",p:[43,55,1356]}],state:"good"},f:[{t:2,x:{r:["adata.disk_used"],s:"Math.round(_0)"},p:[43,89,1390]},"GQ / ",{t:2,r:"adata.disk_size",p:[43,125,1426]},"GQ"]}]}]}," ",{p:[47,4,1499],t:7,e:"ui-display",a:{title:"Primary Software Repository"},f:[{t:4,f:[{p:[49,6,1594],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"filedesc",p:[49,28,1616]}]},f:[{p:[50,7,1637],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"fileinfo",p:[50,61,1691]}]}," ",{p:[52,7,1723],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"filename",p:[53,8,1761]}," (",{t:2,r:"size",p:[53,22,1775]}," GQ)"]}," ",{p:[55,7,1814],t:7,e:"ui-section",a:{label:"Compatibility"},f:[{t:2,r:"compatibility",p:[56,8,1856]}]}," ",{p:[58,7,1900],t:7,e:"ui-button",a:{icon:"signal",action:"PRG_downloadfile",params:['{"filename": "',{t:2,r:"filename",p:[58,80,1973]},'"}']},f:["DOWNLOAD"]}]}," ",{p:[62,6,2052],t:7,e:"br"}],n:52,r:"data.downloadable_programs",p:[48,5,1552]}]}," ",{t:4,f:[{p:[67,5,2128],t:7,e:"ui-display",a:{title:"UNKNOWN Software Repository"}, -f:[{p:[68,6,2182],t:7,e:"i",f:["Please note that Nanotrasen does not recommend download of software from non-official servers."]}," ",{t:4,f:[{p:[70,7,2326],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"filedesc",p:[70,29,2348]}]},f:[{p:[71,8,2370],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"fileinfo",p:[71,62,2424]}]}," ",{p:[73,8,2458],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"filename",p:[74,9,2497]}," (",{t:2,r:"size",p:[74,23,2511]}," GQ)"]}," ",{p:[76,8,2552],t:7,e:"ui-section",a:{label:"Compatibility"},f:[{t:2,r:"compatibility",p:[77,9,2595]}]}," ",{p:[79,8,2641],t:7,e:"ui-button",a:{icon:"signal",action:"PRG_downloadfile",params:['{"filename": "',{t:2,r:"filename",p:[79,81,2714]},'"}']},f:["DOWNLOAD"]}]}," ",{p:[83,7,2797],t:7,e:"br"}],n:52,r:"data.hacked_programs",p:[69,6,2289]}]}],n:50,r:"data.hackedavailable",p:[66,4,2095]}],n:50,x:{r:["data.error"],s:"!_0"},p:[40,3,1207]}],n:50,x:{r:["data.downloadname"],s:"!_0"},p:[39,2,1178]}," ",{p:[89,2,2866],t:7,e:"br"},{p:[89,6,2870],t:7,e:"br"},{p:[89,10,2874],t:7,e:"hr"},{p:[89,14,2878],t:7,e:"i",f:["NTOS v2.0.4b Copyright Nanotrasen 2557 - 2559"]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],424:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{p:[6,2,76],t:7,e:"ui-display",a:{title:"WIRELESS CONNECTIVITY"},f:[{p:[8,3,122],t:7,e:"ui-section",a:{label:"Active NTNetRelays"},f:[{p:[9,4,165],t:7,e:"b",f:[{t:2,r:"data.ntnetrelays",p:[9,7,168]}]}]}," ",{t:4,f:[{p:[12,4,239],t:7,e:"ui-section",a:{label:"System status"},f:[{p:[13,6,279],t:7,e:"b",f:[{t:2,x:{r:["data.ntnetstatus"],s:'_0?"ENABLED":"DISABLED"'},p:[13,9,282]}]}]}," ",{p:[15,4,352],t:7,e:"ui-section",a:{label:"Control"},f:[{p:[17,4,385],t:7,e:"ui-button",a:{icon:"plus",action:"toggleWireless"},f:["TOGGLE"]}]}," ",{p:[21,4,480],t:7,e:"br"},{p:[21,8,484],t:7,e:"br"}," ",{p:[22,4,492],t:7,e:"i",f:["Caution - Disabling wireless transmitters when using wireless device may prevent you from re-enabling them again!"]}],n:50,r:"data.ntnetrelays",p:[11,3,211]},{t:4,n:51,f:[{p:[24,4,627],t:7,e:"br"},{p:[24,8,631],t:7,e:"p",f:["Wireless coverage unavailable, no relays are connected."]}],r:"data.ntnetrelays"}]}," ",{p:[29,2,722],t:7,e:"ui-display",a:{title:"FIREWALL CONFIGURATION"},f:[{p:[31,2,768],t:7,e:"table",f:[{p:[32,3,778],t:7,e:"tr",f:[{p:[33,4,786],t:7,e:"th",f:["PROTOCOL"]},{p:[34,4,802],t:7,e:"th",f:["STATUS"]},{p:[35,4,816],t:7,e:"th",f:["CONTROL"]}]},{p:[36,3,830],t:7,e:"tr",f:[" ",{p:[37,4,838],t:7,e:"td",f:["Software Downloads"]},{p:[38,4,864],t:7,e:"td",f:[{t:2,x:{r:["data.config_softwaredownload"],s:'_0?"ENABLED":"DISABLED"'},p:[38,8,868]}]},{p:[39,4,929],t:7,e:"td",f:[" ",{p:[39,9,934],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "1"}'},f:["TOGGLE"]}]}]},{p:[40,3,1012],t:7,e:"tr",f:[" ",{p:[41,4,1020],t:7,e:"td",f:["Peer to Peer Traffic"]},{p:[42,4,1048],t:7,e:"td",f:[{t:2,x:{r:["data.config_peertopeer"],s:'_0?"ENABLED":"DISABLED"'},p:[42,8,1052]}]},{p:[43,4,1107],t:7,e:"td",f:[{p:[43,8,1111],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "2"}'},f:["TOGGLE"]}]}]},{p:[44,3,1189],t:7,e:"tr",f:[" ",{p:[45,4,1197],t:7,e:"td",f:["Communication Systems"]},{p:[46,4,1226],t:7,e:"td",f:[{t:2,x:{r:["data.config_communication"],s:'_0?"ENABLED":"DISABLED"'},p:[46,8,1230]}]},{p:[47,4,1288],t:7,e:"td",f:[{p:[47,8,1292],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "3"}'},f:["TOGGLE"]}]}]},{p:[48,3,1370],t:7,e:"tr",f:[" ",{p:[49,4,1378],t:7,e:"td",f:["Remote System Control"]},{p:[50,4,1407],t:7,e:"td",f:[{t:2,x:{r:["data.config_systemcontrol"],s:'_0?"ENABLED":"DISABLED"'},p:[50,8,1411]}]},{p:[51,4,1469],t:7,e:"td",f:[{p:[51,8,1473],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "4"}'},f:["TOGGLE"]}]}]}]}]}," ",{p:[55,2,1576],t:7,e:"ui-display",a:{title:"SECURITY SYSTEMS"},f:[{t:4,f:[{p:[58,4,1642],t:7,e:"ui-notice",f:[{p:[59,5,1658],t:7,e:"h1",f:["NETWORK INCURSION DETECTED"]}]}," ",{p:[61,5,1714],t:7,e:"i",f:["An abnormal activity has been detected in the network. Please verify system logs for more information"]}],n:50,r:"data.idsalarm",p:[57,3,1617]}," ",{p:[64,3,1839],t:7,e:"ui-section",a:{label:"Intrusion Detection System"},f:[{p:[65,4,1890],t:7,e:"b",f:[{t:2,x:{r:["data.idsstatus"],s:'_0?"ENABLED":"DISABLED"'},p:[65,7,1893]}]}]}," ",{p:[68,3,1962],t:7,e:"ui-section",a:{label:"Maximal Log Count"},f:[{p:[69,4,2004],t:7,e:"b",f:[{t:2,r:"data.ntnetmaxlogs",p:[69,7,2007]}]}]}," ",{p:[72,3,2054],t:7,e:"ui-section",a:{label:"Controls"},f:[]}," ",{p:[74,4,2103],t:7,e:"table",f:[{p:[75,4,2114],t:7,e:"tr",f:[{p:[75,8,2118],t:7,e:"td",f:[{p:[75,12,2122],t:7,e:"ui-button",a:{action:"resetIDS"},f:["RESET IDS"]}]}]},{p:[76,4,2176],t:7,e:"tr",f:[{p:[76,8,2180],t:7,e:"td",f:[{p:[76,12,2184],t:7,e:"ui-button",a:{action:"toggleIDS"},f:["TOGGLE IDS"]}]}]},{p:[77,4,2240],t:7,e:"tr",f:[{p:[77,8,2244],t:7,e:"td",f:[{p:[77,12,2248],t:7,e:"ui-button",a:{action:"updatemaxlogs"},f:["SET LOG LIMIT"]}]}]},{p:[78,4,2311],t:7,e:"tr",f:[{p:[78,8,2315],t:7,e:"td",f:[{p:[78,12,2319],t:7,e:"ui-button",a:{action:"purgelogs"},f:["PURGE LOGS"]}]}]}]}," ",{p:[81,3,2387],t:7,e:"ui-subdisplay",a:{title:"System Logs"},f:[{p:[82,3,2425],t:7,e:"div",a:{"class":"statusDisplay",style:"overflow: auto;"},f:[{p:[83,3,2479],t:7,e:"div",a:{"class":"item"},f:[{p:[84,4,2501],t:7,e:"div",a:{"class":"itemContent",style:"width: 100%;"},f:[{t:4,f:[{t:2,r:"entry",p:[86,6,2582]},{p:[86,15,2591],t:7,e:"br"}],n:52,r:"data.ntnetlogs",p:[85,5,2552]}]}]}]}]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],425:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{t:4,f:[{p:[7,2,96],t:7,e:"div",a:{"class":"item"},f:[{p:[8,3,117],t:7,e:"h2",f:["An error has occurred during operation..."]}," ",{p:[9,3,170],t:7,e:"b",f:["Additional information:"]},{t:2,r:"data.error",p:[9,34,201]},{p:[9,48,215],t:7,e:"br"}," ",{p:[10,3,222],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Clear"]}]}],n:50,r:"data.error",p:[6,2,76]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.downloading"],s:"_0"},f:[{p:[13,3,309],t:7,e:"h2",f:["Download in progress..."]}," ",{p:[14,3,344],t:7,e:"div",a:{"class":"itemLabel"},f:["Downloaded file:"]}," ",{p:[17,3,400],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_name",p:[18,4,429]}]}," ",{p:[20,3,464],t:7,e:"div",a:{"class":"itemLabel"},f:["Download progress:"]}," ",{p:[23,3,522],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_progress",p:[24,4,551]}," / ",{t:2,r:"data.download_size",p:[24,33,580]}," GQ"]}," ",{p:[26,3,617],t:7,e:"div",a:{"class":"itemLabel"},f:["Transfer speed:"]}," ",{p:[29,3,672],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_netspeed",p:[30,4,701]},"GQ/s"]}," ",{p:[32,3,743],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[35,3,792],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[36,4,821],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Abort download"]}]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading"],s:"(!(_0))&&(_1)"},f:[" ",{p:[39,3,916],t:7,e:"h2",f:["Server enabled"]}," ",{p:[40,3,942],t:7,e:"div",a:{"class":"itemLabel"},f:["Connected clients:"]}," ",{p:[43,3,1e3],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.upload_clients",p:[44,4,1029]}]}," ",{p:[46,3,1064],t:7,e:"div",a:{"class":"itemLabel"},f:["Provided file:"]}," ",{p:[49,3,1118],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.upload_filename",p:[50,4,1147]}]}," ",{p:[52,3,1183],t:7,e:"div",a:{"class":"itemLabel"},f:["Server password:"]}," ",{p:[55,3,1239],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["ENABLED"],n:50,r:"data.upload_haspassword",p:[56,4,1268]},{t:4,n:51,f:["DISABLED"],r:"data.upload_haspassword"}]}," ",{p:[62,3,1359],t:7,e:"div",a:{"class":"itemLabel"},f:["Commands:"]}," ",{p:[65,3,1408],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[66,4,1437],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}," ",{p:[67,4,1501],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Exit server"]}]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading","data.upload_filelist"],s:"(!(_0))&&((!(_1))&&(_2))"},f:[" ",{p:[70,3,1599],t:7,e:"h2",f:["File transfer server ready. Select file to upload:"]}," ",{p:[71,3,1662],t:7,e:"table",f:[{p:[72,3,1672],t:7,e:"tr",f:[{p:[72,7,1676],t:7,e:"th",f:["File name"]},{p:[72,20,1689],t:7,e:"th",f:["File size"]},{p:[72,33,1702],t:7,e:"th",f:["Controls ",{t:4,f:[{p:[74,4,1751],t:7,e:"tr",f:[{p:[74,8,1755],t:7,e:"td",f:[{t:2,r:"filename",p:[74,12,1759]}]},{p:[75,4,1775],t:7,e:"td",f:[{t:2,r:"size",p:[75,8,1779]},"GQ"]},{p:[76,4,1793],t:7,e:"td",f:[{p:[76,8,1797],t:7,e:"ui-button",a:{action:"PRG_uploadfile",params:['{"id": "',{t:2,r:"uid",p:[76,59,1848]},'"}']},f:["Select"]}]}]}],n:52,r:"data.upload_filelist",p:[73,3,1717]}]}]}]}," ",{p:[79,3,1903],t:7,e:"hr"}," ",{p:[80,3,1910],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}," ",{p:[81,3,1973],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Return"]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading","data.upload_filelist"],s:"(!(_0))&&((!(_1))&&(!(_2)))"},f:[" ",{p:[83,3,2034],t:7,e:"h2",f:["Available files:"]}," ",{p:[84,3,2062],t:7,e:"table",a:{border:"1",style:"border-collapse: collapse"},f:[{p:[84,55,2114],t:7,e:"tr",f:[{p:[84,59,2118],t:7,e:"th",f:["Server UID"]},{p:[84,73,2132],t:7,e:"th",f:["File Name"]},{p:[84,86,2145],t:7,e:"th",f:["File Size"]},{p:[84,99,2158],t:7,e:"th",f:["Password Protection"]},{p:[84,122,2181],t:7,e:"th",f:["Operations ",{t:4,f:[{p:[86,5,2226],t:7,e:"tr",f:[{p:[86,9,2230],t:7,e:"td",f:[{t:2,r:"uid",p:[86,13,2234]}]},{p:[87,5,2246],t:7,e:"td",f:[{t:2,r:"filename",p:[87,9,2250]}]},{p:[88,5,2267],t:7,e:"td",f:[{t:2,r:"size",p:[88,9,2271]},"GQ ",{t:4,f:[{p:[90,6,2311],t:7,e:"td",f:["Enabled"]}],n:50,r:"haspassword",p:[89,5,2286]}," ",{t:4,f:[{p:[93,6,2365],t:7,e:"td",f:["Disabled"]}],n:50,x:{r:["haspassword"],s:"!_0"},p:[92,5,2339]}]},{p:[96,5,2399],t:7,e:"td",f:[{p:[96,9,2403],t:7,e:"ui-button",a:{action:"PRG_downloadfile",params:['{"id": "',{t:2,r:"uid",p:[96,62,2456]},'"}']},f:["Download"]}]}]}],n:52,r:"data.servers",p:[85,4,2199]}]}]}]}," ",{p:[99,3,2514],t:7,e:"hr"}," ",{p:[100,3,2521],t:7,e:"ui-button",a:{action:"PRG_uploadmenu"},f:["Send file"]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],426:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargingState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},chargingMode:function(t){return 2==t?"Full":1==t?"Charging":"Draining"},channelState:function(t){return t>=2?"good":"bad"},channelPower:function(t){return t>=2?"On":"Off"},channelMode:function(t){return 1==t||3==t?"Auto":"Manual"}},computed:{graphData:function(){var t=this.get("data.history");return Object.keys(t).map(function(e){return t[e].map(function(t,e){return{x:e,y:t}})})}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[43,1,1040],t:7,e:"ntosheader"}," ",{p:[45,1,1055],t:7,e:"ui-display",a:{title:"Network"},f:[{t:4,f:[{p:[47,5,1111],t:7,e:"ui-linegraph",a:{points:[{t:2,r:"graphData",p:[47,27,1133]}],height:"500",legend:'["Available", "Load"]',colors:'["rgb(0, 102, 0)", "rgb(153, 0, 0)"]',xunit:"seconds ago",xfactor:[{t:2,r:"data.interval",p:[49,38,1283]}],yunit:"W",yfactor:"1",xinc:[{t:2,x:{r:["data.stored"],s:"_0/10"},p:[50,15,1338]}],yinc:"9"}}],n:50,r:"config.fancy",p:[46,3,1086]},{t:4,n:51,f:[{p:[52,5,1386],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[53,7,1423],t:7,e:"span",f:[{t:2,r:"data.supply",p:[53,13,1429]}]}]}," ",{p:[55,5,1474],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[56,9,1508],t:7,e:"span",f:[{t:2,r:"data.demand",p:[56,15,1514]}]}]}],r:"config.fancy"}]}," ",{p:[60,1,1579],t:7,e:"ui-display",a:{title:"Areas"},f:[{p:[61,3,1608],t:7,e:"ui-section",a:{nowrap:0},f:[{p:[62,5,1632],t:7,e:"div",a:{"class":"content"},f:["Area"]}," ",{p:[63,5,1668],t:7,e:"div",a:{"class":"content"},f:["Charge"]}," ",{p:[64,5,1706],t:7,e:"div",a:{"class":"content"},f:["Load"]}," ",{p:[65,5,1742],t:7,e:"div",a:{"class":"content"},f:["Status"]}," ",{p:[66,5,1780],t:7,e:"div",a:{"class":"content"},f:["Equipment"]}," ",{p:[67,5,1821],t:7,e:"div",a:{"class":"content"},f:["Lighting"]}," ",{p:[68,5,1861],t:7,e:"div",a:{"class":"content"},f:["Environment"]}]}," ",{t:4,f:[{p:[71,5,1943],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[71,24,1962]}],nowrap:0},f:[{p:[72,7,1986],t:7,e:"div",a:{"class":"content"},f:[{t:2,x:{r:["@index","adata.areas"],s:"Math.round(_1[_0].charge)"},p:[72,28,2007]}," %"]}," ",{p:[73,7,2064],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.areas",m:[{t:30,n:"@index"},"load"]},p:[73,28,2085]}]}," ",{p:[74,7,2126],t:7,e:"div",a:{"class":"content"},f:[{p:[74,28,2147],t:7,e:"span",a:{"class":[{t:2,x:{r:["chargingState","charging"],s:"_0(_1)"},p:[74,41,2160]}]},f:[{t:2,x:{r:["chargingMode","charging"],s:"_0(_1)"},p:[74,70,2189]}]}]}," ",{p:[75,7,2235],t:7,e:"div",a:{"class":"content"},f:[{p:[75,28,2256],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","eqp"],s:"_0(_1)"},p:[75,41,2269]}]},f:[{t:2,x:{r:["channelPower","eqp"],s:"_0(_1)"},p:[75,64,2292]}," [",{p:[75,87,2315],t:7,e:"span",f:[{t:2,x:{r:["channelMode","eqp"],s:"_0(_1)"},p:[75,93,2321]}]},"]"]}]}," ",{p:[76,7,2369],t:7,e:"div",a:{"class":"content"},f:[{p:[76,28,2390],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","lgt"],s:"_0(_1)"},p:[76,41,2403]}]},f:[{t:2,x:{r:["channelPower","lgt"],s:"_0(_1)"},p:[76,64,2426]}," [",{p:[76,87,2449],t:7,e:"span",f:[{t:2,x:{r:["channelMode","lgt"],s:"_0(_1)"},p:[76,93,2455]}]},"]"]}]}," ",{p:[77,7,2503],t:7,e:"div",a:{"class":"content"},f:[{p:[77,28,2524],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","env"],s:"_0(_1)"},p:[77,41,2537]}]},f:[{t:2,x:{r:["channelPower","env"],s:"_0(_1)"},p:[77,64,2560]}," [",{p:[77,87,2583],t:7,e:"span",f:[{t:2,x:{r:["channelMode","env"],s:"_0(_1)"},p:[77,93,2589]}]},"]"]}]}]}],n:52,r:"data.areas",p:[70,3,1918]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],427:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{p:[4,1,61],t:7,e:"ui-display",f:[{p:[5,2,75],t:7,e:"div",a:{"class":"item"},f:[{p:[6,3,96],t:7,e:"div",a:{"class":"itemLabel"},f:["Payload status:"]}," ",{p:[9,3,150],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["ARMED"],n:50,r:"data.armed",p:[10,4,179]},{t:4,n:51,f:["DISARMED"],r:"data.armed"}]}," ",{p:[16,3,255],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[19,3,303],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[20,4,332],t:7,e:"table",f:[{p:[21,4,343],t:7,e:"tr",f:[{p:[21,8,347],t:7,e:"td",f:[{p:[21,12,351],t:7,e:"ui-button",a:{action:"PRG_obfuscate"},f:["OBFUSCATE PROGRAM NAME"]}]}]},{p:[22,4,423],t:7,e:"tr",f:[{p:[22,8,427],t:7,e:"td",f:[{p:[22,12,431],t:7,e:"ui-button",a:{action:"PRG_arm",state:[{t:2,x:{r:["data.armed"],s:'_0?"danger":null'},p:[22,47,466]}]},f:[{t:2,x:{r:["data.armed"],s:'_0?"DISARM":"ARM"'},p:[22,81,500]}]}," ",{p:[23,4,549],t:7,e:"ui-button",a:{icon:"radiation",state:[{t:2,x:{r:["data.armed"],s:'_0?null:"disabled"'},p:[23,39,584]}],action:"PRG_activate"},f:["ACTIVATE"]}]}]}]}]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],428:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,46],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[5,3,91],t:7,e:"ui-display",a:{title:[{t:2,r:"class",p:[5,22,110]}," Alarms"]},f:[{p:[6,5,133],t:7,e:"ul",f:[{t:4,f:[{p:[8,9,164],t:7,e:"li",f:[{t:2,r:".",p:[8,13,168]}]}],n:52,r:".",p:[7,7,144]},{t:4,n:51,f:[{p:[10,9,202],t:7,e:"li",f:["System Nominal"]}],r:"."}]}]}],n:52,i:"class",r:"data.alarms",p:[4,1,61]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],429:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{integState:function(t){var e=100;return t==e?"good":t>e/2?"average":"bad"},bigState:function(t,e,n){return charge>n?"bad":t>e?"average":"good"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[23,1,399],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[27,2,436],t:7,e:"ui-button",a:{action:"PRG_clear"},f:["Back to Menu"]},{p:[27,56,490],t:7,e:"br"}," ",{p:[28,3,497],t:7,e:"ui-display",a:{title:"Supermatter Status:"},f:[{p:[29,3,540],t:7,e:"ui-section",a:{label:"Core Integrity"},f:[{p:[30,5,580],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"adata.SM_integrity",p:[30,38,613]}],state:[{t:2,x:{r:["integState","adata.SM_integrity"],s:"_0(_1)"},p:[30,69,644]}]},f:[{t:2,r:"data.SM_integrity",p:[30,105,680]},"%"]}]}," ",{p:[32,3,730],t:7,e:"ui-section",a:{label:"Relative EER"},f:[{p:[33,5,768],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_power"],s:"_0(_1,150,300)"},p:[33,18,781]}]},f:[{t:2,r:"data.SM_power",p:[33,55,818]}," MeV/cm3"]}]}," ",{p:[35,3,869],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[36,5,906],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_ambienttemp"],s:"_0(_1,4000,5000)"},p:[36,18,919]}]},f:[{t:2,r:"data.SM_ambienttemp",p:[36,63,964]}," K"]}]}," ",{p:[38,3,1015],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[39,5,1049],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_ambientpressure"],s:"_0(_1,5000,10000)"},p:[39,18,1062]}]},f:[{t:2,r:"data.SM_ambientpressure",p:[39,68,1112]}," kPa"]}]}]}," ",{p:[42,3,1186],t:7,e:"hr"},{p:[42,7,1190],t:7,e:"br"}," ",{p:[43,3,1197],t:7,e:"ui-display",a:{title:"Gas Composition:"},f:[{t:4,f:[{p:[45,5,1263],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[45,24,1282]}]},f:[{t:2,r:"amount",p:[46,6,1298]}," %"]}],n:52,r:"data.gases",p:[44,4,1238]}]}],n:50,r:"data.active",p:[26,1,415]},{t:4,n:51,f:[{p:[51,2,1368],t:7,e:"ui-button",a:{action:"PRG_refresh"},f:["Refresh"]},{p:[51,53,1419],t:7,e:"br"}," ",{p:[52,2,1425],t:7,e:"ui-display",a:{title:"Detected Supermatters"},f:[{t:4,f:[{p:[54,3,1499],t:7,e:"ui-section",a:{label:"Area"},f:[{t:2,r:"area_name",p:[55,5,1529]}," - (#",{t:2,r:"uid",p:[55,23,1547]},")"]}," ",{p:[57,3,1574],t:7,e:"ui-section",a:{label:"Integrity"},f:[{t:2,r:"integrity",p:[58,5,1609]}," %"]}," ",{p:[60,3,1643],t:7,e:"ui-section",a:{label:"Options"},f:[{p:[61,5,1676],t:7,e:"ui-button",a:{action:"PRG_set",params:['{"target" : "',{t:2,r:"uid",p:[61,54,1725]},'"}']},f:["View Details"]}]}],n:52,r:"data.supermatters",p:[53,2,1469]}]}],r:"data.active"}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],430:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"item",style:"float: left"},f:[{p:[2,2,40],t:7,e:"table",f:[{p:[2,9,47],t:7,e:"tr",f:[{t:4,f:[{p:[4,3,110],t:7,e:"td",f:[{p:[4,7,114],t:7,e:"img",a:{src:[{t:2,r:"data.PC_batteryicon",p:[4,17,124]}]}}]}],n:50,x:{r:["data.PC_batteryicon","data.PC_showbatteryicon"],s:"_0&&_1"},p:[3,2,53]}," ",{t:4,f:[{p:[7,3,220],t:7,e:"td",f:[{p:[7,7,224],t:7,e:"b",f:[{t:2,r:"data.PC_batterypercent",p:[7,10,227]}]}]}],n:50,x:{r:["data.PC_batterypercent","data.PC_showbatteryicon"],s:"_0&&_1"},p:[6,2,160]}," ",{t:4,f:[{p:[10,3,296],t:7,e:"td",f:[{p:[10,7,300],t:7,e:"img",a:{src:[{t:2,r:"data.PC_ntneticon",p:[10,17,310]}]}}]}],n:50,r:"data.PC_ntneticon",p:[9,2,268]}," ",{t:4,f:[{p:[13,3,374],t:7,e:"td",f:[{p:[13,7,378],t:7,e:"img",a:{src:[{t:2,r:"data.PC_apclinkicon",p:[13,17,388]}]}}]}],n:50,r:"data.PC_apclinkicon",p:[12,2,344]}," ",{t:4,f:[{p:[16,3,454],t:7,e:"td",f:[{p:[16,7,458],t:7,e:"b",f:[{t:2,r:"data.PC_stationtime",p:[16,10,461]}]}]}],n:50,r:"data.PC_stationtime",p:[15,2,424]}," ",{t:4,f:[{p:[19,3,534],t:7,e:"td",f:[{p:[19,7,538],t:7,e:"img",a:{src:[{t:2,r:"icon",p:[19,17,548]}]}}]}],n:52,r:"data.PC_programheaders",p:[18,2,499]}]}]}]}," ",{p:[23,1,587],t:7,e:"div",a:{style:"float: right; margin-top: 5px"},f:[{p:[24,2,632],t:7,e:"ui-button",a:{action:"PC_shutdown"},f:["Shutdown"]}," ",{t:4,f:[{p:[26,3,720],t:7,e:"ui-button",a:{action:"PC_exit"},f:["EXIT PROGRAM"]}," ",{p:[27,3,775],t:7,e:"ui-button",a:{action:"PC_minimize"},f:["Minimize Program"]}],n:50,r:"data.PC_showexitprogram",p:[25,2,686]}]}," ",{p:[30,1,852],t:7,e:"div",a:{style:"clear: both"}}]},e.exports=a.extend(r.exports)},{341:341}],431:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Auth. Disk:"},f:[{t:4,f:[{p:[3,7,67],t:7,e:"ui-button",a:{icon:"eject",style:"selected",action:"eject_disk"},f:["++++++++++"]}],n:50,r:"data.disk_present",p:[2,3,35]},{t:4,n:51,f:[{p:[5,7,168],t:7,e:"ui-button",a:{icon:"plus",action:"insert_disk"},f:["----------"]}],r:"data.disk_present"}]}," ",{p:[8,1,259],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[9,3,289],t:7,e:"span",f:[{t:2,r:"data.status1",p:[9,9,295]},"-",{t:2,r:"data.status2",p:[9,26,312]}]}]}," ",{p:[11,1,350],t:7,e:"ui-display",a:{title:"Timer"},f:[{p:[12,3,379],t:7,e:"ui-section",a:{label:"Time to Detonation"},f:[{p:[13,5,423],t:7,e:"span",f:[{t:2,x:{r:["data.timing","data.time_left","data.timer_set"],s:"_0?_1:_2"},p:[13,11,429]}]}]}," ",{t:4,f:[{p:[16,5,525],t:7,e:"ui-section",a:{label:"Adjust Timer"},f:[{p:[17,7,565],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_default"],s:'_0&&_1&&_2?null:"disabled"'},p:[17,40,598]}],action:"timer",params:'{"change": "reset"}'},f:["Reset"]}," ",{p:[19,7,768],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_min"],s:'_0&&_1&&_2?null:"disabled"'},p:[19,38,799]}],action:"timer",params:'{"change": "decrease"}'},f:["Decrease"]}," ",{p:[21,7,971],t:7,e:"ui-button",a:{icon:"pencil",state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[21,39,1003]}],action:"timer",params:'{"change": "input"}'},f:["Set"]}," ",{p:[22,7,1134],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_max"],s:'_0&&_1&&_2?null:"disabled"'},p:[22,37,1164]}],action:"timer",params:'{"change": "increase"}'},f:["Increase"]}]}],n:51,r:"data.timing",p:[15,3,504]}," ",{p:[26,3,1369],t:7,e:"ui-section",a:{label:"Timer"},f:[{p:[27,5,1400],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"danger":"caution"'},p:[27,38,1433]}],action:"toggle_timer",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.safety"],s:'_0&&_1&&!_2?null:"disabled"'},p:[29,14,1514]}]},f:[{t:2,x:{r:["data.timing"],s:'_0?"On":"Off"'},p:[30,7,1602]}]}]}]}," ",{p:[34,1,1680],t:7,e:"ui-display",a:{title:"Anchoring"},f:[{p:[35,3,1713],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[36,12,1735]}],icon:[{t:2,x:{r:["data.anchored"],s:'_0?"lock":"unlock"'},p:[37,11,1810]}],style:[{t:2,x:{r:["data.anchored"],s:'_0?null:"caution"'},p:[38,12,1860]}],action:"anchor"},f:[{t:2,x:{r:["data.anchored"],s:'_0?"Engaged":"Off"'},p:[39,21,1918]}]}]}," ",{p:[41,1,1982],t:7,e:"ui-display",a:{title:"Safety"},f:[{p:[42,3,2012],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[43,12,2034]}],icon:[{t:2,x:{r:["data.safety"],s:'_0?"lock":"unlock"'},p:[44,11,2109]}],action:"safety",style:[{t:2,x:{r:["data.safety"],s:'_0?"caution":"danger"'},p:[45,12,2173]}]},f:[{p:[46,7,2220],t:7,e:"span",f:[{t:2,x:{r:["data.safety"],s:'_0?"On":"Off"'},p:[46,13,2226]}]}]}]}," ",{p:[49,1,2293],t:7,e:"ui-display",a:{title:"Code"},f:[{p:[50,3,2321],t:7,e:"ui-section",a:{label:"Message"},f:[{t:2,r:"data.message",p:[50,31,2349]}]}," ",{p:[51,3,2381],t:7,e:"ui-section",a:{label:"Keypad"},f:[{p:[52,5,2413],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[52,39,2447]}],params:'{"digit":"1"}'},f:["1"]}," ",{p:[53,5,2531],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[53,39,2565]}],params:'{"digit":"2"}'},f:["2"]}," ",{p:[54,5,2649],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[54,39,2683]}],params:'{"digit":"3"}'},f:["3"]}," ",{p:[55,5,2767],t:7,e:"br"}," ",{p:[56,5,2776],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[56,39,2810]}],params:'{"digit":"4"}'},f:["4"]}," ",{p:[57,5,2894],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[57,39,2928]}],params:'{"digit":"5"}'},f:["5"]}," ",{p:[58,5,3012],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[58,39,3046]}],params:'{"digit":"6"}'},f:["6"]}," ",{p:[59,5,3130],t:7,e:"br"}," ",{p:[60,5,3139],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[60,39,3173]}],params:'{"digit":"7"}'},f:["7"]}," ",{p:[61,5,3257],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[61,39,3291]}],params:'{"digit":"8"}'},f:["8"]}," ",{p:[62,5,3375],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[62,39,3409]}],params:'{"digit":"9"}'},f:["9"]}," ",{p:[63,5,3493],t:7,e:"br"}," ",{p:[64,5,3502],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[64,39,3536]}],params:'{"digit":"R"}'},f:["R"]}," ",{p:[65,5,3620],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[65,39,3654]}],params:'{"digit":"0"}'},f:["0"]}," ",{p:[66,5,3738],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[66,39,3772]}],params:'{"digit":"E"}'},f:["E"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],432:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,24],t:7,e:"ui-button",a:{icon:"undo",action:"change_menu",params:'{"menu": "1"}'},f:["Return"]}," ",{p:[3,2,111],t:7,e:"ui-display",a:{title:"Advanced Surgery Procedures"},f:[{p:[4,3,162],t:7,e:"ui-button",a:{icon:"download",action:"sync"},f:["Sync with research database"]}," ",{t:4,f:[{p:[6,4,273],t:7,e:"ui-display",f:[{p:[7,6,291],t:7,e:"ui-section",f:[{p:[7,18,303],t:7,e:"b",f:[{t:2,r:"name",p:[7,21,306]}]}]}," ",{p:[8,6,337],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[8,18,349]}]}]}],n:52,r:"data.surgeries",p:[5,3,245]}]}],n:50,x:{r:["data.menu"],s:"_0==2"},p:[1,1,0]},{t:4,n:51,f:[{p:[13,2,425],t:7,e:"ui-button",a:{action:"change_menu",params:'{"menu": "2"}'},f:["View Surgery Procedures"]}," ",{t:4,f:[{p:[15,3,542],t:7,e:"ui-notice",f:["No table detected!"]}],n:51,r:"data.table",p:[14,2,517]}," ",{p:[19,2,605],t:7,e:"ui-display",f:[{p:[20,3,620],t:7,e:"ui-display",a:{title:"Patient State"},f:[{t:4,f:[{p:[22,5,683],t:7,e:"ui-section",a:{label:"State"},f:[{p:[23,6,715],t:7,e:"span",a:{"class":[{t:2,r:"data.patient.statstate",p:[23,19,728]}]},f:[{t:2,r:"data.patient.stat",p:[23,47,756]}]}]}," ",{p:[25,5,807],t:7,e:"ui-section",a:{label:"Blood Type"},f:[{p:[26,6,844],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.patient.blood_type",p:[26,28,866]}]}]}," ",{p:[28,5,923],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[29,6,956],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.patient.minHealth",p:[29,19,969]}],max:[{t:2,r:"data.patient.maxHealth",p:[29,52,1002]}],value:[{t:2,r:"data.patient.health",p:[29,87,1037]}],state:[{t:2,x:{r:["data.patient.health"],s:'_0>=0?"good":"average"'},p:[30,13,1074]}]},f:[{t:2,x:{r:["adata.patient.health"],s:"Math.round(_0)"},p:[30,64,1125]}]}]}," ",{t:4,f:[{p:[33,6,1357],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[33,25,1376]}]},f:[{p:[34,7,1394],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.patient.maxHealth",p:[34,28,1415]}],value:[{t:2,rx:{r:"data.patient",m:[{t:30,n:"type"}]},p:[34,63,1450]}],state:"bad"},f:[{t:2,x:{r:["type","adata.patient"],s:"Math.round(_1[_0])"},p:[34,99,1486]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Burn",type:"fireLoss"},{label:"Toxin",type:"toxLoss"},{label:"Respiratory",type:"oxyLoss"}]'},p:[32,5,1193]}],n:50,r:"data.patient",p:[21,4,658]},{t:4,n:51,f:["No patient detected."],r:"data.patient"}]}," ",{p:[41,3,1630],t:7,e:"ui-display",a:{title:"Initiated Procedures"},f:[{t:4,f:[{t:4,f:[{p:[44,6,1734],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"name",p:[44,28,1756]}]},f:[{p:[45,7,1773],t:7,e:"ui-section",a:{label:"Next Step"},f:[{p:[46,8,1811],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"next_step",p:[46,30,1833]}]}," ",{t:4,f:[{p:[48,9,1890],t:7,e:"span",a:{"class":"content"},f:[{p:[48,31,1912],t:7,e:"b",f:["Required chemicals:"]},{p:[48,57,1938],t:7,e:"br"}," ",{t:2,r:"chems_needed",p:[48,62,1943]}]}],n:50,r:"chems_needed",p:[47,8,1861]}]}," ",{t:4,f:[{p:[52,8,2040],t:7,e:"ui-section",a:{label:"Alternative Step"},f:[{p:[53,9,2086],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"alternative_step",p:[53,31,2108]}]}," ",{t:4,f:[{p:[55,10,2178],t:7,e:"span",a:{"class":"content"},f:[{p:[55,32,2200],t:7,e:"b",f:["Required chemicals:"]},{p:[55,58,2226],t:7,e:"br"}," ",{t:2,r:"chems_needed",p:[55,63,2231]}]}],n:50,r:"alt_chems_needed",p:[54,9,2144]}]}],n:50,r:"alternative_step",p:[51,7,2008]}]}],n:52,r:"data.procedures",p:[43,5,1703]}],n:50,r:"data.procedures",p:[42,4,1675]},{t:4,n:51,f:["No active procedures."],r:"data.procedures"}]}]}],x:{r:["data.menu"],s:"_0==2"}}]},e.exports=a.extend(r.exports)},{341:341}],433:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,2,15],t:7,e:"ui-section",f:["This machine only accepts ore. Gibtonite and Slag are not accepted."]}," ",{p:[5,2,117],t:7,e:"ui-section",f:["Current unclaimed credits: ",{t:2,r:"data.unclaimedPoints",p:[6,30,160]}," ",{p:[7,4,189],t:7,e:"ui-button",a:{action:"Claim"},f:["Claim"]}]}]}," ",{p:[12,1,276],t:7,e:"ui-display",f:[{t:4,f:[{p:[14,3,315],t:7,e:"ui-section",f:[{p:[15,4,332],t:7,e:"ui-button",a:{action:"diskEject",icon:"eject"},f:["Eject Disk"]}]}," ",{t:4,f:[{p:[20,4,460],t:7,e:"ui-section",a:{"class":"candystripe"},f:[{p:[21,5,496],t:7,e:"ui-button",a:{action:"diskUpload",state:[{t:2,x:{r:["canupload"],s:'(_0)?null:"disabled"'},p:[21,42,533]}],icon:"upload",align:"right",params:['{ "design" : "',{t:2,r:"index",p:[21,129,620]},'" }']},f:["Upload"]}," File ",{t:2,r:"index",p:[24,10,676]},": ",{t:2,r:"name",p:[24,21,687]}]}],n:52,r:"data.diskDesigns",p:[19,3,429]}],n:50,r:"data.hasDisk",p:[13,2,291]},{t:4,n:51,f:[{p:[28,3,741],t:7,e:"ui-section",f:[{p:[29,4,758],t:7,e:"ui-button",a:{action:"diskInsert",icon:"floppy-o"},f:["Insert Disk"]}]}],r:"data.hasDisk"}]}," ",{t:4,f:[{p:[36,2,911],t:7,e:"ui-display",f:[{p:[37,3,927],t:7,e:"ui-section",f:[{p:[38,4,944],t:7,e:"b",f:["Warning"]},": ",{t:2,r:"data.disconnected",p:[38,20,960]},". Please contact the quartermaster."]}]}],n:50,r:"data.disconnected",p:[35,1,883]},{t:4,f:[{p:[43,2,1100],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[44,3,1133],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[45,5,1168],t:7,e:"section",a:{"class":"cell"},f:["Mineral"]}," ",{p:[48,5,1226],t:7,e:"section",a:{"class":"cell" -},f:["Sheets"]}," ",{p:[51,5,1283],t:7,e:"section",a:{"class":"cell"},f:[]}," ",{p:[53,5,1327],t:7,e:"section",a:{"class":"cell"},f:[]}," ",{p:[55,5,1371],t:7,e:"section",a:{"class":"cell"},f:["Ore Value"]}]}," ",{t:4,f:[{p:[60,4,1473],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[61,5,1508],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[62,6,1537]}]}," ",{p:[64,5,1567],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[65,6,1610]}]}," ",{p:[67,5,1642],t:7,e:"section",a:{"class":"cell"},f:[{p:[68,6,1671],t:7,e:"input",a:{value:[{t:2,r:"sheets",p:[68,19,1684]}],placeholder:"###","class":"number"}}]}," ",{p:[70,5,1751],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{p:[71,6,1794],t:7,e:"ui-button",a:{"class":"center",grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[71,60,1848]}],params:['{ "id" : ',{t:2,r:"id",p:[71,115,1903]},', "sheets" : ',{t:2,r:"sheets",p:[71,134,1922]}," }"]},f:["Release"]}]}," ",{p:[75,5,1993],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"value",p:[76,6,2036]}]}]}],n:52,r:"data.materials",p:[59,3,1444]}," ",{t:4,f:[{p:[81,4,2119],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[82,5,2154],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[83,6,2183]}]}," ",{p:[85,5,2213],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[86,6,2256]}]}," ",{p:[88,5,2288],t:7,e:"section",a:{"class":"cell"},f:[{p:[89,6,2317],t:7,e:"input",a:{value:[{t:2,r:"sheets",p:[89,19,2330]}],placeholder:"###","class":"number"}}]}," ",{p:[91,5,2397],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{p:[92,6,2440],t:7,e:"ui-button",a:{"class":"center",grid:0,action:"Smelt",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[92,58,2492]}],params:['{ "id" : ',{t:2,r:"id",p:[92,114,2548]},', "sheets" : ',{t:2,r:"sheets",p:[92,133,2567]}," }"]},f:["Smelt"]}]}," ",{p:[96,5,2635],t:7,e:"section",a:{"class":"cell",align:"right"},f:[]}]}],n:52,r:"data.alloys",p:[80,3,2093]}]}],n:50,x:{r:["data.materials","data.alloys"],s:"_0||_1"},p:[42,1,1060]}]},e.exports=a.extend(r.exports)},{341:341}],434:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:{button:[{p:[4,4,84],t:7,e:"ui-button",a:{icon:"remove",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[4,36,116]}],action:"empty_eject_beaker"},f:["Empty and eject"]}," ",{p:[7,4,225],t:7,e:"ui-button",a:{icon:"trash",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[7,35,256]}],action:"empty_beaker"},f:["Empty"]}," ",{p:[10,4,349],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[10,35,380]}],action:"eject_beaker"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{t:4,f:[{p:[15,4,514],t:7,e:"ui-section",f:[{t:4,f:[{p:[17,6,562],t:7,e:"span",a:{"class":"bad"},f:["The beaker is empty!"]}],n:50,r:"data.beaker_empty",p:[16,5,531]},{t:4,n:51,f:[{p:[19,6,626],t:7,e:"ui-subdisplay",a:{title:"Blood"},f:[{t:4,f:[{p:[21,8,692],t:7,e:"ui-section",a:{label:"Blood DNA"},f:[{t:2,r:"data.blood.dna",p:[21,38,722]}]}," ",{p:[22,8,761],t:7,e:"ui-section",a:{label:"Blood type"},f:[{t:2,r:"data.blood.type",p:[22,39,792]}]}],n:50,r:"data.has_blood",p:[20,7,662]},{t:4,n:51,f:[{p:[24,8,847],t:7,e:"ui-section",f:[{p:[25,9,868],t:7,e:"span",a:{"class":"average"},f:["No blood sample detected."]}]}],r:"data.has_blood"}]}],r:"data.beaker_empty"}]}],n:50,r:"data.has_beaker",p:[14,3,487]},{t:4,n:51,f:[{p:[32,4,1023],t:7,e:"ui-section",f:[{p:[33,5,1040],t:7,e:"span",a:{"class":"bad"},f:["No beaker loaded."]}]}],r:"data.has_beaker"}]}," ",{t:4,f:[{p:[38,3,1151],t:7,e:"ui-display",a:{title:"Diseases"},f:[{t:4,f:[{p:{button:[{t:4,f:[{p:[43,8,1301],t:7,e:"ui-button",a:{icon:"pencil",action:"rename_disease",state:[{t:2,x:{r:["can_rename"],s:'_0?"":"disabled"'},p:[43,64,1357]}],params:['{"index": ',{t:2,r:"index",p:[43,116,1409]},"}"]},f:["Name advanced disease"]}],n:50,r:"is_adv",p:[42,7,1279]}," ",{p:[47,7,1492],t:7,e:"ui-button",a:{icon:"flask",action:"create_culture_bottle",state:[{t:2,x:{r:["data.is_ready"],s:'_0?"":"disabled"'},p:[47,69,1554]}],params:['{"index": ',{t:2,r:"index",p:[47,124,1609]},"}"]},f:["Create virus culture bottle"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[40,24,1230]}],button:0},f:[" ",{p:[51,6,1699],t:7,e:"ui-section",a:{label:"Disease agent"},f:[{t:2,r:"agent",p:[51,40,1733]}]}," ",{p:[52,6,1761],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"description",p:[52,38,1793]}]}," ",{p:[53,6,1827],t:7,e:"ui-section",a:{label:"Spread"},f:[{t:2,r:"spread",p:[53,33,1854]}]}," ",{p:[54,6,1883],t:7,e:"ui-section",a:{label:"Possible cure"},f:[{t:2,r:"cure",p:[54,40,1917]}]}," ",{t:4,f:[{p:[56,7,1966],t:7,e:"ui-section",a:{label:"Symptoms"},f:[{t:4,f:[{p:[58,9,2030],t:7,e:"ui-button",a:{action:"symptom_details",state:"",params:['{"picked_symptom": ',{t:2,r:"sym_index",p:[58,81,2102]},', "index": ',{t:2,r:"index",p:[58,105,2126]},"}"]},f:[{t:2,r:"name",p:[59,10,2148]}," "]},{p:[60,21,2177],t:7,e:"br"}],n:52,r:"symptoms",p:[57,8,2003]}]}," ",{p:[63,7,2227],t:7,e:"ui-section",a:{label:"Resistance"},f:[{t:2,r:"resistance",p:[63,38,2258]}]}," ",{p:[64,7,2292],t:7,e:"ui-section",a:{label:"Stealth"},f:[{t:2,r:"stealth",p:[64,35,2320]}]}," ",{p:[65,7,2351],t:7,e:"ui-section",a:{label:"Stage speed"},f:[{t:2,r:"stage_speed",p:[65,39,2383]}]}," ",{p:[66,7,2418],t:7,e:"ui-section",a:{label:"Transmittability"},f:[{t:2,r:"transmission",p:[66,44,2455]}]}],n:50,r:"is_adv",p:[55,6,1945]}]}],n:52,r:"data.viruses",p:[39,4,1184]},{t:4,n:51,f:[{p:[70,5,2532],t:7,e:"ui-section",f:[{p:[71,6,2550],t:7,e:"span",a:{"class":"average"},f:["No detectable virus in the blood sample."]}]}],r:"data.viruses"}]}," ",{p:[75,3,2669],t:7,e:"ui-display",a:{title:"Antibodies"},f:[{t:4,f:[{p:[77,5,2735],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[77,24,2754]}]},f:[{p:[78,7,2771],t:7,e:"ui-button",a:{icon:"eyedropper",state:[{t:2,x:{r:["data.is_ready"],s:'_0?"":"disabled"'},p:[78,43,2807]}],action:"create_vaccine_bottle",params:['{"index": ',{t:2,r:"id",p:[78,129,2893]},"}"]},f:["Create vaccine bottle"]}]}],n:52,r:"data.resistances",p:[76,4,2704]},{t:4,n:51,f:[{p:[83,5,2985],t:7,e:"ui-section",f:[{p:[84,6,3003],t:7,e:"span",a:{"class":"average"},f:["No antibodies detected in the blood sample."]}]}],r:"data.resistances"}]}],n:50,r:"data.has_blood",p:[37,2,1126]}],n:50,x:{r:["data.mode"],s:"_0==1"},p:[1,1,0]},{t:4,n:51,f:[{p:[90,2,3142],t:7,e:"ui-button",a:{icon:"undo",state:"",action:"back"},f:["Back"]}," ",{t:4,f:[{p:[94,4,3237],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[94,23,3256]}]},f:[{p:[95,4,3270],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[96,5,3287]}," ",{t:4,f:[{p:[98,5,3320],t:7,e:"br"}," ",{p:[99,5,3330],t:7,e:"b",f:["This symptom has been neutered, and has no effect. It will still affect the virus' statistics."]}],n:50,r:"neutered",p:[97,4,3299]}]}," ",{p:[102,4,3463],t:7,e:"ui-section",f:[{p:[103,5,3480],t:7,e:"ui-section",a:{label:"Level"},f:[{t:2,r:"level",p:[103,31,3506]}]}," ",{p:[104,5,3533],t:7,e:"ui-section",a:{label:"Resistance"},f:[{t:2,r:"resistance",p:[104,36,3564]}]}," ",{p:[105,5,3596],t:7,e:"ui-section",a:{label:"Stealth"},f:[{t:2,r:"stealth",p:[105,33,3624]}]}," ",{p:[106,5,3653],t:7,e:"ui-section",a:{label:"Stage speed"},f:[{t:2,r:"stage_speed",p:[106,37,3685]}]}," ",{p:[107,5,3718],t:7,e:"ui-section",a:{label:"Transmittability"},f:[{t:2,r:"transmission",p:[107,42,3755]}]}]}," ",{p:[109,4,3805],t:7,e:"ui-subdisplay",a:{title:"Effect Thresholds"},f:[{p:[110,5,3851],t:7,e:"ui-section",f:[{t:3,r:"threshold_desc",p:[110,17,3863]}]}]}]}],n:53,r:"data.symptom",p:[93,2,3211]}],x:{r:["data.mode"],s:"_0==1"}}]},e.exports=a.extend(r.exports)},{341:341}],435:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(483);e.exports={data:{filter:"",tooltiptext:function(t,e,n){var a="";return t&&(a+="REQUIREMENTS: "+t+" "),e&&(a+="CATALYSTS: "+e+" "),n&&(a+="TOOLS: "+n),a}},oninit:function(){var t=this;this.on({hover:function(t){this.set("hovered",t.context.params)},unhover:function(t){this.set("hovered")}}),this.observe("filter",function(e,a,r){var i=null;i=t.get("data.display_compact")?t.findAll(".section"):t.findAll(".display:not(:first-child)"),(0,n.filterMulti)(i,t.get("filter").toLowerCase())},{init:!1})}}}(r),r.exports.template={v:3,t:[" ",{p:[48,1,1295],t:7,e:"ui-display",a:{title:[{t:2,r:"data.category",p:[48,20,1314]},{t:4,f:[" : ",{t:2,r:"data.subcategory",p:[48,64,1358]}],n:50,r:"data.subcategory",p:[48,37,1331]}]},f:[{t:4,f:[{p:[50,3,1410],t:7,e:"ui-section",f:["Crafting... ",{p:[51,16,1438],t:7,e:"i",a:{"class":"fa-spin fa fa-spinner"}}]}],n:50,r:"data.busy",p:[49,2,1390]},{t:4,n:51,f:[{p:[54,3,1504],t:7,e:"ui-section",f:[{p:[55,4,1520],t:7,e:"table",a:{style:"width:100%"},f:[{p:[56,5,1551],t:7,e:"tr",f:[{p:[57,6,1561],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[58,7,1602],t:7,e:"ui-button",a:{icon:"arrow-left",action:"backwardCat"},f:[{t:2,r:"data.prev_cat",p:[59,8,1660]}]}]}," ",{p:[62,6,1713],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[63,7,1754],t:7,e:"ui-button",a:{icon:"arrow-right",action:"forwardCat"},f:[{t:2,r:"data.next_cat",p:[64,7,1811]}]}]}," ",{p:[67,6,1864],t:7,e:"td",a:{style:"float:right!important"},f:[{t:4,f:[{p:[69,7,1946],t:7,e:"ui-button",a:{icon:"lock",action:"toggle_recipes"},f:["Showing Craftable Recipes"]}],n:50,r:"data.display_craftable_only",p:[68,6,1904]},{t:4,n:51,f:[{p:[73,7,2066],t:7,e:"ui-button",a:{icon:"unlock",action:"toggle_recipes"},f:["Showing All Recipes"]}],r:"data.display_craftable_only"}]}," ",{p:[78,6,2191],t:7,e:"td",a:{style:"float:right!important"},f:[{p:[79,7,2232],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.display_compact"],s:'_0?"check-square-o":"square-o"'},p:[79,24,2249]}],action:"toggle_compact"},f:["Compact"]}]}]}," ",{p:[84,5,2391],t:7,e:"tr",f:[{t:4,f:[{p:[86,6,2430],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[87,7,2471],t:7,e:"ui-button",a:{icon:"arrow-left",action:"backwardSubCat"},f:[{t:2,r:"data.prev_subcat",p:[88,8,2532]}]}]}," ",{p:[91,6,2588],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[92,7,2629],t:7,e:"ui-button",a:{icon:"arrow-right",action:"forwardSubCat"},f:[{t:2,r:"data.next_subcat",p:[93,8,2690]}]}]}],n:50,r:"data.subcategory",p:[85,5,2400]}]}]}," ",{t:4,f:[{t:4,f:[" ",{p:[101,6,2892],t:7,e:"ui-input",a:{value:[{t:2,r:"filter",p:[101,23,2909]}],placeholder:"Filter.."}}],n:51,r:"data.display_compact",p:[100,5,2803]}],n:50,r:"config.fancy",p:[99,4,2778]}]}," ",{t:4,f:[{p:[106,5,3039],t:7,e:"ui-display",f:[{t:4,f:[{p:[108,6,3086],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[108,25,3105]}]},f:[{p:[109,7,3122],t:7,e:"ui-button",a:{tooltip:[{t:2,x:{r:["tooltiptext","req_text","catalyst_text","tool_text"],s:"_0(_1,_2,_3)"},p:[109,27,3142]}],"tooltip-side":"right",action:"make",params:['{"recipe": "',{t:2,r:"ref",p:[109,135,3250]},'"}'],icon:"gears"},v:{hover:"hover",unhover:"unhover"},f:["Craft"]}]}],n:52,r:"data.can_craft",p:[107,5,3056]}," ",{t:4,f:[{t:4,f:[{p:[116,7,3452],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[116,26,3471]}]},f:[{p:[117,8,3489],t:7,e:"ui-button",a:{tooltip:[{t:2,x:{r:["tooltiptext","req_text","catalyst_text","tool_text"],s:"_0(_1,_2,_3)"},p:[117,28,3509]}],"tooltip-side":"right",state:"disabled",icon:"gears"},v:{hover:"hover",unhover:"unhover"},f:["Craft"]}]}],n:52,r:"data.cant_craft",p:[115,6,3420]}],n:51,r:"data.display_craftable_only",p:[114,5,3382]}]}],n:50,r:"data.display_compact",p:[105,4,3006]},{t:4,n:51,f:[{t:4,f:[{p:[126,6,3822],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[126,25,3841]}]},f:[{t:4,f:[{p:[128,8,3882],t:7,e:"ui-section",a:{label:"Requirements"},f:[{t:2,r:"req_text",p:[129,9,3924]}]}],n:50,r:"req_text",p:[127,7,3858]}," ",{t:4,f:[{p:[133,8,4007],t:7,e:"ui-section",a:{label:"Catalysts"},f:[{t:2,r:"catalyst_text",p:[134,9,4046]}]}],n:50,r:"catalyst_text",p:[132,7,3978]}," ",{t:4,f:[{p:[138,8,4130],t:7,e:"ui-section",a:{label:"Tools"},f:[{t:2,r:"tool_text",p:[139,9,4165]}]}],n:50,r:"tool_text",p:[137,7,4105]}," ",{p:[142,7,4220],t:7,e:"ui-section",f:[{p:[143,8,4240],t:7,e:"ui-button",a:{icon:"gears",action:"make",params:['{"recipe": "',{t:2,r:"ref",p:[143,66,4298]},'"}']},f:["Craft"]}]}]}],n:52,r:"data.can_craft",p:[125,5,3792]}," ",{t:4,f:[{t:4,f:[{p:[151,7,4471],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[151,26,4490]}]},f:[{t:4,f:[{p:[153,9,4533],t:7,e:"ui-section",a:{label:"Requirements"},f:[{t:2,r:"req_text",p:[154,10,4576]}]}],n:50,r:"req_text",p:[152,8,4508]}," ",{t:4,f:[{p:[158,9,4663],t:7,e:"ui-section",a:{label:"Catalysts"},f:[{t:2,r:"catalyst_text",p:[159,10,4703]}]}],n:50,r:"catalyst_text",p:[157,8,4633]}," ",{t:4,f:[{p:[163,9,4791],t:7,e:"ui-section",a:{label:"Tools"},f:[{t:2,r:"tool_text",p:[164,10,4827]}]}],n:50,r:"tool_text",p:[162,8,4765]}]}],n:52,r:"data.cant_craft",p:[150,6,4439]}],n:51,r:"data.display_craftable_only",p:[149,5,4401]}],r:"data.display_compact"}],r:"data.busy"}]}]},e.exports=a.extend(r.exports)},{341:341,483:483}],436:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,14],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.holding"],s:'_0?"is":"is not"'},p:[2,23,34]}," connected to a tank."]}]}," ",{p:[4,1,110],t:7,e:"ui-display",a:{title:"Status",button:0},f:[{p:[5,3,147],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[6,5,181],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[6,11,187]}," kPa"]}]}," ",{p:[8,3,247],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[9,5,277],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected"],s:'_0?"good":"average"'},p:[9,18,290]}]},f:[{t:2,x:{r:["data.connected"],s:'_0?"Connected":"Not Connected"'},p:[9,59,331]}]}]}]}," ",{p:[12,1,419],t:7,e:"ui-display",a:{title:"Pump"},f:[{p:[13,3,447],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[14,5,478],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[14,22,495]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":"null"'},p:[15,14,545]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[16,22,601]}]}]}," ",{p:[18,3,658],t:7,e:"ui-section",a:{label:"Direction"},f:[{p:[19,5,693],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.direction"],s:'_0=="out"?"sign-out":"sign-in"'},p:[19,22,710]}],action:"direction"},f:[{t:2,x:{r:["data.direction"],s:'_0=="out"?"Out":"In"'},p:[20,26,789]}]}]}," ",{p:[22,3,862],t:7,e:"ui-section",a:{label:"Target Pressure"},f:[{p:[23,5,903],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.min_pressure",p:[23,18,916]}],max:[{t:2,r:"data.max_pressure",p:[23,46,944]}],value:[{t:2,r:"data.target_pressure",p:[24,14,980]}]},f:[{t:2,x:{r:["adata.target_pressure"],s:"Math.round(_0)"},p:[24,40,1006]}," kPa"]}]}," ",{p:[26,3,1075],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[27,5,1119],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.target_pressure","data.default_pressure"],s:'_0!=_1?null:"disabled"'},p:[27,38,1152]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[29,5,1300],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.target_pressure","data.min_pressure"],s:'_0>_1?null:"disabled"'},p:[29,36,1331]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[31,5,1470],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[32,5,1564],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.target_pressure","data.max_pressure"],s:'_0<_1?null:"disabled"'},p:[32,35,1594]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}]}," ",{p:{button:[{t:4,f:[{p:[39,7,1853],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.on"],s:'_0?"danger":null'},p:[39,38,1884]}],action:"eject"},f:["Eject"]}],n:50,r:"data.holding",p:[38,5,1826]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[43,3,2e3],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holding.name",p:[44,4,2030]}]}," ",{p:[46,3,2070],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holding.pressure"],s:"Math.round(_0)"},p:[47,4,2103]}," kPa"]}],n:50,r:"data.holding",p:[42,3,1977]},{t:4,n:51,f:[{p:[50,3,2174],t:7,e:"ui-section",f:[{p:[51,4,2190],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.holding"}]}]},e.exports=a.extend(r.exports)},{341:341}],437:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[3,1,69],t:7,e:"ui-notice",f:[{p:[4,3,84],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.holding"],s:'_0?"is":"is not"'},p:[4,23,104]}," connected to a tank."]}]}," ",{p:[6,1,182],t:7,e:"ui-display",a:{title:"Status",button:0},f:[{p:[7,3,220],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[8,5,255],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[8,11,261]}," kPa"]}]}," ",{p:[10,3,323],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[11,5,354],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected"],s:'_0?"good":"average"'},p:[11,18,367]}]},f:[{t:2,x:{r:["data.connected"],s:'_0?"Connected":"Not Connected"'},p:[11,59,408]}]}]}]}," ",{p:[14,1,499],t:7,e:"ui-display",a:{title:"Filter"},f:[{p:[15,3,530],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[16,5,562],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[16,22,579]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":"null"'},p:[17,14,630]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[18,22,687]}]}]}]}," ",{p:{button:[{t:4,f:[{p:[24,7,856],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.on"],s:'_0?"danger":null'},p:[24,38,887]}],action:"eject"},f:["Eject"]}],n:50,r:"data.holding",p:[23,5,828]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[28,3,1007],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holding.name",p:[29,4,1038]}]}," ",{p:[31,3,1080],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holding.pressure"],s:"Math.round(_0)"},p:[32,4,1114]}," kPa"]}],n:50,r:"data.holding",p:[27,3,983]},{t:4,n:51,f:[{p:[35,3,1188],t:7,e:"ui-section",f:[{p:[36,4,1205],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.holding"}]}," ",{p:[40,1,1293],t:7,e:"ui-display",a:{title:"Filters"},f:[{t:4,f:[{p:[42,5,1345],t:7,e:"filters"}],n:53,r:"data",p:[41,3,1325]}]}]},r.exports.components=r.exports.components||{};var i={filters:t(456)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,456:456}],438:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargingState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},chargingMode:function(t){return 2==t?"Full":1==t?"Charging":"Draining"},channelState:function(t){return t>=2?"good":"bad"},channelPower:function(t){return t>=2?"On":"Off"},channelMode:function(t){return 1==t||3==t?"Auto":"Manual"}},computed:{graphData:function(){var t=this.get("data.history");return Object.keys(t).map(function(e){return t[e].map(function(t,e){return{x:e,y:t}})})}}}}(r),r.exports.template={v:3,t:[" ",{p:[42,1,1035],t:7,e:"ui-display",a:{title:"Network"},f:[{t:4,f:[{p:[44,5,1093],t:7,e:"ui-linegraph",a:{points:[{t:2,r:"graphData",p:[44,27,1115]}],height:"500",legend:'["Available", "Load"]',colors:'["rgb(0, 102, 0)", "rgb(153, 0, 0)"]',xunit:"seconds ago",xfactor:[{t:2,r:"data.interval",p:[46,38,1267]}],yunit:"W",yfactor:"1",xinc:[{t:2,x:{r:["data.stored"],s:"_0/10"},p:[47,15,1323]}],yinc:"9"}}],n:50,r:"config.fancy",p:[43,3,1067]},{t:4,n:51,f:[{p:[49,5,1373],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[50,7,1411],t:7,e:"span",f:[{t:2,r:"data.supply",p:[50,13,1417]}]}]}," ",{p:[52,5,1464],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[53,9,1499],t:7,e:"span",f:[{t:2,r:"data.demand",p:[53,15,1505]}]}]}],r:"config.fancy"}]}," ",{p:[57,1,1574],t:7,e:"ui-display",a:{title:"Areas"},f:[{p:[58,3,1604],t:7,e:"ui-section",a:{nowrap:0},f:[{p:[59,5,1629],t:7,e:"div",a:{"class":"content"},f:["Area"]}," ",{p:[60,5,1666],t:7,e:"div",a:{"class":"content"},f:["Charge"]}," ",{p:[61,5,1705],t:7,e:"div",a:{"class":"content"},f:["Load"]}," ",{p:[62,5,1742],t:7,e:"div",a:{"class":"content"},f:["Status"]}," ",{p:[63,5,1781],t:7,e:"div",a:{"class":"content"},f:["Equipment"]}," ",{p:[64,5,1823],t:7,e:"div",a:{"class":"content"},f:["Lighting"]}," ",{p:[65,5,1864],t:7,e:"div",a:{"class":"content"},f:["Environment"]}]}," ",{t:4,f:[{p:[68,5,1949],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[68,24,1968]}],nowrap:0},f:[{p:[69,7,1993],t:7,e:"div",a:{"class":"content"},f:[{t:2,x:{r:["@index","adata.areas"],s:"Math.round(_1[_0].charge)"},p:[69,28,2014]}," %"]}," ",{p:[70,7,2072],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.areas",m:[{t:30,n:"@index"},"load"]},p:[70,28,2093]}]}," ",{p:[71,7,2135],t:7,e:"div",a:{"class":"content"},f:[{p:[71,28,2156],t:7,e:"span",a:{"class":[{t:2,x:{r:["chargingState","charging"],s:"_0(_1)"},p:[71,41,2169]}]},f:[{t:2,x:{r:["chargingMode","charging"],s:"_0(_1)"},p:[71,70,2198]}]}]}," ",{p:[72,7,2245],t:7,e:"div",a:{"class":"content"},f:[{p:[72,28,2266],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","eqp"],s:"_0(_1)"},p:[72,41,2279]}]},f:[{t:2,x:{r:["channelPower","eqp"],s:"_0(_1)"},p:[72,64,2302]}," [",{p:[72,87,2325],t:7,e:"span",f:[{t:2,x:{r:["channelMode","eqp"],s:"_0(_1)"},p:[72,93,2331]}]},"]"]}]}," ",{p:[73,7,2380],t:7,e:"div",a:{"class":"content"},f:[{p:[73,28,2401],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","lgt"],s:"_0(_1)"},p:[73,41,2414]}]},f:[{t:2,x:{r:["channelPower","lgt"],s:"_0(_1)"},p:[73,64,2437]}," [",{p:[73,87,2460],t:7,e:"span",f:[{t:2,x:{r:["channelMode","lgt"],s:"_0(_1)"},p:[73,93,2466]}]},"]"]}]}," ",{p:[74,7,2515],t:7,e:"div",a:{"class":"content"},f:[{p:[74,28,2536],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","env"],s:"_0(_1)"},p:[74,41,2549]}]},f:[{t:2,x:{r:["channelPower","env"],s:"_0(_1)"},p:[74,64,2572]}," [",{p:[74,87,2595],t:7,e:"span",f:[{t:2,x:{r:["channelMode","env"],s:"_0(_1)"},p:[74,93,2601]}]},"]"]}]}]}],n:52,r:"data.areas",p:[67,3,1923]}]}]},e.exports=a.extend(r.exports)},{341:341}],439:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{readableFrequency:function(){return Math.round(this.get("adata.frequency"))/10}}}}(r),r.exports.template={v:3,t:[" ",{p:[11,1,167],t:7,e:"ui-display",a:{title:"Settings"},f:[{t:4,f:[{p:[13,5,224],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[14,7,257],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.listening"],s:'_0?"power-off":"close"'},p:[14,24,274]}],style:[{t:2,x:{r:["data.listening"],s:'_0?"selected":null'},p:[14,75,325]}],action:"listen"},f:[{t:2,x:{r:["data.listening"],s:'_0?"On":"Off"'},p:[16,9,398]}]}]}],n:50,r:"data.headset",p:[12,3,199]},{t:4,n:51,f:[{p:[19,5,476],t:7,e:"ui-section",a:{label:"Microphone"},f:[{p:[20,7,514],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.broadcasting"],s:'_0?"power-off":"close"'},p:[20,24,531]}],style:[{t:2,x:{r:["data.broadcasting"],s:'_0?"selected":null'},p:[20,78,585]}],action:"broadcast"},f:[{t:2,x:{r:["data.broadcasting"],s:'_0?"Engaged":"Disengaged"'},p:[22,9,664]}]}]}," ",{p:[24,5,746],t:7,e:"ui-section",a:{label:"Speaker"},f:[{p:[25,7,781],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.listening"],s:'_0?"power-off":"close"'},p:[25,24,798]}],style:[{t:2,x:{r:["data.listening"],s:'_0?"selected":null'},p:[25,75,849]}],action:"listen"},f:[{t:2,x:{r:["data.listening"],s:'_0?"Engaged":"Disengaged"'},p:[27,9,922]}]}]}],r:"data.headset"}," ",{t:4,f:[{p:[31,5,1034],t:7,e:"ui-section",a:{label:"High Volume"},f:[{p:[32,7,1073],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.useCommand"],s:'_0?"power-off":"close"'},p:[32,24,1090]}],style:[{t:2,x:{r:["data.useCommand"],s:'_0?"selected":null'},p:[32,76,1142]}],action:"command"},f:[{t:2,x:{r:["data.useCommand"],s:'_0?"On":"Off"'},p:[34,9,1217]}]}]}],n:50,r:"data.command",p:[30,3,1009]}]}," ",{p:[38,1,1305],t:7,e:"ui-display",a:{title:"Channel"},f:[{p:[39,3,1336],t:7,e:"ui-section",a:{label:"Frequency"},f:[{t:4,f:[{p:[41,7,1399],t:7,e:"span",f:[{t:2,r:"readableFrequency",p:[41,13,1405]}]}],n:50,r:"data.freqlock",p:[40,5,1371]},{t:4,n:51,f:[{p:[43,7,1453],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.frequency","data.minFrequency"],s:'_0==_1?"disabled":null'},p:[43,46,1492]}],action:"frequency",params:'{"adjust": -1}'}}," ",{p:[44,7,1603],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.frequency","data.minFrequency"],s:'_0==_1?"disabled":null'},p:[44,41,1637]}],action:"frequency",params:'{"adjust": -.2}'}}," ",{p:[45,7,1749],t:7,e:"ui-button",a:{icon:"pencil",action:"frequency",params:'{"tune": "input"}'},f:[{t:2,r:"readableFrequency",p:[45,78,1820]}]}," ",{p:[46,7,1860],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.frequency","data.maxFrequency"],s:'_0==_1?"disabled":null'},p:[46,40,1893]}],action:"frequency",params:'{"adjust": .2}'}}," ",{p:[47,7,2004],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.frequency","data.maxFrequency"],s:'_0==_1?"disabled":null'},p:[47,45,2042]}],action:"frequency",params:'{"adjust": 1}'}}],r:"data.freqlock"}]}," ",{t:4,f:[{p:[51,5,2212],t:7,e:"ui-section",a:{label:"Subspace Transmission"},f:[{p:[52,7,2261],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.subspace"],s:'_0?"power-off":"close"'},p:[52,24,2278]}],style:[{t:2,x:{r:["data.subspace"],s:'_0?"selected":null'},p:[52,74,2328]}],action:"subspace"},f:[{t:2,x:{r:["data.subspace"],s:'_0?"Active":"Inactive"'},p:[53,29,2395]}]}]}],n:50,r:"data.subspaceSwitchable",p:[50,3,2176]}," ",{t:4,f:[{p:[57,5,2522],t:7,e:"ui-section",a:{label:"Channels"},f:[{t:4,f:[{p:[59,9,2598],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["."],s:'_0?"check-square-o":"square-o"'},p:[59,26,2615]}],style:[{t:2,x:{r:["."],s:'_0?"selected":null'},p:[60,18,2671]}],action:"channel",params:['{"channel": "',{t:2,r:"channel",p:[61,49,2746]},'"}']},f:[{t:2,r:"channel",p:[62,11,2772]}]},{p:[62,34,2795],t:7,e:"br"}],n:52,i:"channel",r:"data.channels",p:[58,7,2558]}]}],n:50,x:{r:["data.subspace","data.channels"],s:"_0&&_1"},p:[56,3,2479]}]}]},e.exports=a.extend(r.exports)},{341:341}],440:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," "," "," "," "," "," "," "," ",{p:[11,1,550],t:7,e:"rdheader"}," ",{t:4,f:[{p:[13,2,583],t:7,e:"ui-display",a:{title:"CONSOLE LOCKED"},f:[{p:[14,3,621],t:7,e:"ui-button",a:{action:"Unlock"},f:["Unlock"]}]}],n:50,r:"data.locked",p:[12,1,562]},{t:4,f:[{p:[18,2,712],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.tabs",p:[18,17,727]}]},f:[{p:[19,3,745],t:7,e:"tab",a:{name:"Technology"},f:[{p:[20,4,772],t:7,e:"techweb"}]}," ",{p:[22,3,794],t:7,e:"tab",a:{name:"View Node"},f:[{p:[23,4,820],t:7,e:"nodeview"}]}," ",{p:[25,3,843],t:7,e:"tab",a:{name:"View Design"},f:[{p:[26,4,871],t:7,e:"designview"}]}," ",{p:[28,3,896],t:7,e:"tab",a:{name:"Disk Operations - Design"},f:[{p:[29,4,937],t:7,e:"diskopsdesign"}]}," ",{p:[31,3,965],t:7,e:"tab",a:{name:"Disk Operations - Technology"},f:[{p:[32,4,1010],t:7,e:"diskopstech"}]}," ",{p:[34,3,1036],t:7,e:"tab",a:{name:"Deconstructive Analyzer"},f:[{p:[35,4,1076],t:7,e:"destruct"}]}," ",{p:[37,3,1099],t:7,e:"tab",a:{name:"Protolathe"},f:[{p:[38,4,1126],t:7,e:"protolathe"}]}," ",{p:[40,3,1151],t:7,e:"tab",a:{name:"Circuit Imprinter"},f:[{p:[41,4,1185],t:7,e:"circuit"}]}," ",{p:[43,3,1207],t:7,e:"tab",a:{name:"Settings"},f:[{p:[44,4,1232],t:7,e:"settings"}]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[17,1,690]}]},r.exports.components=r.exports.components||{};var i={settings:t(449),circuit:t(441),protolathe:t(447),destruct:t(443),diskopsdesign:t(444),diskopstech:t(445),designview:t(442),nodeview:t(446),techweb:t(450),rdheader:t(448)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,441:441,442:442,443:443,444:444,445:445,446:446,447:447,448:448,449:449,450:450}],441:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[3,3,56],t:7,e:"ui-display",a:{title:"Circuit Imprinter Busy!"}}],n:50,r:"data.circuitbusy",p:[2,2,29]},{t:4,n:51,f:[{p:[5,3,126],t:7,e:"ui-display",f:[{p:[6,4,142],t:7,e:"ui-section",f:["Search Available Designs: ",{p:[7,4,183],t:7,e:"input",a:{value:[{t:2,r:"textsearch",p:[7,17,196]}],placeholder:"Type Here","class":"text"}}," ",{p:[8,5,254],t:7,e:"ui-button",a:{action:"textSearch",params:['{"latheType" : "circuit", "inputText" : ',{t:2,r:"textsearch",p:[8,84,333]},"}"]},f:["Search"]}]}," ",{p:[10,4,389],t:7,e:"ui-section",f:["Materials: ",{t:2,r:"data.circuitmats",p:[10,27,412]}," / ",{t:2,r:"data.circuitmaxmats",p:[10,50,435]}]}," ",{p:[11,4,475],t:7,e:"ui-section",f:["Reagents: ",{t:2,r:"data.circuitchems",p:[11,26,497]}," / ",{t:2,r:"data.circuitmaxchems",p:[11,50,521]}]}," ",{p:[12,3,561],t:7,e:"ui-display",f:[{p:[14,3,577],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.lathe_tabs",p:[14,18,592]}]},f:[{p:[15,4,617],t:7,e:"tab",a:{name:"Category List"},f:[{t:4,f:[{p:[17,6,680],t:7,e:"ui-button",a:{action:"switchcat",state:[{t:2,x:{r:["data.circuitcat"],s:'_0=="{{name}}"?"selected":null'},p:[17,43,717]}],params:['{"type" : "circuit", "cat" : "',{t:2,r:"name",p:[17,135,809]},'"}']},f:[{t:2,r:"name",p:[17,147,821]}]}],n:52,r:"data.circuitcats",p:[16,5,648]}]}," ",{p:[20,4,869],t:7,e:"tab",a:{name:"Selected Category"},f:[{t:4,f:[{p:[22,6,935],t:7,e:"ui-section",f:[{t:2,r:"name",p:[22,18,947]},{t:2,r:"matstring",p:[22,26,955]}," ",{p:[23,7,975],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[23,40,1008]}],params:['{"latheType" : "circuit", "id" : "',{t:2,r:"id",p:[23,119,1087]},'"}']},f:["Print"]}]}],n:52,r:"data.circuitdes",p:[21,5,904]}]}," ",{p:[27,4,1161],t:7,e:"tab",a:{name:"Search Results"},f:[{t:4,f:[{p:[29,6,1226],t:7,e:"ui-section",f:[{t:2,r:"name",p:[29,18,1238]},{t:2,r:"matstring",p:[29,26,1246]}," ",{p:[30,7,1266],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[30,40,1299]}],params:['{"latheType" : "circuit", "id" : "',{t:2,r:"id",p:[30,119,1378]},'"}']},f:["Print"]}]}],n:52,r:"data.circuitmatch",p:[28,5,1193]}]}," ",{p:[34,4,1452],t:7,e:"tab",a:{name:"Materials"},f:[{t:4,f:[{p:[36,6,1515],t:7,e:"ui-section",f:[{t:2,r:"name",p:[36,18,1527]}," : ",{t:2,r:"amount",p:[36,29,1538]}," cm3 - ",{t:4,f:[{p:[38,7,1586],t:7,e:"input",a:{value:[{t:2,r:"number",p:[38,20,1599]}],placeholder:["1-",{t:2,r:"sheets",p:[38,46,1625]}],"class":"number"}}," ",{p:[39,7,1660],t:7,e:"ui-button",a:{action:"releasemats",params:['{"latheType" : "circuit", "mat_id" : ',{t:2,r:"mat_id",p:[39,84,1737]},', "sheets" : ',{t:2,r:"number",p:[39,107,1760]},"}"]},f:["Release"]}],n:50,x:{r:["sheets"],s:"_0>0"},p:[37,6,1561]}]}],n:52,r:"data.circuitmat_list",p:[35,5,1479]}]}," ",{p:[44,4,1852],t:7,e:"tab",a:{name:"Chemicals"},f:[{t:4,f:[{p:[46,6,1916],t:7,e:"ui-section",f:[{t:2,r:"name",p:[46,18,1928]}," : ",{t:2,r:"amount",p:[46,29,1939]}," - ",{p:[47,7,1959],t:7,e:"ui-button",a:{action:"purgechem",params:['{"latheType" : "circuit", "name" : ',{t:2,r:"name",p:[47,80,2032]},', "id" : ',{t:2,r:"reagentid",p:[47,97,2049]},"}"]},f:["Purge"]}]}],n:52,r:"data.circuitchem_list",p:[45,5,1879]}]}]}]}]}],r:"data.circuitbusy"}],n:50,r:"data.circuit_linked",p:[1,1,0]},{t:4,n:51,f:[{p:[55,2,2162],t:7,e:"ui-display",a:{title:"No Linked Circuit Imprinter"}}],r:"data.circuit_linked"}]},e.exports=a.extend(r.exports)},{341:341}],442:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,30],t:7,e:"ui-display",a:{title:[{t:2,r:"data.sdesign_name",p:[2,21,49]}]},f:[{p:[3,3,75],t:7,e:"ui-section",a:{title:"Description"},f:[{t:2,r:"data.sdesign_desc",p:[3,35,107]}]}]}," ",{p:[5,2,158],t:7,e:"ui-display",a:{title:"Lathe Types"},f:[{t:4,f:[{p:[7,4,233],t:7,e:"ui-section",a:{title:"Circuit Imprinter"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&1"},p:[6,3,193]}," ",{t:4,f:[{p:[10,4,337],t:7,e:"ui-section",a:{title:"Protolathe"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&2"},p:[9,3,297]}," ",{t:4,f:[{p:[13,4,434],t:7,e:"ui-section",a:{title:"Autolathe"}}], -n:50,x:{r:["data.sdesign_buildtype"],s:"_0&4"},p:[12,3,394]}," ",{t:4,f:[{p:[16,4,530],t:7,e:"ui-section",a:{title:"Crafting Fabricator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&8"},p:[15,3,490]}," ",{t:4,f:[{p:[19,4,637],t:7,e:"ui-section",a:{title:"Exosuit Fabricator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&16"},p:[18,3,596]}," ",{t:4,f:[{p:[22,4,743],t:7,e:"ui-section",a:{title:"Biogenerator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&32"},p:[21,3,702]}," ",{t:4,f:[{p:[25,4,843],t:7,e:"ui-section",a:{title:"Limb Grower"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&64"},p:[24,3,802]}," ",{t:4,f:[{p:[28,4,943],t:7,e:"ui-section",a:{title:"Ore Smelter"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&128"},p:[27,3,901]}]}," ",{p:[31,2,1015],t:7,e:"ui-display",a:{title:"Materials"},f:[{t:4,f:[{p:[33,4,1084],t:7,e:"ui-section",a:{title:[{t:2,r:"matname",p:[33,23,1103]}]},f:[{t:2,r:"matamt",p:[33,36,1116]}," cm^3"]}],n:52,r:"data.sdesign_materials",p:[32,3,1048]}]}],n:50,r:"data.design_selected",p:[1,1,0]},{t:4,f:[{p:[38,2,1211],t:7,e:"ui-display",a:{title:"No Design Selected."}}],n:50,x:{r:["data.design_selected"],s:"!_0"},p:[37,1,1180]}]},e.exports=a.extend(r.exports)},{341:341}],443:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[4,3,57],t:7,e:"ui-display",a:{title:"Destructive Analyzer Busy!"}}],n:50,r:"data.destroybusy",p:[3,2,30]},{t:4,n:51,f:[{t:4,f:[{p:[7,4,162],t:7,e:"ui-display",a:{title:"Destructive Analyzer Unloaded"}}],n:50,x:{r:["data.destroy_loaded"],s:"!_0"},p:[6,3,130]},{t:4,n:51,f:[{p:[9,4,240],t:7,e:"ui-display",a:{title:"Loaded Item"},f:[{p:[10,4,276],t:7,e:"ui-section",a:{title:"Name"},f:[{t:2,r:"data.destroy_name",p:[10,29,301]}]}]}," ",{p:[12,4,356],t:7,e:"ui-display",a:{title:"Boost Nodes"},f:[{t:4,f:[{p:[14,6,425],t:7,e:"ui-section",a:{title:[{t:2,r:"name",p:[14,25,444]}," | ",{t:2,r:"value",p:[14,36,455]}]},f:[{p:[15,7,473],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["allow"],s:'_0?null:"disabled"'},p:[15,25,491]}],action:"deconstruct",params:['{"id":',{t:2,r:"id",p:[15,90,556]},"}"]},f:["Deconstruct and Boost"]}]}],n:52,r:"data.boost_paths",p:[13,5,393]}]}," ",{p:[19,4,652],t:7,e:"ui-button",a:{action:"eject_da"},f:["Eject Item"]}],x:{r:["data.destroy_loaded"],s:"!_0"}}],r:"data.destroybusy"}],n:50,r:"data.destroy_linked",p:[2,1,1]},{t:4,n:51,f:[{p:[23,2,733],t:7,e:"ui-display",a:{title:"No Linked Destructive Analyzer"}}],r:"data.destroy_linked"}]},e.exports=a.extend(r.exports)},{341:341}],444:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[3,2,22],t:7,e:"ui-display",a:{title:"No Design Disk Loaded"}}],n:50,x:{r:["data.ddisk"],s:"!_0"},p:[2,1,1]},{t:4,n:51,f:[{t:4,f:[{p:[6,3,116],t:7,e:"ui-display",a:{title:"Design Disk Updating"}}],n:50,r:"data.ddisk_update",p:[5,2,88]},{t:4,n:51,f:[{t:4,f:[{p:[9,4,213],t:7,e:"ui-display",a:{title:"Design Disk"},f:[{p:[10,5,250],t:7,e:"ui-section",a:{title:"Disk Space"},f:["Disk Capacity: ",{t:2,r:"data.ddisk_size",p:[10,51,296]}," blueprints."]}," ",{p:[11,5,345],t:7,e:"ui-section",a:{title:"Disk IO"},f:[{p:[11,33,373],t:7,e:"ui-button",a:{action:"ddisk_upall"},f:["Upload all designs"]}]}," ",{p:[12,5,453],t:7,e:"ui-section",a:{title:"Clear Disk"},f:[{p:[12,36,484],t:7,e:"ui-button",a:{action:"clear_designdisk",style:"danger"},f:["WIPE ALL DATA"]}]}," ",{p:[13,5,579],t:7,e:"ui-section",a:{title:"Eject Disk"},f:[{p:[13,36,610],t:7,e:"ui-button",a:{action:"eject_designdisk"},f:["Eject Disk"]}]}]}," ",{p:[15,4,703],t:7,e:"ui-display",a:{title:"Disk Contents"},f:[{t:4,f:[{p:[17,6,776],t:7,e:"ui-section",a:{title:"Number"},f:["#",{t:2,r:"pos",p:[17,34,804]},": ",{t:4,f:[{p:[19,8,848],t:7,e:"ui-button",a:{action:"upload_empty_ddisk_slot",params:['{"slot": "',{t:2,r:"pos",p:[19,70,910]},'"}']},f:["Upload to Empty Slot"]}],n:50,x:{r:["id"],s:'_0=="null"'},p:[18,7,820]},{t:4,n:51,f:[{p:[21,8,976],t:7,e:"ui-button",a:{action:"select_design",params:['{"id": "',{t:2,r:"id",p:[21,58,1026]},'"}'],state:[{t:2,x:{r:["data.sdesign_id","id"],s:'_0==_1?"selected":null'},p:[21,75,1043]}]},f:[{t:2,r:"name",p:[21,122,1090]}]}," ",{p:[22,8,1118],t:7,e:"ui-button",a:{action:"ddisk_erasepos",style:"danger",params:['{"id": "',{t:2,r:"id",p:[22,74,1184]},'"}'],state:[{t:2,x:{r:["id"],s:'_0=="null"?"disabled":null'},p:[22,91,1201]}]},f:["Delete Slot"]}],x:{r:["id"],s:'_0=="null"'}}]}],n:52,r:"data.ddisk_designs",p:[16,5,742]}]}],n:50,x:{r:["data.ddisk_upload"],s:"!_0"},p:[8,3,183]},{t:4,n:51,f:[{p:[28,4,1340],t:7,e:"ui-display",a:{title:"Upload Design to Disk"},f:[{p:[28,46,1382],t:7,e:"ui-section",f:["Available Designs:"]}]}," ",{t:4,f:[{p:[30,5,1484],t:7,e:"ui-section",f:[{p:[30,17,1496],t:7,e:"ui-button",a:{action:"ddisk_uploaddesign",params:['{"id": "',{t:2,r:"id",p:[30,72,1551]},'"}']},f:[{t:2,r:"name",p:[30,82,1561]}]}]}],n:52,r:"data.ddisk_possible_designs",p:[29,4,1442]}],x:{r:["data.ddisk_upload"],s:"!_0"}}],r:"data.ddisk_update"}],x:{r:["data.ddisk"],s:"!_0"}}]},e.exports=a.extend(r.exports)},{341:341}],445:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[3,2,22],t:7,e:"ui-display",a:{title:"No Technology Disk Loaded"}}],n:50,x:{r:["data.tdisk"],s:"!_0"},p:[2,1,1]},{t:4,n:51,f:[{t:4,f:[{p:[6,3,120],t:7,e:"ui-display",a:{title:"Technology Disk Updating"}}],n:50,r:"data.tdisk_update",p:[5,2,92]},{t:4,n:51,f:[{p:[8,3,191],t:7,e:"ui-display",a:{title:"Technology Disk"},f:[{p:[9,4,231],t:7,e:"ui-section",a:{title:"Disk IO"},f:[{p:[9,32,259],t:7,e:"ui-button",a:{action:"tdisk_down"},f:["Download Research to Disk"]},{p:[9,100,327],t:7,e:"ui-button",a:{action:"tdisk_up"},f:["Upload Research from Disk"]}," ",{p:[10,4,397],t:7,e:"ui-section",a:{title:"Clear Disk"},f:[{p:[10,35,428],t:7,e:"ui-button",a:{action:"clear_techdisk",style:"danger"},f:["WIPE ALL DATA"]}]}," ",{p:[11,4,520],t:7,e:"ui-section",a:{title:"Eject Disk"},f:[{p:[11,35,551],t:7,e:"ui-button",a:{action:"eject_techdisk"},f:["Eject Disk"]}]}]}]}," ",{p:[13,3,640],t:7,e:"ui-display",a:{title:"Disk Contents"},f:[{t:4,f:[{p:[15,5,709],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[15,53,757]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[15,70,774]}]},f:[{t:2,r:"display_name",p:[15,115,819]}]}],n:52,r:"data.tdisk_nodes",p:[14,4,678]}]}],r:"data.tdisk_update"}],x:{r:["data.tdisk"],s:"!_0"}}]},e.exports=a.extend(r.exports)},{341:341}],446:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,28],t:7,e:"ui-display",a:{title:[{t:2,r:"data.snode_name",p:[2,21,47]}]},f:[{p:[3,3,71],t:7,e:"ui-section",a:{title:"Description"},f:["Description: ",{t:2,r:"data.snode_desc",p:[3,48,116]}]}," ",{p:[4,3,151],t:7,e:"ui-section",a:{title:"Point Cost"},f:["Point Cost: ",{t:2,r:"data.snode_cost",p:[4,46,194]}]}," ",{p:[5,3,229],t:7,e:"ui-section",a:{title:"Export Price"},f:["Export Price: ",{t:2,r:"data.snode_export",p:[5,50,276]}]}," ",{p:[6,3,313],t:7,e:"ui-button",a:{action:"research_node",params:['{"id"="',{t:2,r:"id",p:[6,52,362]},'"}'],state:[{t:2,x:{r:["data.snode_researched"],s:'_0?"disabled":null'},p:[6,69,379]}]},f:[{t:2,x:{r:["data.snode_researched"],s:'_0?"Researched":"Research Node"'},p:[6,115,425]}]}]}," ",{p:[8,2,511],t:7,e:"ui-display",a:{title:"Prerequisites"},f:[{t:4,f:[{p:[10,4,579],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[10,52,627]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[10,69,644]}]},f:[{t:2,r:"display_name",p:[10,114,689]}]}],n:52,r:"data.node_prereqs",p:[9,3,548]}]}," ",{p:[13,2,747],t:7,e:"ui-display",a:{title:"Unlocks"},f:[{t:4,f:[{p:[15,4,809],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[15,52,857]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[15,69,874]}]},f:[{t:2,r:"display_name",p:[15,114,919]}]}],n:52,r:"data.node_unlocks",p:[14,3,778]}]}," ",{p:[18,2,977],t:7,e:"ui-display",a:{title:"Designs"},f:[{t:4,f:[{p:[20,4,1039],t:7,e:"ui-button",a:{action:"select_design",params:['{"id": "',{t:2,r:"id",p:[20,54,1089]},'"}'],state:[{t:2,x:{r:["data.sdesign_id","id"],s:'_0==_1?"selected":null'},p:[20,71,1106]}]},f:[{t:2,r:"name",p:[20,118,1153]}]}],n:52,r:"data.node_designs",p:[19,3,1008]}]}],n:50,r:"data.node_selected",p:[1,1,0]},{t:4,f:[{p:[25,2,1239],t:7,e:"ui-display",a:{title:"No Node Selected."}}],n:50,x:{r:["data.node_selected"],s:"!_0"},p:[24,1,1210]}]},e.exports=a.extend(r.exports)},{341:341}],447:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[3,3,57],t:7,e:"ui-display",a:{title:"Protolathe Busy!"}}],n:50,r:"data.protobusy",p:[2,2,32]},{t:4,n:51,f:[{p:[5,3,120],t:7,e:"ui-display",f:[{p:[6,4,136],t:7,e:"ui-section",f:["Search Available Designs: ",{p:[7,4,177],t:7,e:"input",a:{value:[{t:2,r:"textsearch",p:[7,17,190]}],placeholder:"Type Here","class":"text"}}," ",{p:[8,5,248],t:7,e:"ui-button",a:{action:"textSearch",params:['{"latheType" : "proto", "inputText" : ',{t:2,r:"textsearch",p:[8,82,325]},"}"]},f:["Search"]}]}," ",{p:[10,4,381],t:7,e:"ui-section",f:["Materials: ",{t:2,r:"data.protomats",p:[10,27,404]}," / ",{t:2,r:"data.protomaxmats",p:[10,48,425]}]}," ",{p:[11,4,463],t:7,e:"ui-section",f:["Reagents: ",{t:2,r:"data.protochems",p:[11,26,485]}," / ",{t:2,r:"data.protomaxchems",p:[11,48,507]}]}," ",{p:[12,3,545],t:7,e:"ui-display",f:[{p:[14,3,561],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.lathe_tabs",p:[14,18,576]}]},f:[{p:[15,4,601],t:7,e:"tab",a:{name:"Category List"},f:[{t:4,f:[{p:[17,6,662],t:7,e:"ui-button",a:{action:"switchcat",state:[{t:2,x:{r:["data.protocat","name"],s:'_0==_1?"selected":null'},p:[17,43,699]}],params:['{"type" : "proto", "cat" : "',{t:2,r:"name",p:[17,125,781]},'"}']},f:[{t:2,r:"name",p:[17,137,793]}]}],n:52,r:"data.protocats",p:[16,5,632]}]}," ",{p:[20,4,841],t:7,e:"tab",a:{name:"Selected Category"},f:[{t:4,f:[{p:[22,6,905],t:7,e:"ui-section",f:[{t:2,r:"name",p:[22,18,917]},{t:2,r:"matstring",p:[22,26,925]}," ",{t:4,f:[{p:[24,8,973],t:7,e:"input",a:{value:[{t:2,r:"number",p:[24,21,986]}],placeholder:["1-",{t:2,x:{r:["canprint"],s:"_0>10?10:_0"},p:[24,47,1012]}],"class":"number"}}],n:50,x:{r:["canprint"],s:"_0>1"},p:[23,7,945]}," ",{p:[26,7,1083],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[26,40,1116]}],params:['{"latheType" : "proto", "id" : "',{t:2,r:"id",p:[26,117,1193]},'", "amount" : "',{t:2,r:"number",p:[26,138,1214]},'"}']},f:["Print"]}]}],n:52,r:"data.protodes",p:[21,5,876]}]}," ",{p:[30,4,1292],t:7,e:"tab",a:{name:"Search Results"},f:[{t:4,f:[{p:[32,6,1355],t:7,e:"ui-section",f:[{t:2,r:"name",p:[32,18,1367]},{t:2,r:"matstring",p:[32,26,1375]}," ",{t:4,f:[{p:[34,8,1423],t:7,e:"input",a:{value:[{t:2,r:"number",p:[34,21,1436]}],placeholder:["1-",{t:2,x:{r:["canprint"],s:"_0>10?10:_0"},p:[34,47,1462]}],"class":"number"}}],n:50,x:{r:["canprint"],s:"_0>1"},p:[33,7,1395]}," ",{p:[36,7,1533],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[36,40,1566]}],params:['{"latheType" : "proto", "id" : "',{t:2,r:"id",p:[36,117,1643]},'", "amount" : "',{t:2,r:"number",p:[36,138,1664]},'"}']},f:["Print"]}]}],n:52,r:"data.protomatch",p:[31,5,1324]}]}," ",{p:[40,4,1742],t:7,e:"tab",a:{name:"Materials"},f:[{t:4,f:[{p:[42,6,1803],t:7,e:"ui-section",f:[{t:2,r:"name",p:[42,18,1815]}," : ",{t:2,r:"amount",p:[42,29,1826]}," cm3 - ",{t:4,f:[{p:[44,7,1874],t:7,e:"input",a:{value:[{t:2,r:"number",p:[44,20,1887]}],placeholder:["1-",{t:2,r:"sheets",p:[44,46,1913]}],"class":"number"}}," ",{p:[45,7,1948],t:7,e:"ui-button",a:{action:"releasemats",params:['{"latheType" : "proto", "mat_id" : ',{t:2,r:"mat_id",p:[45,82,2023]},', "sheets" : ',{t:2,r:"number",p:[45,105,2046]},"}"]},f:["Release"]}],n:50,x:{r:["sheets"],s:"_0>0"},p:[43,6,1849]}]}],n:52,r:"data.protomat_list",p:[41,5,1769]}]}," ",{p:[50,4,2138],t:7,e:"tab",a:{name:"Chemicals"},f:[{t:4,f:[{p:[52,6,2200],t:7,e:"ui-section",f:[{t:2,r:"name",p:[52,18,2212]}," : ",{t:2,r:"amount",p:[52,29,2223]}," - ",{p:[53,7,2243],t:7,e:"ui-button",a:{action:"purgechem",params:['{"latheType" : "proto", "name" : ',{t:2,r:"name",p:[53,78,2314]},', "id" : ',{t:2,r:"reagentid",p:[53,95,2331]},"}"]},f:["Purge"]}]}],n:52,r:"data.protochem_list",p:[51,5,2165]}]}]}]}]}],r:"data.protobusy"}],n:50,r:"data.protolathe_linked",p:[1,1,0]},{t:4,n:51,f:[{p:[61,2,2444],t:7,e:"ui-display",a:{title:"No Linked Protolathe"}}],r:"data.protolathe_linked"}]},e.exports=a.extend(r.exports)},{341:341}],448:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,1,13],t:7,e:"span",a:{"class":"memoedit"},f:["Nanotrasen R&D Console"]},{p:[2,53,65],t:7,e:"br"}," Available Points: ",{p:[3,19,89],t:7,e:"ui-section",a:{title:"Research Points"},f:[{t:2,r:"data.research_points_stored",p:[3,55,125]}]}," ",{p:[4,1,170],t:7,e:"ui-section",a:{title:["Page Selection - ",{t:2,r:"page",p:[4,37,206]}]},f:[{p:[4,47,216],t:7,e:"input",a:{value:[{t:2,r:"pageselect",p:[4,60,229]}],placeholder:"1","class":"number"}}," Select Page: ",{p:[5,14,290],t:7,e:"ui-button",a:{action:"page",params:['{"num" : "',{t:2,r:"pageselect",p:[5,57,333]},'"}']},f:["[Go]"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],449:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"span",a:{"class":"bad"},f:["Settings"]},{p:[1,34,33],t:7,e:"br"},{p:[1,39,38],t:7,e:"br"}," ",{p:[2,1,44],t:7,e:"ui-button",a:{action:"Resync"},f:["RESYNC MACHINERY"]},{p:[2,56,99],t:7,e:"br"}," ",{p:[3,1,105],t:7,e:"ui-button",a:{action:"Lock"},f:["LOCK"]}," ",{p:[4,1,147],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "destroy"}',state:[{t:2,x:{r:["data.destroy_linked"],s:'_0?null:"disabled"'},p:[4,71,217]}]},f:["Disconnect Destructive Analyzer"]}," ",{p:[5,1,305],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "lathe"}',state:[{t:2,x:{r:["data.protolathe_linked"],s:'_0?null:"disabled"'},p:[5,69,373]}]},f:["Disconnect Protolathe"]}," ",{p:[6,1,454],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "imprinter"}',state:[{t:2,x:{r:["data.circuit_linked"],s:'_0?null:"disabled"'},p:[6,73,526]}]},f:["Disconnect Circuit Imprinter"]}]},e.exports=a.extend(r.exports)},{341:341}],450:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Available for Research"},f:[{t:4,f:[{p:[3,3,76],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[3,51,124]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[3,68,141]}]},f:[{t:2,r:"display_name",p:[3,113,186]}]}],n:52,r:"data.techweb_avail",p:[2,2,45]}]}," ",{p:[6,1,240],t:7,e:"ui-display",a:{title:"Locked Nodes"},f:[{t:4,f:[{p:[8,3,307],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[8,51,355]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[8,68,372]}]},f:[{t:2,r:"display_name",p:[8,113,417]}]}],n:52,r:"data.techweb_locked",p:[7,2,275]}]}," ",{p:[11,1,472],t:7,e:"ui-display",a:{title:"Researched Nodes"},f:[{t:4,f:[{p:[13,3,547],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[13,51,595]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[13,68,612]}]},f:[{t:2,r:"display_name",p:[13,113,657]}]}],n:52,r:"data.techweb_researched",p:[12,2,511]}]}]},e.exports=a.extend(r.exports)},{341:341}],451:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,1,24],t:7,e:"ui-notice",f:[{p:[3,3,38],t:7,e:"span",f:["The grinder is currently processing and cannot be used."]}]}],n:50,r:"data.processing",p:[1,1,0]},{p:{button:[{p:[8,5,201],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.operating","data.contents"],s:'(_0==0)&&_1?null:"disabled"'},p:[8,36,232]}],action:"eject"},f:["Eject Contents"]}]},t:7,e:"ui-display",a:{title:"Processing Chamber",button:0},f:[" ",{p:[10,3,355],t:7,e:"ui-section",a:{label:"Grinding"},f:[{p:[11,5,389],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.operating"],s:'_0?"average":"good"'},p:[11,18,402]}]},f:[{t:2,x:{r:["data.operating"],s:'_0?"Busy":"Ready"'},p:[11,59,443]}]}," ",{p:[12,2,489],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.operating","data.contents"],s:'(_0==0)&&_1?null:"disabled"'},p:[12,35,522]}],action:"grind"},f:["Activate"]}]}," ",{p:[14,3,640],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{t:4,f:[{p:[17,9,739],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:["The ",{t:2,r:"name",p:[17,56,786]}]},{p:[17,71,801],t:7,e:"br"}],n:52,r:"adata.contentslist",p:[16,7,702]},{t:4,n:51,f:[{p:[19,9,830],t:7,e:"span",f:["No Contents"]}],r:"adata.contentslist"}],n:50,r:"data.contents",p:[15,5,674]},{t:4,n:51,f:[{p:[22,7,890],t:7,e:"span",f:["No Contents"]}],r:"data.contents"}]}]}," ",{p:{button:[{p:[28,5,1020],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.operating","data.isBeakerLoaded"],s:'(_0==0)&&_1?null:"disabled"'},p:[28,36,1051]}],action:"detach"},f:["Detach"]}]},t:7,e:"ui-display",a:{title:"Container",button:0},f:[" ",{p:[30,3,1173],t:7,e:"ui-section",a:{label:"Reagents"},f:[{t:4,f:[{p:[32,7,1241],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[32,13,1247]},"/",{t:2,r:"data.beakerMaxVolume",p:[32,55,1289]}," Units"]}," ",{p:[33,7,1333],t:7,e:"br"}," ",{t:4,f:[{p:[35,9,1384],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[35,52,1427]}," units of ",{t:2,r:"name",p:[35,87,1462]}]},{p:[35,102,1477],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[34,7,1345]},{t:4,n:51,f:[{p:[37,9,1506],t:7,e:"span",a:{"class":"bad"},f:["Container Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[31,5,1207]},{t:4,n:51,f:[{p:[40,7,1582],t:7,e:"span",a:{"class":"average"},f:["No Container"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],452:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Direction"},f:[{t:4,f:[{p:[3,3,62],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,5,101],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[5,23,119]}],action:"setdir",params:['{"dir": ',{t:2,r:"dir",p:[6,22,190]},', "flipped": ',{t:2,r:"flipped",p:[6,42,210]},"}"]},f:[{p:[6,56,224],t:7,e:"span",a:{"class":["pipes32x32 ",{t:2,r:"dir",p:[6,80,248]},"-",{t:2,r:"icon_state",p:[6,88,256]}],title:[{t:2,r:"dir_name",p:[6,111,279]}]}}]}],n:52,r:"previews",p:[4,4,78]}]}],n:52,r:"data.preview_rows",p:[2,2,32]}]}," ",{t:4,f:[{p:[12,2,395],t:7,e:"ui-display",a:{title:"Color"},f:[{t:4,f:[{p:[14,4,455],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["@key","data.selected_color"],s:'_0==_1?"selected":null'},p:[14,22,473]}],action:"color",params:['{"paint_color": ',{t:2,r:"@key",p:[15,44,569]},"}"]},f:[{t:2,r:"@key",p:[15,55,580]}]}],n:52,r:"data.paint_colors",p:[13,3,424]}]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[11,1,367]},{p:[19,1,636],t:7,e:"ui-display",a:{title:"Utilities"},f:[{p:[20,2,668],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&1?"check-square-o":"square-o"'},p:[20,19,685]}],action:"mode",params:'{"mode": 1}'},f:["Build"]}," ",{p:[22,2,792],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&2?"check-square-o":"square-o"'},p:[22,19,809]}],action:"mode",params:'{"mode": 2}'},f:["Wrench"]}," ",{p:[24,2,917],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&4?"check-square-o":"square-o"'},p:[24,19,934]}],action:"mode",params:'{"mode": 4}'},f:["Destroy"]}," ",{t:4,f:[{p:[27,3,1072],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&8?"check-square-o":"square-o"'},p:[27,20,1089]}],action:"mode",params:'{"mode": 8}'},f:["Paint"]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[26,2,1043]}]}," ",{p:[31,1,1219],t:7,e:"ui-display",a:{title:"Category"},f:[{p:[32,2,1250],t:7,e:"ui-section",f:[{p:[33,3,1265],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==0?"check-square-o":"square-o"'},p:[33,20,1282]}],state:[{t:2,x:{r:["data.category"],s:'_0<=0?"selected":null'},p:[33,83,1345]}],action:"category",params:'{"category": 0}'},f:["Atmospherics"]}," ",{p:[35,3,1462],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==1?"check-square-o":"square-o"'},p:[35,20,1479]}],state:[{t:2,x:{r:["data.category"],s:'_0==1?"selected":null'},p:[35,83,1542]}],action:"category",params:'{"category": 1}'},f:["Disposals"]}," ",{p:[37,3,1656],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==2?"check-square-o":"square-o"'},p:[37,20,1673]}],state:[{t:2,x:{r:["data.category"],s:'_0==2?"selected":null'},p:[37,83,1736]}],action:"category",params:'{"category": 2}'},f:["Transit Tubes"]}]}," ",{t:4,f:[{p:[41,3,1897],t:7,e:"ui-section",a:{label:"Piping Layer"},f:[{p:[42,4,1934],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==1?"selected":null'},p:[42,22,1952]}],action:"piping_layer",params:'{"piping_layer": 1}'},f:["1"]}," ",{p:[44,4,2072],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==2?"selected":null'},p:[44,22,2090]}],action:"piping_layer",params:'{"piping_layer": 2}'},f:["2"]}," ",{p:[46,4,2210],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==3?"selected":null'},p:[46,22,2228]}],action:"piping_layer",params:'{"piping_layer": 3}'},f:["3"]}]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[40,2,1868]}]}," ",{t:4,f:[{p:[52,2,2411],t:7,e:"ui-display",a:{title:[{t:2,r:"cat_name",p:[52,21,2430]}]},f:[{t:4,f:[{p:[54,4,2468],t:7,e:"ui-section",f:[{p:[55,5,2485],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[55,23,2503]}],action:"pipe_type",params:['{"pipe_type": ',{t:2,r:"pipe_index",p:[56,28,2583]},', "category": ',{t:2,r:"cat_name",p:[56,56,2611]},"}"]},f:[{t:2,r:"pipe_name",p:[56,71,2626]}]}]}],n:52,r:"recipes",p:[53,3,2447]}]}],n:52,r:"data.categories",p:[51,1,2384]}]},e.exports=a.extend(r.exports)},{341:341}],453:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Color"},f:[{t:4,f:[{p:[3,3,58],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[3,21,76]}],action:"color",params:['{"paint_color": ',{t:2,r:"color_name",p:[4,28,152]},"}"]},f:[{t:2,r:"color_name",p:[4,45,169]}]}],n:52,r:"data.paint_colors",p:[2,2,28]}]}]},e.exports=a.extend(r.exports)},{341:341}],454:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Direction"},f:[{t:4,f:[{p:[3,3,62],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,5,101],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[5,23,119]}],action:"setdir",params:['{"dir": ',{t:2,r:"dir",p:[6,22,190]},', "flipped": ',{t:2,r:"flipped",p:[6,42,210]},"}"]},f:[{p:[6,56,224],t:7,e:"img",a:{src:["pipe.",{t:2,r:"dir",p:[6,71,239]},".",{t:2,r:"icon_state",p:[6,79,247]},".png"],title:[{t:2,r:"dir_name",p:[6,106,274]}]}}]}],n:52,r:"previews",p:[4,4,78]}]}],n:52,r:"data.preview_rows",p:[2,2,32]}]}]},e.exports=a.extend(r.exports)},{341:341}],455:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,22],t:7,e:"ui-notice",f:[{t:2,r:"data.notice",p:[3,5,38]}]}],n:50,r:"data.notice",p:[1,1,0]},{p:[6,1,77],t:7,e:"ui-display",a:{title:"Satellite Network Control",button:0},f:[{t:4,f:[{p:[8,4,161],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[9,9,201],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[9,31,223]}]}," ",{p:[10,9,244],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"mode",p:[10,30,265]}]}," ",{p:[11,9,288],t:7,e:"div",a:{"class":"content"},f:[{p:[12,11,320],t:7,e:"ui-button",a:{action:"toggle",params:['{"id": "',{t:2,r:"id",p:[12,54,363]},'"}']},f:[{t:2,x:{r:["active"],s:'_0?"Deactivate":"Activate"'},p:[12,64,373]}]}]}]}],n:52,r:"data.satellites",p:[7,2,132]}]}," ",{t:4,f:[{p:[18,1,511],t:7,e:"ui-display",a:{title:"Station Shield Coverage"},f:[{p:[19,3,558],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.meteor_shield_coverage_max",p:[19,24,579]}],value:[{t:2,r:"data.meteor_shield_coverage",p:[19,68,623]}]},f:[{t:2,x:{r:["data.meteor_shield_coverage","data.meteor_shield_coverage_max"],s:"100*_0/_1"},p:[19,101,656]}," %"]}," ",{p:[20,1,739],t:7,e:"ui-display",f:[]}]}],n:50,r:"data.meteor_shield",p:[17,1,484]}]},e.exports=a.extend(r.exports)},{341:341}],456:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,25],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["enabled"],s:'_0?"check-square-o":"square-o"'},p:[2,20,42]}],style:[{t:2,x:{r:["enabled"],s:'_0?"selected":null'},p:[2,72,94]}],action:"toggle_filter",params:['{"id_tag": "',{t:2,r:"id_tag",p:[3,48,174]},'", "val": ',{t:2,r:"gas_id",p:[3,68,194]},"}"]},f:[{t:2,r:"gas_name",p:[3,81,207]}]}],n:52,r:"filter_types",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],457:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," ",{p:[5,1,196],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.tabs",p:[5,16,211]}]},f:[{p:[6,2,228],t:7,e:"tab",a:{name:"Status"},f:[{p:[7,3,250],t:7,e:"status"}]}," ",{p:[9,2,269],t:7,e:"tab",a:{name:"Templates"},f:[{p:[10,3,294],t:7,e:"templates"}]}," ",{p:[12,2,316],t:7,e:"tab",a:{name:"Modification"},f:[{t:4,f:[{p:[14,3,368],t:7,e:"modification"}],n:50,r:"data.selected",p:[13,3,344]}," ",{t:4,f:[{p:[17,3,421],t:7,e:"span",a:{"class":"bad"},f:["No shuttle selected."]}],n:50,x:{r:["data.selected"],s:"!_0"},p:[16,3,396]}]}]}]},r.exports.components=r.exports.components||{};var i={modification:t(458),templates:t(460),status:t(459)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,458:458,459:459,460:460}],458:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:["Selected: ",{t:2,r:"data.selected.name",p:[1,30,29]}]},f:[{t:4,f:[{p:[3,5,94],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.selected.description",p:[3,37,126]}]}],n:50,r:"data.selected.description",p:[2,3,56]}," ",{t:4,f:[{p:[6,5,219],t:7,e:"ui-section",a:{label:"Admin Notes"},f:[{t:2,r:"data.selected.admin_notes",p:[6,37,251]}]}],n:50,r:"data.selected.admin_notes",p:[5,3,181]}]}," ",{t:4,f:[{p:[11,3,351],t:7,e:"ui-display",a:{title:["Existing Shuttle: ",{t:2,r:"data.existing_shuttle.name",p:[11,40,388]}]},f:["Status: ",{t:2,r:"data.existing_shuttle.status",p:[12,13,433]}," ",{t:4,f:["(",{t:2,r:"data.existing_shuttle.timeleft",p:[14,8,513]},")"],n:50,r:"data.existing_shuttle.timer",p:[13,5,470]}," ",{p:[16,5,565],t:7,e:"ui-button",a:{action:"jump_to",params:['{"type": "mobile", "id": "',{t:2,r:"data.existing_shuttle.id",p:[17,41,633]},'"}']},f:["Jump To"]}]}],n:50,r:"data.existing_shuttle",p:[10,1,319]},{t:4,f:[{p:[24,3,755],t:7,e:"ui-display",a:{title:"Existing Shuttle: None"}}],n:50,x:{r:["data.existing_shuttle"],s:"!_0"},p:[23,1,722]},{p:[27,1,821],t:7,e:"ui-button",a:{action:"preview",params:['{"shuttle_id": "',{t:2,r:"data.selected.shuttle_id",p:[28,27,875]},'"}']},f:["Preview"]}," ",{p:[31,1,931],t:7,e:"ui-button",a:{action:"load",params:['{"shuttle_id": "',{t:2,r:"data.selected.shuttle_id",p:[32,27,982]},'"}'],style:"danger"},f:["Load"]}," ",{p:[37,1,1053],t:7,e:"ui-display",a:{title:"Status"},f:[]}]},e.exports=a.extend(r.exports)},{341:341}],459:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"table",a:{width:"100%"},f:[{t:4,f:[{p:[3,3,47],t:7,e:"tr",f:[{p:[4,5,56],t:7,e:"td",f:[{p:[5,7,67],t:7,e:"ui-button",a:{action:"jump_to",params:['{"type": "mobile", "id": "',{t:2,r:"id",p:[5,69,129]},'"}']},f:["JMP"]}]}," ",{p:[9,5,185],t:7,e:"td",f:[{p:[10,7,196],t:7,e:"ui-button",a:{action:"fly",params:['{"id": "',{t:2,r:"id",p:[10,47,236]},'"}'],state:[{t:2,x:{r:["can_fly"],s:'_0?null:"disabled"'},p:[10,64,253]}]},f:["Fly"]}]}," ",{p:[14,5,332],t:7,e:"td",f:[{t:2,r:"name",p:[15,7,343]}," (",{p:[15,17,353],t:7,e:"code",f:[{t:2,r:"id",p:[15,23,359]}]},")"]}," ",{p:[17,5,388],t:7,e:"td",f:[{t:2,r:"status",p:[18,7,399]}]}," ",{p:[20,5,424],t:7,e:"td",f:[{t:4,f:[{t:2,r:"mode",p:[22,9,456]}],n:50,r:"mode",p:[21,7,435]}," ",{t:4,f:["(",{t:2,r:"timeleft",p:[25,10,508]},") ",{p:[26,9,530],t:7,e:"ui-button",a:{action:"fast_travel",params:['{"id": "',{t:2,r:"id",p:[26,57,578]},'"}'],state:[{t:2,x:{r:["can_fast_travel"],s:'_0?null:"disabled"'},p:[26,74,595]}]},f:["Fast Travel"]}],n:50,r:"timer",p:[24,7,485]}]}]}],n:52,r:"data.shuttles",p:[2,1,21]}]}]},e.exports=a.extend(r.exports)},{341:341}],460:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.templates_tabs",p:[1,16,15]}]},f:[{t:4,f:[{p:[3,5,72],t:7,e:"tab",a:{name:[{t:2,r:"port_id",p:[3,16,83]}]},f:[{t:4,f:[{p:[5,9,131],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[5,28,150]}]},f:[{t:4,f:[{p:[7,13,203],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"description",p:[7,45,235]}]}],n:50,r:"description",p:[6,11,171]}," ",{t:4,f:[{p:[10,13,324],t:7,e:"ui-section",a:{label:"Admin Notes"},f:[{t:2,r:"admin_notes",p:[10,45,356]}]}],n:50,r:"admin_notes",p:[9,11,292]}," ",{p:[13,11,414],t:7,e:"ui-button",a:{action:"select_template",params:['{"shuttle_id": "',{t:2,r:"shuttle_id",p:[14,37,486]},'"}'],state:[{t:2,x:{r:["data.selected.shuttle_id","shuttle_id"],s:'_0==_1?"selected":null'},p:[15,20,523]}]},f:[{t:2,x:{r:["data.selected.shuttle_id","shuttle_id"],s:'_0==_1?"Selected":"Select"'},p:[17,13,614]}]}]}],n:52,r:"templates",p:[4,7,103]}]}],n:52,r:"data.templates",p:[2,3,43]}]}]},e.exports=a.extend(r.exports)},{341:341}],461:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,33],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,66],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,72]}]}]}," ",{t:4,f:[{p:[6,5,186],t:7,e:"ui-section",a:{label:"State"},f:[{p:[7,7,220],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[7,20,233]}]},f:[{t:2,r:"data.occupant.stat",p:[7,49,262]}]}]}," ",{p:[9,5,315],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[10,7,350],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[10,20,363]}],max:[{t:2,r:"data.occupant.maxHealth",p:[10,54,397]}],value:[{t:2,r:"data.occupant.health",p:[10,90,433]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[11,16,475]}]},f:[{t:2,x:{r:["adata.occupant.health"],s:"Math.round(_0)"},p:[11,68,527]}]}]}," ",{t:4,f:[{p:[14,7,764],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[14,26,783]}]},f:[{p:[15,9,804],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[15,30,825]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[15,66,861]}],state:"bad"},f:[{t:2,x:{r:["type","adata.occupant"],s:"Math.round(_1[_0])"},p:[15,103,898]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[13,5,598]}," ",{t:4,f:[{p:[19,7,1020],t:7,e:"ui-section",a:{label:"Blood"},f:[{p:[20,9,1056],t:7,e:"ui-section",a:{label:"Volume"},f:[{p:[21,11,1095],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.blood.maxBloodVolume",p:[21,32,1116]}],value:[{t:2,r:"data.occupant.blood.currentBloodVolume",p:[21,79,1163]}],state:[{t:2,x:{r:["data.occupant.blood.currentBloodVolume","data.occupant.blood.dangerBloodVolume"],s:'_0<=_1?"bad":"good"'},p:[21,130,1214]}]},f:[{t:3,x:{r:["data.occupant.blood.currentBloodVolume","data.occupant.blood.dangerBloodVolume"],s:'_0<=_1?"LOW":"OK"'},p:[21,232,1316]}," - ",{t:2,x:{r:["data.occupant.blood.currentBloodVolume"],s:"Math.round(_0)"},p:[21,342,1426]}," cl"]}]}," ",{p:[23,9,1525],t:7,e:"ui-section",a:{label:"Type"},f:[{p:[24,11,1562],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:"data.occupant.blood.bloodType",p:[24,35,1586]}]}]}]}],n:50,r:"data.occupant.blood",p:[18,5,985]}," ",{p:[28,5,1689],t:7,e:"ui-section",a:{label:"Cells"},f:[{p:[29,9,1725],t:7, -e:"span",a:{"class":[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"bad":"good"'},p:[29,22,1738]}]},f:[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"Damaged":"Healthy"'},p:[29,68,1784]}]}]}," ",{p:[31,5,1867],t:7,e:"ui-section",a:{label:"Brain"},f:[{p:[32,9,1903],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"bad":"good"'},p:[32,22,1916]}]},f:[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"Abnormal":"Healthy"'},p:[32,68,1962]}]}]}," ",{t:4,f:[{p:[35,3,2083],t:7,e:"ui-section",a:{label:"Failing Organs"},f:[{t:4,f:[{p:[37,5,2167],t:7,e:"span",a:{"class":"bad"},f:[{t:2,r:"name",p:[37,24,2186]}]}],n:52,r:"data.occupant.failing_organs",p:[36,4,2123]}]}],n:50,r:"data.occupant.failing_organs",p:[34,2,2043]}," ",{p:[41,5,2249],t:7,e:"ui-section",a:{label:"Bloodstream"},f:[{t:4,f:[{p:[43,11,2336],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,1)"},p:[43,54,2379]}," units of ",{t:2,r:"name",p:[43,89,2414]}]},{p:[43,104,2429],t:7,e:"br"}],n:52,r:"adata.occupant.reagents",p:[42,9,2291]},{t:4,n:51,f:[{p:[45,11,2464],t:7,e:"span",a:{"class":"good"},f:["Pure"]}],r:"adata.occupant.reagents"}]}],n:50,r:"data.occupied",p:[5,3,159]}]}," ",{p:[50,1,2560],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[51,2,2592],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[52,5,2623],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"unlock":"lock"'},p:[52,22,2640]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Open":"Closed"'},p:[52,71,2689]}]}]}," ",{p:[55,3,2756],t:7,e:"ui-section",a:{label:"Synthesize"},f:[{t:4,f:[{p:[57,7,2826],t:7,e:"ui-button",a:{grid:0,state:[{t:2,x:{r:["synth_allowed"],s:'_0?null:"disabled"'},p:[57,30,2849]}],action:"synth",params:['{"chem": "',{t:2,r:"id",p:[57,102,2921]},'"}']},f:[{t:2,r:"name",p:[57,112,2931]}]}],n:52,r:"data.synthchems",p:[56,5,2793]}]}," ",{p:[61,3,2989],t:7,e:"ui-section",a:{label:"Inject"},f:[{p:[62,2,3019],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[63,3,3052],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[64,4,3086],t:7,e:"section",a:{"class":"compressedcell"},f:["Name"]}," ",{p:[68,4,3150],t:7,e:"section",a:{"class":"compressedcell"},f:["Volume"]}," ",{t:4,f:[{p:[73,5,3250],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[74,6,3289],t:7,e:"span",f:["Purity"]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=4"},p:[72,4,3216]}," ",{t:4,f:[{p:[79,5,3377],t:7,e:"section",a:{"class":"compressedcell"},f:[]}],n:50,x:{r:["data.efficiency"],s:"_0>=3"},p:[78,4,3343]}," ",{t:4,f:[{p:[84,5,3478],t:7,e:"section",a:{"class":"compressedcell"},f:[]}],n:50,x:{r:["data.efficiency"],s:"_0>=2"},p:[83,4,3444]}," ",{p:[88,4,3545],t:7,e:"section",a:{"class":"compressedcell"},f:[]}," ",{p:[91,4,3599],t:7,e:"section",a:{"class":"compressedcell"},f:[]}]}," ",{t:4,f:[{p:[96,4,3691],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[97,5,3726],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[98,6,3765],t:7,e:"span",f:[{p:[98,12,3771],t:7,e:"b",f:[{t:2,r:"name",p:[98,15,3774]}]}]}]}," ",{p:[101,5,3817],t:7,e:"section",a:{"class":"compressedcell",align:"center"},f:[{p:[102,6,3871],t:7,e:"span",f:[{t:2,r:"vol",p:[102,12,3877]},"u"]}]}," ",{t:4,f:[{p:[106,6,3953],t:7,e:"section",a:{"class":"compressedcell",align:"center"},f:[{p:[107,7,4008],t:7,e:"span",f:[{t:2,r:"purity",p:[107,13,4014]}]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=4"},p:[105,7,3918]}," ",{t:4,f:[{p:[112,6,4106],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[113,7,4146],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[113,25,4164]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[113,109,4248]},'", "volume": 1}']},f:["1"]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=3"},p:[111,5,4071]}," ",{t:4,f:[{p:[118,6,4358],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[119,7,4398],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[119,25,4416]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[119,109,4500]},'", "volume": 5}']},f:["5"]}]}],n:50,x:{r:["adata.efficiency"],s:"_0>=2"},p:[117,5,4322]}," ",{p:[123,5,4574],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[124,6,4613],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[124,24,4631]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[124,108,4715]},'", "volume": 10}']},f:["10"]}]}," ",{p:[127,5,4777],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[128,6,4816],t:7,e:"ui-button",a:{action:"purge",params:['{"chem": "',{t:2,r:"id",p:[128,50,4860]},'"}']},f:["Purge"]},{p:[128,77,4887],t:7,e:"br"}]}]}],n:52,r:"data.chems",p:[95,3,3666]}]}]}," ",{p:[135,3,4968],t:7,e:"ui-section",a:{label:"Capacity"},f:[{p:[136,5,5003],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.tot_capacity",p:[136,24,5022]}],value:[{t:2,r:"data.current_vol",p:[136,54,5052]}],state:[{t:2,r:"data.current_vol",p:[137,12,5086]}]},f:[{t:2,r:"data.current_vol",p:[137,34,5108]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],462:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,24],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[2,22,43]}],labelcolor:[{t:2,r:"htmlcolor",p:[2,44,65]}],candystripe:0,right:0},f:[{p:[3,5,103],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[3,32,130],t:7,e:"span",a:{"class":[{t:2,x:{r:["status"],s:'_0=="Dead"?"bad bold":_0=="Unconscious"?"average bold":"good"'},p:[3,45,143]}]},f:[{t:2,r:"status",p:[3,132,230]}]}]}," ",{p:[4,5,265],t:7,e:"ui-section",a:{label:"Jelly"},f:[{t:2,r:"exoticblood",p:[4,31,291]}]}," ",{p:[5,5,324],t:7,e:"ui-section",a:{label:"Location"},f:[{t:2,r:"area",p:[5,34,353]}]}," ",{p:[7,5,380],t:7,e:"ui-button",a:{state:[{t:2,r:"swap_button_state",p:[8,14,404]}],action:"swap",params:['{"ref": "',{t:2,r:"ref",p:[9,38,464]},'"}']},f:[{t:4,f:["You Are Here"],n:50,x:{r:["occupied"],s:'_0=="owner"'},p:[10,7,482]},{t:4,n:51,f:[{t:4,f:["Occupied"],n:50,x:{r:["occupied"],s:'_0=="stranger"'},p:[13,9,554]},{t:4,n:51,f:["Swap"],x:{r:["occupied"],s:'_0=="stranger"'}}],x:{r:["occupied"],s:'_0=="owner"'}}]}]}],n:52,r:"data.bodies",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],463:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{t:4,f:[{p:[4,23,79],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.drying"],s:'_0?"stop":"tint"'},p:[4,40,96]}],action:"Dry"},f:[{t:2,x:{r:["data.drying"],s:'_0?"Stop drying":"Dry"'},p:[4,88,144]}]}],n:50,r:"data.isdryer",p:[4,3,59]}]},t:7,e:"ui-display",a:{title:"Storage",button:0},f:[" ",{t:4,f:[{p:[7,3,252],t:7,e:"ui-notice",f:[{p:[8,5,268],t:7,e:"span",f:["Unfortunately, this ",{t:2,r:"data.name",p:[8,31,294]}," is empty."]}]}],n:50,x:{r:["data.contents.length"],s:"_0==0"},p:[6,1,216]},{t:4,n:51,f:[{p:[11,1,349],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[12,2,380],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[13,4,413],t:7,e:"section",a:{"class":"cell bold"},f:["Item"]}," ",{p:[16,4,467],t:7,e:"section",a:{"class":"cell bold"},f:["Quantity"]}," ",{p:[19,4,525],t:7,e:"section",a:{"class":"cell bold",align:"center"},f:[{t:4,f:[{t:2,r:"data.verb",p:[20,22,589]}],n:50,r:"data.verb",p:[20,5,572]},{t:4,n:51,f:["Dispense"],r:"data.verb"}]}]}," ",{t:4,f:[{p:[24,3,680],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[25,4,713],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[26,5,740]}]}," ",{p:[28,4,766],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[29,5,807]}]}," ",{p:[31,4,835],t:7,e:"section",a:{"class":"table",alight:"right"},f:[{p:[32,5,878],t:7,e:"section",a:{"class":"cell"}}," ",{p:[33,5,915],t:7,e:"section",a:{"class":"cell"},f:[{p:[34,6,943],t:7,e:"ui-button",a:{grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[34,45,982]}],params:['{ "name" : ',{t:2,r:"name",p:[34,102,1039]},', "amount" : 1 }']},f:["One"]}]}," ",{p:[38,5,1114],t:7,e:"section",a:{"class":"cell"},f:[{p:[39,6,1142],t:7,e:"ui-button",a:{grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>1)?null:"disabled"'},p:[39,45,1181]}],params:['{ "name" : ',{t:2,r:"name",p:[39,101,1237]}," }"]},f:["Many"]}]}]}]}],n:52,r:"data.contents",p:[23,2,654]}]}],x:{r:["data.contents.length"],s:"_0==0"}}]}]},e.exports=a.extend(r.exports)},{341:341}],464:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{capacityPercentState:function(){var t=this.get("data.capacityPercent");return t>50?"good":t>15?"average":"bad"},inputState:function(){return this.get("data.capacityPercent")>=100?"good":this.get("data.inputting")?"average":"bad"},outputState:function(){return this.get("data.outputting")?"good":this.get("data.charge")>0?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[24,1,640],t:7,e:"ui-display",a:{title:"Storage"},f:[{p:[25,3,671],t:7,e:"ui-section",a:{label:"Stored Energy"},f:[{p:[26,5,710],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.capacityPercent",p:[26,38,743]}],state:[{t:2,r:"capacityPercentState",p:[26,71,776]}]},f:[{t:2,x:{r:["adata.capacityPercent"],s:"Math.fixed(_0)"},p:[26,97,802]},"%"]}]}]}," ",{p:[29,1,880],t:7,e:"ui-display",a:{title:"Input"},f:[{p:[30,3,909],t:7,e:"ui-section",a:{label:"Charge Mode"},f:[{p:[31,5,946],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"refresh":"close"'},p:[31,22,963]}],style:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"selected":null'},p:[31,74,1015]}],action:"tryinput"},f:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"Auto":"Off"'},p:[32,25,1082]}]},"   [",{p:[34,6,1149],t:7,e:"span",a:{"class":[{t:2,r:"inputState",p:[34,19,1162]}]},f:[{t:2,x:{r:["data.capacityPercent","data.inputting"],s:'_0>=100?"Fully Charged":_1?"Charging":"Not Charging"'},p:[34,35,1178]}]},"]"]}," ",{p:[36,3,1300],t:7,e:"ui-section",a:{label:"Target Input"},f:[{p:[37,5,1338],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.inputLevelMax",p:[37,26,1359]}],value:[{t:2,r:"data.inputLevel",p:[37,57,1390]}]},f:[{t:2,r:"adata.inputLevel_text",p:[37,78,1411]}]}]}," ",{p:[39,3,1463],t:7,e:"ui-section",a:{label:"Adjust Input"},f:[{p:[40,5,1501],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.inputLevel"],s:'_0==0?"disabled":null'},p:[40,44,1540]}],action:"input",params:'{"target": "min"}'}}," ",{p:[41,5,1634],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.inputLevel"],s:'_0==0?"disabled":null'},p:[41,39,1668]}],action:"input",params:'{"adjust": -10000}'}}," ",{p:[42,5,1763],t:7,e:"ui-button",a:{icon:"pencil",action:"input",params:'{"target": "input"}'},f:["Set"]}," ",{p:[43,5,1852],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.inputLevel","data.inputLevelMax"],s:'_0==_1?"disabled":null'},p:[43,38,1885]}],action:"input",params:'{"adjust": 10000}'}}," ",{p:[44,5,1996],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.inputLevel","data.inputLevelMax"],s:'_0==_1?"disabled":null'},p:[44,43,2034]}],action:"input",params:'{"target": "max"}'}}]}," ",{p:[46,3,2159],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[47,3,2192],t:7,e:"span",f:[{t:2,r:"adata.inputAvailable",p:[47,9,2198]}]}]}]}," ",{p:[50,1,2259],t:7,e:"ui-display",a:{title:"Output"},f:[{p:[51,3,2289],t:7,e:"ui-section",a:{label:"Output Mode"},f:[{p:[52,5,2326],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"power-off":"close"'},p:[52,22,2343]}],style:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"selected":null'},p:[52,77,2398]}],action:"tryoutput"},f:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"On":"Off"'},p:[53,26,2467]}]},"   [",{p:[55,6,2533],t:7,e:"span",a:{"class":[{t:2,r:"outputState",p:[55,19,2546]}]},f:[{t:2,x:{r:["data.outputting","data.charge"],s:'_0?"Sending":_1>0?"Not Sending":"No Charge"'},p:[55,36,2563]}]},"]"]}," ",{p:[57,3,2668],t:7,e:"ui-section",a:{label:"Target Output"},f:[{p:[58,5,2707],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.outputLevelMax",p:[58,26,2728]}],value:[{t:2,r:"data.outputLevel",p:[58,58,2760]}]},f:[{t:2,r:"adata.outputLevel_text",p:[58,80,2782]}]}]}," ",{p:[60,3,2835],t:7,e:"ui-section",a:{label:"Adjust Output"},f:[{p:[61,5,2874],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.outputLevel"],s:'_0==0?"disabled":null'},p:[61,44,2913]}],action:"output",params:'{"target": "min"}'}}," ",{p:[62,5,3009],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.outputLevel"],s:'_0==0?"disabled":null'},p:[62,39,3043]}],action:"output",params:'{"adjust": -10000}'}}," ",{p:[63,5,3140],t:7,e:"ui-button",a:{icon:"pencil",action:"output",params:'{"target": "input"}'},f:["Set"]}," ",{p:[64,5,3230],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.outputLevel","data.outputLevelMax"],s:'_0==_1?"disabled":null'},p:[64,38,3263]}],action:"output",params:'{"adjust": 10000}'}}," ",{p:[65,5,3377],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.outputLevel","data.outputLevelMax"],s:'_0==_1?"disabled":null'},p:[65,43,3415]}],action:"output",params:'{"target": "max"}'}}]}," ",{p:[67,3,3543],t:7,e:"ui-section",a:{label:"Outputting"},f:[{p:[68,3,3577],t:7,e:"span",f:[{t:2,r:"adata.outputUsed",p:[68,9,3583]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],465:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:["\ufeff",{t:4,f:[" ",{p:[2,2,32],t:7,e:"ui-display",a:{title:"Dispersal Tank"},f:[{p:[3,3,71],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[4,4,101],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.active"],s:'_0?"power-off":"close"'},p:[4,21,118]}],style:[{t:2,x:{r:["data.active"],s:'_0?"selected":null'},p:[5,12,170]}],state:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?null:"disabled"'},p:[6,12,218]}],action:"power"},f:[{t:2,x:{r:["data.active"],s:'_0?"On":"Off"'},p:[7,20,280]}]}]}," ",{p:[10,3,345],t:7,e:"ui-section",a:{label:"Smoke Radius Setting"},f:[{p:[11,5,391],t:7,e:"div",a:{"class":"content",style:"float:left"},f:[{p:[12,6,437],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=1?null:"disabled"'},p:[12,36,467]}],style:[{t:2,x:{r:["data.setting"],s:'_0==1?"selected":null'},p:[12,89,520]}],action:"setting",params:'{"amount": 1}'},f:["3"]}," ",{p:[13,6,622],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=2?null:"disabled"'},p:[13,36,652]}],style:[{t:2,x:{r:["data.setting"],s:'_0==2?"selected":null'},p:[13,89,705]}],action:"setting",params:'{"amount": 2}'},f:["6"]}," ",{p:[14,6,807],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=3?null:"disabled"'},p:[14,36,837]}],style:[{t:2,x:{r:["data.setting"],s:'_0==3?"selected":null'},p:[14,89,890]}],action:"setting",params:'{"amount": 3}'},f:["9"]}," ",{p:[15,6,992],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=4?null:"disabled"'},p:[15,36,1022]}],style:[{t:2,x:{r:["data.setting"],s:'_0==4?"selected":null'},p:[15,89,1075]}],action:"setting",params:'{"amount": 4}'},f:["12"]}," ",{p:[16,6,1178],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=5?null:"disabled"'},p:[16,36,1208]}],style:[{t:2,x:{r:["data.setting"],s:'_0==5?"selected":null'},p:[16,89,1261]}],action:"setting",params:'{"amount": 5}'},f:["15"]}]}]}," ",{p:[19,3,1392],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[21,6,1456],t:7,e:"span",f:[{t:2,x:{r:["adata.TankCurrentVolume"],s:"Math.round(_0)"},p:[21,12,1462]},"/",{t:2,r:"data.TankMaxVolume",p:[21,52,1502]}," Units"]}," ",{p:[22,6,1543],t:7,e:"br"}," ",{p:[23,5,1553],t:7,e:"br"}," ",{t:4,f:[{p:[25,7,1599],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[25,50,1642]}," units of ",{t:2,r:"name",p:[25,85,1677]}]},{p:[25,100,1692],t:7,e:"br"}],n:52,r:"adata.TankContents",p:[24,6,1564]}],n:50,r:"data.isTankLoaded",p:[20,4,1425]},{t:4,n:51,f:[{p:[28,6,1730],t:7,e:"span",a:{"class":"bad"},f:["Tank Empty"]}],r:"data.isTankLoaded"}," ",{p:[30,4,1780],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"Eject":"Close"'},p:[30,21,1797]}],style:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"selected":null'},p:[31,12,1851]}],state:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?null:"disabled"'},p:[32,12,1905]}],action:"purge"},f:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"Purge Contents":"No chemicals detected"'},p:[33,20,1967]}]}]}]}],n:50,x:{r:["data.screen"],s:'_0=="home"'},p:[1,2,1]}]},e.exports=a.extend(r.exports)},{341:341}],466:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,3,30],t:7,e:"ui-section",a:{label:"Generated Power"},f:[{t:2,x:{r:["adata.generated"],s:"Math.round(_0)"},p:[3,5,71]},"W"]}," ",{p:[5,3,122],t:7,e:"ui-section",a:{label:"Orientation"},f:[{p:[6,5,159],t:7,e:"span",f:[{t:2,x:{r:["adata.angle"],s:"Math.round(_0)"},p:[6,11,165]},"° (",{t:2,r:"data.direction",p:[6,45,199]},")"]}]}," ",{p:[8,3,244],t:7,e:"ui-section",a:{label:"Adjust Angle"},f:[{p:[9,5,282],t:7,e:"ui-button",a:{icon:"step-backward",action:"angle",params:'{"adjust": -15}'},f:["15°"]}," ",{p:[10,5,378],t:7,e:"ui-button",a:{icon:"backward",action:"angle",params:'{"adjust": -5}'},f:["5°"]}," ",{p:[11,5,467],t:7,e:"ui-button",a:{icon:"forward",action:"angle",params:'{"adjust": 5}'},f:["5°"]}," ",{p:[12,5,554],t:7,e:"ui-button",a:{icon:"step-forward",action:"angle",params:'{"adjust": 15}'},f:["15°"]}]}]}," ",{p:[15,1,673],t:7,e:"ui-display",a:{title:"Tracking"},f:[{p:[16,3,705],t:7,e:"ui-section",a:{label:"Tracker Mode"},f:[{p:[17,5,743],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.tracking_state"],s:'_0==0?"selected":null'},p:[17,36,774]}],action:"tracking",params:'{"mode": 0}'},f:["Off"]}," ",{p:[19,5,889],t:7,e:"ui-button",a:{icon:"clock-o",state:[{t:2,x:{r:["data.tracking_state"],s:'_0==1?"selected":null'},p:[19,38,922]}],action:"tracking",params:'{"mode": 1}'},f:["Timed"]}," ",{p:[21,5,1039],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.connected_tracker","data.tracking_state"],s:'_0?_1==2?"selected":null:"disabled"'},p:[21,38,1072]}],action:"tracking",params:'{"mode": 2}'},f:["Auto"]}]}," ",{p:[24,3,1239],t:7,e:"ui-section",a:{label:"Tracking Rate"},f:[{p:[25,3,1276],t:7,e:"span",f:[{t:2,x:{r:["adata.tracking_rate"],s:"Math.round(_0)"},p:[25,9,1282]},"°/h (",{t:2,r:"data.rotating_way",p:[25,53,1326]},")"]}]}," ",{p:[27,3,1373],t:7,e:"ui-section",a:{label:"Adjust Rate"},f:[{p:[28,5,1410],t:7,e:"ui-button",a:{icon:"fast-backward",action:"rate",params:'{"adjust": -180}'},f:["180°"]}," ",{p:[29,5,1507],t:7,e:"ui-button",a:{icon:"step-backward",action:"rate",params:'{"adjust": -30}'},f:["30°"]}," ",{p:[30,5,1602],t:7,e:"ui-button",a:{icon:"backward",action:"rate",params:'{"adjust": -5}'},f:["5°"]}," ",{p:[31,5,1690],t:7,e:"ui-button",a:{icon:"forward",action:"rate",params:'{"adjust": 5}'},f:["5°"]}," ",{p:[32,5,1776],t:7,e:"ui-button",a:{icon:"step-forward",action:"rate",params:'{"adjust": 30}'},f:["30°"]}," ",{p:[33,5,1869],t:7,e:"ui-button",a:{icon:"fast-forward",action:"rate",params:'{"adjust": 180}'},f:["180°"]}]}]}," ",{p:{button:[{p:[38,5,2051],t:7,e:"ui-button",a:{icon:"refresh",action:"refresh"},f:["Refresh"]}]},t:7,e:"ui-display",a:{title:"Devices",button:0},f:[" ",{p:[40,2,2130],t:7,e:"ui-section",a:{label:"Solar Tracker"},f:[{p:[41,5,2169],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected_tracker"],s:'_0?"good":"bad"'},p:[41,18,2182]}]},f:[{t:2,x:{r:["data.connected_tracker"],s:'_0?"":"Not "'},p:[41,63,2227]},"Found"]}]}," ",{p:[43,2,2296],t:7,e:"ui-section",a:{label:"Solar Panels"},f:[{p:[44,3,2332],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected_panels"],s:'_0?"good":"bad"'},p:[44,16,2345]}]},f:[{t:2,x:{r:["adata.connected_panels"],s:"Math.round(_0)"},p:[44,60,2389]}," Panels Connected"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],467:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{t:4,f:[{p:[4,7,84],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.hasPowercell"],s:'_0?null:"disabled"'},p:[4,38,115]}],action:"eject"},f:["Eject"]}],n:50,r:"data.open",p:[3,5,60]}]},t:7,e:"ui-display",a:{title:"Power",button:0},f:[" ",{p:[7,3,220],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[8,5,251],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[8,22,268]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[9,14,318]}],state:[{t:2,x:{r:["data.hasPowercell"],s:'_0?null:"disabled"'},p:[9,54,358]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[10,22,422]}]}]}," ",{p:[12,3,479],t:7,e:"ui-section",a:{label:"Cell"},f:[{t:4,f:[{p:[14,7,541],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.powerLevel",p:[14,40,574]}]},f:[{t:2,x:{r:["adata.powerLevel"],s:"Math.fixed(_0)"},p:[14,61,595]},"%"]}],n:50,r:"data.hasPowercell",p:[13,5,509]},{t:4,n:51,f:[{p:[16,4,652],t:7,e:"span",a:{"class":"bad"},f:["No Cell"]}],r:"data.hasPowercell"}]}]}," ",{p:[20,1,725],t:7,e:"ui-display",a:{title:"Thermostat"},f:[{p:[21,3,759],t:7,e:"ui-section",a:{label:"Current Temperature"},f:[{p:[22,3,802],t:7,e:"span",f:[{t:2,x:{r:["adata.currentTemp"],s:"Math.round(_0)"},p:[22,9,808]},"°C"]}]}," ",{p:[24,2,871],t:7,e:"ui-section",a:{label:"Target Temperature"},f:[{p:[25,3,913],t:7,e:"span",f:[{t:2,x:{r:["adata.targetTemp"],s:"Math.round(_0)"},p:[25,9,919]},"°C"]}]}," ",{t:4,f:[{p:[28,5,1004],t:7,e:"ui-section",a:{label:"Adjust Target"},f:[{p:[29,7,1045],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.targetTemp","data.minTemp"],s:'_0>_1?null:"disabled"'},p:[29,46,1084]}],action:"target",params:'{"adjust": -20}'}}," ",{p:[30,7,1189],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.targetTemp","data.minTemp"],s:'_0>_1?null:"disabled"'},p:[30,41,1223]}],action:"target",params:'{"adjust": -5}'}}," ",{p:[31,7,1327],t:7,e:"ui-button",a:{icon:"pencil",action:"target",params:'{"target": "input"}'},f:["Set"]}," ",{p:[32,7,1419],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.targetTemp","data.maxTemp"],s:'_0<_1?null:"disabled"'},p:[32,40,1452]}],action:"target",params:'{"adjust": 5}'}}," ",{p:[33,7,1555],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.targetTemp","data.maxTemp"],s:'_0<_1?null:"disabled"'},p:[33,45,1593]}],action:"target",params:'{"adjust": 20}'}}]}],n:50,r:"data.open",p:[27,3,982]}," ",{p:[36,3,1719],t:7,e:"ui-section",a:{label:"Mode"},f:[{t:4,f:[{p:[38,7,1771],t:7,e:"ui-button",a:{icon:"long-arrow-up",state:[{t:2,x:{r:["data.mode"],s:'_0=="heat"?"selected":null'},p:[38,46,1810]}],action:"mode",params:'{"mode": "heat"}'},f:["Heat"]}," ",{p:[39,7,1918],t:7,e:"ui-button",a:{icon:"long-arrow-down",state:[{t:2,x:{r:["data.mode"],s:'_0=="cool"?"selected":null'},p:[39,48,1959]}],action:"mode",params:'{"mode": "cool"}'},f:["Cool"]}," ",{p:[40,7,2067],t:7,e:"ui-button",a:{icon:"arrows-v",state:[{t:2,x:{r:["data.mode"],s:'_0=="auto"?"selected":null'},p:[40,41,2101]}],action:"mode",params:'{"mode": "auto"}'},f:["Auto"]}],n:50,r:"data.open",p:[37,3,1747]},{t:4,n:51,f:[{p:[42,4,2217],t:7,e:"span",f:[{t:2,x:{r:["text","data.mode"],s:"_0.titleCase(_1)"},p:[42,10,2223]}]}],r:"data.open"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],468:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:{button:[{p:[4,8,97],t:7,e:"ui-button",a:{action:"jump",params:['{"name" : ',{t:2,r:"name",p:[4,51,140]},"}"]},f:["Jump"]}," ",{p:[7,9,195],t:7,e:"ui-button",a:{action:"spawn",params:['{"name" : ',{t:2,r:"name",p:[7,53,239]},"}"]},f:["Spawn"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[2,22,46]}],button:0},f:[" ",{p:[11,3,308],t:7,e:"ui-section",a:{label:"Description"},f:[{p:[12,5,346],t:7,e:"span",f:[{t:3,r:"desc",p:[12,11,352]}]}]}," ",{p:[14,3,390],t:7,e:"ui-section",a:{label:"Spawners left"},f:[{p:[15,5,430],t:7,e:"span",f:[{t:2,r:"amount_left",p:[15,11,436]}]}]}]}],n:52,r:"data.spawners",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],469:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,30],t:7,e:"ui-display",a:{title:[{t:2,r:"class",p:[2,22,49]}," Alarms"]},f:[{p:[3,5,72],t:7,e:"ul",f:[{t:4,f:[{p:[5,9,103],t:7,e:"li",f:[{t:2,r:".",p:[5,13,107]}]}],n:52,r:".",p:[4,7,83]},{t:4,n:51,f:[{p:[7,9,141],t:7,e:"li",f:["System Nominal"]}],r:"."}]}]}],n:52,i:"class",r:"data.alarms",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],470:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,41],t:7,e:"ui-notice",f:[{p:[3,5,57],t:7,e:"span",f:["Biological entity detected in contents. Please remove."]}]}],n:50,x:{r:["data.occupied","data.safeties"],s:"_0&&_1"},p:[1,1,0]},{t:4,f:[{p:[7,3,173],t:7,e:"ui-notice",f:[{p:[8,5,189],t:7,e:"span",f:["Contents are being disinfected. Please wait."]}]}],n:50,r:"data.uv_active",p:[6,1,148]},{t:4,n:51,f:[{p:{button:[{t:4,f:[{p:[13,25,357],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[13,42,374]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Unlock":"Lock"'},p:[13,93,425]}]}],n:50,x:{r:["data.open"],s:"!_0"},p:[13,7,339]}," ",{t:4,f:[{p:[14,27,506],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"sign-out":"sign-in"'},p:[14,44,523]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Close":"Open"'},p:[14,98,577]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[14,7,486]}]},t:7,e:"ui-display",a:{title:"Storage",button:0},f:[" ",{t:4,f:[{p:[17,7,676],t:7,e:"ui-notice",f:[{p:[18,9,696],t:7,e:"span",f:["Unit Locked"]}]}],n:50,r:"data.locked",p:[16,5,650]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.open"],s:"_0"},f:[{p:[21,9,773],t:7,e:"ui-section",a:{label:"Helmet"},f:[{p:[22,11,811],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.helmet"],s:'_0?"square":"square-o"'},p:[22,28,828]}],state:[{t:2,x:{r:["data.helmet"],s:'_0?null:"disabled"'},p:[22,75,875]}],action:"dispense",params:'{"item": "helmet"}'},f:[{t:2,x:{r:["data.helmet"],s:'_0||"Empty"'},p:[23,59,970]}]}]}," ",{p:[25,9,1039],t:7,e:"ui-section",a:{label:"Suit"},f:[{p:[26,11,1075],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.suit"],s:'_0?"square":"square-o"'},p:[26,28,1092]}],state:[{t:2,x:{r:["data.suit"],s:'_0?null:"disabled"'},p:[26,74,1138]}],action:"dispense",params:'{"item": "suit"}'},f:[{t:2,x:{r:["data.suit"],s:'_0||"Empty"'},p:[27,57,1229]}]}]}," ",{p:[29,9,1296],t:7,e:"ui-section",a:{label:"Mask"},f:[{p:[30,11,1332],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mask"],s:'_0?"square":"square-o"'},p:[30,28,1349]}],state:[{t:2,x:{r:["data.mask"],s:'_0?null:"disabled"'},p:[30,74,1395]}],action:"dispense",params:'{"item": "mask"}'},f:[{t:2,x:{r:["data.mask"],s:'_0||"Empty"'},p:[31,57,1486]}]}]}," ",{p:[33,9,1553],t:7,e:"ui-section",a:{label:"Storage"},f:[{p:[34,11,1592],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.storage"],s:'_0?"square":"square-o"'},p:[34,28,1609]}],state:[{t:2,x:{r:["data.storage"],s:'_0?null:"disabled"'},p:[34,77,1658]}],action:"dispense",params:'{"item": "storage"}'},f:[{t:2,x:{r:["data.storage"],s:'_0||"Empty"'},p:[35,60,1755]}]}]}]},{t:4,n:50,x:{r:["data.open"],s:"!(_0)"},f:[" ",{p:[38,7,1836],t:7,e:"ui-button",a:{icon:"recycle",state:[{t:2,x:{r:["data.occupied","data.safeties"],s:'_0&&_1?"disabled":null'},p:[38,40,1869]}],action:"uv"},f:["Disinfect"]}]}],r:"data.locked"}]}],r:"data.uv_active"}]},e.exports=a.extend(r.exports)},{341:341}],471:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,5,17],t:7,e:"ui-section",a:{label:"Dispense"},f:[{p:[3,9,55],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.plasma"],s:'_0?"square":"square-o"'},p:[3,26,72]}],state:[{t:2,x:{r:["data.plasma"],s:'_0?null:"disabled"'},p:[3,74,120]}],action:"plasma"},f:["Plasma (",{t:2,x:{r:["adata.plasma"],s:"Math.round(_0)"},p:[4,37,193]},")"]}," ",{p:[5,9,243],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.oxygen"],s:'_0?"square":"square-o"'},p:[5,26,260]}],state:[{t:2,x:{r:["data.oxygen"],s:'_0?null:"disabled"'},p:[5,74,308]}],action:"oxygen"},f:["Oxygen (",{t:2,x:{r:["adata.oxygen"],s:"Math.round(_0)"},p:[6,37,381]},")"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],472:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tankPressureState:function(){var t=this.get("data.tankPressure");return t>=200?"good":t>=100?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[14,1,282],t:7,e:"ui-notice",f:[{p:[15,3,296],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.connected"],s:'_0?"is":"is not"'},p:[15,23,316]}," connected to a mask."]}]}," ",{p:[17,1,393],t:7,e:"ui-display",f:[{p:[18,3,408],t:7,e:"ui-section",a:{label:"Tank Pressure"},f:[{p:[19,7,449],t:7,e:"ui-bar",a:{min:"0",max:"1013",value:[{t:2,r:"data.tankPressure",p:[19,41,483]}],state:[{t:2,r:"tankPressureState",p:[20,16,521]}]},f:[{t:2,x:{r:["adata.tankPressure"],s:"Math.round(_0)"},p:[20,39,544]}," kPa"]}]}," ",{p:[22,3,610],t:7,e:"ui-section",a:{label:"Release Pressure"},f:[{p:[23,5,652],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.minReleasePressure",p:[23,18,665]}],max:[{t:2,r:"data.maxReleasePressure",p:[23,52,699]}],value:[{t:2,r:"data.releasePressure",p:[24,14,741]}]},f:[{t:2,x:{r:["adata.releasePressure"],s:"Math.round(_0)"},p:[24,40,767]}," kPa"]}]}," ",{p:[26,3,836],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[27,5,880],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.releasePressure","data.defaultReleasePressure"],s:'_0!=_1?null:"disabled"'},p:[27,38,913]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[29,5,1067],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.releasePressure","data.minReleasePressure"],s:'_0>_1?null:"disabled"'},p:[29,36,1098]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[31,5,1243],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[32,5,1337],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.releasePressure","data.maxReleasePressure"],s:'_0<_1?null:"disabled"'},p:[32,35,1367]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],473:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,5,32],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[3,9,73],t:7,e:"span",f:[{t:2,x:{r:["adata.temperature"],s:"Math.fixed(_0,2)"},p:[3,15,79]}," K"]}]}," ",{p:[5,5,147],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[6,9,185],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.fixed(_0,2)"},p:[6,15,191]}," kPa"]}]}]}," ",{p:[9,1,268],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[10,5,302],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[11,9,337],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[11,26,354]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[11,70,398]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[12,28,458]}]}]}," ",{p:[14,5,518],t:7,e:"ui-section",a:{label:"Target Temperature"},f:[{p:[15,9,566],t:7,e:"ui-button",a:{icon:"fast-backward",style:[{t:2,x:{r:["data.target","data.min"],s:'_0==_1?"disabled":null'},p:[15,48,605]}],action:"target",params:'{"adjust": -20}'}}," ",{p:[17,9,717],t:7,e:"ui-button",a:{icon:"backward",style:[{t:2,x:{r:["data.target","data.min"],s:'_0==_1?"disabled":null'},p:[17,43,751]}],action:"target",params:'{"adjust": -5}'}}," ",{p:[19,9,862],t:7,e:"ui-button",a:{icon:"pencil",action:"target",params:'{"target": "input"}'},f:[{t:2,x:{r:["adata.target"],s:"Math.fixed(_0,2)"},p:[19,79,932]}]}," ",{p:[20,9,984],t:7,e:"ui-button",a:{icon:"forward",style:[{t:2,x:{r:["data.target","data.max"],s:'_0==_1?"disabled":null'},p:[20,42,1017]}],action:"target",params:'{"adjust": 5}'}}," ",{p:[22,9,1127],t:7,e:"ui-button",a:{icon:"fast-forward",style:[{t:2,x:{r:["data.target","data.max"],s:'_0==_1?"disabled":null'},p:[22,47,1165]}],action:"target",params:'{"adjust": 20}'}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],474:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 1:return"good";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[13,1,161], -t:7,e:"ui-notice",f:[{p:[14,2,174],t:7,e:"ui-section",a:{label:"Reconnect"},f:[{p:[15,3,207],t:7,e:"div",a:{style:"float:right"},f:[{p:[16,4,236],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}]}]}]}," ",{p:[20,1,340],t:7,e:"ui-display",a:{title:"Turbine Controller"},f:[{p:[21,2,381],t:7,e:"ui-section",a:{label:"Status"},f:[{t:4,f:[{p:[23,4,434],t:7,e:"span",a:{"class":"bad"},f:["Broken"]}],n:50,r:"data.broken",p:[22,3,411]},{t:4,n:51,f:[{p:[25,4,480],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.online"],s:"_0(_1)"},p:[25,17,493]}]},f:[{t:2,x:{r:["data.online","data.compressor_broke","data.turbine_broke"],s:'_0&&!(_1||_2)?"Online":"Offline"'},p:[25,46,522]}]}],r:"data.broken"}," ",{p:[27,3,630],t:7,e:"div",a:{style:"float:right"},f:[{p:[28,4,659],t:7,e:"ui-button",a:{icon:"power-off",action:"power-on",state:[{t:2,r:"data.broken",p:[28,57,712]}],style:[{t:2,x:{r:["data.online"],s:'_0?"selected":""'},p:[28,81,736]}]},f:["On"]}," ",{p:[29,4,789],t:7,e:"ui-button",a:{icon:"close",action:"power-off",state:[{t:2,r:"data.broken",p:[29,54,839]}],style:[{t:2,x:{r:["data.online"],s:'_0?"":"selected"'},p:[29,78,863]}]},f:["Off"]}]}," ",{t:4,f:[{p:[32,4,958],t:7,e:"br"}," [ ",{p:[33,6,968],t:7,e:"span",a:{"class":"bad"},f:["Compressor is inoperable"]}," ]"],n:50,r:"data.compressor_broke",p:[31,3,925]}," ",{t:4,f:[{p:[36,4,1062],t:7,e:"br"}," [ ",{p:[37,6,1072],t:7,e:"span",a:{"class":"bad"},f:["Turbine is inoperable"]}," ]"],n:50,r:"data.turbine_broke",p:[35,3,1032]}]}]}," ",{p:[41,1,1160],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[42,2,1189],t:7,e:"ui-section",a:{label:"Turbine Speed"},f:[{p:[43,3,1226],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.rpm"],s:'_0?"--":_1'},p:[43,9,1232]}," RPM"]}]}," ",{p:[45,2,1293],t:7,e:"ui-section",a:{label:"Internal Temp"},f:[{p:[46,3,1330],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.temp"],s:'_0?"--":_1'},p:[46,9,1336]}," K"]}]}," ",{p:[48,2,1396],t:7,e:"ui-section",a:{label:"Generated Power"},f:[{p:[49,3,1435],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.power"],s:'_0?"--":_1'},p:[49,9,1441]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],475:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{},oninit:function(){this.on({hover:function(t){var e=this.get("data.telecrystals");e>=t.context.params.cost&&this.set("hovered",t.context.params)},unhover:function(t){this.set("hovered")}})}}}(r),r.exports.template={v:3,t:[" ",{p:{button:[{t:4,f:[{p:[23,7,460],t:7,e:"ui-button",a:{icon:"lock",action:"lock"},f:["Lock"]}],n:50,r:"data.lockable",p:[22,5,432]}]},t:7,e:"ui-display",a:{title:"Uplink",button:0},f:[" ",{p:[26,3,543],t:7,e:"ui-section",a:{label:"Telecrystals",right:0},f:[{p:[27,5,587],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.telecrystals"],s:'_0>0?"good":"bad"'},p:[27,18,600]}]},f:[{t:2,r:"data.telecrystals",p:[27,62,644]}," TC"]}]}]}," ",{t:4,f:[{p:[31,3,734],t:7,e:"ui-display",f:[{p:[32,2,748],t:7,e:"ui-button",a:{action:"select",params:['{"category": "',{t:2,r:"name",p:[32,51,797]},'"}']},f:[{t:2,r:"name",p:[32,63,809]}]}," ",{t:4,f:[{p:[34,4,850],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[34,23,869]}],candystripe:0,right:0},f:[{p:[35,3,900],t:7,e:"ui-button",a:{tooltip:[{t:2,r:"name",p:[35,23,920]},": ",{t:2,r:"desc",p:[35,33,930]}],"tooltip-side":"left",state:[{t:2,x:{r:["data.telecrystals","hovered.cost","cost","hovered.item","name"],s:'_0<_2||(_0-_1<_2&&_3!=_4)?"disabled":null'},p:[36,12,971]}],action:"buy",params:['{"category": "',{t:2,r:"category",p:[37,40,1129]},'", "item": ',{t:2,r:"name",p:[37,63,1152]},', "cost": ',{t:2,r:"cost",p:[37,81,1170]},"}"]},v:{hover:"hover",unhover:"unhover"},f:[{t:2,r:"cost",p:[38,43,1223]}," TC"]}]}],n:52,r:"items",p:[33,2,831]}]}],n:52,r:"data.categories",p:[30,1,706]}]},e.exports=a.extend(r.exports)},{341:341}],476:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{healthState:function(t){var e=this.get("data.vr_avatar.maxhealth");return t>e/1.5?"good":t>e/3?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[14,1,292],t:7,e:"ui-display",f:[{t:4,f:[{p:[16,3,331],t:7,e:"ui-notice",f:[{p:[17,4,347],t:7,e:"span",f:["Safety restraints disabled."]}]}],n:50,r:"data.emagged",p:[15,2,307]}," ",{t:4,f:[{p:[21,3,442],t:7,e:"ui-display",a:{title:"Virtual Avatar"},f:[{p:[22,4,482],t:7,e:"ui-section",a:{label:"Name"},f:[{t:2,r:"data.vr_avatar.name",p:[23,5,513]}]}," ",{t:4,f:[{p:[26,5,586],t:7,e:"ui-section",a:{label:"Status"},f:[{t:2,r:"data.vr_avatar.status",p:[27,6,620]}]}," ",{p:[29,5,670],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[30,6,704],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.vr_avatar.maxhealth",p:[30,27,725]}],value:[{t:2,r:"adata.vr_avatar.health",p:[30,65,763]}],state:[{t:2,x:{r:["healthState","adata.vr_avatar.health"],s:"_0(_1)"},p:[30,100,798]}]},f:[{t:2,x:{r:["adata.vr_avatar.health"],s:"Math.round(_0)"},p:[30,141,839]},"/",{t:2,r:"adata.vr_avatar.maxhealth",p:[30,180,878]}]}]}],n:50,r:"data.isliving",p:[25,4,559]}]}],n:50,r:"data.vr_avatar",p:[20,2,416]},{t:4,n:51,f:[{p:[35,3,979],t:7,e:"ui-display",a:{title:"Virtual Avatar"},f:["No Virtual Avatar detected"]}],r:"data.vr_avatar"}," ",{p:[39,2,1075],t:7,e:"ui-display",a:{title:"VR Commands"},f:[{p:[40,3,1111],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.toggle_open"],s:'_0?"times":"plus"'},p:[40,20,1128]}],action:"toggle_open"},f:[{t:2,x:{r:["data.toggle_open"],s:'_0?"Close":"Open"'},p:[41,4,1195]}," the VR Sleeper"]}," ",{t:4,f:[{p:[44,4,1297],t:7,e:"ui-button",a:{icon:"signal",action:"vr_connect"},f:["Connect to VR"]}],n:50,r:"data.isoccupant",p:[43,3,1269]}," ",{t:4,f:[{p:[49,4,1420],t:7,e:"ui-button",a:{icon:"ban",action:"delete_avatar"},f:["Delete Virtual Avatar"]}],n:50,r:"data.vr_avatar",p:[48,3,1393]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],477:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{t:4,f:[{p:[3,5,40],t:7,e:"ui-section",a:{label:[{t:2,r:"color",p:[3,24,59]},{t:2,x:{r:["wire"],s:'_0?" ("+_0+")":""'},p:[3,33,68]}],labelcolor:[{t:2,r:"color",p:[3,80,115]}],candystripe:0,right:0},f:[{p:[4,7,151],t:7,e:"ui-button",a:{action:"cut",params:['{"wire":"',{t:2,r:"color",p:[4,48,192]},'"}']},f:[{t:2,x:{r:["cut"],s:'_0?"Mend":"Cut"'},p:[4,61,205]}]}," ",{p:[5,7,248],t:7,e:"ui-button",a:{action:"pulse",params:['{"wire":"',{t:2,r:"color",p:[5,50,291]},'"}']},f:["Pulse"]}," ",{p:[6,7,328],t:7,e:"ui-button",a:{action:"attach",params:['{"wire":"',{t:2,r:"color",p:[6,51,372]},'"}']},f:[{t:2,x:{r:["attached"],s:'_0?"Detach":"Attach"'},p:[6,64,385]}]}]}],n:52,r:"data.wires",p:[2,3,15]}]}," ",{t:4,f:[{p:[11,3,498],t:7,e:"ui-display",f:[{t:4,f:[{p:[13,7,543],t:7,e:"ui-section",f:[{t:2,r:".",p:[13,19,555]}]}],n:52,r:"data.status",p:[12,5,515]}]}],n:50,r:"data.status",p:[10,1,476]}]},e.exports=a.extend(r.exports)},{341:341}],478:[function(t,e,n){(function(e){"use strict";var n=t(341),a=e.interopRequireDefault(n);t(331),t(1),t(327),t(330);var r=t(479),i=e.interopRequireDefault(r),o=t(480),s=t(328),p=t(329),u=e.interopRequireDefault(p);a["default"].DEBUG=/minified/.test(function(){}),Object.assign(Math,t(484)),window.initialize=function(e){window.tgui=window.tgui||new i["default"]({el:"#container",data:function(){var n=JSON.parse(e);return{constants:t(481),text:t(485),config:n.config,data:n.data,adata:n.data}}})};var c=document.getElementById("data"),l=c.textContent,d=c.getAttribute("data-ref");"{}"!==l&&(window.initialize(l),c.remove()),(0,o.act)(d,"tgui:initialize"),(0,s.loadCSS)("font-awesome.min.css");var f=new u["default"]("FontAwesome");f.check("").then(function(){return document.body.classList.add("icons")})["catch"](function(){return document.body.classList.add("no-icons")})}).call(this,t("babel/external-helpers"))},{1:1,327:327,328:328,329:329,330:330,331:331,341:341,479:479,480:480,481:481,484:484,485:485,"babel/external-helpers":"babel/external-helpers"}],479:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(480),a=t(482);e.exports={components:{"ui-bar":t(342),"ui-button":t(343),"ui-display":t(344),"ui-input":t(345),"ui-linegraph":t(346),"ui-notice":t(347),"ui-section":t(349),"ui-subdisplay":t(350),"ui-tabs":t(351)},events:{enter:t(339).enter,space:t(339).space},transitions:{fade:t(340)},onconfig:function(){var e=this.get("config.interface"),n={ai_airlock:t(355),airalarm:t(356),"airalarm/back":t(357),"airalarm/modes":t(358),"airalarm/scrubbers":t(359),"airalarm/status":t(360),"airalarm/thresholds":t(361),"airalarm/vents":t(362),airlock_electronics:t(363),apc:t(364),atmos_alert:t(365),atmos_control:t(366),atmos_filter:t(367),atmos_mixer:t(368),atmos_pump:t(369),borgopanel:t(370),brig_timer:t(371),bsa:t(372),canister:t(373),cargo:t(374),cargo_express:t(375),cellular_emporium:t(376),centcom_podlauncher:t(377),chem_dispenser:t(378),chem_heater:t(379),chem_master:t(380),chem_synthesizer:t(381),clockwork_slab:t(382),codex_gigas:t(383),computer_fabricator:t(384),crayon:t(385),crew:t(386),cryo:t(387),disposal_unit:t(388),dna_vault:t(389),dogborg_sleeper:t(390),eightball:t(391),emergency_shuttle_console:t(392),engraved_message:t(393),error:t(394),"exofab - Copia":t(395),exonet_node:t(396),gps:t(397),gulag_console:t(398),gulag_item_reclaimer:t(399),holodeck:t(400),implantchair:t(401),intellicard:t(402),keycard_auth:t(403),labor_claim_console:t(404),language_menu:t(405),launchpad_remote:t(406),mech_bay_power_console:t(407),mulebot:t(408),nanite_chamber_control:t(409),nanite_cloud_control:t(410),nanite_program_hub:t(411),nanite_programmer:t(412),nanite_remote:t(413),notificationpanel:t(414),ntnet_relay:t(415),ntos_ai_restorer:t(416),ntos_card:t(417),ntos_configuration:t(418),ntos_file_manager:t(419),ntos_main:t(420),ntos_net_chat:t(421),ntos_net_dos:t(422),ntos_net_downloader:t(423),ntos_net_monitor:t(424),ntos_net_transfer:t(425),ntos_power_monitor:t(426),ntos_revelation:t(427),ntos_station_alert:t(428),ntos_supermatter_monitor:t(429),ntosheader:t(430),nuclear_bomb:t(431),operating_computer:t(432),ore_redemption_machine:t(433),pandemic:t(434),personal_crafting:t(435),portable_pump:t(436),portable_scrubber:t(437),power_monitor:t(438),radio:t(439),rdconsole:t(440),"rdconsole/circuit":t(441),"rdconsole/designview":t(442),"rdconsole/destruct":t(443),"rdconsole/diskopsdesign":t(444),"rdconsole/diskopstech":t(445),"rdconsole/nodeview":t(446),"rdconsole/protolathe":t(447),"rdconsole/rdheader":t(448),"rdconsole/settings":t(449),"rdconsole/techweb":t(450),reagentgrinder:t(451),rpd:t(452),"rpd/colorsel":t(453),"rpd/dirsel":t(454),sat_control:t(455),scrubbing_types:t(456),shuttle_manipulator:t(457),"shuttle_manipulator/modification":t(458),"shuttle_manipulator/status":t(459),"shuttle_manipulator/templates":t(460),sleeper:t(461),slime_swap_body:t(462),smartvend:t(463),smes:t(464),smoke_machine:t(465),solar_control:t(466),space_heater:t(467),spawners_menu:t(468),station_alert:t(469),suit_storage_unit:t(470),tank_dispenser:t(471),tanks:t(472),thermomachine:t(473),turbine_computer:t(474),uplink:t(475),vr_sleeper:t(476),wires:t(477)};e in n?this.components["interface"]=n[e]:this.components["interface"]=n.error},oninit:function(){this.observe("config.style",function(t,e,n){t&&document.body.classList.add(t),e&&document.body.classList.remove(e)})},oncomplete:function(){if(this.get("config.locked")){var t=(0,a.lock)(window.screenLeft,window.screenTop),e=t.x,r=t.y;(0,n.winset)(this.get("config.window"),"pos",e+","+r)}(0,n.winset)("mapwindow.map","focus",!0)}}}(r),r.exports.template={v:3,t:[" "," "," "," ",{p:[56,1,1819],t:7,e:"titlebar",f:[{t:3,r:"config.title",p:[56,11,1829]}]}," ",{p:[57,1,1859],t:7,e:"main",f:[{p:[58,3,1868],t:7,e:"warnings"}," ",{p:[59,3,1882],t:7,e:"interface"}]}," ",{t:4,f:[{p:[62,3,1929],t:7,e:"resize"}],n:50,r:"config.titlebar",p:[61,1,1903]}]},r.exports.components=r.exports.components||{};var i={warnings:t(354),titlebar:t(353),resize:t(348)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{339:339,340:340,341:341,342:342,343:343,344:344,345:345,346:346,347:347,348:348,349:349,350:350,351:351,353:353,354:354,355:355,356:356,357:357,358:358,359:359,360:360,361:361,362:362,363:363,364:364,365:365,366:366,367:367,368:368,369:369,370:370,371:371,372:372,373:373,374:374,375:375,376:376,377:377,378:378,379:379,380:380,381:381,382:382,383:383,384:384,385:385,386:386,387:387,388:388,389:389,390:390,391:391,392:392,393:393,394:394,395:395,396:396,397:397,398:398,399:399,400:400,401:401,402:402,403:403,404:404,405:405,406:406,407:407,408:408,409:409,410:410,411:411,412:412,413:413,414:414,415:415,416:416,417:417,418:418,419:419,420:420,421:421,422:422,423:423,424:424,425:425,426:426,427:427,428:428,429:429,430:430,431:431,432:432,433:433,434:434,435:435,436:436,437:437,438:438,439:439,440:440,441:441,442:442,443:443,444:444,445:445,446:446,447:447,448:448,449:449,450:450,451:451,452:452,453:453,454:454,455:455,456:456,457:457,458:458,459:459,460:460,461:461,462:462,463:463,464:464,465:465,466:466,467:467,468:468,469:469,470:470,471:471,472:472,473:473,474:474,475:475,476:476,477:477,480:480,482:482}],480:[function(t,e,n){"use strict";function a(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"byond://"+e+"?"+Object.keys(t).map(function(e){return o(e)+"="+o(t[e])}).join("&")}function r(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};window.location.href=a(Object.assign({src:t,action:e},n))}function i(t,e,n){var r;window.location.href=a((r={},r[t+"."+e]=n,r),"winset")}n.__esModule=!0,n.href=a,n.act=r,n.winset=i;var o=encodeURIComponent},{}],481:[function(t,e,n){"use strict";n.__esModule=!0;n.UI_INTERACTIVE=2,n.UI_UPDATE=1,n.UI_DISABLED=0,n.UI_CLOSE=-1},{}],482:[function(t,e,n){"use strict";function a(t,e){return 0>t?t=0:t+window.innerWidth>window.screen.availWidth&&(t=window.screen.availWidth-window.innerWidth),0>e?e=0:e+window.innerHeight>window.screen.availHeight&&(e=window.screen.availHeight-window.innerHeight),{x:t,y:e}}function r(t){if(t.preventDefault(),this.get("drag")){if(this.get("x")){var e=t.screenX-this.get("x")+window.screenLeft,n=t.screenY-this.get("y")+window.screenTop;if(this.get("config.locked")){var r=a(e,n);e=r.x,n=r.y}(0,s.winset)(this.get("config.window"),"pos",e+","+n)}this.set({x:t.screenX,y:t.screenY})}}function i(t,e){return t=Math.clamp(100,window.screen.width,t),e=Math.clamp(100,window.screen.height,e),{x:t,y:e}}function o(t){if(t.preventDefault(),this.get("resize")){if(this.get("x")){var e=t.screenX-this.get("x")+window.innerWidth,n=t.screenY-this.get("y")+window.innerHeight,a=i(e,n);e=a.x,n=a.y,(0,s.winset)(this.get("config.window"),"size",e+","+n)}this.set({x:t.screenX,y:t.screenY})}}n.__esModule=!0,n.lock=a,n.drag=r,n.sane=i,n.resize=o;var s=t(480)},{480:480}],483:[function(t,e,n){"use strict";function a(t,e){for(var n=t,a=Array.isArray(n),i=0,n=a?n:n[Symbol.iterator]();;){var o;if(a){if(i>=n.length)break;o=n[i++]}else{if(i=n.next(),i.done)break;o=i.value}var s=o;s.textContent.toLowerCase().includes(e)?(s.style.display="",r(s,e)):s.style.display="none"}}function r(t,e){for(var n=t.queryAll("section"),a=t.query("header").textContent.toLowerCase().includes(e),r=n,i=Array.isArray(r),o=0,r=i?r:r[Symbol.iterator]();;){var s;if(i){if(o>=r.length)break;s=r[o++]}else{if(o=r.next(),o.done)break;s=o.value}var p=s;a||p.textContent.toLowerCase().includes(e)?p.style.display="":p.style.display="none"}}n.__esModule=!0,n.filterMulti=a,n.filter=r},{}],484:[function(t,e,n){"use strict";function a(t,e,n){return Math.max(t,Math.min(n,e))}function r(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return+(Math.round(t+"e"+e)+"e-"+e)}n.__esModule=!0,n.clamp=a,n.fixed=r},{}],485:[function(t,e,n){"use strict";function a(t){return t[0].toUpperCase()+t.slice(1).toLowerCase()}function r(t){return t.replace(/\w\S*/g,a)}function i(t,e){for(t=""+t;t.length1){for(var p=Array(o),u=0;o>u;u++)p[u]=arguments[u+3];n.children=p}return{$$typeof:t,type:e,key:void 0===a?null:""+a,ref:null,props:n,_owner:null}}}(),e.asyncIterator=function(t){if("function"==typeof Symbol){if(Symbol.asyncIterator){var e=t[Symbol.asyncIterator];if(null!=e)return e.call(t)}if(Symbol.iterator)return t[Symbol.iterator]()}throw new TypeError("Object is not async iterable")},e.asyncGenerator=function(){function t(t){this.value=t}function e(e){function n(t,e){return new Promise(function(n,r){var s={key:t,arg:e,resolve:n,reject:r,next:null};o?o=o.next=s:(i=o=s,a(t,e))})}function a(n,i){try{var o=e[n](i),s=o.value;s instanceof t?Promise.resolve(s.value).then(function(t){a("next",t)},function(t){a("throw",t)}):r(o.done?"return":"normal",o.value)}catch(p){r("throw",p)}}function r(t,e){switch(t){case"return":i.resolve({value:e,done:!0});break;case"throw":i.reject(e);break;default:i.resolve({value:e,done:!1})}i=i.next,i?a(i.key,i.arg):o=null}var i,o;this._invoke=n,"function"!=typeof e["return"]&&(this["return"]=void 0)}return"function"==typeof Symbol&&Symbol.asyncIterator&&(e.prototype[Symbol.asyncIterator]=function(){return this}),e.prototype.next=function(t){return this._invoke("next",t)},e.prototype["throw"]=function(t){return this._invoke("throw",t)},e.prototype["return"]=function(t){return this._invoke("return",t)},{wrap:function(t){return function(){return new e(t.apply(this,arguments))}},await:function(e){return new t(e)}}}(),e.asyncGeneratorDelegate=function(t,e){function n(n,a){return r=!0,a=new Promise(function(e){e(t[n](a))}),{done:!1,value:e(a)}}var a={},r=!1;return"function"==typeof Symbol&&Symbol.iterator&&(a[Symbol.iterator]=function(){return this}),a.next=function(t){return r?(r=!1,t):n("next",t)},"function"==typeof t["throw"]&&(a["throw"]=function(t){if(r)throw r=!1,t;return n("throw",t)}),"function"==typeof t["return"]&&(a["return"]=function(t){return n("return",t)}),a},e.asyncToGenerator=function(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function a(r,i){try{var o=e[r](i),s=o.value}catch(p){return void n(p)}return o.done?void t(s):Promise.resolve(s).then(function(t){a("next",t)},function(t){a("throw",t)})}return a("next")})}},e.classCallCheck=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},e.createClass=function(){function t(t,e){for(var n=0;n=0||Object.prototype.hasOwnProperty.call(t,a)&&(n[a]=t[a]);return n},e.possibleConstructorReturn=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e},e.selfGlobal=void 0===t?self:t,e.set=function a(t,e,n,r){var i=Object.getOwnPropertyDescriptor(t,e);if(void 0===i){var o=Object.getPrototypeOf(t);null!==o&&a(o,e,n,r)}else if("value"in i&&i.writable)i.value=n;else{var s=i.set;void 0!==s&&s.call(r,n)}return n},e.slicedToArray=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),e.slicedToArrayLoose=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var n,a=[],r=t[Symbol.iterator]();!(n=r.next()).done&&(a.push(n.value),!e||a.length!==e););return a}throw new TypeError("Invalid attempt to destructure non-iterable instance")},e.taggedTemplateLiteral=function(t,e){return Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))},e.taggedTemplateLiteralLoose=function(t,e){return t.raw=e,t},e.temporalRef=function(t,e,n){if(t===n)throw new ReferenceError(e+" is not defined - temporal dead zone");return t},e.temporalUndefined={},e.toArray=function(t){return Array.isArray(t)?t:Array.from(t)},e.toConsumableArray=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);ethis.end?(this.step&&this.step(1),this.complete&&this.complete(1),!1):(e=t-this.start,n=this.easing(e/this.duration),this.step&&this.step(n),!0):!1},stop:function(){this.abort&&this.abort(),this.running=!1}};var wf,kf,Sf,Ef,Cf,Pf,Af,Of,Tf=xf,Rf=RegExp("^-(?:"+ro.join("|")+")-"),Mf=function(t){return t.replace(Rf,"")},Lf=RegExp("^(?:"+ro.join("|")+")([A-Z])"),jf=function(t){var e;return t?(Lf.test(t)&&(t="-"+t),e=t.replace(/[A-Z]/g,function(t){return"-"+t.toLowerCase()})):""},Df={},Nf={};Xi?(kf=co("div").style,function(){void 0!==kf.transition?(Sf="transition",Ef="transitionend",Cf=!0):void 0!==kf.webkitTransition?(Sf="webkitTransition",Ef="webkitTransitionEnd",Cf=!0):Cf=!1}(),Sf&&(Pf=Sf+"Duration",Af=Sf+"Property",Of=Sf+"TimingFunction"),wf=function(t,e,n,a,r){setTimeout(function(){var i,o,s,p,u;p=function(){o&&s&&(t.root.fire(t.name+":end",t.node,t.isIntro),r())},i=(t.node.namespaceURI||"")+t.node.tagName,t.node.style[Af]=a.map(bf).map(jf).join(","),t.node.style[Of]=jf(n.easing||"linear"),t.node.style[Pf]=n.duration/1e3+"s",u=function(e){var n;n=a.indexOf(mf(Mf(e.propertyName))),-1!==n&&a.splice(n,1),a.length||(t.node.removeEventListener(Ef,u,!1),s=!0,p())},t.node.addEventListener(Ef,u,!1),setTimeout(function(){for(var r,c,l,d,f,h=a.length,g=[];h--;)d=a[h],r=i+d,Cf&&!Nf[r]&&(t.node.style[bf(d)]=e[d],Df[r]||(c=t.getStyle(d),Df[r]=t.getStyle(d)!=e[d],Nf[r]=!Df[r],Nf[r]&&(t.node.style[bf(d)]=c))),(!Cf||Nf[r])&&(void 0===c&&(c=t.getStyle(d)),l=a.indexOf(d),-1===l?m("Something very strange happened with transitions. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!",{node:t.node}):a.splice(l,1),f=/[^\d]*$/.exec(e[d])[0],g.push({name:bf(d),interpolator:Uo(parseFloat(c),parseFloat(e[d])),suffix:f}));g.length?new Tf({root:t.root,duration:n.duration,easing:mf(n.easing||""),step:function(e){var n,a;for(a=g.length;a--;)n=g[a],t.node.style[n.name]=n.interpolator(e)+n.suffix},complete:function(){o=!0,p()}}):o=!0,a.length||(t.node.removeEventListener(Ef,u,!1),s=!0,p())},0)},n.delay||0)}):wf=null;var Ff,If,Bf,Uf,Vf,qf=wf;if("undefined"!=typeof document){if(Ff="hidden",Vf={},Ff in document)Bf="";else for(Uf=ro.length;Uf--;)If=ro[Uf],Ff=If+"Hidden",Ff in document&&(Bf=If);void 0!==Bf?(document.addEventListener(Bf+"visibilitychange",Va),Va()):("onfocusout"in document?(document.addEventListener("focusout",qa),document.addEventListener("focusin",Ga)):(window.addEventListener("pagehide",qa),window.addEventListener("blur",qa),window.addEventListener("pageshow",Ga),window.addEventListener("focus",Ga)),Vf.hidden=!1)}var Gf,zf,Wf,Hf=Vf;Xi?(zf=window.getComputedStyle||Po.getComputedStyle,Gf=function(t,e,n){var a,r=this;if(4===arguments.length)throw Error("t.animateStyle() returns a promise - use .then() instead of passing a callback");if(Hf.hidden)return this.setStyle(t,e),Wf||(Wf=us.resolve());"string"==typeof t?(a={},a[t]=e):(a=t,n=e),n||(g('The "%s" transition does not supply an options object to `t.animateStyle()`. This will break in a future version of Ractive. For more info see https://github.com/RactiveJS/Ractive/issues/340',this.name),n=this);var i=new us(function(t){var e,i,o,s,p,u,c;if(!n.duration)return r.setStyle(a),void t();for(e=Object.keys(a),i=[],o=zf(r.node),p={},u=e.length;u--;)c=e[u],s=o[bf(c)],"0px"===s&&(s=0),s!=a[c]&&(i.push(c),r.node.style[bf(c)]=s);return i.length?void qf(r,a,n,i,t):void t()});return i}):Gf=null;var Kf=Gf,Qf=function(t,e){return"number"==typeof t?t={duration:t}:"string"==typeof t?t="slow"===t?{duration:600}:"fast"===t?{duration:200}:{duration:400}:t||(t={}),r({},t,e)},Yf=za,$f=function(t,e,n){this.init(t,e,n)};$f.prototype={init:hf,start:Yf,getStyle:yf,setStyle:_f,animateStyle:Kf,processParams:Qf};var Jf,Xf,Zf=$f,th=Ha;Jf=function(){var t=this.node,e=this.fragment.toString(!1);if(window&&window.appearsToBeIELessEqual8&&(t.type="text/css"),t.styleSheet)t.styleSheet.cssText=e;else{for(;t.hasChildNodes();)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(e))}},Xf=function(){this.node.type&&"text/javascript"!==this.node.type||m("Script tag was updated. This does not cause the code to be re-evaluated!",{ractive:this.root}),this.node.text=this.fragment.toString(!1)};var eh=function(){var t,e;return this.template.y?"":(t="<"+this.template.e,t+=this.attributes.map(Xa).join("")+this.conditionalAttributes.map(Xa).join(""),"option"===this.name&&$a(this)&&(t+=" selected"),"input"===this.name&&Ja(this)&&(t+=" checked"),t+=">","textarea"===this.name&&void 0!==this.getAttribute("value")?t+=Se(this.getAttribute("value")):void 0!==this.getAttribute("contenteditable")&&(t+=this.getAttribute("value")||""),this.fragment&&(e="script"!==this.name&&"style"!==this.name,t+=this.fragment.toString(e)),ic.test(this.template.e)||(t+=""),t)},nh=Za,ah=tr,rh=function(t){this.init(t)};rh.prototype={bubble:Tl,detach:Rl,find:Ml,findAll:Ll,findAllComponents:jl,findComponent:Dl,findNextNode:Nl,firstNode:Fl,getAttribute:Il,init:df,rebind:ff,render:th,toString:eh,unbind:nh,unrender:ah};var ih=rh,oh=/^\s*$/,sh=/^\s*/,ph=function(t){var e,n,a,r;return e=t.split("\n"),n=e[0],void 0!==n&&oh.test(n)&&e.shift(),a=D(e),void 0!==a&&oh.test(a)&&e.pop(),r=e.reduce(nr,null),r&&(t=e.map(function(t){return t.replace(r,"")}).join("\n")),t},uh=ar,ch=function(t,e){var n;return e?n=t.split("\n").map(function(t,n){return n?e+t:t}).join("\n"):t},lh='Could not find template for partial "%s"',dh=function(t){var e,n;e=this.parentFragment=t.parentFragment,this.root=e.root,this.type=Au,this.index=t.index,this.name=t.template.r,this.rendered=!1,this.fragment=this.fragmentToRender=this.fragmentToUnrender=null,Gc.init(this,t),this.keypath||((n=uh(this.root,this.name,e))?(_c.call(this),this.isNamed=!0,this.setTemplate(n)):g(lh,this.name))};dh.prototype={bubble:function(){this.parentFragment.bubble()},detach:function(){return this.fragment.detach()},find:function(t){return this.fragment.find(t)},findAll:function(t,e){return this.fragment.findAll(t,e)},findComponent:function(t){return this.fragment.findComponent(t)},findAllComponents:function(t,e){return this.fragment.findAllComponents(t,e)},firstNode:function(){return this.fragment.firstNode()},findNextNode:function(){return this.parentFragment.findNextNode(this)},getPartialName:function(){return this.isNamed&&this.name?this.name:void 0===this.value?this.name:this.value},getValue:function(){return this.fragment.getValue()},rebind:function(t,e){this.isNamed||qc.call(this,t,e),this.fragment&&this.fragment.rebind(t,e)},render:function(){return this.docFrag=document.createDocumentFragment(),this.update(),this.rendered=!0,this.docFrag},resolve:Gc.resolve,setValue:function(t){var e;(void 0===t||t!==this.value)&&(void 0!==t&&(e=uh(this.root,""+t,this.parentFragment)),!e&&this.name&&(e=uh(this.root,this.name,this.parentFragment))&&(_c.call(this),this.isNamed=!0),e||g(lh,this.name,{ractive:this.root}),this.value=t,this.setTemplate(e||[]),this.bubble(),this.rendered&&bs.addView(this))},setTemplate:function(t){this.fragment&&(this.fragment.unbind(),this.rendered&&(this.fragmentToUnrender=this.fragment)),this.fragment=new rg({template:t,root:this.root,owner:this,pElement:this.parentFragment.pElement}),this.fragmentToRender=this.fragment},toString:function(t){var e,n,a,r;return e=this.fragment.toString(t),n=this.parentFragment.items[this.index-1],n&&n.type===ku?(a=n.text.split("\n").pop(),(r=/^\s+$/.exec(a))?ch(e,r[0]):e):e},unbind:function(){this.isNamed||_c.call(this),this.fragment&&this.fragment.unbind()},unrender:function(t){this.rendered&&(this.fragment&&this.fragment.unrender(t),this.rendered=!1)},update:function(){var t,e;this.fragmentToUnrender&&(this.fragmentToUnrender.unrender(!0),this.fragmentToUnrender=null),this.fragmentToRender&&(this.docFrag.appendChild(this.fragmentToRender.render()),this.fragmentToRender=null),this.rendered&&(t=this.parentFragment.getNode(),e=this.parentFragment.findNextNode(this),t.insertBefore(this.docFrag,e))}};var fh,hh,mh,gh=dh,vh=pr,bh=ur,yh=new is("detach"),_h=cr,xh=lr,wh=dr,kh=fr,Sh=hr,Eh=mr,Ch=function(t,e,n,a){var r=t.root,i=t.keypath;a?r.viewmodel.smartUpdate(i,e,a):r.viewmodel.mark(i)},Ph=[],Ah=["pop","push","reverse","shift","sort","splice","unshift"];Ah.forEach(function(t){var e=function(){for(var e=arguments.length,n=Array(e),a=0;e>a;a++)n[a]=arguments[a];var r,i,o,s;for(r=bp(this,t,n),i=Array.prototype[t].apply(this,arguments),bs.start(),this._ractive.setting=!0,s=this._ractive.wrappers.length;s--;)o=this._ractive.wrappers[s],bs.addRactive(o.root),Ch(o,this,t,r);return bs.end(),this._ractive.setting=!1,i};Eo(Ph,t,{value:e})}),fh={},fh.__proto__?(hh=function(t){t.__proto__=Ph},mh=function(t){t.__proto__=Array.prototype}):(hh=function(t){var e,n;for(e=Ah.length;e--;)n=Ah[e],Eo(t,n,{value:Ph[n],configurable:!0})},mh=function(t){var e;for(e=Ah.length;e--;)delete t[Ah[e]]}),hh.unpatch=mh;var Oh,Th,Rh,Mh=hh;Oh={filter:function(t){return i(t)&&(!t._ractive||!t._ractive.setting)},wrap:function(t,e,n){return new Th(t,e,n)}},Th=function(t,e,n){this.root=t,this.value=e,this.keypath=S(n),e._ractive||(Eo(e,"_ractive",{value:{wrappers:[],instances:[],setting:!1},configurable:!0}),Mh(e)),e._ractive.instances[t._guid]||(e._ractive.instances[t._guid]=0,e._ractive.instances.push(t)),e._ractive.instances[t._guid]+=1,e._ractive.wrappers.push(this)},Th.prototype={get:function(){return this.value},teardown:function(){var t,e,n,a,r;if(t=this.value,e=t._ractive,n=e.wrappers,a=e.instances,e.setting)return!1;if(r=n.indexOf(this),-1===r)throw Error(Rh);if(n.splice(r,1),n.length){if(a[this.root._guid]-=1,!a[this.root._guid]){if(r=a.indexOf(this.root),-1===r)throw Error(Rh);a.splice(r,1)}}else delete t._ractive,Mh.unpatch(this.value)}},Rh="Something went wrong in a rather interesting way";var Lh,jh,Dh=Oh,Nh=/^\s*[0-9]+\s*$/,Fh=function(t){return Nh.test(t)?[]:{}};try{Object.defineProperty({},"test",{value:0}),Lh={filter:function(t,e,n){var a,r;return e?(e=S(e),(a=n.viewmodel.wrapped[e.parent.str])&&!a.magic?!1:(r=n.viewmodel.get(e.parent),i(r)&&/^[0-9]+$/.test(e.lastKey)?!1:r&&("object"==typeof r||"function"==typeof r))):!1},wrap:function(t,e,n){return new jh(t,e,n)}},jh=function(t,e,n){var a,r,i;return n=S(n),this.magic=!0,this.ractive=t,this.keypath=n,this.value=e,this.prop=n.lastKey,a=n.parent,this.obj=a.isRoot?t.viewmodel.data:t.viewmodel.get(a),r=this.originalDescriptor=Object.getOwnPropertyDescriptor(this.obj,this.prop),r&&r.set&&(i=r.set._ractiveWrappers)?void(-1===i.indexOf(this)&&i.push(this)):void gr(this,e,r)},jh.prototype={get:function(){return this.value},reset:function(t){return this.updating?void 0:(this.updating=!0,this.obj[this.prop]=t,bs.addRactive(this.ractive),this.ractive.viewmodel.mark(this.keypath,{keepExistingWrapper:!0}),this.updating=!1,!0)},set:function(t,e){this.updating||(this.obj[this.prop]||(this.updating=!0,this.obj[this.prop]=Fh(t),this.updating=!1),this.obj[this.prop][t]=e)},teardown:function(){var t,e,n,a,r;return this.updating?!1:(t=Object.getOwnPropertyDescriptor(this.obj,this.prop),e=t&&t.set,void(e&&(a=e._ractiveWrappers,r=a.indexOf(this),-1!==r&&a.splice(r,1),a.length||(n=this.obj[this.prop],Object.defineProperty(this.obj,this.prop,this.originalDescriptor||{writable:!0,enumerable:!0,configurable:!0}),this.obj[this.prop]=n))))}}}catch(Ao){Lh=!1}var Ih,Bh,Uh=Lh;Uh&&(Ih={filter:function(t,e,n){return Uh.filter(t,e,n)&&Dh.filter(t)},wrap:function(t,e,n){return new Bh(t,e,n)}},Bh=function(t,e,n){this.value=e,this.magic=!0,this.magicWrapper=Uh.wrap(t,e,n),this.arrayWrapper=Dh.wrap(t,e,n)},Bh.prototype={get:function(){return this.value},teardown:function(){this.arrayWrapper.teardown(),this.magicWrapper.teardown()},reset:function(t){return this.magicWrapper.reset(t)}});var Vh=Ih,qh=vr,Gh={},zh=_r,Wh=xr,Hh=Sr,Kh=Or,Qh=Tr,Yh=function(t,e){this.computation=t,this.viewmodel=t.viewmodel,this.ref=e,this.root=this.viewmodel.ractive,this.parentFragment=this.root.component&&this.root.component.parentFragment};Yh.prototype={resolve:function(t){this.computation.softDeps.push(t),this.computation.unresolvedDeps[t.str]=null,this.viewmodel.register(t,this.computation,"computed")}};var $h=Yh,Jh=function(t,e){this.key=t,this.getter=e.getter,this.setter=e.setter,this.hardDeps=e.deps||[],this.softDeps=[],this.unresolvedDeps={},this.depValues={},this._dirty=this._firstRun=!0};Jh.prototype={constructor:Jh,init:function(t){var e,n=this;this.viewmodel=t,this.bypass=!0,e=t.get(this.key),t.clearCache(this.key.str),this.bypass=!1,this.setter&&void 0!==e&&this.set(e),this.hardDeps&&this.hardDeps.forEach(function(e){return t.register(e,n,"computed")})},invalidate:function(){this._dirty=!0},get:function(){var t,e,n=this,a=!1;if(this.getting){var r="The "+this.key.str+" computation indirectly called itself. This probably indicates a bug in the computation. It is commonly caused by `array.sort(...)` - if that's the case, clone the array first with `array.slice().sort(...)`";return h(r),this.value}if(this.getting=!0,this._dirty){if(this._firstRun||!this.hardDeps.length&&!this.softDeps.length?a=!0:[this.hardDeps,this.softDeps].forEach(function(t){var e,r,i;if(!a)for(i=t.length;i--;)if(e=t[i],r=n.viewmodel.get(e),!s(r,n.depValues[e.str]))return n.depValues[e.str]=r,void(a=!0)}),a){this.viewmodel.capture();try{this.value=this.getter()}catch(i){m('Failed to compute "%s"',this.key.str),d(i.stack||i),this.value=void 0}t=this.viewmodel.release(),e=this.updateDependencies(t),e&&[this.hardDeps,this.softDeps].forEach(function(t){t.forEach(function(t){n.depValues[t.str]=n.viewmodel.get(t)})})}this._dirty=!1}return this.getting=this._firstRun=!1,this.value},set:function(t){if(this.setting)return void(this.value=t);if(!this.setter)throw Error("Computed properties without setters are read-only. (This may change in a future version of Ractive!)");this.setter(t)},updateDependencies:function(t){var e,n,a,r,i;for(n=this.softDeps,e=n.length;e--;)a=n[e],-1===t.indexOf(a)&&(r=!0,this.viewmodel.unregister(a,this,"computed"));for(e=t.length;e--;)a=t[e],-1!==n.indexOf(a)||this.hardDeps&&-1!==this.hardDeps.indexOf(a)||(r=!0,Rr(this.viewmodel,a)&&!this.unresolvedDeps[a.str]?(i=new $h(this,a.str),t.splice(e,1),this.unresolvedDeps[a.str]=i,bs.addUnresolved(i)):this.viewmodel.register(a,this,"computed"));return r&&(this.softDeps=t.slice()),r}};var Xh=Jh,Zh=Mr,tm={FAILED_LOOKUP:!0},em=Lr,nm={},am=Dr,rm=Nr,im=function(t,e){this.localKey=t,this.keypath=e.keypath,this.origin=e.origin,this.deps=[],this.unresolved=[],this.resolved=!1};im.prototype={forceResolution:function(){this.keypath=this.localKey,this.setup()},get:function(t,e){return this.resolved?this.origin.get(this.map(t),e):void 0},getValue:function(){return this.keypath?this.origin.get(this.keypath):void 0},initViewmodel:function(t){this.local=t,this.setup()},map:function(t){return void 0===typeof this.keypath?this.localKey:t.replace(this.localKey,this.keypath)},register:function(t,e,n){this.deps.push({keypath:t,dep:e,group:n}),this.resolved&&this.origin.register(this.map(t),e,n)},resolve:function(t){void 0!==this.keypath&&this.unbind(!0),this.keypath=t,this.setup()},set:function(t,e){this.resolved||this.forceResolution(),this.origin.set(this.map(t),e)},setup:function(){var t=this;void 0!==this.keypath&&(this.resolved=!0,this.deps.length&&(this.deps.forEach(function(e){var n=t.map(e.keypath);if(t.origin.register(n,e.dep,e.group),e.dep.setValue)e.dep.setValue(t.origin.get(n));else{if(!e.dep.invalidate)throw Error("An unexpected error occurred. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!");e.dep.invalidate()}}),this.origin.mark(this.keypath)))},setValue:function(t){if(!this.keypath)throw Error("Mapping does not have keypath, cannot set value. Please raise an issue at https://github.com/ractivejs/ractive/issues - thanks!");this.origin.set(this.keypath,t)},unbind:function(t){var e=this;t||delete this.local.mappings[this.localKey],this.resolved&&(this.deps.forEach(function(t){e.origin.unregister(e.map(t.keypath),t.dep,t.group)}),this.tracker&&this.origin.unregister(this.keypath,this.tracker))},unregister:function(t,e,n){var a,r;if(this.resolved){for(a=this.deps,r=a.length;r--;)if(a[r].dep===e){a.splice(r,1);break}this.origin.unregister(this.map(t),e,n)}}};var om=Fr,sm=function(t,e){var n,a,r,i;return n={},a=0,r=t.map(function(t,r){var o,s,p;s=a,p=e.length;do{if(o=e.indexOf(t,s),-1===o)return i=!0,-1;s=o+1}while(n[o]&&p>s);return o===a&&(a+=1),o!==r&&(i=!0),n[o]=!0,o})},pm=Ir,um={},cm=Vr,lm=Gr,dm=zr,fm=Wr,hm=Kr,mm={implicit:!0},gm={noCascade:!0},vm=Yr,bm=$r,ym=function(t){var e,n,a=t.adapt,r=t.data,i=t.ractive,o=t.computed,s=t.mappings;this.ractive=i,this.adaptors=a,this.onchange=t.onchange,this.cache={},this.cacheMap=So(null),this.deps={computed:So(null),"default":So(null)},this.depsMap={computed:So(null),"default":So(null)},this.patternObservers=[],this.specials=So(null),this.wrapped=So(null),this.computations=So(null),this.captureGroups=[],this.unresolvedImplicitDependencies=[],this.changes=[],this.implicitChanges={},this.noCascade={},this.data=r,this.mappings=So(null);for(e in s)this.map(S(e),s[e]);if(r)for(e in r)(n=this.mappings[e])&&void 0===n.getValue()&&n.setValue(r[e]);for(e in o)s&&e in s&&l("Cannot map to a computed property ('%s')",e),this.compute(S(e),o[e]);this.ready=!0};ym.prototype={adapt:qh,applyChanges:Hh,capture:Kh,clearCache:Qh,compute:Zh,get:em,init:am,map:rm,mark:om,merge:pm,register:cm,release:lm,reset:dm,set:fm,smartUpdate:hm,teardown:vm,unregister:bm};var _m=ym;Xr.prototype={constructor:Xr,begin:function(t){this.inProcess[t._guid]=!0},end:function(t){var e=t.parent;e&&this.inProcess[e._guid]?Zr(this.queue,e).push(t):ti(this,t),delete this.inProcess[t._guid]}};var xm=Xr,wm=ei,km=/\$\{([^\}]+)\}/g,Sm=new is("construct"),Em=new is("config"),Cm=new xm("init"),Pm=0,Am=["adaptors","components","decorators","easing","events","interpolators","partials","transitions"],Om=ii,Tm=ci;ci.prototype={bubble:function(){this.dirty||(this.dirty=!0,bs.addView(this))},update:function(){this.callback(this.fragment.getValue()),this.dirty=!1},rebind:function(t,e){this.fragment.rebind(t,e)},unbind:function(){this.fragment.unbind()}};var Rm=function(t,e,n,r,o){var s,p,u,c,l,d,f={},h={},g={},v=[];for(p=t.parentFragment,u=t.root,o=o||{},a(f,o),o.content=r||[],f[""]=o.content,e.defaults.el&&m("The <%s/> component has a default `el` property; it has been disregarded",t.name),c=p;c;){if(c.owner.type===Mu){l=c.owner.container;break}c=c.parent}return n&&Object.keys(n).forEach(function(e){var a,r,o=n[e];if("string"==typeof o)a=dc(o),h[e]=a?a.value:o;else if(0===o)h[e]=!0;else{if(!i(o))throw Error("erm wut");di(o)?(g[e]={origin:t.root.viewmodel,keypath:void 0},r=li(t,o[0],function(t){t.isSpecial?d?s.set(e,t.value):(h[e]=t.value,delete g[e]):d?s.viewmodel.mappings[e].resolve(t):g[e].keypath=t})):r=new Tm(t,o,function(t){d?s.set(e,t):h[e]=t}),v.push(r)}}),s=So(e.prototype),Om(s,{el:null,append:!0,data:h,partials:o,magic:u.magic||e.defaults.magic,modifyArrays:u.modifyArrays,adapt:u.adapt},{parent:u,component:t,container:l,mappings:g,inlinePartials:f,cssIds:p.cssIds}),d=!0,t.resolvers=v,s},Mm=fi,Lm=function(t){var e,n;for(e=t.root;e;)(n=e._liveComponentQueries["_"+t.name])&&n.push(t.instance),e=e.parent},jm=mi,Dm=gi,Nm=vi,Fm=bi,Im=yi,Bm=new is("teardown"),Um=xi,Vm=function(t,e){this.init(t,e)};Vm.prototype={detach:bh,find:_h,findAll:xh,findAllComponents:wh,findComponent:kh,findNextNode:Sh,firstNode:Eh,init:jm,rebind:Dm,render:Nm,toString:Fm,unbind:Im,unrender:Um};var qm=Vm,Gm=function(t){this.type=Ou,this.value=t.template.c};Gm.prototype={detach:vc,firstNode:function(){return this.node},render:function(){return this.node||(this.node=document.createComment(this.value)),this.node},toString:function(){return""},unrender:function(t){t&&this.node.parentNode.removeChild(this.node)}};var zm=Gm,Wm=function(t){var e,n;this.type=Mu,this.container=e=t.parentFragment.root,this.component=n=e.component,this.container=e,this.containerFragment=t.parentFragment,this.parentFragment=n.parentFragment;var a=this.name=t.template.n||"",r=e._inlinePartials[a];r||(m('Could not find template for partial "'+a+'"',{ractive:t.root}),r=[]),this.fragment=new rg({owner:this,root:e.parent,template:r,pElement:this.containerFragment.pElement}),i(n.yielders[a])?n.yielders[a].push(this):n.yielders[a]=[this],bs.scheduleTask(function(){if(n.yielders[a].length>1)throw Error("A component template can only have one {{yield"+(a?" "+a:"")+"}} declaration at a time")})};Wm.prototype={detach:function(){return this.fragment.detach()},find:function(t){return this.fragment.find(t)},findAll:function(t,e){return this.fragment.findAll(t,e)},findComponent:function(t){return this.fragment.findComponent(t)},findAllComponents:function(t,e){return this.fragment.findAllComponents(t,e)},findNextNode:function(){return this.containerFragment.findNextNode(this)},firstNode:function(){return this.fragment.firstNode()},getValue:function(t){return this.fragment.getValue(t)},render:function(){return this.fragment.render()},unbind:function(){this.fragment.unbind()},unrender:function(t){this.fragment.unrender(t),N(this.component.yielders[this.name],this)},rebind:function(t,e){this.fragment.rebind(t,e)},toString:function(){return""+this.fragment}};var Hm=Wm,Km=function(t){this.declaration=t.template.a};Km.prototype={init:ko,render:ko,unrender:ko,teardown:ko,toString:function(){return""}};var Qm=Km,Ym=wi,$m=Si,Jm=Ei,Xm=Ci,Zm=Oi,tg=Ri,eg=function(t){this.init(t)};eg.prototype={bubble:cu,detach:lu,find:du,findAll:fu,findAllComponents:hu,findComponent:mu,findNextNode:gu,firstNode:vu,getArgsList:hc,getNode:mc,getValue:gc,init:Ym,rebind:$m,registerIndexRef:function(t){var e=this.registeredIndexRefs;-1===e.indexOf(t)&&e.push(t)},render:Jm,toString:Xm,unbind:Zm,unregisterIndexRef:function(t){var e=this.registeredIndexRefs;e.splice(e.indexOf(t),1)},unrender:tg};var ng,ag,rg=eg,ig=Mi,og=["template","partials","components","decorators","events"],sg=new is("reset"),pg=function(t,e){function n(e,a,r){r&&r.partials[t]||e.forEach(function(e){e.type===Au&&e.getPartialName()===t&&a.push(e),e.fragment&&n(e.fragment.items,a,r),i(e.fragments)?n(e.fragments,a,r):i(e.items)?n(e.items,a,r):e.type===Ru&&e.instance&&n(e.instance.fragment.items,a,e.instance),e.type===Pu&&(i(e.attributes)&&n(e.attributes,a,r),i(e.conditionalAttributes)&&n(e.conditionalAttributes,a,r))})}var a,r=[];return n(this.fragment.items,r),this.partials[t]=e,a=bs.start(this,!0),r.forEach(function(e){e.value=void 0,e.setValue(t)}),bs.end(),a},ug=Li,cg=_p("reverse"),lg=ji,dg=_p("shift"),fg=_p("sort"),hg=_p("splice"),mg=Ni,gg=Fi,vg=new is("teardown"),bg=Bi,yg=Ui,_g=Vi,xg=new is("unrender"),wg=_p("unshift"),kg=qi,Sg=new is("update"),Eg=Gi,Cg={add:Zo,animate:Ss,detach:Cs,find:As,findAll:Fs,findAllComponents:Is,findComponent:Bs,findContainer:Us,findParent:Vs,fire:Ws,get:Hs,insert:Qs,merge:$s,observe:lp,observeOnce:dp,off:mp,on:gp,once:vp,pop:xp,push:wp,render:Tp,reset:ig,resetPartial:pg,resetTemplate:ug,reverse:cg,set:lg,shift:dg,sort:fg,splice:hg,subtract:mg,teardown:gg,toggle:bg,toHTML:yg,toHtml:yg,unrender:_g,unshift:wg,update:kg,updateModel:Eg},Pg=function(t,e,n){return n||Wi(t,e)?function(){var n,a="_super"in this,r=this._super;return this._super=e,n=t.apply(this,arguments),a&&(this._super=r),n}:t},Ag=Hi,Og=$i,Tg=function(t){var e,n,a={};return t&&(e=t._ractive)?(a.ractive=e.root,a.keypath=e.keypath.str,a.index={},(n=Oc(e.proxy.parentFragment))&&(a.index=Oc.resolve(n)),a):a};ng=function(t){return this instanceof ng?void Om(this,t):new ng(t)},ag={DEBUG:{writable:!0,value:!0},DEBUG_PROMISES:{writable:!0,value:!0},extend:{value:Og},getNodeInfo:{value:Tg},parse:{value:Hp},Promise:{value:us},svg:{value:ao},magic:{value:eo},VERSION:{value:"0.7.3"},adaptors:{writable:!0,value:{}},components:{writable:!0,value:{}},decorators:{writable:!0,value:{}},easing:{writable:!0,value:po},events:{writable:!0,value:{}},interpolators:{writable:!0,value:qo},partials:{writable:!0,value:{}},transitions:{writable:!0,value:{}}},Co(ng,ag),ng.prototype=a(Cg,so),ng.prototype.constructor=ng,ng.defaults=ng.prototype;var Rg="function";if(typeof Date.now!==Rg||typeof String.prototype.trim!==Rg||typeof Object.keys!==Rg||typeof Array.prototype.indexOf!==Rg||typeof Array.prototype.forEach!==Rg||typeof Array.prototype.map!==Rg||typeof Array.prototype.filter!==Rg||"undefined"!=typeof window&&typeof window.addEventListener!==Rg)throw Error("It looks like you're attempting to use Ractive.js in an older browser. You'll need to use one of the 'legacy builds' in order to continue - see http://docs.ractivejs.org/latest/legacy-builds for more information.");var Mg=ng;return Mg})},{}],342:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.observe("value",function(e,n,a){var r=t.get(),i=r.min,o=r.max,s=Math.clamp(i,o,e);t.animate("percentage",Math.round((s-i)/(o-i)*100))})}}}(r),r.exports.template={v:3,t:[" ",{p:[13,1,305],t:7,e:"div",a:{"class":"bar"},f:[{p:[14,3,326],t:7,e:"div",a:{"class":["barFill ",{t:2,r:"state",p:[14,23,346]}],style:["width: ",{t:2,r:"percentage",p:[14,48,371]},"%"]}}," ",{p:[15,3,398],t:7,e:"span",a:{"class":"barText"},f:[{t:16,p:[15,25,420]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],343:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(481),a=t(480);e.exports={computed:{clickable:function(){return!this.get("enabled")||this.get("state")&&"toggle"!=this.get("state")?!1:!0},enabled:function(){return this.get("config.status")===n.UI_INTERACTIVE?!0:!1},styles:function(){var t="";if(this.get("class")&&(t+=" "+this.get("class")),this.get("tooltip-side")&&(t=" tooltip-"+this.get("tooltip-side")),this.get("grid")&&(t+=" gridable"),this.get("enabled")){var e=this.get("state"),n=this.get("style");return e?"inactive "+e+" "+t:"active normal "+n+" "+t}return"inactive disabled "+t}},oninit:function(){var t=this;this.on("press",function(e){var n=t.get(),r=n.action,i=n.params;(0,a.act)(t.get("config.ref"),r,i),e.node.blur()})},data:{iconStackToHTML:function(t){var e="",n=t.split(",");if(n.length){e+='';for(var a=n,r=Array.isArray(a),i=0,a=r?a:a[Symbol.iterator]();;){var o;if(r){if(i>=a.length)break;o=a[i++]}else{if(i=a.next(),i.done)break;o=i.value}var s=o,p=/([\w\-]+)\s*(\dx)/g,u=p.exec(s),c=u[1],l=u[2];e+=''}}return e&&(e+=""),e}}}}(r),r.exports.template={v:3,t:[" ",{p:[70,1,2019],t:7,e:"span",a:{"class":["button ",{t:2,r:"styles",p:[70,21,2039]}],unselectable:"on","data-tooltip":[{t:2,r:"tooltip",p:[73,17,2124]}]},m:[{t:4,f:["tabindex='0'"],r:"clickable",p:[72,3,2075]}],v:{"mouseover-mousemove":"hover",mouseleave:"unhover","click-enter":{n:[{t:4,f:["press"],r:"clickable",p:[76,19,2217]}],d:[]}},f:[{t:4,f:[{p:[78,5,2265],t:7,e:"i",a:{"class":["fa fa-",{t:2,r:"icon",p:[78,21,2281]}]}}],n:50,r:"icon",p:[77,3,2247]}," ",{t:4,f:[{t:3,x:{r:["iconStackToHTML","icon_stack"],s:"_0(_1)"},p:[81,6,2335]}],n:50,r:"icon_stack",p:[80,3,2310]}," ",{t:16,p:[83,3,2383]}]}]},e.exports=a.extend(r.exports)},{341:341,480:480,481:481}],344:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"display"},f:[{t:4,f:[{p:[3,5,44],t:7,e:"header",f:[{p:[4,7,60],t:7,e:"h3",f:[{t:2,r:"title",p:[4,11,64]}]}," ",{t:4,f:[{p:[6,9,110],t:7,e:"div",a:{"class":"buttonRight"},f:[{t:16,n:"button",p:[6,34,135]}]}],n:50,r:"button",p:[5,7,86]}]}],n:50,r:"title",p:[2,3,25]}," ",{p:[10,3,202],t:7,e:"article",f:[{t:16,p:[11,5,217]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],345:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.on("clear",function(){t.set("value",""),t.find("input").focus()})}}}(r),r.exports.template={v:3,t:[" ",{p:[12,1,170],t:7,e:"input",a:{type:"text",value:[{t:2,r:"value",p:[12,27,196]}],placeholder:[{t:2,r:"placeholder",p:[12,51,220]}]}}," ",{p:[13,1,240],t:7,e:"ui-button",a:{icon:"refresh"},v:{press:"clear"}}]},e.exports=a.extend(r.exports)},{341:341}],346:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";e.exports={data:{graph:t(338),xaccessor:function(t){return t.x},yaccessor:function(t){return t.y}},computed:{size:function(){var t=this.get("points");return t[0].length},scale:function(){var t=this.get("points");return Math.max.apply(Math,Array.map(t,function(t){return Math.max.apply(Math,Array.map(t,function(t){return t.y}))}))},xaxis:function(){var t=this.get("xinc"),e=this.get("size");return Array.from(Array(e).keys()).filter(function(e){return e&&e%t==0})},yaxis:function(){var t=this.get("yinc"),e=this.get("scale");return Array.from(Array(t).keys()).map(function(t){return Math.round(e*(++t/100)*10)})}},oninit:function(){var t=this;this.on({enter:function(t){this.set("selected",t.index.count)},exit:function(t){this.set("selected")}}),window.addEventListener("resize",function(e){t.set("width",t.el.clientWidth)})},onrender:function(){this.set("width",this.el.clientWidth)}}}(r),r.exports.template={v:3,t:[" ",{p:[47,1,1269],t:7,e:"svg",a:{"class":"linegraph",width:"100%",height:[{t:2,x:{r:["height"],s:"_0+10"},p:[47,45,1313]}]},f:[{p:[48,3,1334],t:7,e:"g",a:{transform:"translate(0, 5)"},f:[{t:4,f:[{t:4,f:[{p:[51,9,1504],t:7,e:"line",a:{x1:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[51,19,1514]}],x2:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[51,38,1533]}],y1:"0",y2:[{t:2,r:"height",p:[51,64,1559]}],stroke:"darkgray"}}," ",{t:4,f:[{p:[53,11,1635],t:7,e:"text",a:{x:[{t:2,x:{r:["xscale","."],s:"_0(_1)"},p:[53,20,1644]}],y:[{t:2,x:{r:["height"],s:"_0-5"},p:[53,38,1662]}],"text-anchor":"middle",fill:"white"},f:[{t:2,x:{r:["size",".","xfactor"],s:"(_0-_1)*_2"},p:[53,88,1712]}," ",{t:2,r:"xunit",p:[53,113,1737]}]}],n:50,x:{r:["@index"],s:"_0%2==0"},p:[52,9,1600]}],n:52,r:"xaxis",p:[50,7,1479]}," ",{t:4,f:[{p:[57,9,1820],t:7,e:"line",a:{x1:"0",x2:[{t:2,r:"width",p:[57,26,1837]}],y1:[{t:2,x:{r:["yscale","."],s:"_0(_1)"},p:[57,41,1852]}],y2:[{t:2,x:{r:["yscale","."],s:"_0(_1)"},p:[57,60,1871]}],stroke:"darkgray"}}," ",{p:[58,9,1915],t:7,e:"text",a:{x:"0",y:[{t:2,x:{r:["yscale","."],s:"_0(_1)-5"},p:[58,24,1930]}],"text-anchor":"begin",fill:"white"},f:[{t:2,x:{r:[".","yfactor"],s:"_0*_1"},p:[58,76,1982]}," ",{t:2,r:"yunit",p:[58,92,1998]}]}],n:52,r:"yaxis",p:[56,7,1795]}," ",{t:4,f:[{p:[61,9,2071],t:7,e:"path",a:{d:[{t:2,x:{r:["area.path"],s:"_0.print()"},p:[61,18,2080]}],fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[61,47,2109]}],opacity:"0.1"}}],n:52,i:"curve",r:"curves",p:[60,7,2039]}," ",{t:4,f:[{p:[64,9,2200],t:7,e:"path",a:{d:[{t:2,x:{r:["line.path"],s:"_0.print()"},p:[64,18,2209]}],stroke:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[64,49,2240]}],fill:"none"}}],n:52, +i:"curve",r:"curves",p:[63,7,2168]}," ",{t:4,f:[{t:4,f:[{p:[68,11,2375],t:7,e:"circle",a:{transform:["translate(",{t:2,r:".",p:[68,40,2404]},")"],r:[{t:2,x:{r:["selected","count"],s:"_0==_1?10:4"},p:[68,51,2415]}],fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[68,89,2453]}]},v:{mouseenter:"enter",mouseleave:"exit"}}],n:52,i:"count",x:{r:["line.path"],s:"_0.points()"},p:[67,9,2329]}],n:52,i:"curve",r:"curves",p:[66,7,2297]}," ",{t:4,f:[{t:4,f:[{t:4,f:[{p:[74,13,2678],t:7,e:"text",a:{transform:["translate(",{t:2,r:".",p:[74,40,2705]},") ",{t:2,x:{r:["count","size"],s:'_0<=_1/2?"translate(15, 4)":"translate(-15, 4)"'},p:[74,47,2712]}],"text-anchor":[{t:2,x:{r:["count","size"],s:'_0<=_1/2?"start":"end"'},p:[74,126,2791]}],fill:"white"},f:[{t:2,x:{r:["count","item","yfactor"],s:"_1[_0].y*_2"},p:[75,15,2861]}," ",{t:2,r:"yunit",p:[75,43,2889]}," @ ",{t:2,x:{r:["size","count","item","xfactor"],s:"(_0-_2[_1].x)*_3"},p:[75,55,2901]}," ",{t:2,r:"xunit",p:[75,92,2938]}]}],n:50,x:{r:["selected","count"],s:"_0==_1"},p:[73,11,2638]}],n:52,i:"count",x:{r:["line.path"],s:"_0.points()"},p:[72,9,2592]}],n:52,i:"curve",r:"curves",p:[71,7,2560]}," ",{t:4,f:[{p:[81,9,3063],t:7,e:"g",a:{transform:["translate(",{t:2,x:{r:["width","curves.length","@index"],s:"(_0/(_1+1))*(_2+1)"},p:[81,33,3087]},", 10)"]},f:[{p:[82,11,3154],t:7,e:"circle",a:{r:"4",fill:[{t:2,rx:{r:"colors",m:[{t:30,n:"curve"}]},p:[82,31,3174]}]}}," ",{p:[83,11,3206],t:7,e:"text",a:{x:"8",y:"4",fill:"white"},f:[{t:2,rx:{r:"legend",m:[{t:30,n:"curve"}]},p:[83,42,3237]}]}]}],n:52,i:"curve",r:"curves",p:[80,7,3031]}],x:{r:["graph","points","xaccessor","yaccessor","width","height"],s:"_0({data:_1,xaccessor:_2,yaccessor:_3,width:_4,height:_5})"},p:[49,5,1371]}]}]}]},e.exports=a.extend(r.exports)},{338:338,341:341}],347:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"notice"},f:[{t:16,p:[2,3,24]}]}]},e.exports=a.extend(r.exports)},{341:341}],348:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(480),a=t(482);e.exports={oninit:function(){var t=this,e=a.resize.bind(this),r=function(){return t.set({resize:!1,x:null,y:null})};this.observe("config.fancy",function(a,i,o){(0,n.winset)(t.get("config.window"),"can-resize",!a),a?(document.addEventListener("mousemove",e),document.addEventListener("mouseup",r)):(document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",r))}),this.on("resize",function(){return t.toggle("resize")})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[28,3,766],t:7,e:"div",a:{"class":"resize"},v:{mousedown:"resize"}}],n:50,r:"config.fancy",p:[27,1,742]}]},e.exports=a.extend(r.exports)},{341:341,480:480,482:482}],349:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"section",a:{"class":[{t:4,f:["candystripe"],r:"candystripe",p:[1,17,16]}]},f:[{t:4,f:[{p:[3,5,84],t:7,e:"span",a:{"class":"label",style:[{t:4,f:["color:",{t:2,r:"labelcolor",p:[3,53,132]}],r:"labelcolor",p:[3,32,111]}]},f:[{t:2,r:"label",p:[3,84,163]},":"]}],n:50,r:"label",p:[2,3,65]}," ",{t:4,f:[{t:16,p:[6,5,215]}],n:50,r:"nowrap",p:[5,3,195]},{t:4,n:51,f:[{p:[8,5,242],t:7,e:"div",a:{"class":"content",style:[{t:4,f:["float:right;"],r:"right",p:[8,33,270]}]},f:[{t:16,p:[9,7,312]}]}],r:"nowrap"}]}]},e.exports=a.extend(r.exports)},{341:341}],350:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"subdisplay"},f:[{t:4,f:[{p:[3,5,47],t:7,e:"header",f:[{p:[4,7,63],t:7,e:"h4",f:[{t:2,r:"title",p:[4,11,67]}]}," ",{t:4,f:[{t:16,n:"button",p:[5,21,103]}],n:50,r:"button",p:[5,7,89]}]}],n:50,r:"title",p:[2,3,28]}," ",{p:[8,3,156],t:7,e:"article",f:[{t:16,p:[9,5,171]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],351:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={oninit:function(){var t=this;this.set("active",this.findComponent("tab").get("name")),this.on("switch",function(e){t.set("active",e.node.textContent.trim())}),this.observe("active",function(e,n,a){for(var r=t.findAllComponents("tab"),i=Array.isArray(r),o=0,r=i?r:r[Symbol.iterator]();;){var s;if(i){if(o>=r.length)break;s=r[o++]}else{if(o=r.next(),o.done)break;s=o.value}var p=s;p.set("shown",p.get("name")===e)}})}}}(r),r.exports.template={v:3,t:[" "," ",{p:[20,1,524],t:7,e:"header",f:[{t:4,f:[{p:[22,5,556],t:7,e:"ui-button",a:{pane:[{t:2,r:".",p:[22,22,573]}]},v:{press:"switch"},f:[{t:2,r:".",p:[22,47,598]}]}],n:52,r:"tabs",p:[21,3,536]}]}," ",{p:[25,1,641],t:7,e:"ui-display",f:[{t:8,r:"content",p:[26,3,657]}]}]},r.exports.components=r.exports.components||{};var i={tab:t(352)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,352:352}],352:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:16,p:[2,3,17]}],n:50,r:"shown",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],353:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(481),a=t(480),r=t(482);e.exports={computed:{visualStatus:function(){switch(this.get("config.status")){case n.UI_INTERACTIVE:return"good";case n.UI_UPDATE:return"average";case n.UI_DISABLED:return"bad";default:return"bad"}}},oninit:function(){var t=this,e=r.drag.bind(this),n=function(e){return t.set({drag:!1,x:null,y:null})};this.observe("config.fancy",function(r,i,o){(0,a.winset)(t.get("config.window"),"titlebar",!r&&t.get("config.titlebar")),r?(document.addEventListener("mousemove",e),document.addEventListener("mouseup",n)):(document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",n))}),this.on({drag:function(){this.toggle("drag")},close:function(){(0,a.winset)(this.get("config.window"),"is-visible",!1),window.location.href=(0,a.href)({command:"uiclose "+this.get("config.ref")},"winset")},minimize:function(){(0,a.winset)(this.get("config.window"),"is-minimized",!0)}})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[50,3,1440],t:7,e:"header",a:{"class":"titlebar"},v:{mousedown:"drag"},f:[{p:[51,5,1491],t:7,e:"i",a:{"class":["statusicon fa fa-eye fa-2x ",{t:2,r:"visualStatus",p:[51,42,1528]}]}}," ",{p:[52,5,1556],t:7,e:"span",a:{"class":"title"},f:[{t:16,p:[52,25,1576]}]}," ",{t:4,f:[{p:[54,7,1626],t:7,e:"i",a:{"class":"minimize fa fa-minus fa-2x"},v:{click:"minimize"}}," ",{p:[55,7,1696],t:7,e:"i",a:{"class":"close fa fa-close fa-2x"},v:{click:"close"}}],n:50,r:"config.fancy",p:[53,5,1598]}]}],n:50,r:"config.titlebar",p:[49,1,1413]}]},e.exports=a.extend(r.exports)},{341:341,480:480,481:481,482:482}],354:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";var e=[11,10,9,8];t.exports={data:{userAgent:navigator.userAgent},computed:{ie:function(){if(document.documentMode)return document.documentMode;for(var t in e){var n=document.createElement("div");if(n.innerHTML="",n.getElementsByTagName("span").length)return t}}},oninit:function(){var t=this;this.on("debug",function(){return t.toggle("debug")})}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[27,3,662],t:7,e:"ui-notice",f:[{p:[28,5,679],t:7,e:"span",f:["You have an old (IE",{t:2,r:"ie",p:[28,30,704]},"), end-of-life (click 'EOL Info' for more information) version of Internet Explorer installed."]},{p:[28,137,811],t:7,e:"br"}," ",{p:[29,5,822],t:7,e:"span",f:["To upgrade, click 'Upgrade IE' to download IE11 from Microsoft."]},{p:[29,81,898],t:7,e:"br"}," ",{p:[30,5,909],t:7,e:"span",f:["If you are unable to upgrade directly, click 'IE VMs' to download a VM with IE11 or Edge from Microsoft."]},{p:[30,122,1026],t:7,e:"br"}," ",{p:[31,5,1037],t:7,e:"span",f:["Otherwise, click 'No Frills' below to disable potentially incompatible features (and this message)."]}," ",{p:[32,5,1155],t:7,e:"hr"}," ",{p:[33,5,1166],t:7,e:"ui-button",a:{icon:"close",action:"tgui:nofrills"},f:["No Frills"]}," ",{p:[34,5,1240],t:7,e:"ui-button",a:{icon:"internet-explorer",action:"tgui:link",params:'{"url": "http://windows.microsoft.com/en-us/internet-explorer/download-ie"}'},f:["Upgrade IE"]}," ",{p:[36,5,1416],t:7,e:"ui-button",a:{icon:"edge",action:"tgui:link",params:'{"url": "https://dev.windows.com/en-us/microsoft-edge/tools/vms"}'},f:["IE VMs"]}," ",{p:[38,5,1565],t:7,e:"ui-button",a:{icon:"info",action:"tgui:link",params:'{"url": "https://support.microsoft.com/en-us/lifecycle#gp/Microsoft-Internet-Explorer"}'},f:["EOL Info"]}," ",{p:[40,5,1738],t:7,e:"ui-button",a:{icon:"bug"},v:{press:"debug"},f:["Debug Info"]}," ",{t:4,f:[{p:[42,7,1826],t:7,e:"hr"}," ",{p:[43,7,1839],t:7,e:"span",f:["Detected: IE",{t:2,r:"ie",p:[43,25,1857]}]},{p:[43,38,1870],t:7,e:"br"}," ",{p:[44,7,1883],t:7,e:"span",f:["User Agent: ",{t:2,r:"userAgent",p:[44,25,1901]}]}],n:50,r:"debug",p:[41,5,1805]}]}],n:50,x:{r:["config.fancy","ie"],s:"_0&&_1&&_1<11"},p:[26,1,621]}]},e.exports=a.extend(r.exports)},{341:341}],355:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},shockState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[22,1,348],t:7,e:"ui-display",a:{title:"Power Status"},f:[{p:[23,2,384],t:7,e:"ui-section",a:{label:"Main"},f:[{p:[24,3,413],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.power.main"],s:"_0(_1)"},p:[24,16,426]}]},f:[{t:2,x:{r:["data.power.main"],s:'_0?"Online":"Offline"'},p:[24,49,459]}]}," ",{t:4,f:["[ ",{p:[26,6,567],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.main_1","data.wires.main_2"],s:"!_0||!_1"},p:[25,3,512]},{t:4,n:51,f:[{t:4,f:["[ ",{t:2,r:"data.power.main_timeleft",p:[29,7,674]}," seconds left ]"],n:50,x:{r:["data.power.main_timeleft"],s:"_0>0"},p:[28,4,630]}],x:{r:["data.wires.main_1","data.wires.main_2"],s:"!_0||!_1"}}," ",{p:[32,3,744],t:7,e:"div",a:{style:"float:right"},f:[{p:[33,4,774],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"disrupt-main",state:[{t:2,x:{r:["data.power.main"],s:'_0?null:"disabled"'},p:[33,63,833]}]},f:["Disrupt"]}]}]}," ",{p:[36,2,922],t:7,e:"ui-section",a:{label:"Backup"},f:[{p:[37,3,953],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.power.backup"],s:"_0(_1)"},p:[37,16,966]}]},f:[{t:2,x:{r:["data.power.backup"],s:'_0?"Online":"Offline"'},p:[37,51,1001]}]}," ",{t:4,f:["[ ",{p:[39,6,1115],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.backup_1","data.wires.backup_2"],s:"!_0||!_1"},p:[38,3,1056]},{t:4,n:51,f:[{t:4,f:["[ ",{t:2,r:"data.power.backup_timeleft",p:[42,7,1224]}," seconds left ]"],n:50,x:{r:["data.power.backup_timeleft"],s:"_0>0"},p:[41,4,1178]}],x:{r:["data.wires.backup_1","data.wires.backup_2"],s:"!_0||!_1"}}," ",{p:[45,3,1296],t:7,e:"div",a:{style:"float:right"},f:[{p:[46,4,1326],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"disrupt-backup",state:[{t:2,x:{r:["data.power.backup"],s:'_0?null:"disabled"'},p:[46,65,1387]}]},f:["Disrupt"]}]}]}," ",{p:[49,2,1478],t:7,e:"ui-section",a:{label:"Electrify"},f:[{p:[50,3,1512],t:7,e:"span",a:{"class":[{t:2,x:{r:["shockState","data.shock"],s:"_0(_1)"},p:[50,16,1525]}]},f:[{t:2,x:{r:["data.shock"],s:'_0==2?"Safe":"Electrified"'},p:[50,44,1553]}]}," ",{t:4,f:["[ ",{p:[52,6,1640],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.shock"],s:"!_0"},p:[51,3,1608]},{t:4,n:51,f:[{t:4,f:["[ ",{p:[55,7,1742],t:7,e:"span",a:{"class":"bad"},f:[{t:2,r:"data.shock_timeleft",p:[55,25,1760]}," seconds left"]}," ]"],n:50,x:{r:["data.shock_timeleft"],s:"_0>0"},p:[54,4,1703]}," ",{t:4,f:["[ ",{p:[58,7,1863],t:7,e:"span",a:{"class":"bad"},f:["Permanent"]}," ]"],n:50,x:{r:["data.shock_timeleft"],s:"_0==-1"},p:[57,4,1822]}],x:{r:["data.wires.shock"],s:"!_0"}}," ",{p:[61,3,1926],t:7,e:"div",a:{style:"float:right"},f:[{p:[62,4,1956],t:7,e:"ui-button",a:{icon:"wrench",action:"shock-restore",state:[{t:2,x:{r:["data.wires.shock","data.shock"],s:'_0&&_1==0?null:"disabled"'},p:[62,59,2011]}]},f:["Restore"]}," ",{p:[63,4,2094],t:7,e:"ui-button",a:{icon:"bolt",action:"shock-temp",state:[{t:2,x:{r:["data.wires.shock"],s:"!_0"},p:[63,54,2144]}]},f:["Set (Temporary)"]}," ",{p:[64,4,2199],t:7,e:"ui-button",a:{icon:"bolt",action:"shock-perm",state:[{t:2,x:{r:["data.wires.shock"],s:"!_0"},p:[64,53,2248]}]},f:["Set (Permanent)"]}]}]}]}," ",{p:[68,1,2341],t:7,e:"ui-display",a:{title:"Access & Door Control"},f:[{p:[69,2,2386],t:7,e:"ui-section",a:{label:"ID Scan"},f:[{t:4,f:["[ ",{p:[71,6,2455],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[70,3,2418]}," ",{p:[73,3,2516],t:7,e:"div",a:{style:"float:right"},f:[{p:[74,4,2546],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[74,22,2564]}],icon:"power-off",action:"idscan-on",style:[{t:2,x:{r:["data.id_scanner"],s:'_0?"selected":""'},p:[74,93,2635]}]},f:["Enabled"]}," ",{p:[75,4,2698],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.id_scanner"],s:"!_0"},p:[75,22,2716]}],icon:"close",action:"idscan-off",style:[{t:2,x:{r:["data.id_scanner"],s:'_0?"":"selected"'},p:[75,90,2784]}]},f:["Disabled"]}]}]}," ",{p:[78,2,2872],t:7,e:"ui-section",a:{label:"Emergency Access"},f:[{p:[79,3,2913],t:7,e:"div",a:{style:"float:right"},f:[{p:[80,4,2943],t:7,e:"ui-button",a:{icon:"power-off",action:"emergency-on",style:[{t:2,x:{r:["data.emergency"],s:'_0?"selected":""'},p:[80,61,3e3]}]},f:["Enabled"]}," ",{p:[81,4,3062],t:7,e:"ui-button",a:{icon:"close",action:"emergency-off",style:[{t:2,x:{r:["data.emergency"],s:'_0?"":"selected"'},p:[81,58,3116]}]},f:["Disabled"]}]}]}," ",{p:[84,2,3203],t:7,e:"br"}," ",{p:[85,2,3212],t:7,e:"ui-section",a:{label:"Door bolts"},f:[{t:4,f:["[ ",{p:[87,6,3279],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.bolts"],s:"!_0"},p:[86,3,3247]}," ",{p:[89,3,3340],t:7,e:"div",a:{style:"float:right"},f:[{p:[90,4,3370],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.bolts"],s:"!_0"},p:[90,22,3388]}],icon:"unlock",action:"bolt-raise",style:[{t:2,x:{r:["data.locked"],s:'_0?"":"selected"'},p:[90,85,3451]}]},f:["Raised"]}," ",{p:[91,4,3509],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.bolts"],s:"!_0"},p:[91,22,3527]}],icon:"lock",action:"bolt-drop",style:[{t:2,x:{r:["data.locked"],s:'_0?"selected":""'},p:[91,82,3587]}]},f:["Dropped"]}]}]}," ",{p:[94,2,3670],t:7,e:"ui-section",a:{label:"Door bolt lights"},f:[{t:4,f:["[ ",{p:[96,6,3744],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.lights"],s:"!_0"},p:[95,3,3711]}," ",{p:[98,3,3805],t:7,e:"div",a:{style:"float:right"},f:[{p:[99,4,3835],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.lights"],s:"!_0"},p:[99,22,3853]}],icon:"power-off",action:"light-on",style:[{t:2,x:{r:["data.lights"],s:'_0?"selected":""'},p:[99,88,3919]}]},f:["Enabled"]}," ",{p:[100,4,3978],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.lights"],s:"!_0"},p:[100,22,3996]}],icon:"close",action:"light-off",style:[{t:2,x:{r:["data.lights"],s:'_0?"":"selected"'},p:[100,85,4059]}]},f:["Disabled"]}]}]}," ",{p:[103,2,4143],t:7,e:"ui-section",a:{label:"Door force sensors"},f:[{t:4,f:["[ ",{p:[105,6,4217],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.safe"],s:"!_0"},p:[104,3,4186]}," ",{p:[107,3,4278],t:7,e:"div",a:{style:"float:right"},f:[{p:[108,4,4308],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.safe"],s:"!_0"},p:[108,22,4326]}],icon:"power-off",action:"safe-on",style:[{t:2,x:{r:["data.safe"],s:'_0?"selected":""'},p:[108,85,4389]}]},f:["Enabled"]}," ",{p:[109,4,4446],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.safe"],s:"!_0"},p:[109,22,4464]}],icon:"close",action:"safe-off",style:[{t:2,x:{r:["data.safe"],s:'_0?"":"selected"'},p:[109,82,4524]}]},f:["Disabled"]}]}]}," ",{p:[112,2,4606],t:7,e:"ui-section",a:{label:"Door timing safety"},f:[{t:4,f:["[ ",{p:[114,6,4682],t:7,e:"span",a:{"class":"bad"},f:["Wires have been cut"]}," ]"],n:50,x:{r:["data.wires.timing"],s:"!_0"},p:[113,3,4649]}," ",{p:[116,3,4743],t:7,e:"div",a:{style:"float:right"},f:[{p:[117,4,4773],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.timing"],s:"!_0"},p:[117,22,4791]}],icon:"power-off",action:"speed-on",style:[{t:2,x:{r:["data.speed"],s:'_0?"selected":""'},p:[117,88,4857]}]},f:["Enabled"]}," ",{p:[118,4,4915],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.wires.timing"],s:"!_0"},p:[118,22,4933]}],icon:"close",action:"speed-off",style:[{t:2,x:{r:["data.speed"],s:'_0?"":"selected"'},p:[118,85,4996]}]},f:["Disabled"]}]}]}," ",{p:[121,2,5079],t:7,e:"br"}," ",{p:[122,2,5088],t:7,e:"ui-section",a:{label:"Door control"},f:[{t:4,f:["[ ",{p:[124,6,5166],t:7,e:"span",a:{"class":"bad"},f:["Door is ",{t:2,x:{r:["data.locked","data.welded"],s:'(_0?"bolted":"")+(_0&&_1?" and ":"")+(_1?"welded":"")'},p:[124,32,5192]}]}," ]"],n:50,x:{r:["data.locked","data.welded"],s:"_0||_1"},p:[123,3,5125]}," ",{p:[126,3,5327],t:7,e:"div",a:{style:"float:right"},f:[{p:[127,4,5357],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.locked","data.welded","data.opened"],s:'(_0||_1)||(_2&&"disabled")'},p:[127,22,5375]}],icon:"sign-out",action:"open-close"},f:["Open door"]}," ",{p:[128,4,5502],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.locked","data.welded","data.opened"],s:'(_0||_1)||(!_2&&"disabled")'},p:[128,22,5520]}],icon:"sign-in",action:"open-close"},f:["Close door"]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],356:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," "," "," ",{p:[7,1,267],t:7,e:"ui-notice",f:[{t:4,f:[{p:[9,5,312],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[10,7,355],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[10,24,372]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[10,75,423]}]}]}],n:50,r:"data.siliconUser",p:[8,3,282]},{t:4,n:51,f:[{p:[13,5,514],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[13,31,540]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[16,1,625],t:7,e:"status"}," ",{t:4,f:[{t:4,f:[{p:[19,7,719],t:7,e:"ui-display",a:{title:"Air Controls"},f:[{p:[20,9,762],t:7,e:"ui-section",f:[{p:[21,11,786],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"exclamation-triangle":"exclamation"'},p:[21,28,803]}],style:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"caution":null'},p:[21,98,873]}],action:[{t:2,x:{r:["data.atmos_alarm"],s:'_0?"reset":"alarm"'},p:[22,23,937]}]},f:["Area Atmosphere Alarm"]}]}," ",{p:[24,9,1045],t:7,e:"ui-section",f:[{p:[25,11,1069],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0==3?"exclamation-triangle":"exclamation"'},p:[25,28,1086]}],style:[{t:2,x:{r:["data.mode"],s:'_0==3?"danger":null'},p:[25,96,1154]}],action:"mode",params:['{"mode": ',{t:2,x:{r:["data.mode"],s:"_0==3?1:3"},p:[26,44,1236]},"}"]},f:["Panic Siphon"]}]}," ",{p:[28,9,1322],t:7,e:"br"}," ",{p:[29,9,1337],t:7,e:"ui-section",f:[{p:[30,11,1361],t:7,e:"ui-button",a:{icon:"sign-out",action:"tgui:view",params:'{"screen": "vents"}'},f:["Vent Controls"]}]}," ",{p:[32,9,1494],t:7,e:"ui-section",f:[{p:[33,11,1518],t:7,e:"ui-button",a:{icon:"filter",action:"tgui:view",params:'{"screen": "scrubbers"}'},f:["Scrubber Controls"]}]}," ",{p:[35,9,1657],t:7,e:"ui-section",f:[{p:[36,11,1681],t:7,e:"ui-button",a:{icon:"cog",action:"tgui:view",params:'{"screen": "modes"}'},f:["Operating Mode"]}]}," ",{p:[38,9,1810],t:7,e:"ui-section",f:[{p:[39,11,1834],t:7,e:"ui-button",a:{icon:"bar-chart",action:"tgui:view",params:'{"screen": "thresholds"}'},f:["Alarm Thresholds"]}]}]}],n:50,x:{r:["config.screen"],s:'_0=="home"'},p:[18,3,680]},{t:4,n:51,f:[{t:4,n:50,x:{r:["config.screen"],s:'_0=="vents"'},f:[{p:[43,5,2032],t:7,e:"vents"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&(_0=="scrubbers")'},f:[" ",{p:[45,5,2089],t:7,e:"scrubbers"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&((!(_0=="scrubbers"))&&(_0=="modes"))'},f:[" ",{p:[47,5,2146],t:7,e:"modes"}]},{t:4,n:50,x:{r:["config.screen"],s:'(!(_0=="vents"))&&((!(_0=="scrubbers"))&&((!(_0=="modes"))&&(_0=="thresholds")))'},f:[" ",{p:[49,5,2204],t:7,e:"thresholds"}]}],x:{r:["config.screen"],s:'_0=="home"'}}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[17,1,636]}]},r.exports.components=r.exports.components||{};var i={vents:t(362),modes:t(358),thresholds:t(361),status:t(360),scrubbers:t(359)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,358:358,359:359,360:360,361:361,362:362}],357:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-button",a:{icon:"arrow-left",action:"tgui:view",params:'{"screen": "home"}'},f:["Back"]}]},e.exports=a.extend(r.exports)},{341:341}],358:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,115],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Operating Modes",button:0},f:[" ",{t:4,f:[{p:[8,5,168],t:7,e:"ui-section",f:[{p:[9,7,188],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["selected"],s:'_0?"check-square-o":"square-o"'},p:[9,24,205]}],state:[{t:2,x:{r:["selected","danger"],s:'_0?_1?"danger":"selected":null'},p:[10,16,267]}],action:"mode",params:['{"mode": ',{t:2,r:"mode",p:[11,40,361]},"}"]},f:[{t:2,r:"name",p:[11,51,372]}]}]}],n:52,r:"data.modes",p:[7,3,142]}]}]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],359:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," ",{p:{button:[{p:[6,5,185],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Scrubber Controls",button:0},f:[" ",{t:4,f:[{p:[9,5,242],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"long_name",p:[9,27,264]}]},f:[{p:[10,7,287],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[11,9,323],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["power"],s:'_0?"power-off":"close"'},p:[11,26,340]}],style:[{t:2,x:{r:["power"],s:'_0?"selected":null'},p:[11,68,382]}],action:"power",params:['{"id_tag": "',{t:2,r:"id_tag",p:[12,46,459]},'", "val": ',{t:2,x:{r:["power"],s:"+!_0"},p:[12,66,479]},"}"]},f:[{t:2,x:{r:["power"],s:'_0?"On":"Off"'},p:[12,80,493]}]}]}," ",{p:[14,7,558],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[15,9,593],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["scrubbing"],s:'_0?"filter":"sign-in"'},p:[15,26,610]}],style:[{t:2,x:{r:["scrubbing"],s:'_0?null:"danger"'},p:[15,71,655]}],action:"scrubbing",params:['{"id_tag": "',{t:2,r:"id_tag",p:[16,50,738]},'", "val": ',{t:2,x:{r:["scrubbing"],s:"+!_0"},p:[16,70,758]},"}"]},f:[{t:2,x:{r:["scrubbing"],s:'_0?"Scrubbing":"Siphoning"'},p:[16,88,776]}]}]}," ",{p:[18,7,858],t:7,e:"ui-section",a:{label:"Range"},f:[{p:[19,9,894],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["widenet"],s:'_0?"expand":"compress"'},p:[19,26,911]}],style:[{t:2,x:{r:["widenet"],s:'_0?"selected":null'},p:[19,70,955]}],action:"widenet",params:['{"id_tag": "',{t:2,r:"id_tag",p:[20,48,1036]},'", "val": ',{t:2,x:{r:["widenet"],s:"+!_0"},p:[20,68,1056]},"}"]},f:[{t:2,x:{r:["widenet"],s:'_0?"Expanded":"Normal"'},p:[20,84,1072]}]}]}," ",{p:[22,7,1148],t:7,e:"ui-section",a:{label:"Filters"},f:[{p:[23,9,1186],t:7,e:"filters"}]}]}],n:52,r:"data.scrubbers",p:[8,3,212]},{t:4,n:51,f:[{p:[27,5,1257],t:7,e:"span",a:{"class":"bad"},f:["Error: No scrubbers connected."]}],r:"data.scrubbers"}]}]},r.exports.components=r.exports.components||{};var i={filters:t(456),back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357,456:456}],360:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Air Status"},f:[{t:4,f:[{t:4,f:[{p:[4,7,110],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[4,26,129]}]},f:[{p:[5,6,146],t:7,e:"span",a:{"class":[{t:2,x:{r:["danger_level"],s:'_0==2?"bad":_0==1?"average":"good"'},p:[5,19,159]}]},f:[{t:2,x:{r:["value"],s:"Math.fixed(_0,2)"},p:[6,5,237]},{t:2,r:"unit",p:[6,29,261]}]}]}],n:52,r:"adata.environment_data",p:[3,5,70]}," ",{p:[10,5,322],t:7,e:"ui-section",a:{label:"Local Status"},f:[{p:[11,7,363],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.danger_level"],s:'_0==2?"bad bold":_0==1?"average bold":"good"'},p:[11,20,376]}]},f:[{t:2,x:{r:["data.danger_level"],s:'_0==2?"Danger (Internals Required)":_0==1?"Caution":"Optimal"'},p:[12,6,475]}]}]}," ",{p:[15,5,619],t:7,e:"ui-section",a:{label:"Area Status"},f:[{p:[16,7,659],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.atmos_alarm","data.fire_alarm"],s:'_0||_1?"bad bold":"good"'},p:[16,20,672]}]},f:[{t:2,x:{r:["data.atmos_alarm","fire_alarm"],s:'_0?"Atmosphere Alarm":_1?"Fire Alarm":"Nominal"'},p:[17,8,744]}]}]}],n:50,r:"data.environment_data",p:[2,3,35]},{t:4,n:51,f:[{p:[21,5,876],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[22,7,912],t:7,e:"span",a:{"class":"bad bold"},f:["Cannot obtain air sample for analysis."]}]}],r:"data.environment_data"}," ",{t:4,f:[{p:[26,5,1040],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[27,7,1076],t:7,e:"span",a:{"class":"bad bold"},f:["Safety measures offline. Device may exhibit abnormal behavior."]}]}],n:50,r:"data.emagged",p:[25,3,1014]}]}]},e.exports=a.extend(r.exports)},{341:341}],361:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.css=" th, td {\r\n padding-right: 16px;\r\n text-align: left;\r\n }",r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,116],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Alarm Thresholds",button:0},f:[" ",{p:[7,3,143],t:7,e:"table",f:[{p:[8,5,156],t:7,e:"thead",f:[{p:[8,12,163],t:7,e:"tr",f:[{p:[9,7,175],t:7,e:"th"}," ",{p:[10,7,192],t:7,e:"th",f:[{p:[10,11,196],t:7,e:"span",a:{"class":"bad"},f:["min2"]}]}," ",{p:[11,7,238],t:7,e:"th",f:[{p:[11,11,242],t:7,e:"span",a:{"class":"average"},f:["min1"]}]}," ",{p:[12,7,288],t:7,e:"th",f:[{p:[12,11,292],t:7,e:"span",a:{"class":"average"},f:["max1"]}]}," ",{p:[13,7,338],t:7,e:"th",f:[{p:[13,11,342],t:7,e:"span",a:{"class":"bad"},f:["max2"]}]}]}]}," ",{p:[15,5,401],t:7,e:"tbody",f:[{t:4,f:[{p:[16,32,441],t:7,e:"tr",f:[{p:[17,9,455],t:7,e:"th",f:[{t:3,r:"name",p:[17,13,459]}]}," ",{t:4,f:[{p:[18,27,502],t:7,e:"td",f:[{p:[19,11,518],t:7,e:"ui-button",a:{action:"threshold",params:['{"env": "',{t:2,r:"env",p:[19,58,565]},'", "var": "',{t:2,r:"val",p:[19,76,583]},'"}']},f:[{t:2,x:{r:["selected"],s:"Math.fixed(_0,2)"},p:[19,87,594]}]}]}],n:52,r:"settings",p:[18,9,484]}]}],n:52,r:"data.thresholds",p:[16,7,416]}]}," ",{p:[23,3,697],t:7,e:"table",f:[]}]}]}," "]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],362:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:{button:[{p:[5,5,113],t:7,e:"back"}]},t:7,e:"ui-display",a:{title:"Vent Controls",button:0},f:[" ",{t:4,f:[{p:[8,5,166],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"long_name",p:[8,27,188]}]},f:[{p:[9,7,211],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[10,9,247],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["power"],s:'_0?"power-off":"close"'},p:[10,26,264]}],style:[{t:2,x:{r:["power"],s:'_0?"selected":null'},p:[10,68,306]}],action:"power",params:['{"id_tag": "',{t:2,r:"id_tag",p:[11,46,383]},'", "val": ',{t:2,x:{r:["power"],s:"+!_0"},p:[11,66,403]},"}"]},f:[{t:2,x:{r:["power"],s:'_0?"On":"Off"'},p:[11,80,417]}]}]}," ",{p:[13,7,482],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[14,9,517],t:7,e:"span",f:[{t:2,x:{r:["direction"],s:'_0=="release"?"Pressurizing":"Siphoning"'},p:[14,15,523]}]}]}," ",{p:[16,7,616],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[17,9,665],t:7,e:"ui-button",a:{icon:"sign-in",style:[{t:2,x:{r:["incheck"],s:'_0?"selected":null'},p:[17,42,698]}],action:"incheck",params:['{"id_tag": "',{t:2,r:"id_tag",p:[18,48,779]},'", "val": ',{t:2,r:"checks",p:[18,68,799]},"}"]},f:["Internal"]}," ",{p:[19,9,842],t:7,e:"ui-button",a:{icon:"sign-out",style:[{t:2,x:{r:["excheck"],s:'_0?"selected":null'},p:[19,43,876]}],action:"excheck",params:['{"id_tag": "',{t:2,r:"id_tag",p:[20,48,957]},'", "val": ',{t:2,r:"checks",p:[20,68,977]},"}"]},f:["External"]}]}," ",{t:4,f:[{p:[23,9,1064],t:7,e:"ui-section",a:{label:"Internal Target Pressure"},f:[{p:[24,11,1121],t:7,e:"ui-button",a:{icon:"pencil",action:"set_internal_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[25,33,1210]},'"}']},f:[{t:2,x:{r:["internal"],s:"Math.fixed(_0)"},p:[25,47,1224]}]}," ",{p:[26,11,1272],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["intdefault"],s:'_0?"disabled":null'},p:[26,44,1305]}],action:"reset_internal_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[27,33,1407]},'"}']},f:["Reset"]}]}],n:50,r:"incheck",p:[22,7,1039]}," ",{t:4,f:[{p:[31,11,1511],t:7,e:"ui-section",a:{label:"External Target Pressure"},f:[{p:[32,13,1570],t:7,e:"ui-button",a:{icon:"pencil",action:"set_external_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[33,35,1661]},'"}']},f:[{t:2,x:{r:["external"],s:"Math.fixed(_0)"},p:[33,49,1675]}]}," ",{p:[34,13,1725],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["extdefault"],s:'_0?"disabled":null'},p:[34,46,1758]}],action:"reset_external_pressure",params:['{"id_tag": "',{t:2,r:"id_tag",p:[35,35,1862]},'"}']},f:["Reset"]}]}],n:50,r:"excheck",p:[30,7,1484]}]}],n:52,r:"data.vents",p:[7,3,140]},{t:4,n:51,f:[{p:[40,5,1973],t:7,e:"span",a:{"class":"bad"},f:["Error: No vents connected."]}],r:"data.vents"}]}]},r.exports.components=r.exports.components||{};var i={back:t(357)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,357:357}],363:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.css=" table {\r\n width: 100%;\r\n border-spacing: 2px;\r\n }\r\n th {\r\n text-align: left;\r\n }\r\n td {\r\n vertical-align: top;\r\n }\r\n td .button {\r\n margin-top: 4px\r\n }",r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",f:[{p:[3,5,34],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.oneAccess"],s:'_0?"unlock":"lock"'},p:[3,22,51]}],action:"one_access"},f:[{t:2,x:{r:["data.oneAccess"],s:'_0?"One":"All"'},p:[3,82,111]}," Required"]}," ",{p:[4,5,172],t:7,e:"ui-button",a:{icon:"refresh",action:"clear"},f:["Clear"]}]}," ",{p:[6,3,251],t:7,e:"hr"}," ",{p:[7,3,260],t:7,e:"table",f:[{p:[8,3,271],t:7,e:"thead",f:[{p:[9,4,283],t:7,e:"tr",f:[{t:4,f:[{p:[10,5,315],t:7,e:"th",f:[{p:[10,9,319],t:7,e:"span",a:{"class":"highlight bold"},f:[{t:2,r:"name",p:[10,38,348]}]}]}],n:52,r:"data.regions",p:[9,8,287]}]}]}," ",{p:[13,3,403],t:7,e:"tbody",f:[{p:[14,4,415],t:7,e:"tr",f:[{t:4,f:[{p:[15,5,447],t:7,e:"td",f:[{t:4,f:[{p:[16,11,481],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["req"],s:'_0?"check-square-o":"square-o"'},p:[16,28,498]}],style:[{t:2,x:{r:["req"],s:'_0?"selected":null'},p:[16,76,546]}],action:"set",params:['{"access": "',{t:2,r:"id",p:[17,46,621]},'"}']},f:[{t:2,r:"name",p:[17,56,631]}]}," ",{p:[18,9,661],t:7,e:"br"}],n:52,r:"accesses",p:[15,9,451]}]}],n:52,r:"data.regions",p:[14,8,419]}]}]}]}," ",{p:[23,2,731],t:7,e:"hr"}," ",{p:[24,2,739],t:7,e:"span",a:{"class":"highlight bold"},f:["Unrestricted Access:"]}," ",{p:[25,2,798],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&1?"check-square-o":"square-o"'},p:[25,19,815]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&1?"selected":null'},p:[25,88,884]}],action:"direc_set",params:'{"unres_direction": "1"}'},f:["North"]}," ",{p:[26,2,1007],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&4?"check-square-o":"square-o"'},p:[26,19,1024]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&4?"selected":null'},p:[26,88,1093]}],action:"direc_set",params:'{"unres_direction": "4"}'},f:["East"]}," ",{p:[27,2,1215],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&2?"check-square-o":"square-o"'},p:[27,19,1232]}],style:[{t:2,x:{r:["data.unres_direction"], +s:'_0&2?"selected":null'},p:[27,88,1301]}],action:"direc_set",params:'{"unres_direction": "2"}'},f:["South"]}," ",{p:[28,2,1424],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.unres_direction"],s:'_0&8?"check-square-o":"square-o"'},p:[28,19,1441]}],style:[{t:2,x:{r:["data.unres_direction"],s:'_0&8?"selected":null'},p:[28,88,1510]}],action:"direc_set",params:'{"unres_direction": "8"}'},f:["West"]}]}," "]},e.exports=a.extend(r.exports)},{341:341}],364:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}}},computed:{malfAction:function(){switch(this.get("data.malfStatus")){case 1:return"hack";case 2:return"occupy";case 3:return"deoccupy"}},malfButton:function(){switch(this.get("data.malfStatus")){case 1:return"Override Programming";case 2:case 4:return"Shunt Core Process";case 3:return"Return to Main Core"}},malfIcon:function(){switch(this.get("data.malfStatus")){case 1:return"terminal";case 2:case 4:return"caret-square-o-down";case 3:return"caret-square-o-left"}},powerCellStatusState:function(){var t=this.get("data.powerCellStatus");return t>50?"good":t>25?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[46,2,1206],t:7,e:"ui-notice",f:[{p:[47,3,1221],t:7,e:"b",f:[{p:[47,6,1224],t:7,e:"h3",f:["SYSTEM FAILURE"]}]}," ",{p:[48,3,1255],t:7,e:"i",f:["I/O regulators malfunction detected! Waiting for system reboot..."]},{p:[48,75,1327],t:7,e:"br"}," Automatic reboot in ",{t:2,r:"data.failTime",p:[49,23,1355]}," seconds... ",{p:[50,3,1387],t:7,e:"ui-button",a:{icon:"refresh",action:"reboot"},f:["Reboot Now"]},{p:[50,67,1451],t:7,e:"br"},{p:[50,71,1455],t:7,e:"br"},{p:[50,75,1459],t:7,e:"br"}]}],n:50,r:"data.failTime",p:[45,1,1182]},{t:4,n:51,f:[{p:[53,2,1491],t:7,e:"ui-notice",f:[{t:4,f:[{p:[55,3,1535],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[56,5,1576],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[56,22,1593]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[56,73,1644]}]}]}],n:50,r:"data.siliconUser",p:[54,4,1507]},{t:4,n:51,f:[{p:[59,3,1732],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[59,29,1758]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[62,2,1846],t:7,e:"ui-display",a:{title:"Power Status"},f:[{p:[63,4,1884],t:7,e:"ui-section",a:{label:"Main Breaker"},f:[{t:4,f:[{p:[65,5,1967],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.isOperating"],s:'_0?"good":"bad"'},p:[65,18,1980]}]},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[65,57,2019]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[64,3,1921]},{t:4,n:51,f:[{p:[67,5,2079],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOperating"],s:'_0?"power-off":"close"'},p:[67,22,2096]}],style:[{t:2,x:{r:["data.isOperating"],s:'_0?"selected":null'},p:[67,75,2149]}],action:"breaker"},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[68,21,2212]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}," ",{p:[71,4,2293],t:7,e:"ui-section",a:{label:"External Power"},f:[{p:[72,3,2332],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.externalPower"],s:"_0(_1)"},p:[72,16,2345]}]},f:[{t:2,x:{r:["data.externalPower"],s:'_0==2?"Good":_0==1?"Low":"None"'},p:[72,52,2381]}]}]}," ",{p:[74,4,2490],t:7,e:"ui-section",a:{label:"Power Cell"},f:[{t:4,f:[{p:[76,5,2567],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.powerCellStatus",p:[76,38,2600]}],state:[{t:2,r:"powerCellStatusState",p:[76,71,2633]}]},f:[{t:2,x:{r:["adata.powerCellStatus"],s:"Math.fixed(_0)"},p:[76,97,2659]},"%"]}],n:50,x:{r:["data.powerCellStatus"],s:"_0!=null"},p:[75,3,2525]},{t:4,n:51,f:[{p:[78,5,2724],t:7,e:"span",a:{"class":"bad"},f:["Removed"]}],x:{r:["data.powerCellStatus"],s:"_0!=null"}}]}," ",{t:4,f:[{p:[82,3,2830],t:7,e:"ui-section",a:{label:"Charge Mode"},f:[{t:4,f:[{p:[84,4,2913],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.chargeMode"],s:'_0?"good":"bad"'},p:[84,17,2926]}]},f:[{t:2,x:{r:["data.chargeMode"],s:'_0?"Auto":"Off"'},p:[84,55,2964]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[83,5,2868]},{t:4,n:51,f:[{p:[86,4,3026],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.chargeMode"],s:'_0?"refresh":"close"'},p:[86,21,3043]}],style:[{t:2,x:{r:["data.chargeMode"],s:'_0?"selected":null'},p:[86,71,3093]}],action:"charge"},f:[{t:2,x:{r:["data.chargeMode"],s:'_0?"Auto":"Off"'},p:[87,22,3156]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}," [",{p:[90,6,3236],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.chargingStatus"],s:"_0(_1)"},p:[90,19,3249]}]},f:[{t:2,x:{r:["data.chargingStatus"],s:'_0==2?"Fully Charged":_0==1?"Charging":"Not Charging"'},p:[90,56,3286]}]},"]"]}],n:50,x:{r:["data.powerCellStatus"],s:"_0!=null"},p:[81,4,2790]}]}," ",{p:[94,2,3445],t:7,e:"ui-display",a:{title:"Power Channels"},f:[{t:4,f:[{p:[96,3,3517],t:7,e:"ui-section",a:{label:[{t:2,r:"title",p:[96,22,3536]}],nowrap:0},f:[{p:[97,5,3560],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.powerChannels",m:[{t:30,n:"@index"},"powerLoad"]},p:[97,26,3581]}]}," ",{p:[98,5,3634],t:7,e:"div",a:{"class":"content"},f:[{p:[98,26,3655],t:7,e:"span",a:{"class":[{t:2,x:{r:["status"],s:'_0>=2?"good":"bad"'},p:[98,39,3668]}]},f:[{t:2,x:{r:["status"],s:'_0>=2?"On":"Off"'},p:[98,73,3702]}]}]}," ",{p:[99,5,3751],t:7,e:"div",a:{"class":"content"},f:["[",{p:[99,27,3773],t:7,e:"span",f:[{t:2,x:{r:["status"],s:'_0==1||_0==3?"Auto":"Manual"'},p:[99,33,3779]}]},"]"]}," ",{p:[100,5,3849],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{t:4,f:[{p:[102,6,3942],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["status"],s:'_0==1||_0==3?"selected":null'},p:[102,39,3975]}],action:"channel",params:[{t:2,r:"topicParams.auto",p:[103,30,4057]}]},f:["Auto"]}," ",{p:[104,6,4102],t:7,e:"ui-button",a:{icon:"power-off",state:[{t:2,x:{r:["status"],s:'_0==2?"selected":null'},p:[104,41,4137]}],action:"channel",params:[{t:2,r:"topicParams.on",p:[105,13,4204]}]},f:["On"]}," ",{p:[106,6,4245],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["status"],s:'_0==0?"selected":null'},p:[106,37,4276]}],action:"channel",params:[{t:2,r:"topicParams.off",p:[107,13,4343]}]},f:["Off"]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[101,4,3895]}]}]}],n:52,r:"data.powerChannels",p:[95,4,3485]}," ",{p:[112,4,4439],t:7,e:"ui-section",a:{label:"Total Load"},f:[{p:[113,3,4474],t:7,e:"span",a:{"class":"bold"},f:[{t:2,r:"adata.totalLoad",p:[113,22,4493]}]}]}]}," ",{t:4,f:[{p:[117,4,4585],t:7,e:"ui-display",a:{title:"System Overrides"},f:[{p:[118,3,4626],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"overload"},f:["Overload"]}," ",{t:4,f:[{p:[120,5,4727],t:7,e:"ui-button",a:{icon:[{t:2,r:"malfIcon",p:[120,22,4744]}],state:[{t:2,x:{r:["data.malfStatus"],s:'_0==4?"disabled":null'},p:[120,43,4765]}],action:[{t:2,r:"malfAction",p:[120,97,4819]}]},f:[{t:2,r:"malfButton",p:[120,113,4835]}]}],n:50,r:"data.malfStatus",p:[119,3,4698]}]}],n:50,r:"data.siliconUser",p:[116,2,4556]}," ",{p:[124,2,4903],t:7,e:"ui-notice",f:[{p:[125,4,4919],t:7,e:"ui-section",a:{label:"Emergency Light Fallback"},f:[{t:4,f:[{p:[127,8,5020],t:7,e:"span",f:[{t:2,x:{r:["data.emergencyLights"],s:'_0?"Enabled":"Disabled"'},p:[127,14,5026]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[126,6,4971]},{t:4,n:51,f:[{p:[129,8,5106],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"emergency_lighting"},f:[{t:2,x:{r:["data.emergencyLights"],s:'_0?"Enabled":"Disabled"'},p:[129,66,5164]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}]}," ",{p:[133,2,5275],t:7,e:"ui-notice",f:[{p:[134,4,5291],t:7,e:"ui-section",a:{label:"Night Shift Lighting"},f:[{t:4,f:[{p:[136,8,5412],t:7,e:"span",f:[{t:2,x:{r:["data.nightshiftLights"],s:'_0?"Enabled":"Disabled"'},p:[136,14,5418]}]}],n:50,x:{r:["data.locked","data.siliconUser","data.lock_nightshift"],s:"_0&&!_1&&_2"},p:[135,6,5339]},{t:4,n:51,f:[{p:[138,8,5499],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"toggle_nightshift"},f:[{t:2,x:{r:["data.nightshiftLights"],s:'_0?"Enabled":"Disabled"'},p:[138,65,5556]}]}],x:{r:["data.locked","data.siliconUser","data.lock_nightshift"],s:"_0&&!_1&&_2"}}]}]}," ",{p:[142,2,5668],t:7,e:"ui-notice",f:[{p:[143,4,5684],t:7,e:"ui-section",a:{label:"Cover Lock"},f:[{t:4,f:[{p:[145,5,5765],t:7,e:"span",f:[{t:2,x:{r:["data.coverLocked"],s:'_0?"Engaged":"Disengaged"'},p:[145,11,5771]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"},p:[144,3,5719]},{t:4,n:51,f:[{p:[147,5,5843],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.coverLocked"],s:'_0?"lock":"unlock"'},p:[147,22,5860]}],action:"cover"},f:[{t:2,x:{r:["data.coverLocked"],s:'_0?"Engaged":"Disengaged"'},p:[147,79,5917]}]}],x:{r:["data.locked","data.siliconUser"],s:"_0&&!_1"}}]}]}],r:"data.failTime"}]},e.exports=a.extend(r.exports)},{341:341}],365:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Alarms"},f:[{p:[2,3,31],t:7,e:"ul",f:[{t:4,f:[{p:[4,7,72],t:7,e:"li",f:[{p:[4,11,76],t:7,e:"ui-button",a:{icon:"close",style:"danger",action:"clear",params:['{"zone": "',{t:2,r:".",p:[4,83,148]},'"}']},f:[{t:2,r:".",p:[4,92,157]}]}]}],n:52,r:"data.priority",p:[3,5,41]},{t:4,n:51,f:[{p:[6,7,201],t:7,e:"li",f:[{p:[6,11,205],t:7,e:"span",a:{"class":"good"},f:["No Priority Alerts"]}]}],r:"data.priority"}," ",{t:4,f:[{p:[9,7,303],t:7,e:"li",f:[{p:[9,11,307],t:7,e:"ui-button",a:{icon:"close",style:"caution",action:"clear",params:['{"zone": "',{t:2,r:".",p:[9,84,380]},'"}']},f:[{t:2,r:".",p:[9,93,389]}]}]}],n:52,r:"data.minor",p:[8,5,275]},{t:4,n:51,f:[{p:[11,7,433],t:7,e:"li",f:[{p:[11,11,437],t:7,e:"span",a:{"class":"good"},f:["No Minor Alerts"]}]}],r:"data.minor"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],366:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:[{t:2,x:{r:["data.tank","data.sensors.0.long_name"],s:"_0?_1:null"},p:[1,20,19]}]},f:[{t:4,f:[{p:[3,5,102],t:7,e:"ui-subdisplay",a:{title:[{t:2,x:{r:["data.tank","long_name"],s:"!_0?_1:null"},p:[3,27,124]}]},f:[{p:[4,7,167],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[5,3,200],t:7,e:"span",f:[{t:2,x:{r:["pressure"],s:"Math.fixed(_0,2)"},p:[5,9,206]}," kPa"]}]}," ",{t:4,f:[{p:[8,9,302],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[9,11,346],t:7,e:"span",f:[{t:2,x:{r:["temperature"],s:"Math.fixed(_0,2)"},p:[9,17,352]}," K"]}]}],n:50,r:"temperature",p:[7,7,273]}," ",{t:4,f:[{p:[13,9,462],t:7,e:"ui-section",a:{label:[{t:2,r:"id",p:[13,28,481]}]},f:[{p:[14,5,495],t:7,e:"span",f:[{t:2,x:{r:["."],s:"Math.fixed(_0,2)"},p:[14,11,501]},"%"]}]}],n:52,i:"id",r:"gases",p:[12,4,434]}]}],n:52,r:"adata.sensors",p:[2,3,73]}]}," ",{t:4,f:[{p:{button:[{p:[23,5,704],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}]},t:7,e:"ui-display",a:{title:"Controls",button:0},f:[" ",{p:[25,5,792],t:7,e:"ui-section",a:{label:"Input Injector"},f:[{p:[26,7,835],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.inputting"],s:'_0?"power-off":"close"'},p:[26,24,852]}],style:[{t:2,x:{r:["data.inputting"],s:'_0?"selected":null'},p:[26,75,903]}],action:"input"},f:[{t:2,x:{r:["data.inputting"],s:'_0?"Injecting":"Off"'},p:[27,9,968]}]}]}," ",{p:[29,5,1044],t:7,e:"ui-section",a:{label:"Input Rate"},f:[{p:[30,7,1083],t:7,e:"span",f:[{t:2,x:{r:["adata.inputRate"],s:"Math.fixed(_0)"},p:[30,13,1089]}," L/s"]}]}," ",{p:[32,5,1156],t:7,e:"ui-section",a:{label:"Output Regulator"},f:[{p:[33,7,1201],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.outputting"],s:'_0?"power-off":"close"'},p:[33,24,1218]}],style:[{t:2,x:{r:["data.outputting"],s:'_0?"selected":null'},p:[33,76,1270]}],action:"output"},f:[{t:2,x:{r:["data.outputting"],s:'_0?"Open":"Closed"'},p:[34,9,1337]}]}]}," ",{p:[36,5,1412],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[37,7,1456],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure"},f:[{t:2,x:{r:["adata.outputPressure"],s:"Math.round(_0)"},p:[37,50,1499]}," kPa"]}]}]}],n:50,r:"data.tank",p:[20,1,618]}]},e.exports=a.extend(r.exports)},{341:341}],367:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,48],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,65]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,109]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,164]}]}]}," ",{p:[6,3,223],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{p:[7,5,263],t:7,e:"ui-button",a:{icon:"pencil",action:"rate",params:'{"rate": "input"}'},f:["Set"]}," ",{p:[8,5,350],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.rate","data.max_rate"],s:'_0==_1?"disabled":null'},p:[8,35,380]}],action:"rate",params:'{"rate": "max"}'},f:["Max"]}," ",{p:[9,5,492],t:7,e:"span",f:[{t:2,x:{r:["adata.rate"],s:"Math.round(_0)"},p:[9,11,498]}," L/s"]}]}," ",{p:[11,3,556],t:7,e:"ui-section",a:{label:"Filter"},f:[{t:4,f:[{p:[13,7,624],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[13,25,642]}],action:"filter",params:['{"mode": ',{t:2,r:"id",p:[14,42,718]},"}"]},f:[{t:2,r:"name",p:[14,51,727]}]}],n:52,r:"data.filter_types",p:[12,5,589]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],368:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,48],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,65]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,109]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,164]}]}]}," ",{p:[6,3,223],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[7,5,265],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[8,5,360],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.set_pressure","data.max_pressure"],s:'_0==_1?"disabled":null'},p:[8,35,390]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}," ",{p:[9,5,522],t:7,e:"span",f:[{t:2,x:{r:["adata.set_pressure"],s:"Math.round(_0)"},p:[9,11,528]}," kPa"]}]}," ",{p:[11,3,594],t:7,e:"ui-section",a:{label:"Node 1"},f:[{p:[12,5,627],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==0?"disabled":null'},p:[12,44,666]}],action:"node1",params:'{"concentration": -0.1}'}}," ",{p:[14,5,783],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==0?"disabled":null'},p:[14,39,817]}],action:"node1",params:'{"concentration": -0.01}'}}," ",{p:[16,5,935],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==100?"disabled":null'},p:[16,38,968]}],action:"node1",params:'{"concentration": 0.01}'}}," ",{p:[18,5,1087],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.node1_concentration"],s:'_0==100?"disabled":null'},p:[18,43,1125]}],action:"node1",params:'{"concentration": 0.1}'}}," ",{p:[20,5,1243],t:7,e:"span",f:[{t:2,x:{r:["adata.node1_concentration"],s:"Math.round(_0)"},p:[20,11,1249]},"%"]}]}," ",{p:[22,3,1319],t:7,e:"ui-section",a:{label:"Node 2"},f:[{p:[23,5,1352],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==0?"disabled":null'},p:[23,44,1391]}],action:"node2",params:'{"concentration": -0.1}'}}," ",{p:[25,5,1508],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==0?"disabled":null'},p:[25,39,1542]}],action:"node2",params:'{"concentration": -0.01}'}}," ",{p:[27,5,1660],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==100?"disabled":null'},p:[27,38,1693]}],action:"node2",params:'{"concentration": 0.01}'}}," ",{p:[29,5,1812],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.node2_concentration"],s:'_0==100?"disabled":null'},p:[29,43,1850]}],action:"node2",params:'{"concentration": 0.1}'}}," ",{p:[31,5,1968],t:7,e:"span",f:[{t:2,x:{r:["adata.node2_concentration"],s:"Math.round(_0)"},p:[31,11,1974]},"%"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],369:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,48],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[3,22,65]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[3,66,109]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[4,22,164]}]}]}," ",{t:4,f:[{p:[7,5,250],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{p:[8,7,292],t:7,e:"ui-button",a:{icon:"pencil",action:"rate",params:'{"rate": "input"}'},f:["Set"]}," ",{p:[9,7,381],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.rate","data.max_rate"],s:'_0==_1?"disabled":null'},p:[9,37,411]}],action:"rate",params:'{"rate": "max"}'},f:["Max"]}," ",{p:[10,7,525],t:7,e:"span",f:[{t:2,x:{r:["adata.rate"],s:"Math.round(_0)"},p:[10,13,531]}," L/s"]}]}],n:50,r:"data.max_rate",p:[6,3,223]},{t:4,n:51,f:[{p:[13,5,605],t:7,e:"ui-section",a:{label:"Output Pressure"},f:[{p:[14,7,649],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[15,7,746],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.pressure","data.max_pressure"],s:'_0==_1?"disabled":null'},p:[15,37,776]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}," ",{p:[16,7,906],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[16,13,912]}," kPa"]}]}],r:"data.max_rate"}]}]},e.exports=a.extend(r.exports)},{341:341}],370:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,3,72],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:["Rename"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"data.borg.name",p:[1,20,19]}],button:0},f:[" ",{p:[5,2,149],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[6,4,181],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.emagged"],s:'_0?"check-square-o":"square-o"'},p:[6,21,198]}],style:[{t:2,x:{r:["data.borg.emagged"],s:'_0?"selected":null'},p:[6,83,260]}],action:"toggle_emagged"},f:["Emagged"]}," ",{p:[7,4,351],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.lockdown"],s:'_0?"check-square-o":"square-o"'},p:[7,21,368]}],style:[{t:2,x:{r:["data.borg.lockdown"],s:'_0?"selected":null'},p:[7,84,431]}],action:"toggle_lockdown"},f:["Locked down"]}," ",{p:[8,4,528],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.scrambledcodes"],s:'_0?"check-square-o":"square-o"'},p:[8,21,545]}],style:[{t:2,x:{r:["data.borg.scrambledcodes"],s:'_0?"selected":null'},p:[8,90,614]}],action:"toggle_scrambledcodes"},f:["Scrambled codes"]}]}," ",{p:[10,2,741],t:7,e:"ui-section",a:{label:"Charge"},f:[{t:4,f:[{p:[12,4,803],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.cell.maxcharge",p:[12,25,824]}],value:[{t:2,r:"data.cell.charge",p:[12,57,856]}]},f:[{t:2,x:{r:["data.cell.charge"],s:"Math.round(_0)"},p:[12,79,878]}," / ",{t:2,x:{r:["data.cell.maxcharge"],s:"Math.round(_0)"},p:[12,114,913]}]}],n:50,x:{r:["data.cell.missing"],s:"!_0"},p:[11,3,772]},{t:4,n:51,f:[{p:[14,4,974],t:7,e:"span",a:{"class":"warning"},f:["Cell missing"]},{p:[14,45,1015],t:7,e:"br"}],x:{r:["data.cell.missing"],s:"!_0"}}," ",{p:[16,3,1035],t:7,e:"ui-button",a:{icon:"pencil",action:"set_charge"},f:["Set"]},{p:[16,63,1095],t:7,e:"ui-button",a:{icon:"eject",action:"change_cell"},f:["Change"]},{p:[16,126,1158],t:7,e:"ui-button",a:{icon:"trash","class":"bad",action:"remove_cell"},f:["Remove"]}]}," ",{p:[18,2,1252],t:7,e:"ui-section",a:{label:"Radio channels"},f:[{t:4,f:[{p:[20,4,1319],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["installed"],s:'_0?"check-square-o":"square-o"'},p:[20,21,1336]}],style:[{t:2,x:{r:["installed"],s:'_0?"selected":null'},p:[20,75,1390]}],action:"toggle_radio",params:['{"channel": "',{t:2,r:"name",p:[20,154,1469]},'"}']},f:[{t:2,r:"name",p:[20,166,1481]}]}],n:52,r:"data.channels",p:[19,3,1291]}]}," ",{p:[23,2,1533],t:7,e:"ui-section",a:{label:"Module"},f:[{t:4,f:[{p:[25,4,1591],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.active_module","type"],s:'_0==_1?"check-square-o":"square-o"'},p:[25,21,1608]}],style:[{t:2,x:{r:["data.borg.active_module","type"],s:'_0==_1?"selected":null'},p:[25,97,1684]}],action:"setmodule",params:['{"module": "',{t:2,r:"type",p:[25,193,1780]},'"}']},f:[{t:2,r:"name",p:[25,205,1792]}]}],n:52,r:"data.modules",p:[24,3,1564]}]}," ",{p:[28,2,1844],t:7,e:"ui-section",a:{label:"Upgrades"},f:[{t:4,f:[{p:[30,4,1905],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["installed"],s:'_0?"check-square-o":"square-o"'},p:[30,21,1922]}],style:[{t:2,x:{r:["installed"],s:'_0?"selected":null'},p:[30,75,1976]}],action:"toggle_upgrade",params:['{"upgrade": "',{t:2,r:"type",p:[30,155,2056]},'"}']},f:[{t:2,r:"name",p:[30,167,2068]}]}],n:52,r:"data.upgrades",p:[29,3,1877]}]}," ",{p:[33,2,2120],t:7,e:"ui-section",a:{label:"Master AI"},f:[{t:4,f:[{p:[35,4,2177],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["connected"],s:'_0?"check-square-o":"square-o"'},p:[35,21,2194]}],style:[{t:2,x:{r:["connected"],s:'_0?"selected":null'},p:[35,75,2248]}],action:"slavetoai",params:['{"slavetoai": "',{t:2,r:"ref",p:[35,152,2325]},'"}']},f:[{t:2,r:"name",p:[35,163,2336]}]}],n:52,r:"data.ais",p:[34,3,2154]}]}]}," ",{p:{button:[{p:[41,3,2460],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.borg.lawupdate"],s:'_0?"check-square-o":"square-o"'},p:[41,20,2477]}],style:[{t:2,x:{r:["data.borg.lawupdate"],s:'_0?"selected":null'},p:[41,84,2541]}],action:"toggle_lawupdate"},f:["Lawsync"]}]},t:7,e:"ui-display",a:{title:"Laws",button:0},f:[" ",{t:4,f:[{p:[44,3,2672],t:7,e:"p",f:[{t:2,r:".",p:[44,6,2675]}]}],n:52,r:"data.laws",p:[43,2,2649]}]}]},e.exports=a.extend(r.exports)},{341:341}],371:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,5,67],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"selected":null'},p:[3,38,100]}],action:[{t:2,x:{r:["data.timing"],s:'_0?"stop":"start"'},p:[3,83,145]}]},f:[{t:2,x:{r:["data.timing"],s:'_0?"Stop":"Start"'},p:[3,119,181]}]}," ",{p:[4,5,233],t:7,e:"ui-button",a:{icon:"lightbulb-o",action:"flash",style:[{t:2,x:{r:["data.flash_charging"],s:'_0?"disabled":null'},p:[4,57,285]}]},f:[{t:2,x:{r:["data.flash_charging"],s:'_0?"Recharging":"Flash"'},p:[4,102,330]}]}]},t:7,e:"ui-display",a:{title:"Cell Timer",button:0},f:[" ",{p:[6,3,410],t:7,e:"ui-section",f:[{p:[7,5,428],t:7,e:"ui-button",a:{icon:"fast-backward",action:"time",params:'{"adjust": -600}'}}," ",{p:[8,5,518],t:7,e:"ui-button",a:{icon:"backward",action:"time",params:'{"adjust": -100}'}}," ",{p:[9,5,603],t:7,e:"span",f:[{t:2,x:{r:["text","data.minutes"],s:"_0.zeroPad(_1,2)"},p:[9,11,609]},":",{t:2,x:{r:["text","data.seconds"],s:"_0.zeroPad(_1,2)"},p:[9,45,643]}]}," ",{p:[10,5,689],t:7,e:"ui-button",a:{icon:"forward",action:"time",params:'{"adjust": 100}'}}," ",{p:[11,5,772],t:7,e:"ui-button",a:{icon:"fast-forward",action:"time",params:'{"adjust": 600}'}}]}," ",{p:[13,3,875],t:7,e:"ui-section",f:[{p:[14,7,895],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "short"}'},f:["Short"]}," ",{p:[15,7,999],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "medium"}'},f:["Medium"]}," ",{p:[16,7,1105],t:7,e:"ui-button",a:{icon:"hourglass-start",action:"preset",params:'{"preset": "long"}'},f:["Long"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],372:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,23],t:7,e:"ui-notice",f:[{t:2,r:"data.notice",p:[3,5,40]}]}],n:50,r:"data.notice",p:[1,1,0]},{p:[6,1,82],t:7,e:"ui-display",a:{title:"Bluespace Artillery Control",button:0},f:[{t:4,f:[{p:[8,3,167],t:7,e:"ui-section",a:{label:"Target"},f:[{p:[9,5,200],t:7,e:"ui-button",a:{icon:"crosshairs",action:"recalibrate"},f:[{t:2,r:"data.target",p:[9,55,250]}]}]}," ",{p:[11,3,298],t:7,e:"ui-section",a:{label:"Controls"},f:[{t:4,f:[{p:[13,3,356],t:7,e:"ui-notice",f:[{p:[14,4,372],t:7,e:"span",f:["Bluespace Artillery firing protocols must be globally unlocked from two keycard authentication devices first!"]}]}],n:50,x:{r:["data.unlocked"],s:"!_0"},p:[12,2,330]},{t:4,n:51,f:[{p:[17,3,525],t:7,e:"ui-button",a:{icon:"warning",state:[{t:2,x:{r:["data.ready"],s:'_0?null:"disabled"'},p:[17,36,558]}],action:"fire"},f:["FIRE!"]}],x:{r:["data.unlocked"],s:"!_0"}}]}],n:50,r:"data.connected",p:[7,3,141]}," ",{t:4,f:[{p:[22,3,694],t:7,e:"ui-section",a:{label:"Maintenance"},f:[{p:[23,7,734],t:7,e:"ui-button",a:{icon:"wrench",action:"build"},f:["Complete Deployment."]}]}],n:50,x:{r:["data.connected"],s:"!_0"},p:[21,3,667]}]}]},e.exports=a.extend(r.exports)},{341:341}],373:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,15],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.hasHoldingTank"],s:'_0?"is":"is not"'},p:[2,23,35]}," connected to a tank."]}]}," ",{p:{button:[{p:[6,5,185],t:7,e:"ui-button",a:{icon:"pencil",action:"relabel"},f:["Relabel"]}]},t:7,e:"ui-display",a:{title:"Canister",button:0},f:[" ",{p:[8,3,266],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[9,5,301],t:7,e:"span",f:[{t:2,x:{r:["adata.tankPressure"],s:"Math.round(_0)"},p:[9,11,307]}," kPa"]}]}," ",{p:[11,3,373],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[12,5,404],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.portConnected"],s:'_0?"good":"average"'},p:[12,18,417]}]},f:[{t:2,x:{r:["data.portConnected"],s:'_0?"Connected":"Not Connected"'},p:[12,63,462]}]}]}," ",{t:4,f:[{p:[15,3,573],t:7,e:"ui-section",a:{label:"Access"},f:[{p:[16,7,608],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.restricted"],s:'_0?"lock":"unlock"'},p:[16,24,625]}],style:[{t:2,x:{r:[],s:'"caution"'},p:[17,14,680]}],action:"restricted"},f:[{t:2,x:{r:["data.restricted"],s:'_0?"Restricted to Engineering":"Public"'},p:[18,27,722]}]}]}],n:50,r:"data.isPrototype",p:[14,3,544]}]}," ",{p:[22,1,839],t:7,e:"ui-display",a:{title:"Valve"},f:[{p:[23,3,869],t:7,e:"ui-section",a:{label:"Release Pressure"},f:[{p:[24,5,912],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.minReleasePressure",p:[24,18,925]}],max:[{t:2,r:"data.maxReleasePressure",p:[24,52,959]}],value:[{t:2,r:"data.releasePressure",p:[25,14,1002]}]},f:[{t:2,x:{r:["adata.releasePressure"],s:"Math.round(_0)"},p:[25,40,1028]}," kPa"]}]}," ",{p:[27,3,1099],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[28,5,1144],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.releasePressure","data.defaultReleasePressure"],s:'_0!=_1?null:"disabled"'},p:[28,38,1177]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[30,5,1333],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.releasePressure","data.minReleasePressure"],s:'_0>_1?null:"disabled"'},p:[30,36,1364]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[32,5,1511],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[33,5,1606],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.releasePressure","data.maxReleasePressure"],s:'_0<_1?null:"disabled"'},p:[33,35,1636]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}," ",{p:[36,3,1798],t:7,e:"ui-section",a:{label:"Valve"},f:[{p:[37,5,1830],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.valveOpen"],s:'_0?"unlock":"lock"'},p:[37,22,1847]}],style:[{t:2,x:{r:["data.valveOpen","data.hasHoldingTank"],s:'_0?_1?"caution":"danger":null'},p:[38,14,1901]}],action:"valve"},f:[{t:2,x:{r:["data.valveOpen"],s:'_0?"Open":"Closed"'},p:[39,22,1995]}]}]}]}," ",{t:4,f:[{p:[42,1,2090],t:7,e:"ui-display",a:{title:"Valve Toggle Timer"},f:[{t:4,f:[{p:[44,5,2155],t:7,e:"ui-section",a:{label:"Adjust Timer"},f:[{p:[45,7,2196],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.timer_is_not_default"],s:'_0?null:"disabled"'},p:[45,40,2229]}],action:"timer",params:'{"change": "reset"}'},f:["Reset"]}," ",{p:[47,7,2358],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.timer_is_not_min"],s:'_0?null:"disabled"'},p:[47,38,2389]}],action:"timer",params:'{"change": "decrease"}'},f:["Decrease"]}," ",{p:[49,7,2520],t:7,e:"ui-button",a:{icon:"pencil",state:[{t:2,x:{r:[],s:'"disabled"'},p:[49,39,2552]}],action:"timer",params:'{"change": "input"}'},f:["Set"]}," ",{p:[51,7,2637],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.timer_is_not_max"],s:'_0?null:"disabled"'},p:[51,37,2667]}],action:"timer",params:'{"change": "increase"}'},f:["Increase"]}]}],n:51,r:"data.timing",p:[43,3,2133]}," ",{p:[55,3,2833],t:7,e:"ui-section",a:{label:"Timer"},f:[{p:[56,6,2866],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"danger":"caution"'},p:[56,39,2899]}],action:"toggle_timer"},f:[{t:2,x:{r:["data.timing"],s:'_0?"On":"Off"'},p:[57,30,2969]}]}," ",{p:[59,2,3017],t:7,e:"ui-section",a:{label:"Time until Valve Toggle"},f:[{p:[60,2,3064],t:7,e:"span",f:[{t:2,x:{r:["data.timing","data.time_left","data.timer_set"],s:"_0?_1:_2"},p:[60,8,3070]}]}]}]}]}],n:50,r:"data.isPrototype",p:[41,1,2062]},{p:{button:[{t:4,f:[{p:[69,7,3277],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.valveOpen"],s:'_0?"danger":null'},p:[69,38,3308]}],action:"eject"},f:["Eject"]}],n:50,r:"data.hasHoldingTank",p:[68,5,3242]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[73,3,3442],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holdingTank.name",p:[74,4,3473]}]}," ",{p:[76,3,3519],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holdingTank.tankPressure"],s:"Math.round(_0)"},p:[77,4,3553]}," kPa"]}],n:50,r:"data.hasHoldingTank",p:[72,3,3411]},{t:4,n:51,f:[{p:[80,3,3635],t:7,e:"ui-section",f:[{p:[81,4,3652],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.hasHoldingTank"}]}]},e.exports=a.extend(r.exports)},{341:341}],374:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tabs:function(){return Object.keys(this.get("data.supplies"))}}}}(r),r.exports.template={v:3,t:[" ",{p:[11,1,158],t:7,e:"ui-display",a:{title:"Cargo"},f:[{p:[12,3,188],t:7,e:"ui-section",a:{label:"Shuttle"},f:[{t:4,f:[{p:[14,7,270],t:7,e:"ui-button",a:{action:"send"},f:[{t:2,r:"data.location",p:[14,32,295]}]}],n:50,x:{r:["data.docked","data.requestonly"],s:"_0&&!_1"},p:[13,5,222]},{t:4,n:51,f:[{p:[16,7,346],t:7,e:"span",f:[{t:2,r:"data.location",p:[16,13,352]}]}],x:{r:["data.docked","data.requestonly"],s:"_0&&!_1"}}]}," ",{p:[19,3,410],t:7,e:"ui-section",a:{label:"Credits"},f:[{p:[20,5,444],t:7,e:"span",f:[{t:2,x:{r:["adata.points"],s:"Math.floor(_0)"},p:[20,11,450]}]}]}," ",{p:[22,3,506],t:7,e:"ui-section",a:{label:"CentCom Message"},f:[{p:[23,7,550],t:7,e:"span",f:[{t:2,r:"data.message",p:[23,13,556]}]}]}," ",{t:4,f:[{p:[26,5,644],t:7,e:"ui-section",a:{label:"Loan"},f:[{t:4,f:[{p:[28,9,716],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.away","data.docked"],s:'_0&&_1?null:"disabled"'},p:[29,17,744]}],action:"loan"},f:["Loan Shuttle"]}],n:50,x:{r:["data.loan_dispatched"],s:"!_0"},p:[27,7,677]},{t:4,n:51,f:[{p:[32,9,868],t:7,e:"span",a:{"class":"bad"},f:["Loaned to CentCom"]}],x:{r:["data.loan_dispatched"],s:"!_0"}}]}],n:50,x:{r:["data.loan","data.requestonly"],s:"_0&&!_1"},p:[25,3,600]}]}," ",{t:4,f:[{p:{button:[{p:[40,7,1066],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.cart.length"],s:'_0?null:"disabled"'},p:[40,38,1097]}],action:"clear"},f:["Clear"]}]},t:7,e:"ui-display",a:{title:"Cart",button:0},f:[" ",{t:4,f:[{p:[43,7,1222],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[44,9,1263],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[44,31,1285]}]}," ",{p:[45,9,1307],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"object",p:[45,30,1328]}]}," ",{p:[46,9,1354],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"cost",p:[46,30,1375]}," Credits"]}," ",{p:[47,9,1407],t:7,e:"div",a:{"class":"content"},f:[{p:[48,11,1440],t:7,e:"ui-button",a:{icon:"minus", +action:"remove",params:['{"id": "',{t:2,r:"id",p:[48,67,1496]},'"}']}}]}]}],n:52,r:"data.cart",p:[42,5,1195]},{t:4,n:51,f:[{p:[52,7,1566],t:7,e:"span",f:["Nothing in Cart"]}],r:"data.cart"}]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[37,1,972]},{p:{button:[{t:4,f:[{p:[59,7,1735],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.requests.length"],s:'_0?null:"disabled"'},p:[59,38,1766]}],action:"denyall"},f:["Clear"]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[58,5,1702]}]},t:7,e:"ui-display",a:{title:"Requests",button:0},f:[" ",{t:4,f:[{p:[63,5,1908],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[64,7,1947],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[64,29,1969]}]}," ",{p:[65,7,1989],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"object",p:[65,28,2010]}]}," ",{p:[66,7,2034],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"cost",p:[66,28,2055]}," Credits"]}," ",{p:[67,7,2085],t:7,e:"div",a:{"class":"content"},f:["By ",{t:2,r:"orderer",p:[67,31,2109]}]}," ",{p:[68,7,2134],t:7,e:"div",a:{"class":"content"},f:["Comment: ",{t:2,r:"reason",p:[68,37,2164]}]}," ",{t:4,f:[{p:[70,9,2223],t:7,e:"div",a:{"class":"content"},f:[{p:[71,11,2256],t:7,e:"ui-button",a:{icon:"check",action:"approve",params:['{"id": "',{t:2,r:"id",p:[71,68,2313]},'"}']}}," ",{p:[72,11,2336],t:7,e:"ui-button",a:{icon:"close",action:"deny",params:['{"id": "',{t:2,r:"id",p:[72,65,2390]},'"}']}}]}],n:50,x:{r:["data.requestonly"],s:"!_0"},p:[69,7,2188]}]}],n:52,r:"data.requests",p:[62,3,1879]},{t:4,n:51,f:[{p:[77,7,2473],t:7,e:"span",f:["No Requests"]}],r:"data.requests"}]}," ",{p:[80,1,2529],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"tabs",p:[80,16,2544]}]},f:[{t:4,f:[{p:[82,5,2587],t:7,e:"tab",a:{name:[{t:2,r:"name",p:[82,16,2598]}]},f:[{t:4,f:[{p:[84,9,2641],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[84,28,2660]}],candystripe:0,right:0},f:[{p:[85,11,2700],t:7,e:"ui-button",a:{tooltip:[{t:2,r:"desc",p:[85,31,2720]}],"tooltip-side":"left",action:"add",params:['{"id": "',{t:2,r:"id",p:[85,90,2779]},'"}']},f:[{t:2,r:"cost",p:[85,100,2789]}," Credits"]}]}],n:52,r:"packs",p:[83,7,2616]}]}],n:52,r:"data.supplies",p:[81,3,2558]}]}]},e.exports=a.extend(r.exports)},{341:341}],375:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tabs:function(){return Object.keys(this.get("data.supplies"))}}}}(r),r.exports.template={v:3,t:[" ",{p:[12,1,174],t:7,e:"ui-notice",f:[{t:4,f:[{p:[14,5,220],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[15,7,263],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[15,24,280]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[15,75,331]}]}]}],n:50,r:"data.siliconUser",p:[13,3,189]},{t:4,n:51,f:[{p:[18,5,422],t:7,e:"span",f:["Swipe a QM-Level ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[18,39,456]}," this interface."]}],r:"data.siliconUser"}]}," ",{t:4,f:[{p:[23,3,568],t:7,e:"ui-display",a:{title:"Express Cargo Console"},f:[{p:[25,5,618],t:7,e:"ui-section",a:{label:"Landing Location"},f:[{p:[26,7,663],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.usingBeacon"],s:'_0?null:"selected"'},p:[26,25,681]}],action:"LZCargo"},f:["Cargo Bay"]}," ",{p:[27,7,770],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.hasBeacon","data.usingBeacon"],s:'_0?_1?"selected":null:"disabled"'},p:[27,25,788]}],action:"LZBeacon"},f:[{t:2,r:"data.beaconzone",p:[27,116,879]}," (",{t:2,r:"data.beaconName",p:[27,137,900]},")"]}," ",{p:[28,7,940],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.canBuyBeacon"],s:'_0?null:"disabled"'},p:[28,25,958]}],action:"printBeacon"},f:[{t:2,r:"data.printMsg",p:[28,90,1023]}]}]}," ",{p:[31,5,1079],t:7,e:"ui-section",a:{label:"Credits"},f:[{p:[32,7,1115],t:7,e:"span",f:[{t:2,x:{r:["adata.points"],s:"Math.floor(_0)"},p:[32,13,1121]}]}]}," ",{p:[35,5,1183],t:7,e:"ui-section",a:{label:"Notice"},f:[{p:[36,7,1218],t:7,e:"span",f:[{t:2,r:"data.message",p:[36,13,1224]}]}]}]}," ",{p:[39,3,1287],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"tabs",p:[39,18,1302]}]},f:[{t:4,f:[{p:[41,7,1349],t:7,e:"tab",a:{name:[{t:2,r:"name",p:[41,18,1360]}]},f:[{t:4,f:[{p:[43,11,1407],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[43,30,1426]}],candystripe:0,right:0},f:[{p:[44,13,1468],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.canBeacon"],s:'_0?null:"disabled"'},p:[44,31,1486]}],tooltip:[{t:2,r:"desc",p:[44,80,1535]}],"tooltip-side":"left",action:"add",params:['{"id": "',{t:2,r:"id",p:[44,139,1594]},'"}']},f:[{t:2,r:"cost",p:[44,149,1604]}," Credits ",{t:2,r:"data.beaconError",p:[44,166,1621]}]}]}],n:52,r:"packs",p:[42,9,1380]}]}],n:52,r:"data.supplies",p:[40,5,1318]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[22,1,543]}]},e.exports=a.extend(r.exports)},{341:341}],376:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Cellular Emporium",button:0},f:[{p:[2,3,49],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.can_readapt"],s:'_0?null:"disabled"'},p:[2,36,82]}],action:"readapt"},f:["Readapt"]}," ",{p:[4,3,169],t:7,e:"ui-section",a:{label:"Genetic Points Remaining",right:0},f:[{t:2,r:"data.genetic_points_remaining",p:[5,5,226]}]}]}," ",{p:[8,1,293],t:7,e:"ui-display",f:[{t:4,f:[{p:[10,3,335],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[10,22,354]}],candystripe:0,right:0},f:[{p:[11,5,388],t:7,e:"span",f:[{t:2,r:"desc",p:[11,11,394]}]}," ",{p:[12,5,415],t:7,e:"span",f:[{t:2,r:"helptext",p:[12,11,421]}]}," ",{p:[13,5,446],t:7,e:"span",f:["Cost: ",{t:2,r:"dna_cost",p:[13,17,458]}]}," ",{p:[14,5,483],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["owned","can_purchase"],s:'_0?"selected":_1?null:"disabled"'},p:[15,14,508]}],action:"evolve",params:['{"name": "',{t:2,r:"name",p:[17,25,615]},'"}']},f:[{t:2,x:{r:["owned"],s:'_0?"Evolved":"Evolve"'},p:[18,7,635]}]}]}],n:52,r:"data.abilities",p:[9,1,307]},{t:4,f:[{p:[23,3,738],t:7,e:"span",a:{"class":"warning"},f:["No abilities available."]}],n:51,r:"data.abilities",p:[22,1,715]}]}]},e.exports=a.extend(r.exports)},{341:341}],377:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,5,17],t:7,e:"span",f:["To use this, simply spawn the atoms you want in one of the five Centcom Supplypod Bays. Items in the bay will then be launched inside your supplypod, one turf-full at a time! You can optionally use the following buttons to configure how the supplypod acts."]}]}," ",{p:[5,1,304],t:7,e:"ui-display",a:{title:"Centcom Pod Customization (to be used against helen weinstein)"},f:[{p:[8,5,397],t:7,e:"ui-section",a:{label:"Which supplypod bay will you use?"},f:[{p:[9,6,458],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==1?"selected":null'},p:[9,24,476]}],action:"bay1"},f:["Bay #1"]}," ",{p:[10,6,561],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==2?"selected":null'},p:[10,24,579]}],action:"bay2"},f:["Bay #2"]}," ",{p:[11,6,664],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==3?"selected":null'},p:[11,24,682]}],action:"bay3"},f:["Bay #3"]}," ",{p:[12,6,766],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==4?"selected":null'},p:[12,24,784]}],action:"bay4"},f:["Bay #4"]}," ",{p:[13,6,868],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.bayNumber"],s:'_0==5?"selected":null'},p:[13,24,886]}],action:"bay5","tooltip-side":"left",tooltip:"This bay is located on the western edge of CentCom. Its the glass room directly west of where ERT spawn, and south of the CentCom ferry. Useful for launching ERT/Deathsquads/etc. onto the station via drop pods."},f:["ERT Bay"]}]}," ",{p:[18,5,1236],t:7,e:"ui-section",a:{label:"Teleport to:"},f:[{p:[19,9,1279],t:7,e:"ui-button",a:{action:"teleportCentcom"},f:[{t:2,r:"data.bay",p:[19,45,1315]}]}," ",{p:[20,9,1349],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.oldArea"],s:'_0?null:"disabled"'},p:[20,27,1367]}],action:"teleportBack"},f:[{t:2,x:{r:["data.oldArea"],s:'_0?_0:"where you were"'},p:[20,86,1426]}]}]}," ",{p:[25,5,1519],t:7,e:"ui-section",a:{label:"Launch the real atoms?"},f:[{p:[26,6,1570],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchClone"],s:'_0?"selected":null'},p:[26,24,1588]}],action:"launchClone","tooltip-side":"left",tooltip:"Choosing this will create a duplicate of the item to be launched in Centcom, allowing you to send one type of item multiple times. Either way, the atoms are forceMoved into the supplypod after it lands (but before it opens)."},f:["Launch Clones"]}]}," ",{p:[29,5,1958],t:7,e:"ui-section",a:{label:"Launch all at once?"},f:[{p:[30,9,2008],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchChoice"],s:'_0==1?"selected":null'},p:[30,27,2026]}],action:"launchOrdered","tooltip-side":"left",tooltip:'Instead of launching everything in the bay at once, this will "scan" things (one turf-full at a time) in order, left to right and top to bottom. Refreshing will reset the "scanner" to the top-leftmost position.'},f:["Ordered"]}," ",{p:[32,9,2376],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.launchChoice"],s:'_0==2?"selected":null'},p:[32,27,2394]}],action:"launchRandom","tooltip-side":"left",tooltip:"Instead of launching everything in the bay at once, this will launch one random turf of items at a time."},f:["Random"]}]}," ",{p:[38,5,2656],t:7,e:"ui-section",a:{label:"Add an explosion?"},f:[{p:[39,5,2700],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.explosionChoice"],s:'_0==1?"selected":null'},p:[39,23,2718]}],action:"explosionCustom","tooltip-side":"left",tooltip:"This will cause an explosion of whatever size you like (including flame range) to occur as soon as the supplypod lands. Dont worry, supply-pods are explosion-proof!"},f:["Custom Size"]}," ",{p:[41,5,3023],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.explosionChoice"],s:'_0==2?"selected":null'},p:[41,23,3041]}],action:"explosionBus","tooltip-side":"left",tooltip:"This will cause a maxcap explosion (dependent on server config) to occur as soon as the supplypod lands. Dont worry, supply-pods are explosion-proof!"},f:["Adminbus"]}]}," ",{p:[46,5,3344],t:7,e:"ui-section",a:{label:"Extra damage?","(default":"None)"},f:[{p:[47,5,3401],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.damageChoice"],s:'_0==1?"selected":null'},p:[47,23,3419]}],action:"damageCustom","tooltip-side":"left",tooltip:"Anyone caught under the pod when it lands will be dealt this amount of brute damage. Sucks to be them!"},f:["Custom Damage"]}," ",{p:[49,5,3659],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.damageChoice"],s:'_0==2?"selected":null'},p:[49,23,3677]}],action:"damageGib","tooltip-side":"left",tooltip:"This will attempt to gib any mob caught under the pod when it lands, as well as dealing a nice 5000 brute damage. Ya know, just to be sure!"},f:["Gib"]}]}," ",{p:[54,5,3960],t:7,e:"ui-section",a:{label:"Damaging effects?"},f:[{p:[55,5,4004],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectStun"],s:'_0?"selected":null'},p:[55,23,4022]}],action:"effectStun","tooltip-side":"left",tooltip:"Anyone who is on the turf when the supplypod is launched will be stunned until the supplypod lands. They cant get away that easy!"},f:["Stun"]}," ",{p:[57,5,4271],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectLimb"],s:'_0?"selected":null'},p:[57,23,4289]}],action:"effectLimb","tooltip-side":"left",tooltip:"This will cause anyone caught under the pod to lose a limb, excluding their head."},f:["Delimb"]}," ",{p:[59,5,4492],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectOrgans"],s:'_0?"selected":null'},p:[59,23,4510]}],action:"effectOrgans","tooltip-side":"left",tooltip:"This will cause anyone caught under the pod to lose all their limbs and organs in a spectacular fashion."},f:["Yeet Organs"]}]}," ",{p:[64,5,4764],t:7,e:"ui-section",a:{label:"Movement effects?"},f:[{p:[65,5,4808],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectBluespace"],s:'_0?"selected":null'},p:[65,23,4826]}],action:"effectBluespace","tooltip-side":"left",tooltip:"Gives the supplypod an advanced Bluespace Recyling Device. After opening, the supplypod will be warped directly to the surface of a nearby NT-designated trash planet (/r/ss13)."},f:["Bluespace"]}," ",{p:[67,5,5137],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectStealth"],s:'_0?"selected":null'},p:[67,23,5155]}],action:"effectStealth","tooltip-side":"left",tooltip:'This hides the red target icon from appearing when you launch the supplypod. Combos well with the "Invisible" style. Sneak attack, go!'},f:["Stealth"]}," ",{p:[69,5,5418],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectQuiet"],s:'_0?"selected":null'},p:[69,23,5436]}],action:"effectQuiet","tooltip-side":"left",tooltip:"This will keep the supplypod from making any sounds, except for those specifically set by admins in the Sound section."},f:["Quiet Landing"]}," ",{p:[71,5,5685],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectReverse"],s:'_0?"selected":null'},p:[71,23,5703]}],action:"effectReverse","tooltip-side":"left",tooltip:"This pod will not send any items. Instead, after landing, the supplypod will close (similar to a normal closet closing), and then launch back to the right centcom bay to drop off any new contents."},f:["Reverse Mode"]}," ",{p:[73,5,6033],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectMissile"],s:'_0?"selected":null'},p:[73,23,6051]}],action:"effectMissile","tooltip-side":"left",tooltip:"This pod will not send any items. Instead, it will immediatley delete after landing (Similar visually to setting openDelay & departDelay to 0, but this looks nicer). Useful if you just wanna fuck some shit up. Combos well with the Missile style."},f:["Missile Mode"]}," ",{p:[75,5,6430],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectCircle"],s:'_0?"selected":null'},p:[75,23,6448]}],action:"effectCircle","tooltip-side":"left",tooltip:"This will make the supplypod come in from any angle. Im not sure why this feature exists, but here it is."},f:["Any Descent Angle"]}," ",{p:[77,5,6690],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectBurst"],s:'_0?"selected":null'},p:[77,23,6708]}],action:"effectBurst","tooltip-side":"left",tooltip:"This will make each click launch 5 supplypods inaccuratly around the target turf (a 3x3 area). Combos well with the Missle Mode if you dont want shit lying everywhere after."},f:["Machine Gun Mode"]}," ",{p:[79,5,7015],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectTarget"],s:'_0?"selected":null'},p:[79,23,7033]}],action:"effectTarget","tooltip-side":"left",tooltip:"This will make the supplypod target a specific atom, instead of the mouses position. Smiting does this automatically!"},f:["Specific Target"]}]}," ",{p:[84,5,7304],t:7,e:"ui-section",a:{label:"Change Name/Desc?"},f:[{p:[85,5,7348],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectName"],s:'_0?"selected":null'},p:[85,23,7366]}],action:"effectName","tooltip-side":"left",tooltip:"Allows you to add a custom name and description."},f:["Custom Name/Desc"]}," ",{p:[87,5,7546],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.effectAnnounce"],s:'_0?"selected":null'},p:[87,23,7564]}],action:"effectAnnounce","tooltip-side":"left",tooltip:"Alerts ghosts when a pod is launched. Useful if some dumb shit is aboutta come outta the pod."},f:["Alert Ghosts"]}]}," ",{p:[92,5,7812],t:7,e:"ui-section",a:{label:"Sound?"},f:[{p:[93,5,7845],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.fallingSound"],s:'_0?"selected":null'},p:[93,23,7863]}],action:"fallingSound","tooltip-side":"left",tooltip:"Choose a sound to play as the pod falls. Note that for this to work right you should know the exact length of the sound, in seconds."},f:["Custom Falling Sound"]}," ",{p:[95,5,8135],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.landingSound"],s:'_0?"selected":null'},p:[95,23,8153]}],action:"landingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod lands."},f:["Custom Landing Sound"]}," ",{p:[97,5,8335],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.openingSound"],s:'_0?"selected":null'},p:[97,23,8353]}],action:"openingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod opens."},f:["Custom Opening Sound"]}," ",{p:[99,5,8535],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.leavingSound"],s:'_0?"selected":null'},p:[99,23,8553]}],action:"leavingSound","tooltip-side":"left",tooltip:"Choose a sound to play when the pod departs (whether that be delection in the case of a bluespace pod, or leaving for centcom for a reversing pod)."},f:["Custom Leaving Sound"]}," ",{p:[101,5,8840],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.soundVolume"],s:'_0?"selected":null'},p:[101,23,8858]}],action:"soundVolume","tooltip-side":"left",tooltip:"Choose the volume for the sound to play at. Default values are between 1 and 100, but hey, do whatever. Im a tooltip, not a cop."},f:["Admin Sound Volume"]}]}," ",{p:[106,5,9141],t:7,e:"ui-section",a:{label:"Delay timers?"},f:[{p:[107,5,9181],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.fallDuration"],s:'_0!=4?"selected":null'},p:[107,23,9199]}],action:"fallDuration","tooltip-side":"left",tooltip:"Set how long the animation for the pod falling lasts. Create dramatic, slow falling pods!"},f:["Custom Falling Duration"]}," ",{p:[109,5,9436],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.landingDelay"],s:'_0!=20?"selected":null'},p:[109,23,9454]}],action:"landingDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to hit the station. By default this value is 0.5 seconds."},f:["Custom Landing Time"]}," ",{p:[111,9,9713],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.openingDelay"],s:'_0!=30?"selected":null'},p:[111,27,9731]}],action:"openingDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to open after landing. Useful for giving whatevers inside the pod a nice dramatic entrance! By default this value is 3 seconds."},f:["Custom Opening Time"]}," ",{p:[113,5,10056],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.departureDelay"],s:'_0!=30?"selected":null'},p:[113,23,10074]}],action:"departureDelay","tooltip-side":"left",tooltip:"Choose the amount of time it takes for the supplypod to leave after landing. By default this value is 3 seconds."},f:["Custom Leaving Time"]}]}," ",{p:[118,5,10354],t:7,e:"ui-section",a:{label:"Style?"},f:[{p:[119,5,10387],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==1?"selected":null'},p:[119,23,10405]}],action:"styleStandard","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to your standard Nanotrasen black and orange. Same color scheme as the normal station-used supplypods."},f:["Standard"]}," ",{p:[121,5,10701],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==2?"selected":null'},p:[121,23,10719]}],action:"styleBluespace","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to the same as the stations upgraded blue-and-white Bluespace Supplypods."},f:["Advanced"]}," ",{p:[123,5,10987],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==4?"selected":null'},p:[123,23,11005]}],action:"styleSyndie","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a menacing black and blood-red. Great for sending meme-ops in style!"},f:["Syndicate"]}," ",{p:[125,5,11269],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==5?"selected":null'},p:[125,23,11287]}],action:"styleBlue","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a menacing black and dark blue. Great for sending deathsquads in style!"},f:["Deathsquad"]}," ",{p:[127,5,11553],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==6?"selected":null'},p:[127,23,11571]}],action:"styleCult","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a blood and rune covered cult pod!"},f:["Cult Pod"]}," ",{p:[129,5,11791],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==7?"selected":null'},p:[129,23,11809]}],action:"styleMissile","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large missile. Combos well with a missile mode, so the missile doesnt stick around after landing."},f:["Missile"]}," ",{p:[131,5,12096],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==8?"selected":null'},p:[131,23,12114]}],action:"styleSMissile","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large blood-red missile. Combos well with missile mode, so the missile doesnt stick around after landing."},f:["Syndicate Missile"]}," ",{p:[133,5,12420],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==9?"selected":null'},p:[133,23,12438]}],action:"styleBox","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom style to a large, dark-green military supply crate."},f:["Supply Crate"]}," ",{p:[135,5,12669],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==10?"selected":null'},p:[135,23,12687]}],action:"styleHONK","tooltip-side":"left",tooltip:"Changes the pods style from the default Centcom color scheme to a colorful, clown inspired look."},f:["HONK"]}," ",{p:[137,5,12909],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==11?"selected":null'},p:[137,23,12927]}],action:"styleFruit","tooltip-side":"left",tooltip:"for when an orange is angry"},f:["Fruit~"]}," ",{p:[139,5,13083],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==12?"selected":null'},p:[139,23,13101]}],action:"styleInvisible","tooltip-side":"left",tooltip:'Makes the supplypod invisible! Useful for when you want to use this feature with a gateway or something. Combos well with the "Stealth" and "Quiet Landing" effects.'},f:["Invisible"]}," ",{p:[141,5,13400],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==13?"selected":null'},p:[141,23,13418]}],action:"styleGondola","tooltip-side":"left",tooltip:"this gondola can control when he wants to deliver his supplies if he has a smart enough mind, so offer up his body to ghosts for maximum enjoyment. (Make sure to turn off bluespace and set a arbitrarily high open-time if you do!)"},f:["Gondola (alive)"]}," ",{p:[143,5,13787],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.styleChoice"],s:'_0==14?"selected":null'},p:[143,23,13805]}],action:"styleSeeThrough","tooltip-side":"left",tooltip:"By selecting this, the pod will instead look like whatevers inside it (as if it were the contents falling by themselves, without a pod). Useful for launching mechs at the station and standing tall as they soar in from the heavens."},f:["Show Contents (See-Through Pod)!"]}]}]}," ",{p:[148,1,14223],t:7,e:"ui-display",f:[{p:[149,5,14241],t:7,e:"ui-section",a:{label:[{t:2,r:"data.numObjects",p:[149,24,14260]}," turfs in ",{t:2,r:"data.bay",p:[149,53,14289]}],candystripe:0,right:0},f:[{p:[150,9,14331],t:7,e:"ui-button",a:{action:"refresh","tooltip-side":"left",tooltip:"Manually refreshes the possible things to launch in the pod bay."},f:["Refresh Pod Bay"]}," ",{p:[152,9,14500],t:7,e:"ui-button",a:{style:[{t:2,x:{r:["data.giveLauncher"],s:'_0?"selected":null'},p:[152,27,14518]}],action:"giveLauncher","tooltip-side":"left",tooltip:"THE CODEX ASTARTES CALLS THIS MANEUVER: STEEL RAIN"},f:["Enter Launch Mode"]}," ",{p:[154,9,14712],t:7,e:"ui-button",a:{style:"danger",action:"clearBay","tooltip-side":"left",tooltip:"This will delete all objs and mobs from the selected bay."},f:["Clear Selected Bay"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],378:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,3,31],t:7,e:"ui-section",a:{label:"Energy"},f:[{p:[3,5,64],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.maxEnergy",p:[3,26,85]}],value:[{t:2,r:"data.energy",p:[3,53,112]}]},f:[{t:2,x:{r:["adata.energy"],s:"Math.fixed(_0)"},p:[3,70,129]}," Units"]}]}]}," ",{p:[6,1,206],t:7,e:"ui-display",a:{title:"Saved Recipes",button:0},f:[{p:[7,3,251],t:7,e:"ui-section",f:[{p:[8,5,269],t:7,e:"ui-button",a:{icon:"plus",action:"add_recipe"},f:["Add Recipe"]}," ",{p:[9,2,337],t:7,e:"ui-button",a:{icon:"minus",action:"clear_recipes"},f:["Clear Recipes"]}," ",{t:4,f:[{p:[11,7,445],t:7,e:"ui-button",a:{grid:0,icon:"tint",action:"dispense_recipe",params:['{"recipe": "',{t:2,r:"contents",p:[11,80,518]},'"}']},f:[{t:2,r:"recipe_name",p:[11,96,534]}]}],n:52,r:"data.recipes",p:[10,5,415]}]}]}," ",{p:{button:[{t:4,f:[{p:[18,7,719],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.amount","."],s:'_0==_1?"selected":null'},p:[18,37,749]}],action:"amount",params:['{"target": ',{t:2,r:".",p:[18,114,826]},"}"]},f:[{t:2,r:".",p:[18,122,834]}]}],n:52,r:"data.beakerTransferAmounts",p:[17,5,675]}]},t:7,e:"ui-display",a:{title:"Dispense",button:0},f:[" ",{p:[21,3,886],t:7,e:"ui-section",f:[{t:4,f:[{p:[23,7,936],t:7,e:"ui-button",a:{grid:0,icon:"tint",action:"dispense",params:['{"reagent": "',{t:2,r:"id",p:[23,74,1003]},'"}']},f:[{t:2,r:"title",p:[23,84,1013]}]}],n:52,r:"data.chemicals",p:[22,5,904]}]}]}," ",{p:{button:[{t:4,f:[{p:[30,7,1190],t:7,e:"ui-button",a:{icon:"minus",action:"remove",params:['{"amount": ',{t:2,r:".",p:[30,66,1249]},"}"]},f:[{t:2,r:".",p:[30,74,1257]}]}],n:52,r:"data.beakerTransferAmounts",p:[29,5,1146]}," ",{p:[32,5,1295],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[32,36,1326]}],action:"eject"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[34,3,1423],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[36,7,1493],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[36,13,1499]},"/",{t:2,r:"data.beakerMaxVolume",p:[36,55,1541]}," Units"]}," ",{p:[37,4,1583],t:7,e:"span",f:["pH: ",{t:2,x:{r:["adata.beakerCurrentpH","adata.partRating"],s:"Math.round(_0*_1)/_1"},p:[37,14,1593]}]}," ",{p:[38,7,1679],t:7,e:"br"}," ",{t:4,f:[{p:[40,9,1732],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[40,52,1775]}," units of ",{t:2,r:"name",p:[40,87,1810]}]},{p:[40,102,1825],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[39,7,1692]},{t:4,n:51,f:[{p:[42,9,1856],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[35,5,1458]},{t:4,n:51,f:[{p:[45,7,1932],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],379:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Thermostat"},f:[{p:[2,3,35],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,5,67],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isActive"],s:'_0?"power-off":"close"'},p:[3,22,84]}],style:[{t:2,x:{r:["data.isActive"],s:'_0?"selected":null'},p:[4,10,137]}],state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,10,186]}],action:"power"},f:[{t:2,x:{r:["data.isActive"],s:'_0?"On":"Off"'},p:[6,18,249]}]}]}," ",{p:[8,3,314],t:7,e:"ui-section",a:{label:"Target"},f:[{p:[9,4,346],t:7,e:"ui-button",a:{icon:"pencil",action:"temperature",params:'{"target": "input"}'},f:[{t:2,x:{r:["adata.targetTemp"],s:"Math.round(_0)"},p:[9,79,421]}," K"]}]}]}," ",{p:{button:[{p:[14,5,564],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[14,36,595]}],action:"eject"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[16,3,692],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[18,7,762],t:7,e:"span",f:["Temperature: ",{t:2,x:{r:["adata.currentTemp"],s:"Math.round(_0)"},p:[18,26,781]}," K"]}," ",{p:[19,4,828],t:7,e:"br"}," ",{p:[20,7,842],t:7,e:"span",f:["pH: ",{t:2,x:{r:["adata.currentpH","adata.partRating"],s:"Math.round(_0*_1)/_1"},p:[20,17,852]}]}," ",{p:[21,7,932],t:7,e:"br"}," ",{t:4,f:[{p:[23,3,980],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[23,46,1023]}," units of ",{t:2,r:"name",p:[23,81,1058]}]},{p:[23,96,1073],t:7,e:"br"}," ",{t:4,f:[{p:[25,4,1111],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:["Purity: ",{t:2,x:{r:["purity"],s:"Math.fixed(_0,2)"},p:[25,55,1162]}]},{p:[25,87,1194],t:7,e:"br"}],n:50,r:"data.showPurity",p:[24,3,1083]}],n:52,r:"adata.beakerContents",p:[22,7,946]},{t:4,n:51,f:[{p:[28,9,1237],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[17,5,727]},{t:4,n:51,f:[{p:[31,7,1313],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],380:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:["\ufeff",{t:4,f:[" ",{p:[2,2,33],t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[{p:[3,3,71],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"Eject":"close"'},p:[3,20,88]}],style:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"selected":null'},p:[4,11,144]}],state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,11,200]}],action:"eject"},f:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"Eject":"No beaker"'},p:[7,5,269]}]}," ",{p:[10,3,341],t:7,e:"ui-section",f:[{t:4,f:[{t:4,f:[{p:[13,6,427],t:7,e:"ui-section",a:{label:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[13,25,446]}," units of ",{t:2,r:"name",p:[13,60,481]}],nowrap:0},f:[{p:[14,7,506],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{p:[15,8,556],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[15,61,609]},'", "amount": 1}']},f:["1"]}," ",{p:[16,8,654],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[16,61,707]},'", "amount": 5}']},f:["5"]}," ",{p:[17,8,752],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[17,61,805]},'", "amount": 10}']},f:["10"]}," ",{p:[18,8,852],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[18,61,905]},'", "amount": 1000}']},f:["All"]}," ",{p:[19,8,955],t:7,e:"ui-button",a:{action:"transferToBuffer",params:['{"id": "',{t:2,r:"id",p:[19,61,1008]},'", "amount": -1}']},f:["Custom"]}," ",{p:[20,8,1059],t:7,e:"ui-button",a:{action:"analyzeBeak",params:['{"id": "',{t:2,r:"id",p:[20,56,1107]},'"}']},f:["Analyze"]}]}]}],n:52,r:"data.beakerContents",p:[12,5,391]},{t:4,n:51,f:[{p:[24,5,1189],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"data.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[11,4,358]},{t:4,n:51,f:[{p:[27,5,1260],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}," ",{p:[32,2,1348],t:7,e:"ui-display",a:{title:"Buffer"},f:[{p:[33,3,1379],t:7,e:"ui-button",a:{action:"toggleMode",state:[{t:2,x:{r:["data.mode"],s:'_0?null:"selected"'},p:[33,41,1417]}]},f:["Destroy"]}," ",{p:[34,3,1475],t:7,e:"ui-button",a:{action:"toggleMode",state:[{t:2,x:{r:["data.mode"],s:'_0?"selected":null'},p:[34,41,1513]}]},f:["Transfer to Beaker"]}," ",{p:[35,3,1582],t:7,e:"ui-section",f:[{t:4,f:[{p:[37,5,1634],t:7,e:"ui-section",a:{label:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[37,24,1653]}," units of ",{t:2,r:"name",p:[37,59,1688]}],nowrap:0},f:[{p:[38,6,1712],t:7,e:"div",a:{"class":"content",style:"float:right"},f:[{p:[39,7,1761],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[39,62,1816]},'", "amount": 1}']},f:["1"]}," ",{p:[40,7,1860],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[40,62,1915]},'", "amount": 5}']},f:["5"]}," ",{p:[41,7,1959],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[41,62,2014]},'", "amount": 10}']},f:["10"]}," ",{p:[42,7,2060],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[42,62,2115]},'", "amount": 1000}']},f:["All"]}," ",{p:[43,7,2164],t:7,e:"ui-button",a:{action:"transferFromBuffer",params:['{"id": "',{t:2,r:"id",p:[43,62,2219]},'", "amount": -1}']},f:["Custom"]}," ",{p:[44,7,2269],t:7,e:"ui-button",a:{action:"analyzeBuff", +params:['{"id": "',{t:2,r:"id",p:[44,55,2317]},'"}']},f:["Analyze"]}]}]}],n:52,r:"data.bufferContents",p:[36,4,1599]}]}]}," ",{t:4,f:[{p:[52,3,2453],t:7,e:"ui-display",a:{title:"Pills, Bottles and Patches"},f:[{t:4,f:[{p:[54,5,2537],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["id","data.chosenPillStyle"],s:'_0==_1?"selected":null'},p:[54,23,2555]}],action:"pillStyle",params:['{"id": "',{t:2,r:"id",p:[54,108,2640]},'"}']},f:[{t:3,r:"htmltag",p:[54,118,2650]}]}],n:52,r:"data.pillStyles",p:[53,4,2506]}," ",{p:[56,4,2694],t:7,e:"br"}," ",{t:4,f:[{p:[58,5,2740],t:7,e:"ui-button",a:{action:"ejectp",state:[{t:2,x:{r:["data.isPillBottleLoaded"],s:'_0?null:"disabled"'},p:[58,39,2774]}]},f:[{t:2,x:{r:["data.isPillBottleLoaded"],s:'_0?"Eject":"No Pill bottle loaded"'},p:[58,88,2823]}]}," ",{p:[59,5,2904],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.pillBotContent",p:[59,27,2926]},"/",{t:2,r:"data.pillBotMaxContent",p:[59,51,2950]}]}],n:50,r:"data.isPillBottleLoaded",p:[57,4,2703]},{t:4,n:51,f:[{p:[61,5,3002],t:7,e:"span",a:{"class":"average"},f:["No Pillbottle"]}],r:"data.isPillBottleLoaded"}," ",{p:[64,4,3063],t:7,e:"br"}," ",{p:[65,4,3073],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[65,63,3132]}]},f:["Create Pill (max 50µ)"]}," ",{p:[66,4,3216],t:7,e:"br"}," ",{p:[67,4,3226],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[67,63,3285]}]},f:["Create Multiple Pills"]}," ",{p:[68,4,3369],t:7,e:"br"}," ",{p:[69,4,3379],t:7,e:"br"}," ",{p:[70,4,3389],t:7,e:"ui-button",a:{action:"createPatch",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[70,64,3449]}]},f:["Create Patch (max 40µ)"]}," ",{p:[71,4,3534],t:7,e:"br"}," ",{p:[72,4,3544],t:7,e:"ui-button",a:{action:"createPatch",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[72,64,3604]}]},f:["Create Multiple Patches"]}," ",{p:[73,4,3690],t:7,e:"br"}," ",{p:[74,4,3700],t:7,e:"br"}," ",{p:[75,4,3710],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[75,65,3771]}]},f:["Create Bottle (max 30µ)"]}," ",{p:[76,4,3857],t:7,e:"br"}," ",{p:[77,4,3867],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[77,65,3928]}]},f:["Dispense Buffer to Bottles"]}," ",{p:[78,4,4017],t:7,e:"br"}," ",{p:[79,4,4027],t:7,e:"br"}," ",{p:[80,4,4037],t:7,e:"ui-button",a:{action:"createVial",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[80,63,4096]}]},f:["Create Hypo Vial (max 60µ)"]}," ",{p:[81,4,4185],t:7,e:"br"}," ",{p:[82,4,4195],t:7,e:"ui-button",a:{action:"createVial",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[82,63,4254]}]},f:["Dispense Buffer to Hypo vials"]}," ",{p:[83,4,4347],t:7,e:"br"}," ",{p:[84,4,4357],t:7,e:"br"}," ",{p:[85,4,4367],t:7,e:"ui-button",a:{action:"createDart",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[85,63,4426]}]},f:["Create SmartDart (max 20µ)"]}," ",{p:[86,4,4515],t:7,e:"br"}," ",{p:[87,4,4525],t:7,e:"ui-button",a:{action:"createDart",params:'{"many": 1}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[87,63,4584]}]},f:["Create Multiple SmartDarts"]}," ",{p:[88,4,4674],t:7,e:"br"}]}],n:50,x:{r:["data.condi"],s:"!_0"},p:[51,2,2430]},{t:4,n:51,f:[{p:[93,3,4717],t:7,e:"ui-display",a:{title:"Condiments bottles and packs"},f:[{p:[94,4,4772],t:7,e:"ui-button",a:{action:"createPill",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[94,63,4831]}]},f:["Create Pack (max 10µ)"]}," ",{p:[95,4,4915],t:7,e:"br"}," ",{p:[96,4,4925],t:7,e:"br"}," ",{p:[97,4,4935],t:7,e:"ui-button",a:{action:"createBottle",params:'{"many": 0}',state:[{t:2,x:{r:["data.bufferContents"],s:'_0?null:"disabled"'},p:[97,65,4996]}]},f:["Create Bottle (max 50µ)"]}]}],x:{r:["data.condi"],s:"!_0"}}],n:50,x:{r:["data.screen"],s:'_0=="home"'},p:[1,2,1]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.screen"],s:'_0=="analyze"'},f:[{p:[101,2,5144],t:7,e:"ui-display",a:{title:[{t:2,r:"data.analyzeVars.name",p:[101,20,5162]}]},f:[{p:[102,3,5193],t:7,e:"span",a:{"class":"highlight"},f:["Description:"]}," ",{p:[103,3,5241],t:7,e:"span",a:{"class":"content",style:"float:center"},f:[{t:2,r:"data.analyzeVars.description",p:[103,46,5284]}]}," ",{p:[104,3,5327],t:7,e:"br"}," ",{p:[105,3,5336],t:7,e:"span",a:{"class":"highlight"},f:["Color:"]}," ",{p:[106,3,5378],t:7,e:"span",a:{style:["color: ",{t:2,r:"data.analyzeVars.color",p:[106,23,5398]},"; background-color: ",{t:2,r:"data.analyzeVars.color",p:[106,69,5444]}]},f:[{t:2,r:"data.analyzeVars.color",p:[106,97,5472]}]}," ",{p:[107,3,5509],t:7,e:"br"}," ",{p:[108,3,5518],t:7,e:"span",a:{"class":"highlight"},f:["State:"]}," ",{p:[109,3,5560],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.state",p:[109,25,5582]}]}," ",{p:[110,3,5619],t:7,e:"br"}," ",{p:[111,3,5628],t:7,e:"span",a:{"class":"highlight"},f:["Metabolization Rate:"]}," ",{p:[112,3,5684],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.metaRate",p:[112,25,5706]},"µ/minute"]}," ",{p:[113,3,5754],t:7,e:"br"}," ",{p:[114,3,5763],t:7,e:"span",a:{"class":"highlight"},f:["Overdose Threshold:"]}," ",{p:[115,3,5818],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.overD",p:[115,25,5840]}]}," ",{p:[116,3,5877],t:7,e:"br"}," ",{p:[117,3,5886],t:7,e:"span",a:{"class":"highlight"},f:["Addiction Threshold:"]}," ",{p:[118,3,5942],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.addicD",p:[118,25,5964]}]}," ",{p:[119,3,6002],t:7,e:"br"}," ",{t:4,f:[{p:[121,4,6041],t:7,e:"span",a:{"class":"highlight"},f:["Minumum Reaction Temperature:"]}," ",{p:[122,4,6107],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.minTemp",p:[122,26,6129]},"K"]}," ",{p:[123,4,6170],t:7,e:"br"}," ",{p:[124,4,6180],t:7,e:"span",a:{"class":"highlight"},f:["Optimal Reaction Temperature:"]}," ",{p:[125,4,6246],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.maxTemp",p:[125,26,6268]},"K"]}," ",{p:[126,4,6309],t:7,e:"br"}," ",{p:[127,4,6319],t:7,e:"span",a:{"class":"highlight"},f:["Explosion Reaction Temperature:"]}," ",{p:[128,4,6387],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.eTemp",p:[128,26,6409]},"K"]}," ",{p:[129,4,6448],t:7,e:"br"}," ",{p:[130,4,6458],t:7,e:"span",a:{"class":"highlight"},f:["Optimal reaction pH:"]}," ",{p:[131,4,6515],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.pHpeak",p:[131,26,6537]}]}," ",{p:[132,4,6576],t:7,e:"br"}," ",{p:[133,4,6586],t:7,e:"span",a:{"class":"highlight"},f:["Current Purity:"]}," ",{p:[134,4,6638],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.purityF",p:[134,26,6660]}]}," ",{p:[135,4,6700],t:7,e:"br"}," ",{p:[136,4,6710],t:7,e:"span",a:{"class":"highlight"},f:["Inverse Purity Threshold:"]}," ",{p:[137,4,6772],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.inverseRatioF",p:[137,26,6794]}]}," ",{p:[138,4,6840],t:7,e:"br"}," ",{p:[139,4,6850],t:7,e:"span",a:{"class":"highlight"},f:["Explosion Purity Threshold:"]}," ",{p:[140,4,6914],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.analyzeVars.purityE",p:[140,26,6936]}]}," ",{p:[141,4,6976],t:7,e:"br"}],n:50,r:"data.fermianalyze",p:[120,3,6011]}," ",{p:[143,3,6996],t:7,e:"br"}," ",{p:[144,3,7005],t:7,e:"ui-button",a:{action:"goScreen",params:'{"screen": "home"}'},f:["Back"]}]}]}],x:{r:["data.screen"],s:'_0=="home"'}}]},e.exports=a.extend(r.exports)},{341:341}],381:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Recipient Contents"},f:[{p:[2,2,42],t:7,e:"ui-section",f:[{p:[3,3,58],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[3,34,89]}],action:"ejectBeaker"},f:["Eject"]}," ",{p:[4,3,176],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[4,35,208]}],action:"input"},f:["Input"]}," ",{p:[5,3,289],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[5,35,321]}],action:"amount"},f:[{t:2,r:"data.amount",p:[5,96,382]},"U"]}," ",{p:[6,3,414],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?"disabled":null'},p:[6,33,444]}],action:"makecup"},f:["Create Beaker"]}]}]}," ",{p:[9,1,564],t:7,e:"ui-display",a:{title:"Recipient"},f:[{p:[10,2,597],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[12,4,662],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[12,10,668]},"/",{t:2,r:"data.beakerMaxVolume",p:[12,52,710]}," Units"]}," ",{t:4,f:[{p:[14,5,788],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[14,48,831]}," units of ",{t:2,r:"name",p:[14,83,866]}]},{p:[14,98,881],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[13,4,752]},{t:4,n:51,f:[{p:[16,5,905],t:7,e:"span",a:{"class":"bad"},f:["Recipient Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[11,3,630]},{t:4,n:51,f:[{p:[19,4,976],t:7,e:"span",a:{"class":"average"},f:["No Recipient"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],382:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-button",a:{action:"toggle"},f:[{t:2,x:{r:["data.recollection"],s:'_0?"Recital":"Recollection"'},p:[2,30,43]}]}]}," ",{t:4,f:[{p:[5,3,149],t:7,e:"ui-display",f:[{t:3,r:"data.rec_text",p:[6,3,165]}," ",{t:4,f:[{p:[8,4,231],t:7,e:"br"},{p:[8,8,235],t:7,e:"ui-button",a:{action:"rec_category",params:['{"category": "',{t:2,r:"name",p:[8,63,290]},'"}']},f:[{t:3,r:"name",p:[8,75,302]}," - ",{t:3,r:"desc",p:[8,88,315]}]}],n:52,r:"data.recollection_categories",p:[7,3,188]}," ",{t:3,r:"data.rec_section",p:[10,3,354]}," ",{t:3,r:"data.rec_binds",p:[11,3,380]}]}],n:50,r:"data.recollection",p:[4,1,120]},{t:4,n:51,f:[{p:[14,2,431],t:7,e:"ui-display",a:{title:"Power",button:0},f:[{p:[15,4,469],t:7,e:"ui-section",f:[{t:3,r:"data.power",p:[16,6,488]}]}]}," ",{p:[19,2,541],t:7,e:"ui-display",f:[{p:[20,3,557],t:7,e:"ui-section",f:[{p:[21,4,574],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Driver"?"selected":null'},p:[21,22,592]}],action:"select",params:'{"category": "Driver"}'},f:["Driver"]}," ",{p:[22,4,715],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Script"?"selected":null'},p:[22,22,733]}],action:"select",params:'{"category": "Script"}'},f:["Scripts"]}," ",{p:[23,4,857],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.selected"],s:'_0=="Application"?"selected":null'},p:[23,22,875]}],action:"select",params:'{"category": "Application"}'},f:["Applications"]}," ",{p:[24,4,1014],t:7,e:"br"},{t:3,r:"data.tier_info",p:[24,8,1018]}]}," ",{p:[26,3,1059],t:7,e:"ui-section",f:[{t:3,r:"data.scripturecolors",p:[27,4,1076]}]},{p:[28,16,1119],t:7,e:"hr"}," ",{p:[29,3,1127],t:7,e:"ui-section",f:[{t:4,f:[{p:[31,4,1172],t:7,e:"div",f:[{p:[31,9,1177],t:7,e:"ui-button",a:{tooltip:[{t:3,r:"tip",p:[31,29,1197]}],"tooltip-side":"right",action:"recite",params:['{"category": "',{t:2,r:"type",p:[31,99,1267]},'"}']},f:["Recite ",{t:3,r:"required",p:[31,118,1286]}]}," ",{t:4,f:[{t:4,f:[{p:[34,6,1362],t:7,e:"ui-button",a:{action:"bind",params:['{"category": "',{t:2,r:"type",p:[34,53,1409]},'"}']},f:["Unbind ",{t:3,r:"bound",p:[34,72,1428]}]}],n:50,r:"bound",p:[33,5,1342]},{t:4,n:51,f:[{p:[36,6,1472],t:7,e:"ui-button",a:{action:"bind",params:['{"category": "',{t:2,r:"type",p:[36,53,1519]},'"}']},f:["Quickbind"]}],r:"bound"}],n:50,r:"quickbind",p:[32,6,1319]}," ",{t:3,r:"name",p:[39,6,1586]}," ",{t:3,r:"descname",p:[39,17,1597]}," ",{t:3,r:"invokers",p:[39,32,1612]}]}],n:52,r:"data.scripture",p:[30,3,1143]}]}]}],r:"data.recollection"}]},e.exports=a.extend(r.exports)},{341:341}],383:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Codex Gigas"},f:[{p:[2,2,35],t:7,e:"ui-section",f:[{t:2,r:"data.name",p:[3,3,51]}]}," ",{p:[5,5,86],t:7,e:"ui-section",a:{label:"Prefix"},f:[{p:[6,3,117],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[6,22,136]}],action:"Dark "},f:["Dark"]}," ",{p:[7,3,221],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[7,22,240]}],action:"Hellish "},f:["Hellish"]}," ",{p:[8,3,331],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[8,22,350]}],action:"Fallen "},f:["Fallen"]}," ",{p:[9,3,439],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[9,22,458]}],action:"Fiery "},f:["Fiery"]}," ",{p:[10,3,545],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[10,22,564]}],action:"Sinful "},f:["Sinful"]}," ",{p:[11,3,653],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[11,22,672]}],action:"Blood "},f:["Blood"]}," ",{p:[12,3,759],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==1?null:"disabled"'},p:[12,22,778]}],action:"Fluffy "},f:["Fluffy"]}]}," ",{p:[14,5,888],t:7,e:"ui-section",a:{label:"Title"},f:[{p:[15,3,918],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[15,22,937]}],action:"Lord "},f:["Lord"]}," ",{p:[16,3,1022],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[16,22,1041]}],action:"Prelate "},f:["Prelate"]}," ",{p:[17,3,1132],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[17,22,1151]}],action:"Count "},f:["Count"]}," ",{p:[18,3,1238],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[18,22,1257]}],action:"Viscount "},f:["Viscount"]}," ",{p:[19,3,1350],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[19,22,1369]}],action:"Vizier "},f:["Vizier"]}," ",{p:[20,3,1458],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[20,22,1477]}],action:"Elder "},f:["Elder"]}," ",{p:[21,3,1564],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=2?null:"disabled"'},p:[21,22,1583]}],action:"Adept "},f:["Adept"]}]}," ",{p:[23,5,1691],t:7,e:"ui-section",a:{label:"Name"},f:[{p:[24,3,1720],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[24,22,1739]}],action:"hal"},f:["hal"]}," ",{p:[25,3,1821],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[25,22,1840]}],action:"ve"},f:["ve"]}," ",{p:[26,3,1920],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[26,22,1939]}],action:"odr"},f:["odr"]}," ",{p:[27,3,2021],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[27,22,2040]}],action:"neit"},f:["neit"]}," ",{p:[28,3,2124],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[28,22,2143]}],action:"ci"},f:["ci"]}," ",{p:[29,3,2223],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[29,22,2242]}],action:"quon"},f:["quon"]}," ",{p:[30,3,2326],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[30,22,2345]}],action:"mya"},f:["mya"]}," ",{p:[31,3,2427],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[31,22,2446]}],action:"folth"},f:["folth"]}," ",{p:[32,3,2532],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[32,22,2551]}],action:"wren"},f:["wren"]}," ",{p:[33,3,2635],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[33,22,2654]}],action:"geyr"},f:["geyr"]}," ",{p:[34,3,2738],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[34,22,2757]}],action:"hil"},f:["hil"]}," ",{p:[35,3,2839],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[35,22,2858]}],action:"niet"},f:["niet"]}," ",{p:[36,3,2942],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[36,22,2961]}],action:"twou"},f:["twou"]}," ",{p:[37,3,3045],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[37,22,3064]}],action:"phi"},f:["phi"]}," ",{p:[38,3,3146],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0<=4?null:"disabled"'},p:[38,22,3165]}],action:"coa"},f:["coa"]}]}," ",{p:[40,5,3268],t:7,e:"ui-section",a:{label:"suffix"},f:[{p:[41,3,3299],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[41,22,3318]}],action:" the Red"},f:["the Red"]}," ",{p:[42,3,3409],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[42,22,3428]}],action:" the Soulless"},f:["the Soulless"]}," ",{p:[43,3,3529],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[43,22,3548]}],action:" the Master"},f:["the Master"]}," ",{p:[44,3,3645],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[44,22,3664]}],action:", the Lord of all things"},f:["the Lord of all things"]}," ",{p:[45,3,3786],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0==4?null:"disabled"'},p:[45,22,3805]}],action:", Jr."},f:["jr"]}]}," ",{p:[47,5,3909],t:7,e:"ui-section",a:{label:"submit"},f:[{p:[48,3,3941],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.currentSection"],s:'_0>=4?null:"disabled"'},p:[48,21,3959]}],action:"search"},f:["search"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],384:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[2,1,2],t:7,e:"ui-button",a:{icon:"circle",action:"clean_order"},f:["Clear Order"]},{p:[2,70,71],t:7,e:"br"},{p:[2,74,75],t:7,e:"br"}," ",{p:[3,1,81],t:7,e:"i",f:["Your new computer device you always dreamed of is just four steps away..."]},{p:[3,81,161],t:7,e:"hr"}," ",{t:4,f:[" ",{p:[5,1,223],t:7,e:"div",a:{"class":"item"},f:[{p:[6,2,244],t:7,e:"h2",f:["Step 1: Select your device type"]}," ",{p:[7,2,287],t:7,e:"ui-button",a:{icon:"calc",action:"pick_device",params:'{"pick" : "1"}'},f:["Laptop"]}," ",{p:[8,2,377],t:7,e:"ui-button",a:{icon:"calc",action:"pick_device",params:'{"pick" : "2"}'},f:["LTablet"]}]}],n:50,x:{r:["data.state"],s:"_0==0"},p:[4,1,167]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.state"],s:"_0==1"},f:[{p:[11,1,502],t:7,e:"div",a:{"class":"item"},f:[{p:[12,2,523],t:7,e:"h2",f:["Step 2: Personalise your device"]}," ",{p:[13,2,566],t:7,e:"table",f:[{p:[14,3,577],t:7,e:"tr",f:[{p:[15,4,586],t:7,e:"td",f:[{p:[15,8,590],t:7,e:"b",f:["Current Price:"]}]},{p:[16,4,616],t:7,e:"td",f:[{t:2,r:"data.totalprice",p:[16,8,620]},"C"]}]}," ",{p:[18,3,653],t:7,e:"tr",f:[{p:[19,4,663],t:7,e:"td",f:[{p:[19,8,667],t:7,e:"b",f:["Battery:"]}]},{p:[20,4,687],t:7,e:"td",f:[{p:[20,8,691],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "1"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==1?"selected":null'},p:[20,73,756]}]},f:["Standard"]}]},{p:[21,4,827],t:7,e:"td",f:[{p:[21,8,831],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "2"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==2?"selected":null'},p:[21,73,896]}]},f:["Upgraded"]}]},{p:[22,4,967],t:7,e:"td",f:[{p:[22,8,971],t:7,e:"ui-button",a:{action:"hw_battery",params:'{"battery" : "3"}',state:[{t:2,x:{r:["data.hw_battery"],s:'_0==3?"selected":null'},p:[22,73,1036]}]},f:["Advanced"]}]}]}," ",{p:[24,3,1115],t:7,e:"tr",f:[{p:[25,4,1124],t:7,e:"td",f:[{p:[25,8,1128],t:7,e:"b",f:["Hard Drive:"]}]},{p:[26,4,1151],t:7,e:"td",f:[{p:[26,8,1155],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "1"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==1?"selected":null'},p:[26,67,1214]}]},f:["Standard"]}]},{p:[27,4,1282],t:7,e:"td",f:[{p:[27,8,1286],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "2"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==2?"selected":null'},p:[27,67,1345]}]},f:["Upgraded"]}]},{p:[28,4,1413],t:7,e:"td",f:[{p:[28,8,1417],t:7,e:"ui-button",a:{action:"hw_disk",params:'{"disk" : "3"}',state:[{t:2,x:{r:["data.hw_disk"],s:'_0==3?"selected":null'},p:[28,67,1476]}]},f:["Advanced"]}]}]}," ",{p:[30,3,1552],t:7,e:"tr",f:[{p:[31,4,1561],t:7,e:"td",f:[{p:[31,8,1565],t:7,e:"b",f:["Network Card:"]}]},{p:[32,4,1590],t:7,e:"td",f:[{p:[32,8,1594],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "0"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==0?"selected":null'},p:[32,73,1659]}]},f:["None"]}]},{p:[33,4,1726],t:7,e:"td",f:[{p:[33,8,1730],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "1"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==1?"selected":null'},p:[33,73,1795]}]},f:["Standard"]}]},{p:[34,4,1866],t:7,e:"td",f:[{p:[34,8,1870],t:7,e:"ui-button",a:{action:"hw_netcard",params:'{"netcard" : "2"}',state:[{t:2,x:{r:["data.hw_netcard"],s:'_0==2?"selected":null'},p:[34,73,1935]}]},f:["Advanced"]}]}]}," ",{p:[36,3,2014],t:7,e:"tr",f:[{p:[37,4,2023],t:7,e:"td",f:[{p:[37,8,2027],t:7,e:"b",f:["Nano Printer:"]}]},{p:[38,4,2052],t:7,e:"td",f:[{p:[38,8,2056],t:7,e:"ui-button",a:{action:"hw_nanoprint",params:'{"print" : "0"}',state:[{t:2,x:{r:["data.hw_nanoprint"],s:'_0==0?"selected":null'},p:[38,73,2121]}]},f:["None"]}]},{p:[39,4,2190],t:7,e:"td",f:[{p:[39,8,2194],t:7,e:"ui-button",a:{action:"hw_nanoprint",params:'{"print" : "1"}',state:[{t:2,x:{r:["data.hw_nanoprint"],s:'_0==1?"selected":null'},p:[39,73,2259]}]},f:["Standard"]}]}]}," ",{p:[41,3,2340],t:7,e:"tr",f:[{p:[42,4,2349],t:7,e:"td",f:[{p:[42,8,2353],t:7,e:"b",f:["Card Reader:"]}]},{p:[43,4,2377],t:7,e:"td",f:[{p:[43,8,2381],t:7,e:"ui-button",a:{action:"hw_card",params:'{"card" : "0"}',state:[{t:2,x:{r:["data.hw_card"],s:'_0==0?"selected":null'},p:[43,67,2440]}]},f:["None"]}]},{p:[44,4,2504],t:7,e:"td",f:[{p:[44,8,2508],t:7,e:"ui-button",a:{action:"hw_card",params:'{"card" : "1"}',state:[{t:2,x:{r:["data.hw_card"],s:'_0==1?"selected":null'},p:[44,67,2567]}]},f:["Standard"]}]}]}]}," ",{t:4,f:[" ",{p:[49,4,2706],t:7,e:"table",f:[{p:[50,5,2719],t:7,e:"tr",f:[{p:[51,6,2730],t:7,e:"td",f:[{p:[51,10,2734],t:7,e:"b",f:["Processor Unit:"]}]},{p:[52,6,2763],t:7,e:"td",f:[{p:[52,10,2767],t:7,e:"ui-button",a:{action:"hw_cpu",params:'{"cpu" : "1"}',state:[{t:2,x:{r:["data.hw_cpu"],s:'_0==1?"selected":null'},p:[52,67,2824]}]},f:["Standard"]}]},{p:[53,6,2893],t:7,e:"td",f:[{p:[53,10,2897],t:7,e:"ui-button",a:{action:"hw_cpu",params:'{"cpu" : "2"}',state:[{t:2,x:{r:["data.hw_cpu"],s:'_0==2?"selected":null'},p:[53,67,2954]}]},f:["Advanced"]}]}]}," ",{p:[55,5,3033],t:7,e:"tr",f:[{p:[56,6,3044],t:7,e:"td",f:[{p:[56,10,3048],t:7,e:"b",f:["Tesla Relay:"]}]},{p:[57,6,3074],t:7,e:"td",f:[{p:[57,10,3078],t:7,e:"ui-button",a:{action:"hw_tesla",params:'{"tesla" : "0"}',state:[{t:2,x:{r:["data.hw_tesla"],s:'_0==0?"selected":null'},p:[57,71,3139]}]},f:["None"]}]},{p:[58,6,3206],t:7,e:"td",f:[{p:[58,10,3210],t:7,e:"ui-button",a:{action:"hw_tesla",params:'{"tesla" : "1"}',state:[{t:2,x:{r:["data.hw_tesla"],s:'_0==1?"selected":null'},p:[58,71,3271]}]},f:["Standard"]}]}]}]}],n:50,x:{r:["data.devtype"],s:"_0!=2"},p:[48,3,2659]}," ",{p:[62,3,3374],t:7,e:"table",f:[{p:[63,4,3386],t:7,e:"tr",f:[{p:[64,5,3396],t:7,e:"td",f:[{p:[64,9,3400],t:7,e:"b",f:["Confirm Order:"]}]},{p:[65,5,3427],t:7,e:"td",f:[{p:[65,9,3431],t:7,e:"ui-button",a:{action:"confirm_order"},f:["CONFIRM"]}]}]}]}," ",{p:[69,2,3512],t:7,e:"hr"}," ",{p:[70,2,3519],t:7,e:"b",f:["Battery"]}," allows your device to operate without external utility power source. Advanced batteries increase battery life.",{p:[70,127,3644],t:7,e:"br"}," ",{p:[71,2,3651],t:7,e:"b",f:["Hard Drive"]}," stores file on your device. Advanced drives can store more files, but use more power, shortening battery life.",{p:[71,130,3779],t:7,e:"br"}," ",{p:[72,2,3786],t:7,e:"b",f:["Network Card"]}," allows your device to wirelessly connect to stationwide NTNet network. Basic cards are limited to on-station use, while advanced cards can operate anywhere near the station, which includes the asteroid outposts.",{p:[72,233,4017],t:7,e:"br"}," ",{p:[73,2,4024],t:7,e:"b",f:["Processor Unit"]}," is critical for your device's functionality. It allows you to run programs from your hard drive. Advanced CPUs use more power, but allow you to run more programs on background at once.",{p:[73,208,4230],t:7,e:"br"}," ",{p:[74,2,4237],t:7,e:"b",f:["Tesla Relay"]}," is an advanced wireless power relay that allows your device to connect to nearby area power controller to provide alternative power source. This component is currently unavailable on tablet computers due to size restrictions.",{p:[74,246,4481],t:7,e:"br"}," ",{p:[75,2,4488],t:7,e:"b",f:["Nano Printer"]}," is device that allows for various paperwork manipulations, such as, scanning of documents or printing new ones. This device was certified EcoFriendlyPlus and is capable of recycling existing paper for printing purposes.",{p:[75,241,4727],t:7,e:"br"}," ",{p:[76,2,4734],t:7,e:"b",f:["Card Reader"]}," adds a slot that allows you to manipulate RFID cards. Please note that this is not necessary to allow the device to read your identification, it is just necessary to manipulate other cards."]}]},{t:4,n:50,x:{r:["data.state"],s:"(!(_0==1))&&(_0==2)"},f:[" ",{p:[79,2,4981],t:7,e:"h2",f:["Step 3: Payment"]}," ",{p:[80,2,5008],t:7,e:"b",f:["Your device is now ready for fabrication.."]},{p:[80,51,5057],t:7,e:"br"}," ",{p:[81,2,5064],t:7,e:"i",f:["Please ensure the required amount of credits are in the machine, then press purchase."]},{p:[81,94,5156],t:7,e:"br"}," ",{p:[82,2,5163],t:7,e:"i",f:["Current credits: ",{p:[82,22,5183],t:7,e:"b",f:[{t:2,r:"data.credits",p:[82,25,5186]},"C"]}]},{p:[82,50,5211],t:7,e:"br"}," ",{p:[83,2,5218],t:7,e:"i",f:["Total price: ",{p:[83,18,5234],t:7,e:"b",f:[{t:2,r:"data.totalprice",p:[83,21,5237]},"C"]}]},{p:[83,49,5265],t:7,e:"br"},{p:[83,53,5269],t:7,e:"br"}," ",{p:[84,2,5276],t:7,e:"ui-button",a:{action:"purchase",state:[{t:2,x:{r:["data.credits","data.totalprice"],s:'_0>=_1?null:"disabled"'},p:[84,38,5312]}]},f:["PURCHASE"]}]},{t:4,n:50,x:{r:["data.state"],s:"(!(_0==1))&&((!(_0==2))&&(_0==3))"},f:[" ",{p:[87,2,5423],t:7,e:"h2",f:["Step 4: Thank you for your purchase"]},{p:[87,46,5467],t:7,e:"br"}," ",{p:[88,2,5474],t:7,e:"b",f:["Should you experience any issues with your new device, contact your local network admin for assistance."]}]}],x:{r:["data.state"],s:"_0==0"}}]},e.exports=a.extend(r.exports)},{341:341}],385:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,1,22],t:7,e:"ui-display",f:[{p:[3,2,37],t:7,e:"ui-section",a:{label:"Cap"},f:[{p:[4,3,65],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.is_capped"],s:'_0?"power-off":"close"'},p:[4,20,82]}],style:[{t:2,x:{r:["data.is_capped"],s:'_0?null:"selected"'},p:[4,71,133]}],action:"toggle_cap"},f:[{t:2,x:{r:["data.is_capped"],s:'_0?"On":"Off"'},p:[6,4,202]}]}]}]}],n:50,r:"data.has_cap",p:[1,1,0]},{p:[10,1,288],t:7,e:"ui-display",f:[{t:4,f:[{p:[14,2,419],t:7,e:"ui-section",f:[{p:[15,3,435],t:7,e:"ui-button",a:{action:"select_colour"},f:["Select New Colour"]}]}],n:50,r:"data.can_change_colour",p:[13,1,386]}]}," ",{p:[19,1,540],t:7,e:"ui-display",a:{title:"Stencil"},f:[{t:4,f:[{p:[21,2,599],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[21,21,618]}]},f:[{t:4,f:[{p:[23,7,655],t:7,e:"ui-button",a:{action:"select_stencil",params:['{"item":"',{t:2,r:"item",p:[23,59,707]},'"}'],style:[{t:2,x:{r:["item","data.selected_stencil"],s:'_0==_1?"selected":null'},p:[24,12,731]}]},f:[{t:2,r:"item",p:[25,4,791]}]}],n:52,r:"items",p:[22,3,632]}]}],n:52,r:"data.drawables",p:[20,3,572]}]}," ",{p:[31,1,874],t:7,e:"ui-display",a:{title:"Text Mode"},f:[{p:[32,2,907],t:7,e:"ui-section",a:{label:"Current Buffer"},f:[{t:2,r:"data.text_buffer",p:[32,37,942]}]}," ",{p:[34,2,981],t:7,e:"ui-section",f:[{p:[34,14,993],t:7,e:"ui-button",a:{action:"enter_text"},f:["New Text"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],386:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{isHead:function(t){return t%10==0},dept_class:function(t){return 0==t?"dept-cap":t>=10&&20>t?"dept-sec":t>=20&&30>t?"dept-med":t>=30&&40>t?"dept-sci":t>=40&&50>t?"dept-eng":t>=50&&60>t?"dept-cargo":t>=200&&230>t?"dept-cent":"dept-other"},health_state:function(t,e,n,a){var r=t+e+n+a;return 0>=r?"health-5":25>=r?"health-4":50>=r?"health-3":75>=r?"health-2":"health-0"}}}}(r),r.exports.css=" .health {\r\n width: 16px;\r\n height: 16px;\r\n background-color: #FFF;\r\n border: 1px solid #434343;\r\n position: relative;\r\n top: 2px;\r\n display: inline-block;\r\n }\r\n .health-5 { background-color: #17d568; }\r\n .health-4 { background-color: #2ecc71; }\r\n .health-3 { background-color: #e67e22; }\r\n .health-2 { background-color: #ed5100; }\r\n .health-1 { background-color: #e74c3c; }\r\n .health-0 { background-color: #ed2814; }\r\n\r\n .dept-cap {color : #C06616;}\r\n .dept-sec {color : #E74C3C;}\r\n .dept-med {color : #3498DB;}\r\n .dept-sci {color : #9B59B6;}\r\n .dept-eng {color : #F1C40F;}\r\n .dept-cargo {color : #F39C12;}\r\n .dept-cent {color : #00C100;}\r\n .dept-other {color: #C38312;}\r\n\r\n .oxy { color : #3498db; }\r\n .toxin { color : #2ecc71; }\r\n .burn { color : #e67e22; }\r\n .brute { color : #e74c3c; }\r\n\r\n table.crew{\r\n border-collapse: collapse;\r\n }\r\n\r\n table.crew td {\r\n padding : 0px 10px;\r\n }",r.exports.template={v:3,t:[" ",{p:[27,1,1030],t:7,e:"ui-display",f:[{p:[28,2,1045],t:7,e:"ui-section",f:[{p:[29,3,1061],t:7,e:"table",a:{"class":"crew"},f:[{p:[30,3,1085],t:7,e:"thead",f:[{p:[31,3,1096],t:7,e:"tr",f:[{p:[32,4,1105],t:7,e:"th",f:["Name"]}," ",{p:[33,4,1123],t:7,e:"th",f:["Status"]}," ",{p:[34,4,1143],t:7,e:"th",f:["Vitals"]}," ",{p:[35,4,1163],t:7,e:"th",f:["Position"]}," ",{t:4,f:[{p:[37,5,1216],t:7,e:"th",f:["Tracking"]}],n:50,r:"data.link_allowed",p:[36,4,1185]}]}]}," ",{p:[41,3,1270],t:7,e:"tbody",f:[{t:4,f:[{p:[43,4,1308],t:7,e:"tr",f:[{p:[44,5,1318],t:7,e:"td",f:[{p:[45,6,1329],t:7,e:"span",a:{"class":[{t:2,x:{r:["isHead","ijob"],s:'_0(_1)?"bold ":""'},p:[45,19,1342]},{t:2,x:{r:["dept_class","ijob"],s:"_0(_1)"},p:[45,49,1372]}]},f:[{t:2,r:"name",p:[46,7,1402]}," (",{t:2,r:"assignment",p:[46,17,1412]},") ",{p:[47,6,1434],t:7,e:"span",f:[]}]}]}," ",{p:[49,5,1457],t:7,e:"td",f:[{t:4,f:[{p:[51,7,1498],t:7,e:"span",a:{"class":["health ",{t:2,x:{r:["health_state","oxydam","toxdam","burndam","brutedam"],s:"_0(_1,_2,_3,_4)"},p:[51,27,1518]}]}}],n:50,x:{r:["oxydam"],s:"_0!=null"},p:[50,6,1468]},{t:4,n:51,f:[{t:4,f:[{p:[54,8,1626],t:7,e:"span",a:{"class":"health health-5"}}],n:50,r:"life_status",p:[53,7,1598]},{t:4,n:51,f:[{p:[56,8,1688],t:7,e:"span",a:{"class":"health health-0"}}],r:"life_status"}],x:{r:["oxydam"],s:"_0!=null"}}]}," ",{p:[60,5,1771],t:7,e:"td",f:[{t:4,f:[{p:[62,7,1812],t:7,e:"span",f:["( ",{p:[64,8,1836],t:7,e:"span",a:{"class":"oxy"},f:[{t:2,r:"oxydam",p:[64,26,1854]}]}," / ",{p:[66,8,1890],t:7,e:"span",a:{"class":"toxin"},f:[{t:2,r:"toxdam",p:[66,28,1910]}]}," / ",{p:[68,8,1946],t:7,e:"span",a:{"class":"burn"},f:[{t:2,r:"burndam",p:[68,27,1965]}]}," / ",{p:[70,8,2002],t:7,e:"span",a:{"class":"brute"},f:[{t:2,r:"brutedam",p:[70,28,2022]}]}," )"]}],n:50,x:{r:["oxydam"],s:"_0!=null"},p:[61,6,1782]},{t:4,n:51,f:[{t:4,f:[{p:[75,8,2116],t:7,e:"span",f:["Alive"]}],n:50,r:"life_status",p:[74,7,2088]},{t:4,n:51,f:[{p:[77,8,2159],t:7,e:"span",f:["Dead"]}],r:"life_status"}],x:{r:["oxydam"],s:"_0!=null"}}]}," ",{p:[81,5,2222],t:7,e:"td",f:[{t:4,f:[{p:[83,6,2260],t:7,e:"span", +f:[{t:2,r:"area",p:[83,12,2266]}]}],n:50,x:{r:["pos_x"],s:"_0!=null"},p:[82,5,2232]},{t:4,n:51,f:[{p:[85,6,2302],t:7,e:"span",f:["N/A"]}],x:{r:["pos_x"],s:"_0!=null"}}]}," ",{t:4,f:[{p:[89,6,2381],t:7,e:"td",f:[{p:[90,7,2393],t:7,e:"ui-button",a:{action:"select_person",state:[{t:2,x:{r:["can_track"],s:'_0?null:"disabled"'},p:[90,48,2434]}],params:['{"name":"',{t:2,r:"name",p:[90,100,2486]},'"}']},f:["Track"]}]}],n:50,r:"data.link_allowed",p:[88,5,2348]}]}],n:52,r:"data.sensors",p:[42,3,1281]}]}]}]}]}," "]},e.exports=a.extend(r.exports)},{341:341}],387:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,33],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,66],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,72]}]}]}," ",{t:4,f:[{p:[6,5,189],t:7,e:"ui-section",a:{label:"State"},f:[{p:[7,7,223],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[7,20,236]}]},f:[{t:2,r:"data.occupant.stat",p:[7,49,265]}]}]}," ",{p:[9,4,317],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[10,6,356],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.temperaturestatus",p:[10,19,369]}]},f:[{t:2,r:"data.occupant.bodyTemperature",p:[10,56,406]}," K"]}]}," ",{p:[12,5,472],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[13,7,507],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[13,20,520]}],max:[{t:2,r:"data.occupant.maxHealth",p:[13,54,554]}],value:[{t:2,r:"data.occupant.health",p:[13,90,590]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[14,16,632]}]},f:[{t:2,r:"data.occupant.health",p:[14,68,684]}]}]}," ",{t:4,f:[{p:[17,7,908],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[17,26,927]}]},f:[{p:[18,9,948],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[18,30,969]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[18,66,1005]}],state:"bad"},f:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[18,103,1042]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[16,5,742]}],n:50,r:"data.hasOccupant",p:[5,3,159]}]}," ",{p:[23,1,1138],t:7,e:"ui-display",a:{title:"Cell"},f:[{p:[24,3,1167],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[25,5,1199],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOperating"],s:'_0?"power-off":"close"'},p:[25,22,1216]}],style:[{t:2,x:{r:["data.isOperating"],s:'_0?"selected":null'},p:[26,14,1276]}],state:[{t:2,x:{r:["data.isOpen"],s:'_0?"disabled":null'},p:[27,14,1332]}],action:"power"},f:[{t:2,x:{r:["data.isOperating"],s:'_0?"On":"Off"'},p:[28,22,1391]}]}]}," ",{p:[30,3,1459],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[31,3,1495],t:7,e:"span",a:{"class":[{t:2,r:"data.temperaturestatus",p:[31,16,1508]}]},f:[{t:2,r:"data.cellTemperature",p:[31,44,1536]}," K"]}]}," ",{p:[33,2,1588],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[34,5,1619],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isOpen"],s:'_0?"unlock":"lock"'},p:[34,22,1636]}],action:"door"},f:[{t:2,x:{r:["data.isOpen"],s:'_0?"Open":"Closed"'},p:[34,73,1687]}]}," ",{p:[35,5,1740],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoEject"],s:'_0?"sign-out":"sign-in"'},p:[35,22,1757]}],action:"autoeject"},f:[{t:2,x:{r:["data.autoEject"],s:'_0?"Auto":"Manual"'},p:[35,86,1821]}]}]}]}," ",{p:{button:[{p:[40,5,1967],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.isBeakerLoaded"],s:'_0?null:"disabled"'},p:[40,36,1998]}],action:"ejectbeaker"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{p:[42,3,2101],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{t:4,f:[{p:[45,9,2211],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,r:"volume",p:[45,52,2254]}," units of ",{t:2,r:"name",p:[45,72,2274]}]},{p:[45,87,2289],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[44,7,2171]},{t:4,n:51,f:[{p:[47,9,2320],t:7,e:"span",a:{"class":"bad"},f:["Beaker Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[43,5,2136]},{t:4,n:51,f:[{p:[50,7,2396],t:7,e:"span",a:{"class":"average"},f:["No Beaker"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],388:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,2,15],t:7,e:"ui-section",a:{label:"State"},f:[{t:4,f:[{p:[4,4,76],t:7,e:"span",a:{"class":"good"},f:["Ready"]}],n:50,r:"data.full_pressure",p:[3,3,45]},{t:4,n:51,f:[{t:4,f:[{p:[7,5,153],t:7,e:"span",a:{"class":"bad"},f:["Power Disabled"]}],n:50,r:"data.panel_open",p:[6,4,124]},{t:4,n:51,f:[{t:4,f:[{p:[10,6,248],t:7,e:"span",a:{"class":"average"},f:["Pressurizing"]}],n:50,r:"data.pressure_charging",p:[9,5,211]},{t:4,n:51,f:[{p:[12,6,310],t:7,e:"span",a:{"class":"bad"},f:["Off"]}],r:"data.pressure_charging"}],r:"data.panel_open"}],r:"data.full_pressure"}]}," ",{p:[17,2,393],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[18,3,426],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.per",p:[18,36,459]}],state:"good"},f:[{t:2,r:"data.per",p:[18,63,486]},"%"]}]}," ",{p:[20,5,530],t:7,e:"ui-section",a:{label:"Handle"},f:[{p:[21,9,567],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.flush"],s:'_0?"toggle-on":"toggle-off"'},p:[22,10,589]}],state:[{t:2,x:{r:["data.isai","data.panel_open"],s:'_0||_1?"disabled":null'},p:[23,11,647]}],action:[{t:2,x:{r:["data.flush"],s:'_0?"handle-0":"handle-1"'},p:[24,12,714]}]},f:[{t:2,x:{r:["data.flush"],s:'_0?"Disengage":"Engage"'},p:[25,5,763]}]}]}," ",{p:[27,2,837],t:7,e:"ui-section",a:{label:"Eject"},f:[{p:[28,3,867],t:7,e:"ui-button",a:{icon:"sign-out",state:[{t:2,x:{r:["data.isai"],s:'_0?"disabled":null'},p:[28,37,901]}],action:"eject"},f:["Eject Contents"]},{p:[28,114,978],t:7,e:"br"}]}," ",{p:[30,2,1002],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[31,3,1032],t:7,e:"ui-button",a:{icon:"power-off",state:[{t:2,x:{r:["data.panel_open"],s:'_0?"disabled":null'},p:[31,38,1067]}],action:[{t:2,x:{r:["data.pressure_charging"],s:'_0?"pump-0":"pump-1"'},p:[31,87,1116]}],style:[{t:2,x:{r:["data.pressure_charging"],s:'_0?"selected":null'},p:[31,145,1174]}]}},{p:[31,206,1235],t:7,e:"br"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],389:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"DNA Vault Database"},f:[{p:[2,3,43],t:7,e:"ui-section",a:{label:"Human DNA"},f:[{p:[3,7,81],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.dna_max",p:[3,28,102]}],value:[{t:2,r:"data.dna",p:[3,53,127]}]},f:[{t:2,r:"data.dna",p:[3,67,141]},"/",{t:2,r:"data.dna_max",p:[3,80,154]}," Samples"]}]}," ",{p:[5,3,208],t:7,e:"ui-section",a:{label:"Plant Data"},f:[{p:[6,5,245],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.plants_max",p:[6,26,266]}],value:[{t:2,r:"data.plants",p:[6,54,294]}]},f:[{t:2,r:"data.plants",p:[6,71,311]},"/",{t:2,r:"data.plants_max",p:[6,87,327]}," Samples"]}]}," ",{p:[8,3,384],t:7,e:"ui-section",a:{label:"Animal Data"},f:[{p:[9,5,422],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.animals_max",p:[9,26,443]}],value:[{t:2,r:"data.animals",p:[9,55,472]}]},f:[{t:2,r:"data.animals",p:[9,73,490]},"/",{t:2,r:"data.animals_max",p:[9,90,507]}," Samples"]}]}]}," ",{t:4,f:[{p:[13,1,616],t:7,e:"ui-display",a:{title:"Personal Gene Therapy"},f:[{p:[14,3,663],t:7,e:"ui-section",f:[{p:[15,2,678],t:7,e:"span",f:["Applicable gene therapy treatments:"]}]}," ",{p:[17,3,747],t:7,e:"ui-section",f:[{p:[18,2,762],t:7,e:"ui-button",a:{action:"gene",params:['{"choice": "',{t:2,r:"data.choiceA",p:[18,47,807]},'"}']},f:[{t:2,r:"data.choiceA",p:[18,67,827]}]}," ",{p:[19,2,858],t:7,e:"ui-button",a:{action:"gene",params:['{"choice": "',{t:2,r:"data.choiceB",p:[19,47,903]},'"}']},f:[{t:2,r:"data.choiceB",p:[19,67,923]}]}]}]}],n:50,x:{r:["data.completed","data.used"],s:"_0&&!_1"},p:[12,1,578]}]},e.exports=a.extend(r.exports)},{341:341}],390:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,33],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,66],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,72]}]}]}," ",{t:4,f:[{p:[6,5,183],t:7,e:"ui-section",a:{label:"Items in storage"},f:[{p:[7,4,225],t:7,e:"span",f:[{t:2,r:"data.items",p:[7,10,231]}]}]}],n:50,r:"data.items",p:[5,3,159]}," ",{t:4,f:[{p:[11,5,310],t:7,e:"ui-section",a:{label:"State"},f:[{p:[12,7,344],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[12,20,357]}]},f:[{t:2,r:"data.occupant.stat",p:[12,49,386]}]}]}," ",{p:[14,5,439],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[15,7,474],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[15,20,487]}],max:[{t:2,r:"data.occupant.maxHealth",p:[15,54,521]}],value:[{t:2,r:"data.occupant.health",p:[15,90,557]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[16,16,599]}]},f:[{t:2,x:{r:["adata.occupant.health"],s:"Math.round(_0)"},p:[16,68,651]}]}]}," ",{t:4,f:[{p:[19,7,888],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[19,26,907]}]},f:[{p:[20,9,928],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[20,30,949]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[20,66,985]}],state:"bad"},f:[{t:2,x:{r:["type","adata.occupant"],s:"Math.round(_1[_0])"},p:[20,103,1022]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[18,5,722]}," ",{p:[23,5,1109],t:7,e:"ui-section",a:{label:"Cells"},f:[{p:[24,9,1145],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"bad":"good"'},p:[24,22,1158]}]},f:[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"Damaged":"Healthy"'},p:[24,68,1204]}]}]}," ",{p:[26,5,1287],t:7,e:"ui-section",a:{label:"Brain"},f:[{p:[27,9,1323],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"bad":"good"'},p:[27,22,1336]}]},f:[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"Abnormal":"Healthy"'},p:[27,68,1382]}]}]}," ",{p:[29,5,1466],t:7,e:"ui-section",a:{label:"Bloodstream"},f:[{t:4,f:[{p:[31,11,1553],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,1)"},p:[31,54,1596]}," units of ",{t:2,r:"name",p:[31,89,1631]}]},{p:[31,104,1646],t:7,e:"br"}],n:52,r:"adata.occupant.reagents",p:[30,9,1508]},{t:4,n:51,f:[{p:[33,11,1681],t:7,e:"span",a:{"class":"good"},f:["Pure"]}],r:"adata.occupant.reagents"}]}],n:50,r:"data.occupied",p:[10,3,283]}]}," ",{p:[38,1,1777],t:7,e:"ui-display",a:{title:"Operations"},f:[{p:[39,3,1812],t:7,e:"ui-section",a:{label:"Inject"},f:[{t:4,f:[{p:[41,7,1872],t:7,e:"ui-button",a:{icon:"flask",state:[{t:2,x:{r:["data.occupied"],s:'_0?null:"disabled"'},p:[41,38,1903]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[41,111,1976]},'"}']},f:[{t:2,r:"name",p:[41,121,1986]}]},{p:[41,141,2006],t:7,e:"br"}],n:52,r:"data.chem",p:[40,5,1845]}]}," ",{p:[44,2,2046],t:7,e:"ui-section",a:{label:"Eject"},f:[{p:[45,6,2079],t:7,e:"ui-button",a:{icon:"sign-out",action:"eject"},f:["Eject Contents"]}]}," ",{p:[47,2,2166],t:7,e:"ui-section",a:{label:"Self Cleaning"},f:[{p:[48,3,2204],t:7,e:"ui-button",a:{icon:"recycle",action:"cleaning"},f:["Self-Clean Cycle"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],391:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,24],t:7,e:"ui-display",a:{title:[{t:2,r:"data.question",p:[2,21,42]}]},f:[{p:[3,5,66],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,9,118],t:7,e:"ui-button",a:{action:"vote",params:['{"answer": "',{t:2,r:"answer",p:[6,45,174]},'"}'],style:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[7,18,206]}]},f:[{t:2,r:"answer",p:[7,53,241]}," (",{t:2,r:"amount",p:[7,65,253]},")"]}],n:52,r:"data.answers",p:[4,7,86]}]}]}],n:50,r:"data.shaking",p:[1,1,0]},{t:4,n:51,f:[{p:[13,3,353],t:7,e:"ui-notice",f:["The eightball is not currently being shaken."]}],r:"data.shaking"}]},e.exports=a.extend(r.exports)},{341:341}],392:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,5,17],t:7,e:"span",f:["Time Until Launch: ",{t:2,r:"data.timer_str",p:[2,30,42]}]}]}," ",{p:[4,1,83],t:7,e:"ui-notice",f:[{p:[5,3,98],t:7,e:"span",f:["Engines: ",{t:2,x:{r:["data.engines_started"],s:'_0?"Online":"Idle"'},p:[5,18,113]}]}]}," ",{p:[7,1,180],t:7,e:"ui-display",a:{title:"Early Launch"},f:[{p:[8,2,216],t:7,e:"span",f:["Authorizations Remaining: ",{t:2,x:{r:["data.emagged","data.authorizations_remaining"],s:'_0?"ERROR":_1'},p:[9,2,250]}]}," ",{p:[10,2,318],t:7,e:"ui-button",a:{icon:"exclamation-triangle",action:"authorize",style:"danger",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[12,10,404]}]},f:["AUTHORIZE"]}," ",{p:[15,2,473],t:7,e:"ui-button",a:{icon:"minus",action:"repeal",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[16,10,523]}]},f:["Repeal"]}," ",{p:[19,2,589],t:7,e:"ui-button",a:{icon:"close",action:"abort",state:[{t:2,x:{r:["data.enabled"],s:'_0?null:"disabled"'},p:[20,10,638]}]},f:["Repeal All"]}]}," ",{p:[24,1,722],t:7,e:"ui-display",a:{title:"Authorizations"},f:[{t:4,f:[{p:[26,3,793],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{t:2,r:"name",p:[26,34,824]}," (",{t:2,r:"job",p:[26,44,834]},")"]}],n:52,r:"data.authorizations",p:[25,2,760]},{t:4,n:51,f:[{p:[28,3,870],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:["No authorizations."]}],r:"data.authorizations"}]}]},e.exports=a.extend(r.exports)},{341:341}],393:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Message"},f:[{t:2,r:"data.hidden_message",p:[3,5,50]}]}," ",{p:[5,3,94],t:7,e:"ui-section",a:{label:"Created On"},f:[{t:2,r:"data.realdate",p:[6,5,131]}]}," ",{p:[8,3,169],t:7,e:"ui-section",a:{label:"Approval"},f:[{p:[9,5,204],t:7,e:"ui-button",a:{icon:"arrow-up",state:[{t:2,x:{r:["data.is_creator","data.has_liked"],s:'_0?"disabled":_1?"selected":null'},p:[11,14,252]}],action:"like"},f:[{t:2,r:"data.num_likes",p:[12,21,344]}]}," ",{p:[13,5,380],t:7,e:"ui-button",a:{icon:"circle",state:[{t:2,x:{r:["data.is_creator","data.has_liked","data.has_disliked"],s:'_0?"disabled":!_1&&!_2?"selected":null'},p:[15,14,426]}],action:"neutral"}}," ",{p:[17,5,562],t:7,e:"ui-button",a:{icon:"arrow-down",state:[{t:2,x:{r:["data.is_creator","data.has_disliked"],s:'_0?"disabled":_1?"selected":null'},p:[19,14,612]}],action:"dislike"},f:[{t:2,r:"data.num_dislikes",p:[20,24,710]}]}]}]}," ",{t:4,f:[{p:[24,3,805],t:7,e:"ui-display",a:{title:"Admin Panel"},f:[{p:[25,5,843],t:7,e:"ui-section",a:{label:"Creator Ckey"},f:[{t:2,r:"data.creator_key",p:[25,38,876]}]}," ",{p:[26,5,915],t:7,e:"ui-section",a:{label:"Creator Character Name"},f:[{t:2,r:"data.creator_name",p:[26,48,958]}]}," ",{p:[27,5,998],t:7,e:"ui-button",a:{icon:"remove",action:"delete",style:"danger"},f:["Delete"]}]}],n:50,r:"data.admin_mode",p:[23,1,778]}]},e.exports=a.extend(r.exports)},{341:341}],394:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,15],t:7,e:"span",f:["The requested interface (",{t:2,r:"config.interface",p:[2,34,46]},") was not found. Does it exist?"]}]}]},e.exports=a.extend(r.exports)},{341:341}],395:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,20],t:7,e:"ui-notice",f:["Currently syncing with the database"]}],n:50,r:"data.sync",p:[1,1,0]},{t:4,n:51,f:[{p:{button:[{p:[8,4,163],t:7,e:"ui-button",a:{icon:"eject",action:"eject_all"},f:["Eject all"]}," ",{p:[9,4,232],t:7,e:"ui-button",a:{icon:["toggle-",{t:2,x:{r:["data.show_materials"],s:'_0?"off":"on"'},p:[9,28,256]}],action:"toggle_materials_visibility"},f:[{t:2,x:{r:["data.show_materials"],s:'_0?"Hide":"Show"'},p:[10,5,339]}]}]},t:7,e:"ui-display",a:{title:"Materials",button:0},f:[" ",{t:4,f:[{p:[14,4,449],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[15,5,484],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[16,6,520],t:7,e:"section",a:{"class":"cell"}}," ",{p:[17,6,559],t:7,e:"section",a:{"class":"cell"},f:["Mineral"]}," ",{p:[20,6,620],t:7,e:"section",a:{"class":"cell"},f:["Amount"]}," ",{p:[23,6,680],t:7,e:"section",a:{"class":"cell"}}," ",{p:[24,6,719],t:7,e:"section",a:{"class":"cell"}}]}," ",{t:4,f:[{p:[27,6,808],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[28,7,845],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[29,8,876]}]}," ",{p:[31,7,910],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"amount",p:[32,8,941]}]}," ",{p:[34,7,977],t:7,e:"section",a:{"class":"cell"},f:[{p:[35,8,1008],t:7,e:"ui-button",a:{icon:"eject"},f:["Release amount"]}]}," ",{p:[37,7,1084],t:7,e:"section",a:{"class":"cell",style:"width: 40px;"},f:[{p:[38,8,1136],t:7,e:"ui-button",a:{icon:"eject"},f:["Release all"]}]}]}],n:52,r:"data.all_materials",p:[26,5,773]}]}],n:50,r:"data.show_materials",p:[13,3,417]}]}," ",{p:[45,2,1274],t:7,e:"ui-display",a:{title:"Categories"},f:[{t:4,f:[{p:[47,4,1334],t:7,e:"ui-button",f:[{t:2,r:".",p:[47,15,1345]}]}],r:"data.categories",p:[46,3,1309]}]}],r:"data.sync"}]},e.exports=a.extend(r.exports)},{341:341}],396:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,3,16],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[3,5,49],t:7,e:"ui-button",a:{action:"toggle_power",style:[{t:2,x:{r:["data.toggle"],s:'_0?"selected":null'},p:[5,18,111]}]},f:["Turn ",{t:2,x:{r:["data.toggle"],s:'_0?"off":"on"'},p:[6,16,166]}]}]}," ",{p:[9,3,235],t:7,e:"ui-display",a:{title:"Logging"},f:[{t:4,f:[{p:[11,3,292],t:7,e:"ui-section",a:{label:">"},f:[{t:2,r:".",p:[11,25,314]},{p:[11,30,319],t:7,e:"ui-section",f:[]}]}],n:52,r:"data.logs",p:[10,5,269]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],397:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[2,1,31],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[3,2,60],t:7,e:"ui-button",a:{icon:"power-off",style:[{t:2,x:{r:["data.power"],s:'_0?"selected":"danger"'},p:[3,37,95]}],action:"power"},f:[{t:2,x:{r:["data.power"],s:'_0?"Enabled":"Disabled"'},p:[3,92,150]}]}]}," ",{p:[5,1,218],t:7,e:"ui-section",a:{label:"Tag"},f:[{p:[6,2,245],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:[{t:2,r:"data.tag",p:[6,43,286]}]}]}," ",{p:[8,1,327],t:7,e:"ui-section",a:{label:"Scanning mode"},f:[{p:[9,2,364],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.updating"],s:'_0?"unlock":"lock"'},p:[9,18,380]}],style:[{t:2,x:{r:["data.updating"],s:'_0?null:"danger"'},p:[9,63,425]}],action:"updating",tooltip:"Toggle between automatic scanning or scan only when a button is pressed.","tooltip-side":"right"},f:[{t:2,x:{r:["data.updating"],s:'_0?"AUTO":"MANUAL"'},p:[9,221,583]}]}]}," ",{p:[11,1,649],t:7,e:"ui-section",a:{label:"Detection range"},f:[{p:[12,2,688],t:7,e:"ui-button",a:{icon:"refresh",style:[{t:2,x:{r:["data.globalmode"],s:'_0?null:"selected"'},p:[12,35,721]}],action:"globalmode",tooltip:"Local sector or whole region scanning.","tooltip-side":"right"},f:[{t:2,x:{r:["data.globalmode"],s:'_0?"MAXIMUM":"LOCAL"'},p:[12,165,851]}]}]}]}," ",{t:4,f:[{p:[16,2,957],t:7,e:"ui-display",a:{title:"Current Location"},f:[{p:[17,3,998],t:7,e:"span",f:[{t:2,r:"data.current",p:[17,9,1004]}]}]}," ",{p:[20,2,1048],t:7,e:"ui-display",a:{title:"Detected Signals"},f:[{t:4,f:[{p:[22,3,1114],t:7,e:"ui-section",a:{label:[{t:2,r:"entrytag",p:[22,21,1132]}]},f:[{p:[23,3,1149],t:7,e:"span",f:[{t:2,r:"area",p:[23,9,1155]}," (",{t:2,r:"coord",p:[23,19,1165]},")"]}," ",{t:4,f:[{p:[25,4,1209],t:7,e:"span",f:["Dist: ",{t:2,r:"dist",p:[25,16,1221]},"m Dir: ",{t:2,r:"degrees",p:[25,31,1236]},"° (",{t:2,r:"direction",p:[25,45,1250]},")"]}],n:50,r:"direction",p:[24,3,1187]}]}],n:52,r:"data.signals",p:[21,2,1088]}]}],n:50,r:"data.power",p:[15,1,936]}]},e.exports=a.extend(r.exports)},{341:341}],398:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Labor Camp Teleporter"},f:[{p:[2,2,45],t:7,e:"ui-section",a:{label:"Teleporter Status"},f:[{p:[3,3,87],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.teleporter"],s:'_0?"good":"bad"'},p:[3,16,100]}]},f:[{t:2,x:{r:["data.teleporter"],s:'_0?"Connected":"Not connected"'},p:[3,54,138]}]}]}," ",{t:4,f:[{p:[6,4,244],t:7,e:"ui-section",a:{label:"Location"},f:[{p:[7,5,279],t:7,e:"span",f:[{t:2,r:"data.teleporter_location",p:[7,11,285]}]}]}," ",{p:[9,4,343],t:7,e:"ui-section",a:{label:"Locked status"},f:[{p:[10,5,383],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.teleporter_lock"],s:'_0?"lock":"unlock"'},p:[10,22,400]}],action:"teleporter_lock"},f:[{t:2,x:{r:["data.teleporter_lock"],s:'_0?"Locked":"Unlocked"'},p:[10,93,471]}]}," ",{p:[11,5,537],t:7,e:"ui-button",a:{action:"toggle_open"},f:[{t:2,x:{r:["data.teleporter_state_open"],s:'_0?"Open":"Closed"'},p:[11,37,569]}]}]}],n:50,r:"data.teleporter",p:[5,3,216]},{t:4,n:51,f:[{p:[14,4,666],t:7,e:"span",f:[{p:[14,10,672],t:7,e:"ui-button",a:{action:"scan_teleporter"},f:["Scan Teleporter"]}]}],r:"data.teleporter"}]}," ",{p:[17,1,770],t:7,e:"ui-display",a:{title:"Labor Camp Beacon"},f:[{p:[18,2,811],t:7,e:"ui-section",a:{label:"Beacon Status"},f:[{p:[19,3,849],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.beacon"],s:'_0?"good":"bad"'},p:[19,16,862]}]},f:[{t:2,x:{r:["data.beacon"],s:'_0?"Connected":"Not connected"'},p:[19,50,896]}]}]}," ",{t:4,f:[{p:[22,3,992],t:7,e:"ui-section",a:{label:"Location"},f:[{p:[23,4,1026],t:7,e:"span",f:[{t:2,r:"data.beacon_location",p:[23,10,1032]}]}]}],n:50,r:"data.beacon",p:[21,2,969]},{t:4,n:51,f:[{p:[26,4,1097],t:7,e:"span",f:[{p:[26,10,1103],t:7,e:"ui-button",a:{action:"scan_beacon"},f:["Scan Beacon"]}]}],r:"data.beacon"}]}," ",{p:[29,1,1193],t:7,e:"ui-display",a:{title:"Prisoner details"},f:[{p:[30,2,1233],t:7,e:"ui-section",a:{label:"Prisoner ID"},f:[{p:[31,3,1269],t:7,e:"ui-button",a:{action:"handle_id"},f:[{t:2,x:{r:["data.id","data.id_name"],s:'_0?_1:"-------------"'},p:[31,33,1299]}]}]}," ",{t:4,f:[{p:[34,2,1392],t:7,e:"ui-section",a:{label:"Set ID goal"},f:[{p:[35,4,1429],t:7,e:"ui-button",a:{action:"set_goal"},f:[{t:2,r:"data.goal",p:[35,33,1458]}]}]}],n:50,r:"data.id",p:[33,2,1374]}," ",{p:[38,2,1512],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[39,3,1545],t:7,e:"span",f:[{t:2,x:{r:["data.prisoner.name"],s:'_0?_0:"No Occupant"'},p:[39,9,1551]}]}]}," ",{t:4,f:[{p:[42,3,1661],t:7,e:"ui-section",a:{label:"Criminal Status"},f:[{p:[43,4,1702],t:7,e:"span",f:[{t:2,r:"data.prisoner.crimstat",p:[43,10,1708]}]}]}],n:50,r:"data.prisoner",p:[41,2,1636]}]}," ",{p:[47,1,1785],t:7,e:"ui-display",f:[{p:[48,2,1800],t:7,e:"center",f:[{p:[48,10,1808],t:7,e:"ui-button",a:{action:"teleport",state:[{t:2,x:{r:["data.can_teleport"],s:'_0?null:"disabled"'},p:[48,45,1843]}]},f:["Process Prisoner"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],399:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Stored Items"},f:[{t:4,f:[{p:[3,3,59],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[3,22,78]}]},f:[{p:[4,4,93],t:7,e:"ui-button",a:{action:"release_items",params:['{"mobref":',{t:2,r:"mob",p:[4,56,145]},"}"],state:[{t:2,x:{r:["data.can_reclaim"],s:'_0?null:"disabled"'},p:[4,72,161]}]},f:["Drop Items"]}]}],n:52,r:"data.mobs",p:[2,2,36]}]}]},e.exports=a.extend(r.exports)},{341:341}],400:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{p:[3,3,70],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.emagged"],s:'_0?"un":null'},p:[3,20,87]},"lock"],state:[{t:2,x:{r:["data.can_toggle_safety"],s:'_0?null:"disabled"'},p:[3,63,130]}],action:"safety"},f:["Safeties: ",{p:[4,14,209],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.emagged"],s:'_0?"bad":"good"'},p:[4,27,222]}]},f:[{t:2,x:{r:["data.emagged"],s:'_0?"OFF":"ON"'},p:[4,62,257]}]}]}]},t:7,e:"ui-display",a:{title:"Default Programs",button:0},f:[" ",{t:4,f:[{p:[8,2,363],t:7,e:"ui-button",a:{action:"load_program",params:['{"type": ',{t:2,r:"type",p:[8,52,413]},"}"],style:[{t:2,x:{r:["data.program","type"],s:'_0==_1?"selected":null'},p:[8,70,431]}]},f:[{t:2,r:"name",p:[9,5,483]}," "]},{p:[10,14,506],t:7,e:"br"}],n:52,r:"data.default_programs",p:[7,2,329]}]}," ",{t:4,f:[{p:[14,2,562],t:7,e:"ui-display",a:{title:"Dangerous Programs"},f:[{t:4,f:[{p:[16,4,638],t:7,e:"ui-button",a:{icon:"warning",action:"load_program",params:['{"type": ',{t:2,r:"type",p:[16,69,703]},"}"],style:[{t:2,x:{r:["data.program","type"],s:'_0==_1?"selected":null'},p:[16,87,721]}]},f:[{t:2,r:"name",p:[17,5,773]}," "]},{p:[18,16,798],t:7,e:"br"}],n:52,r:"data.emag_programs",p:[15,3,605]}]}],n:50,r:"data.emagged",p:[13,1,539]}]},e.exports=a.extend(r.exports)},{341:341}],401:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{occupantStatState:function(){switch(this.get("data.occupant.stat")){case 0:return"good";case 1:return"average";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[15,1,280],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[16,3,313],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[17,3,346],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[17,9,352]}]}]}," ",{t:4,f:[{p:[20,5,466],t:7,e:"ui-section",a:{label:"State"},f:[{p:[21,7,500],t:7,e:"span",a:{"class":[{t:2,r:"occupantStatState",p:[21,20,513]}]},f:[{t:2,x:{r:["data.occupant.stat"],s:'_0==0?"Conscious":_0==1?"Unconcious":"Dead"'},p:[21,43,536]}]}]}],n:50,r:"data.occupied",p:[19,3,439]}]}," ",{p:[25,1,680],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[26,2,712],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[27,5,743],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"unlock":"lock"'},p:[27,22,760]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Open":"Closed"'},p:[27,71,809]}]}]}," ",{p:[29,3,874],t:7,e:"ui-section",a:{label:"Uses"},f:[{t:2,r:"data.ready_implants",p:[30,5,905]}," ",{t:4,f:[{p:[32,7,969],t:7,e:"span",a:{"class":"fa fa-cog fa-spin"}}],n:50,r:"data.replenishing",p:[31,5,936]}]}," ",{p:[35,3,1036],t:7,e:"ui-section",a:{label:"Activate"},f:[{p:[36,7,1073],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","data.ready_implants","data.ready"],s:'_0&&_1>0&&_2?null:"disabled"'},p:[36,25,1091]}],action:"implant"},f:[{t:2,x:{r:["data.ready","data.special_name"],s:'_0?(_1?_1:"Implant"):"Recharging"'},p:[37,9,1198]}," "]},{p:[38,19,1302],t:7,e:"br"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],402:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{healthState:function(){var t=this.get("data.health");return t>70?"good":t>50?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{t:4,f:[{p:[15,3,296],t:7,e:"ui-notice",f:[{p:[16,5,313],t:7,e:"span",f:["Wipe in progress!"]}]}],n:50,r:"data.wiping",p:[14,1,273]},{p:{button:[{t:4,f:[{p:[22,7,479],t:7,e:"ui-button",a:{icon:"trash",state:[{t:2,x:{r:["data.isDead"],s:'_0?"disabled":null'},p:[22,38,510]}],action:"wipe"},f:[{t:2,x:{r:["data.wiping"],s:'_0?"Stop Wiping":"Wipe"'},p:[22,89,561]}," AI"]}],n:50,r:"data.name",p:[21,5,454]}]},t:7,e:"ui-display",a:{title:[{t:2,x:{r:["data.name"],s:'_0||"Empty Card"'},p:[19,19,388]}],button:0},f:[" ",{t:4,f:[{p:[26,5,672],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[27,9,709],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.isDead","data.isBraindead"],s:'_0||_1?"bad":"good"'},p:[27,22,722]}]},f:[{t:2,x:{r:["data.isDead","data.isBraindead"],s:'_0||_1?"Offline":"Operational"'},p:[27,76,776]}]}]}," ",{p:[29,5,871],t:7,e:"ui-section",a:{label:"Software Integrity"},f:[{p:[30,7,918],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.health",p:[30,40,951]}],state:[{t:2,r:"healthState",p:[30,64,975]}]},f:[{t:2,x:{r:["adata.health"],s:"Math.round(_0)"},p:[30,81,992]},"%"]}]}," ",{p:[32,5,1055],t:7,e:"ui-section",a:{label:"Laws"},f:[{t:4,f:[{p:[34,9,1117],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:".",p:[34,33,1141]}]},{p:[34,45,1153],t:7,e:"br"}],n:52,r:"data.laws",p:[33,7,1088]}]}," ",{p:[37,5,1200],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[38,7,1237],t:7,e:"ui-button",a:{icon:"signal",style:[{t:2,x:{r:["data.wireless"],s:'_0?"selected":null'},p:[38,39,1269]}],action:"wireless"},f:["Wireless Activity"]}," ",{p:[39,7,1363],t:7,e:"ui-button",a:{icon:"microphone",style:[{t:2,x:{r:["data.radio"],s:'_0?"selected":null'},p:[39,43,1399]}],action:"radio"},f:["Subspace Radio"]}]}],n:50,r:"data.name",p:[25,3,649]}]}]},e.exports=a.extend(r.exports)},{341:341}],403:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,23],t:7,e:"ui-notice",f:[{p:[3,3,38],t:7,e:"span",f:["Waiting for another device to confirm your request..."]}]}],n:50,r:"data.waiting",p:[1,1,0]},{t:4,n:51,f:[{p:[6,2,132],t:7,e:"ui-display",f:[{p:[7,3,148],t:7,e:"ui-section",f:[{t:4,f:[{p:[9,5,197],t:7,e:"ui-button",a:{icon:"check",action:"auth_swipe"},f:["Authorize ",{t:2,r:"data.auth_required",p:[9,59,251]}]}],n:50,r:"data.auth_required",p:[8,4,165]},{t:4,n:51,f:[{p:[11,5,304],t:7,e:"ui-button",a:{icon:"warning",state:[{t:2,x:{r:["data.red_alert"],s:'_0?"disabled":null'},p:[11,38,337]}],action:"red_alert"},f:["Red Alert"]}," ",{p:[12,5,423],t:7,e:"ui-button",a:{icon:"wrench",state:[{t:2,x:{r:["data.emergency_maint"],s:'_0?"disabled":null'},p:[12,37,455]}],action:"emergency_maint"},f:["Emergency Maintenance Access"]}," ",{p:[13,5,572],t:7,e:"ui-button",a:{icon:"warning",state:"null",action:"bsa_unlock"},f:["Bluespace Artillery Unlock"]}],r:"data.auth_required"}]}]}],r:"data.waiting"}]},e.exports=a.extend(r.exports)},{341:341}],404:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Ore values"},f:[{t:4,f:[{p:[3,3,57],t:7,e:"ui-section",a:{label:[{t:2,r:"ore",p:[3,22,76]}]},f:[{p:[4,4,90],t:7,e:"span",f:[{t:2,r:"value",p:[4,10,96]}]}]}],n:52,r:"data.ores",p:[2,2,34]}]}," ",{p:[8,1,158],t:7,e:"ui-display",a:{title:"Points"},f:[{p:[9,2,188],t:7,e:"ui-section",a:{label:"Unclaimed points"},f:[{p:[10,3,229],t:7,e:"span",f:[{t:2,r:"data.unclaimed_points",p:[10,9,235]}]}," ",{p:[11,3,271],t:7,e:"ui-button",a:{action:"claim_points",state:[{t:2,x:{r:["data.unclaimed_points"],s:'_0?null:"disabled"'},p:[11,42,310]}]},f:["Claim points"]}]}]}," ",{p:[14,1,413],t:7,e:"ui-display",f:[{p:[15,2,428],t:7,e:"span",f:["Points: ",{t:2,r:"data.id_points",p:[15,16,442]}]}," ",{p:[16,2,470],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[17,3,501],t:7,e:"span",f:[{t:2,r:"data.status_info",p:[17,9,507]}]}," ",{p:[18,3,538],t:7,e:"ui-button",a:{action:"move_shuttle",state:[{t:2,x:{r:["data.can_go_home"],s:'_0?null:"disabled"'},p:[18,42,577]}]},f:["Move shuttle"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],405:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Known Languages"},f:[{t:4,f:[{p:[3,5,70],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[3,23,88]}]},f:[{p:[4,7,105],t:7,e:"span",f:[{t:2,r:"desc",p:[4,13,111]}]}," ",{p:[5,7,134],t:7,e:"span",f:["Key: ,",{t:2,r:"key",p:[5,19,146]}]}," ",{t:4,f:[{p:[7,9,192],t:7,e:"span",f:["(gained from mob)"]}],n:50,r:"shadow",p:[6,7,168]}," ",{p:[9,7,245],t:7,e:"span",f:[{t:2,x:{r:["can_speak"],s:'_0?"Can Speak":"Cannot Speak"'},p:[9,13,251]}]}," ",{t:4,f:[{p:[11,9,342],t:7,e:"ui-button",a:{action:"select_default",params:['{"language_name":"',{t:2,r:"name",p:[13,37,425]},'"}'],style:[{t:2,x:{r:["is_default","can_speak"],s:'_0?"selected":_1?null:"disabled"'},p:[14,18,455]}]},f:[{t:2,x:{r:["is_default"],s:'_0?"Default Language":"Select as Default"'},p:[15,10,526]}]}],n:50,r:"data.is_living",p:[10,7,310]}," ",{t:4,f:[{t:4,f:[{p:[20,11,685],t:7,e:"ui-button",a:{action:"grant_language",params:['{"language_name":"',{t:2,r:"name",p:[20,72,746]},'"}']},f:["Grant"]}],n:50,r:"shadow",p:[19,9,659]},{t:4,n:51,f:[{p:[22,11,805],t:7,e:"ui-button",a:{action:"remove_language",params:['{"language_name":"',{t:2,r:"name",p:[22,73,867]},'"}']},f:["Remove"]}],r:"shadow"}],n:50,r:"data.admin_mode",p:[18,7,626]}]}],n:52,r:"data.languages",p:[2,3,40]}]}," ",{t:4,f:[{t:4,f:[{p:[30,5,1033],t:7,e:"ui-button",a:{action:"toggle_omnitongue", +style:[{t:2,x:{r:["data.omnitongue"],s:'_0?"selected":null'},p:[32,14,1092]}]},f:["Omnitongue ",{t:2,x:{r:["data.omnitongue"],s:'_0?"Enabled":"Disabled"'},p:[33,19,1152]}]}],n:50,r:"data.is_living",p:[29,3,1005]}," ",{p:[36,3,1231],t:7,e:"ui-display",a:{title:"Unknown Languages"},f:[{t:4,f:[{p:[38,7,1315],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[38,25,1333]}]},f:[{p:[39,9,1352],t:7,e:"span",f:[{t:2,r:"desc",p:[39,15,1358]}]}," ",{p:[40,9,1383],t:7,e:"span",f:["Key: ,",{t:2,r:"key",p:[40,21,1395]}]}," ",{p:[41,9,1419],t:7,e:"ui-button",a:{action:"grant_language",params:['{"language_name":"',{t:2,r:"name",p:[43,37,1502]},'"}']},f:["Grant"]}]}],n:52,r:"data.unknown_languages",p:[37,5,1275]}]}],n:50,r:"data.admin_mode",p:[28,1,978]}]},e.exports=a.extend(r.exports)},{341:341}],406:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Controls"},f:[{t:4,f:[{t:4,f:[{p:[4,4,84],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[5,5,118],t:7,e:"span",f:["Launchpad closed."]}]}],n:50,r:"data.pad_closed",p:[3,3,56]},{t:4,n:51,f:[{p:[8,4,183],t:7,e:"ui-section",a:{label:"Launchpad"},f:[{p:[9,4,218],t:7,e:"span",f:[{p:[9,10,224],t:7,e:"b",f:[{t:2,r:"data.pad_name",p:[9,13,227]}]}]},{p:[9,41,255],t:7,e:"br"}," ",{p:[10,4,264],t:7,e:"ui-button",a:{icon:"pencil",action:"rename"},f:["Rename"]}," ",{p:[11,4,328],t:7,e:"ui-button",a:{icon:"remove",style:"danger",action:"remove"},f:["Remove"]}]}," ",{p:[14,4,427],t:7,e:"ui-section",a:{label:"Set Target"},f:[{p:[15,4,463],t:7,e:"table",f:[{p:[16,4,475],t:7,e:"tr",f:[{p:[17,5,485],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[17,38,518],t:7,e:"ui-button",a:{action:"up-left"},f:["↖"]}]}," ",{p:[18,5,570],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[18,57,622],t:7,e:"ui-button",a:{action:"up"},f:["↑"]}]}," ",{p:[19,5,669],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[19,56,720],t:7,e:"ui-button",a:{action:"up-right"},f:["↗"]}]}]}," ",{p:[21,4,782],t:7,e:"tr",f:[{p:[22,5,792],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[22,38,825],t:7,e:"ui-button",a:{action:"left",style:"width:35px!important"},f:["â†"]}]}," ",{p:[23,5,903],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[23,57,955],t:7,e:"ui-button",a:{action:"reset"},f:["R"]}]}," ",{p:[24,5,1005],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[24,56,1056],t:7,e:"ui-button",a:{action:"right"},f:["→"]}]}]}," ",{p:[26,4,1115],t:7,e:"tr",f:[{p:[27,5,1125],t:7,e:"td",a:{style:"width:25px!important"},f:[{p:[27,38,1158],t:7,e:"ui-button",a:{action:"down-left"},f:["↙"]}]}," ",{p:[28,5,1212],t:7,e:"td",a:{style:"width:25px!important; text-align:center"},f:[{p:[28,57,1264],t:7,e:"ui-button",a:{action:"down"},f:["↓"]}]}," ",{p:[29,5,1313],t:7,e:"td",a:{style:"width:25px!important; text-align:right"},f:[{p:[29,56,1364],t:7,e:"ui-button",a:{action:"down-right"},f:["↘"]}]}]}]}]}," ",{p:[33,4,1459],t:7,e:"ui-section",a:{label:"Current Target"},f:[{p:[34,5,1500],t:7,e:"span",f:[{t:2,r:"data.abs_y",p:[34,11,1506]}," ",{t:2,r:"data.north_south",p:[34,26,1521]}]},{p:[34,53,1548],t:7,e:"br"}," ",{p:[35,5,1558],t:7,e:"span",f:[{t:2,r:"data.abs_x",p:[35,11,1564]}," ",{t:2,r:"data.east_west",p:[35,26,1579]}]}]}," ",{p:[37,4,1627],t:7,e:"ui-section",a:{label:"Activate"},f:[{p:[38,5,1662],t:7,e:"ui-button",a:{action:"launch",tooltip:"Teleport everything on the pad to the target.","tooltip-side":"down"},f:["Launch"]}," ",{p:[39,5,1789],t:7,e:"ui-button",a:{action:"pull",tooltip:"Teleport everything from the target to the pad.","tooltip-side":"down"},f:["Pull"]}]}],r:"data.pad_closed"}],n:50,r:"data.has_pad",p:[2,2,32]},{t:4,n:51,f:[{p:[45,3,1956],t:7,e:"ui-section",a:{label:"Warning"},f:[{p:[46,4,1989],t:7,e:"span",f:["No launchpad found. Link the remote to a launchpad."]}]}],r:"data.has_pad"}]}]},e.exports=a.extend(r.exports)},{341:341}],407:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{mechChargeState:function(t){var e=this.get("data.recharge_port.mech.cell.maxcharge");return t>=e/1.5?"good":t>=e/3?"average":"bad"},mechHealthState:function(t){var e=this.get("data.recharge_port.mech.maxhealth");return t>e/1.5?"good":t>e/3?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[20,1,545],t:7,e:"ui-display",a:{title:"Mech Status"},f:[{t:4,f:[{t:4,f:[{p:[23,4,646],t:7,e:"ui-section",a:{label:"Integrity"},f:[{p:[24,6,683],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.recharge_port.mech.maxhealth",p:[24,27,704]}],value:[{t:2,r:"adata.recharge_port.mech.health",p:[24,74,751]}],state:[{t:2,x:{r:["mechHealthState","adata.recharge_port.mech.health"],s:"_0(_1)"},p:[24,117,794]}]},f:[{t:2,x:{r:["adata.recharge_port.mech.health"],s:"Math.round(_0)"},p:[24,171,848]},"/",{t:2,r:"adata.recharge_port.mech.maxhealth",p:[24,219,896]}]}]}," ",{t:4,f:[{t:4,f:[{p:[28,5,1061],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[28,31,1087],t:7,e:"span",a:{"class":"bad"},f:["Cell Critical Failure"]}]}],n:50,r:"data.recharge_port.mech.cell.critfail",p:[27,3,1010]},{t:4,n:51,f:[{p:[30,11,1170],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[31,13,1210],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.recharge_port.mech.cell.maxcharge",p:[31,34,1231]}],value:[{t:2,r:"adata.recharge_port.mech.cell.charge",p:[31,86,1283]}],state:[{t:2,x:{r:["mechChargeState","adata.recharge_port.mech.cell.charge"],s:"_0(_1)"},p:[31,134,1331]}]},f:[{t:2,x:{r:["adata.recharge_port.mech.cell.charge"],s:"Math.round(_0)"},p:[31,193,1390]},"/",{t:2,x:{r:["adata.recharge_port.mech.cell.maxcharge"],s:"Math.round(_0)"},p:[31,246,1443]}]}]}],r:"data.recharge_port.mech.cell.critfail"}],n:50,r:"data.recharge_port.mech.cell",p:[26,4,970]},{t:4,n:51,f:[{p:[35,3,1558],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[35,29,1584],t:7,e:"span",a:{"class":"bad"},f:["Cell Missing"]}]}],r:"data.recharge_port.mech.cell"}],n:50,r:"data.recharge_port.mech",p:[22,2,610]},{t:4,n:51,f:[{p:[38,4,1662],t:7,e:"ui-section",f:["Mech Not Found"]}],r:"data.recharge_port.mech"}],n:50,r:"data.recharge_port",p:[21,3,581]},{t:4,n:51,f:[{p:[41,5,1729],t:7,e:"ui-section",f:["Recharging Port Not Found"]}," ",{p:[42,2,1782],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}],r:"data.recharge_port"}]}]},e.exports=a.extend(r.exports)},{341:341}],408:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{t:4,f:[{p:[3,5,45],t:7,e:"ui-section",a:{label:"Interface Lock"},f:[{p:[4,7,88],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock":"unlock"'},p:[4,24,105]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Engaged":"Disengaged"'},p:[4,75,156]}]}]}],n:50,r:"data.siliconUser",p:[2,3,15]},{t:4,n:51,f:[{p:[7,5,247],t:7,e:"span",f:["Swipe an ID card to ",{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[7,31,273]}," this interface."]}],r:"data.siliconUser"}]}," ",{p:[10,1,358],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[11,3,389],t:7,e:"ui-section",a:{label:"Power"},f:[{t:4,f:[{p:[13,7,470],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[13,24,487]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[13,68,531]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[13,116,579]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[12,5,421]},{t:4,n:51,f:[{p:[15,7,639],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.on"],s:'_0?"good":"bad"'},p:[15,20,652]}],state:[{t:2,x:{r:["data.cell"],s:'_0?null:"disabled"'},p:[15,57,689]}]},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[15,92,724]}]}],x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"}}]}," ",{p:[18,3,791],t:7,e:"ui-section",a:{label:"Cell"},f:[{p:[19,5,822],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.cell"],s:'_0?null:"bad"'},p:[19,18,835]}]},f:[{t:2,x:{r:["data.cell","data.cellPercent"],s:'_0?_1+"%":"No Cell"'},p:[19,48,865]}]}]}," ",{p:[21,3,943],t:7,e:"ui-section",a:{label:"Mode"},f:[{p:[22,5,974],t:7,e:"span",a:{"class":[{t:2,r:"data.modeStatus",p:[22,18,987]}]},f:[{t:2,r:"data.mode",p:[22,39,1008]}]}]}," ",{p:[24,3,1049],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[25,5,1080],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.load"],s:'_0?"good":"average"'},p:[25,18,1093]}]},f:[{t:2,x:{r:["data.load"],s:'_0?_0:"None"'},p:[25,54,1129]}]}]}," ",{p:[27,3,1191],t:7,e:"ui-section",a:{label:"Destination"},f:[{p:[28,5,1229],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.destination"],s:'_0?"good":"average"'},p:[28,18,1242]}]},f:[{t:2,x:{r:["data.destination"],s:'_0?_0:"None"'},p:[28,60,1284]}]}]}]}," ",{t:4,f:[{p:{button:[{t:4,f:[{p:[35,9,1513],t:7,e:"ui-button",a:{icon:"eject",action:"unload"},f:["Unload"]}],n:50,r:"data.load",p:[34,7,1486]}," ",{t:4,f:[{p:[38,9,1623],t:7,e:"ui-button",a:{icon:"eject",action:"ejectpai"},f:["Eject PAI"]}],n:50,r:"data.haspai",p:[37,7,1594]}," ",{p:[40,7,1709],t:7,e:"ui-button",a:{icon:"pencil",action:"setid"},f:["Set ID"]}]},t:7,e:"ui-display",a:{title:"Controls",button:0},f:[" ",{p:[42,5,1791],t:7,e:"ui-section",a:{label:"Destination"},f:[{p:[43,7,1831],t:7,e:"ui-button",a:{icon:"pencil",action:"destination"},f:["Set Destination"]}," ",{p:[44,7,1912],t:7,e:"ui-button",a:{icon:"stop",action:"stop"},f:["Stop"]}," ",{p:[45,7,1973],t:7,e:"ui-button",a:{icon:"play",action:"go"},f:["Go"]}]}," ",{p:[47,5,2047],t:7,e:"ui-section",a:{label:"Home"},f:[{p:[48,7,2080],t:7,e:"ui-button",a:{icon:"home",action:"home"},f:["Go Home"]}," ",{p:[49,7,2144],t:7,e:"ui-button",a:{icon:"pencil",action:"sethome"},f:["Set Home"]}]}," ",{p:[51,5,2231],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[52,7,2268],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoReturn"],s:'_0?"check-square-o":"square-o"'},p:[52,24,2285]}],style:[{t:2,x:{r:["data.autoReturn"],s:'_0?"selected":null'},p:[52,84,2345]}],action:"autoret"},f:["Auto-Return Home"]}," ",{p:[54,7,2449],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.autoPickup"],s:'_0?"check-square-o":"square-o"'},p:[54,24,2466]}],style:[{t:2,x:{r:["data.autoPickup"],s:'_0?"selected":null'},p:[54,84,2526]}],action:"autopick"},f:["Auto-Pickup Crate"]}," ",{p:[56,7,2632],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.reportDelivery"],s:'_0?"check-square-o":"square-o"'},p:[56,24,2649]}],style:[{t:2,x:{r:["data.reportDelivery"],s:'_0?"selected":null'},p:[56,88,2713]}],action:"report"},f:["Report Deliveries"]}]}]}],n:50,x:{r:["data.locked","data.siliconUser"],s:"!_0||_1"},p:[31,1,1373]}]},e.exports=a.extend(r.exports)},{341:341}],409:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Chamber Console"},f:[{p:[2,1,45],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{t:4,f:[{p:[4,2,104],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]},{p:[4,63,165],t:7,e:"br"}," ",{t:4,f:[{p:[6,3,200],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[6,36,233]}]}," ",{p:[7,3,268],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[7,35,300]}]}," ",{p:[8,3,335],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["data.disk.activated"],s:'_0?"Active":"Inactive"'},p:[8,41,373]}]}," ",{t:4,f:[{p:[10,4,477],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"data.disk.activation_delay",p:[10,41,514]}]}],n:50,r:"data.disk.activation_delay",p:[9,3,438]}," ",{t:4,f:[{p:[13,4,600],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"data.disk.timer",p:[13,30,626]}]}," ",{p:[14,4,663],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"data.disk.timer_type",p:[14,36,695]}]}],n:50,r:"data.disk.timer",p:[12,3,572]}," ",{t:4,f:[{p:[17,4,785],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"data.disk.activation_code",p:[17,40,821]}]}],n:50,r:"data.disk.activation_code",p:[16,3,747]}," ",{t:4,f:[{p:[20,4,918],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"data.disk.deactivation_code",p:[20,42,956]}]}],n:50,r:"data.disk.deactivation_code",p:[19,3,878]}," ",{t:4,f:[{p:[23,4,1047],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"data.disk.kill_code",p:[23,34,1077]}]}],n:50,r:"data.disk.kill_code",p:[22,3,1015]}," ",{t:4,f:[{p:[26,4,1163],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"data.disk.trigger_code",p:[26,37,1196]}]}],n:50,r:"data.disk.trigger_code",p:[25,3,1128]}," ",{t:4,f:[{t:4,f:[{p:[30,6,1332],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[30,25,1351]}]},f:[{t:2,r:"value",p:[30,35,1361]}]}],n:52,r:"data.disk.extra_settings",p:[29,4,1291]}],n:50,r:"data.disk.has_extra_settings",p:[28,3,1250]}],n:50,r:"data.has_program",p:[5,2,172]},{t:4,n:51,f:[{p:[34,3,1423],t:7,e:"ui-notice",f:["No program detected."]}],r:"data.has_program"}],n:50,r:"data.has_disk",p:[3,1,80]},{t:4,n:51,f:[{p:[37,2,1489],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"}]}," ",{p:[40,1,1550],t:7,e:"br"}," ",{t:4,f:[{p:[42,2,1582],t:7,e:"ui-notice",f:[{t:2,r:"data.status_msg",p:[42,13,1593]}]}],n:50,r:"data.status_msg",p:[41,1,1556]},{t:4,n:51,f:[{p:[44,2,1637],t:7,e:"ui-display",a:{title:"Chamber"},f:[{p:[45,2,1668],t:7,e:"ui-section",f:[{p:[45,14,1680],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"lock-open":"lock"'},p:[45,30,1696]}],action:"toggle_lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Unlock":"Lock"'},p:[45,90,1756]}," Chamber"]},{p:[45,146,1812],t:7,e:"br"}]}," ",{p:[46,2,1832],t:7,e:"ui-section",f:[{p:[46,14,1844],t:7,e:"b",f:["Occupant:"]}," ",{t:2,r:"data.occupant_name",p:[46,31,1861]}]}," ",{t:4,f:[{p:[48,4,1929],t:7,e:"ui-section",f:[{p:[48,16,1941],t:7,e:"ui-notice",f:["No nanites detected."]}]}," ",{p:[49,4,2002],t:7,e:"ui-section",f:[{p:[49,16,2014],t:7,e:"ui-button",a:{icon:"syringe",action:"nanite_injection"},f:["Implant Nanites"]}]}],n:50,x:{r:["data.has_nanites"],s:"!_0"},p:[47,2,1899]},{t:4,n:51,f:[{p:[51,3,2121],t:7,e:"ui-display",a:{title:"Nanites"},f:[{t:4,f:[{p:[53,5,2181],t:7,e:"ui-button",a:{icon:"download",action:"add_program"},f:["Install Program From Disk"]},{p:[53,90,2266],t:7,e:"br"}," ",{p:[54,5,2276],t:7,e:"br"}],n:50,r:"data.has_disk",p:[52,4,2154]}," ",{p:[56,4,2297],t:7,e:"ui-section",f:[{p:[57,5,2315],t:7,e:"ui-section",a:{label:"Nanite Volume"},f:[{t:2,r:"data.nanite_volume",p:[57,39,2349]}]}," ",{p:[58,5,2390],t:7,e:"ui-section",a:{label:"Growth Rate"},f:[{t:2,r:"data.regen_rate",p:[58,37,2422]}]}," ",{p:[59,5,2460],t:7,e:"ui-section",a:{label:"Safety Threshold"},f:[{t:2,r:"data.safety_threshold",p:[59,42,2497]}," ",{p:[59,68,2523],t:7,e:"ui-button",a:{icon:"pencil",action:"set_safety"},f:["Set"]}]}," ",{p:[60,5,2603],t:7,e:"ui-section",a:{label:"Cloud ID"},f:[{t:2,x:{r:["data.cloud_id"],s:'_0?_0:"No Cloud"'},p:[60,34,2632]}," ",{p:[60,82,2680],t:7,e:"ui-button",a:{icon:"pencil",action:"set_cloud"},f:["Set"]}]}]}," ",{p:[62,4,2776],t:7,e:"ui-display",a:{title:"Programs"},f:[{t:4,f:[{p:[64,6,2845],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[64,25,2864]}],button:0},f:[{p:[65,6,2888],t:7,e:"ui-button",a:{icon:"minus",action:"remove_program",params:['{"program_id": "',{t:2,r:"id",p:[65,78,2960]},'"}']},f:["Uninstall"]}," ",{p:[66,6,2998],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"desc",p:[66,38,3030]}]}," ",{t:4,f:[{p:[68,7,3094],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["activated"],s:'_0?"Active":"Inactive"'},p:[68,45,3132]}]}," ",{p:[69,7,3191],t:7,e:"ui-section",a:{label:"Nanites Consumed"},f:[{t:2,r:"use_rate",p:[69,44,3228]},"/s"]}," ",{t:4,f:[{p:[71,8,3291],t:7,e:"ui-section",a:{label:"Trigger Cost"},f:[{t:2,r:"trigger_cost",p:[71,41,3324]}]}," ",{p:[72,8,3362],t:7,e:"ui-section",a:{label:"Trigger Cooldown"},f:[{t:2,r:"trigger_cooldown",p:[72,45,3399]}," seconds"]}],n:50,r:"can_trigger",p:[70,7,3263]}," ",{t:4,f:[{t:4,f:[{p:[76,9,3534],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"activation_delay",p:[76,46,3571]}]}],n:50,r:"activation_delay",p:[75,8,3500]}," ",{t:4,f:[{p:[79,9,3652],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"timer",p:[79,35,3678]}]}," ",{p:[80,9,3710],t:7,e:"ui-section",a:{label:"Timer Type"},f:[{t:2,r:"timer_type",p:[80,40,3741]}]}],n:50,r:"timer",p:[78,8,3629]}," ",{t:4,f:[{t:4,f:[{p:[84,11,3865],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[84,30,3884]}]},f:[{t:2,r:"value",p:[84,40,3894]}]}],n:52,r:"extra_settings",p:[83,9,3829]}],n:50,r:"has_extra_settings",p:[82,8,3793]}," ",{t:4,f:[{t:4,f:[{p:[89,10,4032],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"activation_code",p:[89,46,4068]}]}],n:50,r:"activation_code",p:[88,9,3998]}," ",{t:4,f:[{p:[92,10,4163],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"deactivation_code",p:[92,48,4201]}]}],n:50,r:"deactivation_code",p:[91,9,4127]}," ",{t:4,f:[{p:[95,10,4290],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"kill_code",p:[95,40,4320]}]}],n:50,r:"kill_code",p:[94,9,4262]}," ",{t:4,f:[{p:[98,10,4404],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"trigger_code",p:[98,43,4437]}]}],n:50,r:"trigger_code",p:[97,9,4373]}],n:50,x:{r:["data.scan_level"],s:"_0>=4"},p:[87,8,3960]}],n:50,x:{r:["data.scan_level"],s:"_0>=3"},p:[74,7,3463]}],n:50,x:{r:["data.scan_level"],s:"_0>=2"},p:[67,6,3058]}]}],n:52,r:"data.mob_programs",p:[63,5,2811]}]}]}],x:{r:["data.has_nanites"],s:"!_0"}}]}],r:"data.status_msg"}]}]},e.exports=a.extend(r.exports)},{341:341}],410:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Cloud Console"},f:[{p:[2,1,43],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{t:4,f:[{p:[4,3,104],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]},{p:[4,64,165],t:7,e:"br"}," ",{t:4,f:[{p:[6,4,202],t:7,e:"ui-section",f:[{p:[7,5,220],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[7,38,253]}]}," ",{p:[8,5,290],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[8,37,322]}]}," ",{p:[9,5,359],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["data.disk.activated"],s:'_0?"Active":"Inactive"'},p:[9,43,397]}]}," ",{t:4,f:[{p:[11,6,505],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"data.disk.activation_delay",p:[11,43,542]}]}],n:50,r:"data.disk.activation_delay",p:[10,5,464]}," ",{t:4,f:[{p:[14,6,634],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"data.disk.timer",p:[14,32,660]}]}," ",{p:[15,6,699],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"data.disk.timer_type",p:[15,38,731]}]}],n:50,r:"data.disk.timer",p:[13,5,604]}," ",{t:4,f:[{p:[18,6,827],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"data.disk.activation_code",p:[18,42,863]}]}],n:50,r:"data.disk.activation_code",p:[17,5,787]}," ",{t:4,f:[{p:[21,6,966],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"data.disk.deactivation_code",p:[21,44,1004]}]}],n:50,r:"data.disk.deactivation_code",p:[20,5,924]}," ",{t:4,f:[{p:[24,6,1101],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"data.disk.kill_code",p:[24,36,1131]}]}],n:50,r:"data.disk.kill_code",p:[23,5,1067]}," ",{t:4,f:[{p:[27,6,1223],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"data.disk.trigger_code",p:[27,39,1256]}]}],n:50,r:"data.disk.trigger_code",p:[26,5,1186]}," ",{t:4,f:[{t:4,f:[{p:[31,8,1400],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[31,27,1419]}]},f:[{t:2,r:"value",p:[31,37,1429]}]}],n:52,r:"data.disk.extra_settings",p:[30,6,1357]}],n:50,r:"data.disk.has_extra_settings",p:[29,5,1314]}]}],n:50,r:"data.has_program",p:[5,3,173]},{t:4,n:51,f:[{p:[36,4,1515],t:7,e:"ui-notice",f:["No program detected."]}],r:"data.has_program"}],n:50,r:"data.has_disk",p:[3,2,79]},{t:4,n:51,f:[{p:[39,3,1584],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"}]}," ",{p:[42,1,1646],t:7,e:"ui-display",a:{title:"Cloud Storage"},f:[{t:4,f:[{p:[44,3,1713],t:7,e:"ui-button",a:{icon:"plus-circle",action:"create_backup"},f:["Create New Backup"]}," ",{p:[45,3,1799],t:7,e:"ui-display",a:{title:"Active Backups"},f:[{t:4,f:[{p:[47,5,1873],t:7,e:"ui-button",a:{action:"set_view",params:['{"view": "',{t:2,r:"cloud_id",p:[47,52,1920]},'"}']},f:["Backup #",{t:2,r:"cloud_id",p:[47,76,1944]}]}],n:52,r:"data.cloud_backups",p:[46,4,1839]}]}],n:50,x:{r:["data.current_view"],s:"!_0"},p:[43,2,1683]},{t:4,n:51,f:[{p:[51,3,2014],t:7,e:"ui-button",a:{icon:"undo",action:"set_view",params:'{"view": "0"}'},f:["Return"]}," ",{t:4,f:[{p:[53,4,2131],t:7,e:"ui-notice",f:["ERROR: Backup not found."]}],n:50,x:{r:["data.cloud_backup"],s:"!_0"},p:[52,3,2100]},{t:4,n:51,f:[{p:[55,4,2195],t:7,e:"ui-display",a:{title:["Backup #",{t:2,r:"data.current_view",p:[55,31,2222]}]},f:[{t:4,f:[{p:[57,6,2282],t:7,e:"ui-button",a:{icon:"upload",action:"upload_program",style:"selected"},f:["Upload Program From Disk"]},{p:[57,108,2384],t:7,e:"br"}],n:50,r:"data.has_program",p:[56,5,2251]}," ",{t:4,f:[{p:[60,6,2443],t:7,e:"hr"}," ",{p:[61,6,2454],t:7,e:"ui-section",f:[{p:[62,7,2474],t:7,e:"h3",f:[{t:2,r:"name",p:[62,11,2478]}]}," ",{p:[63,7,2499],t:7,e:"div",a:{style:"float:right"},f:[{p:[64,8,2533],t:7,e:"ui-button",a:{icon:"minus-circle",action:"remove_program",style:"danger",params:['{"program_id": "',{t:2,r:"id",p:[64,102,2627]},'"}']},f:["Uninstall"]}]}]}," ",{p:[67,6,2699],t:7,e:"ui-section",f:[{p:[68,7,2719],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"desc",p:[68,39,2751]}]}," ",{p:[69,7,2780],t:7,e:"ui-section",a:{label:"Activation Status"},f:[{t:2,x:{r:["activated"],s:'_0?"Active":"Inactive"'},p:[69,45,2818]}]}," ",{p:[70,7,2877],t:7,e:"ui-section",a:{label:"Nanites Consumed"},f:[{t:2,r:"use_rate",p:[70,44,2914]},"/s"]}," ",{t:4,f:[{p:[72,8,2977],t:7,e:"ui-section",a:{label:"Trigger Cost"},f:[{t:2,r:"trigger_cost",p:[72,41,3010]},"/s"]}," ",{p:[73,8,3050],t:7,e:"ui-section",a:{label:"Trigger Cooldown"},f:[{t:2,r:"trigger_cooldown",p:[73,45,3087]},"/s"]}],n:50,r:"can_trigger",p:[71,7,2949]}," ",{t:4,f:[{p:[76,8,3178],t:7,e:"ui-section",a:{label:"Activation Delay"},f:[{t:2,r:"activation_delay",p:[76,45,3215]}]}],n:50,r:"activation_delay",p:[75,7,3145]}," ",{t:4,f:[{p:[79,8,3293],t:7,e:"ui-section",a:{label:"Timer"},f:[{t:2,r:"timer",p:[79,34,3319]}]}," ",{p:[80,8,3350],t:7,e:"ui-section",a:{label:"Timer Type "},f:[{t:2,r:"timer_type",p:[80,40,3382]}]}],n:50,r:"timer",p:[78,7,3271]}," ",{t:4,f:[{p:[83,8,3464],t:7,e:"ui-section",a:{label:"Activation Code"},f:[{t:2,r:"activation_code",p:[83,44,3500]}]}],n:50,r:"activation_code",p:[82,7,3432]}," ",{t:4,f:[{p:[86,8,3589],t:7,e:"ui-section",a:{label:"Deactivation Code"},f:[{t:2,r:"deactivation_code",p:[86,46,3627]}]}],n:50,r:"deactivation_code",p:[85,7,3555]}," ",{t:4,f:[{p:[89,8,3710],t:7,e:"ui-section",a:{label:"Kill Code"},f:[{t:2,r:"kill_code",p:[89,38,3740]}]}],n:50,r:"kill_code",p:[88,7,3684]}," ",{t:4,f:[{p:[92,8,3818],t:7,e:"ui-section",a:{label:"Trigger Code"},f:[{t:2,r:"trigger_code",p:[92,41,3851]}]}],n:50,r:"trigger_code",p:[91,7,3789]}," ",{t:4,f:[{t:4,f:[{p:[96,10,3973],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[96,29,3992]}]},f:[{t:2,r:"value",p:[96,39,4002]}]}],n:52,r:"extra_settings",p:[95,8,3938]}],n:50,r:"has_extra_settings",p:[94,7,3903]}]}],n:52,r:"data.cloud_programs",p:[59,5,2407]}]}],x:{r:["data.cloud_backup"],s:"!_0"}}],x:{r:["data.current_view"],s:"!_0"}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],411:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Program Hub"},f:[{t:4,f:[{p:[3,2,65],t:7,e:"ui-display",a:{title:"Program Disk"},f:[{p:[4,3,102],t:7,e:"ui-section",f:[{p:[5,4,119],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]}," ",{p:[6,4,185],t:7,e:"ui-button",a:{icon:"minus-circle",action:"clear"},f:["Delete Program"]}]}," ",{t:4,f:[{p:[9,4,307],t:7,e:"ui-section",a:{label:"Program Name"},f:[{t:2,r:"data.disk.name",p:[9,37,340]}]}," ",{p:[10,4,376],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.disk.desc",p:[10,36,408]}]}],n:50,r:"data.has_program",p:[8,3,278]},{t:4,n:51,f:[{p:[12,4,456],t:7,e:"ui-notice",f:["No program installed."]}],r:"data.has_program"}]}],n:50,r:"data.has_disk",p:[2,1,41]},{t:4,n:51,f:[{p:[16,2,540],t:7,e:"ui-notice",f:["Insert disk."]}],r:"data.has_disk"},{p:[18,1,586],t:7,e:"br"}," ",{p:[19,1,592],t:7,e:"ui-display",a:{title:"Programs"},f:[{p:[20,2,624],t:7,e:"ui-section",f:[{p:[21,3,640],t:7,e:"ui-button",a:{icon:"undo",action:"set_category",params:'{"category": "Main"}'},f:["Return"]}," ",{p:[22,3,737],t:7,e:"ui-button",a:{icon:"align-justify ",action:"toggle_details"},f:[{t:2,x:{r:["data.detail_view"],s:'_0?"Compact View":"Detailed View"'},p:[22,60,794]}]}]}," ",{t:4,f:[{p:[25,3,916],t:7,e:"ui-display",f:[{t:4,f:[{p:[27,5,964],t:7,e:"ui-section",f:[{p:[27,17,976],t:7,e:"ui-button",a:{action:"set_category",params:['{"category": "',{t:2,r:"name",p:[27,72,1031]},'"}']},f:[{t:2,r:"name",p:[27,84,1043]}]}]}],n:52,r:"data.categories",p:[26,4,933]}]}],n:50,x:{r:["data.category"],s:'_0=="Main"'},p:[24,2,881]},{t:4,n:51,f:[{p:[31,3,1122],t:7,e:"ui-display",a:{title:[{t:2,r:"data.category",p:[31,22,1141]}]},f:[{t:4,f:[{t:4,f:[{p:[34,6,1229],t:7,e:"ui-display",f:[{p:[35,7,1249],t:7,e:"ui-section",f:[{p:[35,19,1261],t:7,e:"b",f:[{t:2,r:"name",p:[35,22,1264]}]}]}," ",{p:[36,7,1297],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[36,19,1309]}]}," ",{p:[37,7,1338],t:7,e:"ui-section",f:[{p:[38,8,1359],t:7,e:"ui-button",a:{icon:"download",action:"download",params:['{"program_id": "',{t:2,r:"id",p:[38,77,1428]},'"}'],state:[{t:2,x:{r:["data.has_disk"],s:'_0?null:"disabled"'},p:[38,94,1445]}]},f:["Download"]}]}]}],n:50,r:"data.detail_view",p:[33,5,1198]},{t:4,n:51,f:[{p:[44,6,1585],t:7,e:"ui-section",f:[{p:[44,18,1597],t:7,e:"ui-button",a:{action:"download",params:['{"program_id": "',{t:2,r:"id",p:[44,71,1650]},'"}']},f:[{t:2,r:"name",p:[44,81,1660]}]}]}],r:"data.detail_view"}],n:52,r:"data.program_list",p:[32,4,1165]}]}],x:{r:["data.category"],s:'_0=="Main"'}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],412:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Programming"},f:[{t:4,f:[{p:[3,3,67],t:7,e:"ui-notice",f:["Insert a nanite program disk."]}],n:50,x:{r:["data.has_disk"],s:"!_0"},p:[2,1,41]},{t:4,n:51,f:[{p:[5,3,133],t:7,e:"ui-button",a:{icon:"eject",action:"eject"},f:["Eject Disk"]}," ",{t:4,f:[{p:[7,5,229],t:7,e:"ui-notice",f:["No program detected."]}],n:50,x:{r:["data.has_program"],s:"!_0"},p:[6,3,198]},{t:4,n:51,f:[{p:[9,5,290],t:7,e:"ui-section",f:[{p:[10,7,310],t:7,e:"ui-display",a:{title:[{t:2,r:"data.name",p:[10,26,329]}]},f:[{t:2,r:"data.desc",p:[11,9,354]}]}]}," ",{p:[14,5,413],t:7,e:"ui-section",f:[{p:[15,7,433],t:7,e:"ui-section",a:{label:"Program Info"},f:["Nanites Consumed: ",{t:2,r:"data.use_rate",p:[16,26,493]},{p:[16,43,510],t:7,e:"br"}," ",{t:4,f:["Trigger Cost: ",{t:2,r:"data.trigger_cost",p:[18,25,574]},"u",{p:[18,47,596],t:7,e:"br"}],n:50,r:"data.can_trigger",p:[17,9,524]}]}," ",{p:[22,7,648],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[23,9,685],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.activated"],s:'_0?"toggle-on":"toggle-off"'},p:[24,17,713]}],action:"toggle_active"},f:[{t:2,x:{r:["data.activated"],s:'_0?"Active":"Inactive"'},p:[26,11,809]}]}]}," ",{p:[30,7,905],t:7,e:"ui-section",a:{label:"Settings"},f:[{p:[31,9,944],t:7,e:"ui-button",a:{icon:"pencil",action:"set_activation_delay"}}," Activation Delay: ",{t:2,r:"data.activation_delay",p:[31,95,1030]}," ",{p:[31,121,1056],t:7,e:"br"}," ",{p:[32,9,1070],t:7,e:"ui-button",a:{icon:"pencil",action:"set_timer"}}," Timer: ",{t:2,r:"data.timer",p:[32,73,1134]}," ",{p:[32,88,1149],t:7,e:"br"}," ",{p:[33,9,1163],t:7,e:"ui-button",a:{icon:"pencil",action:"set_timer_type"}}," Timer Type: ",{t:2,r:"data.timer_type",p:[33,83,1237]}," ",{p:[33,103,1257],t:7,e:"br"}]}," ",{p:[36,7,1292],t:7,e:"ui-section",a:{label:"Codes"},f:[{p:[37,9,1328],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "activation"}'}}," Activation Code: ",{t:2,r:"data.activation_code",p:[37,121,1440]}," ",{p:[37,146,1465],t:7,e:"br"}," ",{p:[38,9,1479],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "deactivation"}'}}," Deactivation Code: ",{t:2,r:"data.deactivation_code",p:[38,125,1595]}," ",{p:[38,152,1622],t:7,e:"br"}," ",{p:[39,9,1636],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "kill"}'}}," Kill Code: ",{t:2,r:"data.kill_code",p:[39,109,1736]}," ",{p:[39,128,1755],t:7,e:"br"}," ",{t:4,f:[{p:[41,11,1805],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code",params:'{"target_code": "trigger"}'}}," Trigger Code: ",{t:2,r:"data.trigger_code",p:[41,117,1911]}," ",{p:[41,139,1933],t:7,e:"br"}],n:50,r:"data.can_trigger",p:[40,9,1769]}]}," ",{t:4,f:[{p:[46,9,2026],t:7,e:"ui-section",a:{label:"Special"},f:[{t:4,f:[{p:[48,13,2109],t:7,e:"ui-button",a:{icon:"pencil",action:"set_extra_setting",params:['{"target_setting": "',{t:2,r:"name",p:[48,93,2189]},'"}']}}," ",{t:2,r:"name",p:[48,118,2214]},": ",{t:2,r:"value",p:[48,128,2224]}," ",{p:[48,138,2234],t:7,e:"br"}],n:52,r:"data.extra_settings",p:[47,11,2066]}]}],n:50,r:"data.has_extra_settings",p:[45,7,1985]}]}],x:{r:["data.has_program"],s:"!_0"}}],x:{r:["data.has_disk"],s:"!_0"}}]}]},e.exports=a.extend(r.exports)},{341:341}],413:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Nanite Control"},f:[{t:4,f:[{p:[3,3,60],t:7,e:"ui-notice",f:["The interface is locked."]}],n:50,r:"data.locked",p:[2,1,37]},{t:4,n:51,f:[{p:[5,3,121],t:7,e:"ui-button",a:{icon:"lock",action:"lock"},f:["Lock Interface"]}," ",{p:[6,3,188],t:7,e:"ui-button",a:{icon:"save",action:"save"},f:["Save Current Setting"]}," ",{p:[7,3,261],t:7,e:"ui-section",a:{label:"Signal Code"},f:[{p:[8,5,299],t:7,e:"span",f:[{t:2,r:"data.code",p:[8,11,305]}]}," ",{p:[9,4,330],t:7,e:"ui-button",a:{icon:"pencil",action:"set_code"},f:["Set"]}]}," ",{t:4,f:[{p:[12,5,443],t:7,e:"ui-section",a:{label:"Relay Code"},f:[{p:[13,7,482],t:7,e:"span",f:[{t:2,r:"data.relay_code",p:[13,13,488]}]}," ",{p:[14,5,520],t:7,e:"ui-button",a:{icon:"pencil",action:"set_relay_code"},f:["Set"]}]}],n:50,x:{r:["data.mode"],s:'_0=="Relay"'},p:[11,3,409]}," ",{p:[17,3,618],t:7,e:"ui-section",a:{label:"Signal Mode"},f:[{p:[18,5,656],t:7,e:"span",f:[{t:2,r:"data.mode",p:[18,11,662]}]}," ",{p:[19,5,688],t:7,e:"br"}," ",{p:[20,4,697],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Off"}'},f:["Off"]}," ",{p:[21,5,775],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Local"}'},f:["Local"]}," ",{p:[22,5,857],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Targeted"}'},f:["Targeted"]}," ",{p:[23,5,945],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Area"}'},f:["Area"]}," ",{p:[24,5,1025],t:7,e:"ui-button",a:{action:"select_mode",params:'{"mode": "Relay"}'},f:["Relay"]}]}],r:"data.locked"}]}," ",{p:[28,1,1144],t:7,e:"ui-display",a:{title:"Saved Settings"},f:[{t:4,f:[{p:[30,3,1215],t:7,e:"ui-button",a:{icon:"load",action:"load",params:['{"save_id": "',{t:2,r:"id",p:[30,61,1273]},'"}']},f:[{t:2,r:"name",p:[30,71,1283]}]}," ",{t:4,f:[{p:[32,4,1332],t:7,e:"ui-button",a:{icon:"remove",action:"remove_save",params:['{"save_id": "',{t:2,r:"id",p:[32,71,1399]},'"}']},f:["Remove"]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[31,3,1307]}," ",{p:[34,3,1442],t:7,e:"br"}],n:52,r:"data.saved_settings",p:[29,2,1182]}]}]},e.exports=a.extend(r.exports)},{341:341}],414:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Ghost roles"},f:[{p:[2,2,35],t:7,e:"ui-section",a:{label:"Ignored roles"},f:[{t:4,f:[{p:[4,4,99],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["enabled"],s:'_0?"check-square-o":"square-o"'},p:[4,21,116]}],style:[{t:2,x:{r:["enabled"],s:'_0?"danger":null'},p:[4,73,168]}],action:"toggle_ignore",params:['{"key": "',{t:2,r:"key",p:[4,144,239]},'"}']},f:[{t:2,r:"desc",p:[4,155,250]}]}],n:52,r:"data.ignore",p:[3,3,73]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],415:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Relay"},f:[{ +t:4,f:[{p:[3,3,57],t:7,e:"h2",f:["NETWORK BUFFERS OVERLOADED"]}," ",{p:[4,3,96],t:7,e:"h3",f:["Overload Recovery Mode"]}," ",{p:[5,3,131],t:7,e:"i",f:["This system is suffering temporary outage due to overflow of traffic buffers. Until buffered traffic is processed, all further requests will be dropped. Frequent occurences of this error may indicate insufficient hardware capacity of your network. Please contact your network planning department for instructions on how to resolve this issue."]}," ",{p:[6,3,484],t:7,e:"h3",f:["ADMINISTRATIVE OVERRIDE"]}," ",{p:[7,3,520],t:7,e:"b",f:["CAUTION - Data loss may occur"]}," ",{p:[8,3,562],t:7,e:"ui-button",a:{icon:"signal",action:"restart"},f:["Purge buffered traffic"]}],n:50,r:"data.dos_crashed",p:[2,2,29]},{t:4,n:51,f:[{p:[12,3,663],t:7,e:"ui-section",a:{label:"Relay status"},f:[{p:[13,4,701],t:7,e:"ui-button",a:{icon:"power-off",action:"toggle"},f:[{t:2,x:{r:["data.enabled"],s:'_0?"ENABLED":"DISABLED"'},p:[14,6,752]}]}]}," ",{p:[18,3,836],t:7,e:"ui-section",a:{label:"Network buffer status"},f:[{t:2,r:"data.dos_overload",p:[19,4,883]}," / ",{t:2,r:"data.dos_capacity",p:[19,28,907]}," GQ"]}],r:"data.dos_crashed"}]}]},e.exports=a.extend(r.exports)},{341:341}],416:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{healthState:function(){var t=this.get("data.health");return t>70?"good":t>50?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[15,1,320],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[18,3,363],t:7,e:"ui-notice",f:[{p:[19,5,380],t:7,e:"span",f:["Reconstruction in progress!"]}]}],n:50,r:"data.restoring",p:[17,1,337]},{p:[24,1,451],t:7,e:"ui-display",f:[{p:[26,1,467],t:7,e:"div",a:{"class":"item"},f:[{p:[27,3,489],t:7,e:"div",a:{"class":"itemLabel"},f:["Inserted AI:"]}," ",{p:[30,3,541],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[31,2,569],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",state:[{t:2,x:{r:["data.nocard"],s:'_0?"disabled":null'},p:[31,52,619]}]},f:[{t:2,x:{r:["data.name"],s:'_0?_0:"---"'},p:[31,89,656]}]}]}]}," ",{t:4,f:[{p:[36,2,744],t:7,e:"b",f:["ERROR: ",{t:2,r:"data.error",p:[36,12,754]}]}],n:50,r:"data.error",p:[35,1,723]},{t:4,n:51,f:[{p:[38,2,785],t:7,e:"h2",f:["System Status"]}," ",{p:[39,2,810],t:7,e:"div",a:{"class":"item"},f:[{p:[40,3,832],t:7,e:"div",a:{"class":"itemLabel"},f:["Current AI:"]}," ",{p:[43,3,885],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.name",p:[44,4,915]}]}," ",{p:[46,3,942],t:7,e:"div",a:{"class":"itemLabel"},f:["Status:"]}," ",{p:[49,3,991],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["Nonfunctional"],n:50,r:"data.isDead",p:[50,4,1021]},{t:4,n:51,f:["Functional"],r:"data.isDead"}]}," ",{p:[56,3,1114],t:7,e:"div",a:{"class":"itemLabel"},f:["System Integrity:"]}," ",{p:[59,3,1173],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[60,4,1203],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.health",p:[60,37,1236]}],state:[{t:2,r:"healthState",p:[61,11,1264]}]},f:[{t:2,x:{r:["adata.health"],s:"Math.round(_0)"},p:[61,28,1281]},"%"]}]}," ",{p:[63,3,1336],t:7,e:"div",a:{"class":"itemLabel"},f:["Active Laws:"]}," ",{p:[66,3,1390],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[67,4,1420],t:7,e:"table",f:[{t:4,f:[{p:[69,6,1462],t:7,e:"tr",f:[{p:[69,10,1466],t:7,e:"td",f:[{p:[69,14,1470],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:".",p:[69,38,1494]}]}]}]}],n:52,r:"data.ai_laws",p:[68,5,1433]}]}]}," ",{p:[73,2,1547],t:7,e:"ui-section",a:{label:"Operations"},f:[{p:[74,3,1582],t:7,e:"ui-button",a:{icon:"plus",style:[{t:2,x:{r:["data.restoring"],s:'_0?"disabled":null'},p:[74,33,1612]}],action:"PRG_beginReconstruction"},f:["Begin Reconstruction"]}]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],417:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[5,1,91],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"home",params:'{"target" : "mod"}',state:[{t:2,x:{r:["data.mmode"],s:'_0==1?"disabled":null'},p:[5,80,170]}]},f:["Access Modification"]}],n:50,r:"data.have_id_slot",p:[4,1,64]},{p:[7,1,253],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"folder-open",params:'{"target" : "manage"}',state:[{t:2,x:{r:["data.mmode"],s:'_0==2?"disabled":null'},p:[7,90,342]}]},f:["Job Management"]}," ",{p:[8,1,411],t:7,e:"ui-button",a:{action:"PRG_switchm",icon:"folder-open",params:'{"target" : "manifest"}',state:[{t:2,x:{r:["data.mmode"],s:'!_0?"disabled":null'},p:[8,92,502]}]},f:["Crew Manifest"]}," ",{t:4,f:[{p:[10,1,593],t:7,e:"ui-button",a:{action:"PRG_print",icon:"print",state:[{t:2,x:{r:["data.has_id","data.mmode"],s:'!_1||_0&&_1==1?null:"disabled"'},p:[10,51,643]}]},f:["Print"]}],n:50,r:"data.have_printer",p:[9,1,566]},{t:4,f:[{p:[14,1,766],t:7,e:"div",a:{"class":"item"},f:[{p:[15,3,788],t:7,e:"h2",f:["Crew Manifest"]}," ",{p:[16,3,814],t:7,e:"br"},"Please use security record computer to modify entries.",{p:[16,61,872],t:7,e:"br"},{p:[16,65,876],t:7,e:"br"}]}," ",{t:4,f:[{p:[19,2,916],t:7,e:"div",a:{"class":"item"},f:[{t:2,r:"name",p:[20,2,937]}," - ",{t:2,r:"rank",p:[20,13,948]}]}],n:52,r:"data.manifest",p:[18,1,890]}],n:50,x:{r:["data.mmode"],s:"!_0"},p:[13,1,745]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.mmode"],s:"_0==2"},f:[{p:[25,1,1008],t:7,e:"div",a:{"class":"item"},f:[{p:[26,3,1030],t:7,e:"h2",f:["Job Management"]}]}," ",{p:[28,1,1063],t:7,e:"table",f:[{p:[29,1,1072],t:7,e:"tr",f:[{p:[29,5,1076],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,27,1098],t:7,e:"b",f:["Job"]}]},{p:[29,42,1113],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,64,1135],t:7,e:"b",f:["Slots"]}]},{p:[29,81,1152],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,103,1174],t:7,e:"b",f:["Open job"]}]},{p:[29,123,1194],t:7,e:"td",a:{style:"width:25%"},f:[{p:[29,145,1216],t:7,e:"b",f:["Close job"]}]}]}," ",{t:4,f:[{p:[32,2,1269],t:7,e:"tr",f:[{p:[32,6,1273],t:7,e:"td",f:[{t:2,r:"title",p:[32,10,1277]}]},{p:[32,24,1291],t:7,e:"td",f:[{t:2,r:"current",p:[32,28,1295]},"/",{t:2,r:"total",p:[32,40,1307]}]},{p:[32,54,1321],t:7,e:"td",f:[{p:[32,58,1325],t:7,e:"ui-button",a:{action:"PRG_open_job",params:['{"target" : "',{t:2,r:"title",p:[32,112,1379]},'"}'],state:[{t:2,x:{r:["status_open"],s:'_0?null:"disabled"'},p:[32,132,1399]}]},f:[{t:2,r:"desc_open",p:[32,169,1436]}]},{p:[32,194,1461],t:7,e:"br"}]},{p:[32,203,1470],t:7,e:"td",f:[{p:[32,207,1474],t:7,e:"ui-button",a:{action:"PRG_close_job",params:['{"target" : "',{t:2,r:"title",p:[32,262,1529]},'"}'],state:[{t:2,x:{r:["status_close"],s:'_0?null:"disabled"'},p:[32,282,1549]}]},f:[{t:2,r:"desc_close",p:[32,320,1587]}]}]}]}],n:52,r:"data.slots",p:[30,1,1244]}]}]},{t:4,n:50,x:{r:["data.mmode"],s:"!(_0==2)"},f:[" ",{p:[40,1,1665],t:7,e:"div",a:{"class":"item"},f:[{p:[41,3,1687],t:7,e:"h2",f:["Access Modification"]}]}," ",{t:4,f:[{p:[45,3,1751],t:7,e:"span",a:{"class":"alert"},f:[{p:[45,23,1771],t:7,e:"i",f:["Please insert the ID into the terminal to proceed."]}]},{p:[45,87,1835],t:7,e:"br"}],n:50,x:{r:["data.has_id"],s:"!_0"},p:[44,1,1727]},{p:[48,1,1852],t:7,e:"div",a:{"class":"item"},f:[{p:[49,3,1874],t:7,e:"div",a:{"class":"itemLabel"},f:["Target Identity:"]}," ",{p:[52,3,1930],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[53,2,1958],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",params:'{"target" : "id"}'},f:[{t:2,r:"data.id_name",p:[53,72,2028]}]}]}]}," ",{p:[56,1,2076],t:7,e:"div",a:{"class":"item"},f:[{p:[57,3,2098],t:7,e:"div",a:{"class":"itemLabel"},f:["Auth Identity:"]}," ",{p:[60,3,2152],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[61,2,2180],t:7,e:"ui-button",a:{icon:"eject",action:"PRG_eject",params:'{"target" : "auth"}'},f:[{t:2,r:"data.auth_name",p:[61,74,2252]}]}]}]}," ",{p:[64,1,2302],t:7,e:"hr"}," ",{t:4,f:[{t:4,f:[{p:[68,2,2362],t:7,e:"div",a:{"class":"item"},f:[{p:[69,4,2385],t:7,e:"h2",f:["Details"]}]}," ",{t:4,f:[{p:[73,2,2436],t:7,e:"div",a:{"class":"item"},f:[{p:[74,4,2459],t:7,e:"div",a:{"class":"itemLabel"},f:["Registered Name:"]}," ",{p:[77,4,2518],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.id_owner",p:[78,3,2547]}]}]}," ",{p:[81,2,2587],t:7,e:"div",a:{"class":"item"},f:[{p:[82,4,2610],t:7,e:"div",a:{"class":"itemLabel"},f:["Rank:"]}," ",{p:[85,4,2658],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.id_rank",p:[86,3,2687]}]}]}," ",{p:[89,2,2726],t:7,e:"div",a:{"class":"item"},f:[{p:[90,4,2749],t:7,e:"div",a:{"class":"itemLabel"},f:["Demote:"]}," ",{p:[93,4,2799],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[94,3,2828],t:7,e:"ui-button",a:{action:"PRG_terminate",icon:"gear",state:[{t:2,x:{r:["data.id_rank"],s:'_0=="Unassigned"?"disabled":null'},p:[94,56,2881]}]},f:["Demote ",{t:2,r:"data.id_owner",p:[94,117,2942]}]}]}]}],n:50,r:"data.minor",p:[72,2,2415]},{t:4,n:51,f:[{p:[99,2,3007],t:7,e:"div",a:{"class":"item"},f:[{p:[100,4,3030],t:7,e:"div",a:{"class":"itemLabel"},f:["Registered Name:"]}," ",{p:[103,4,3089],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[104,3,3118],t:7,e:"ui-button",a:{action:"PRG_edit",icon:"pencil",params:'{"name" : "1"}'},f:[{t:2,r:"data.id_owner",p:[104,70,3185]}]}]}]}," ",{p:[108,2,3239],t:7,e:"div",a:{"class":"item"},f:[{p:[109,4,3262],t:7,e:"h2",f:["Assignment"]}]}," ",{p:[111,3,3294],t:7,e:"ui-button",a:{action:"PRG_togglea",icon:"gear"},f:[{t:2,x:{r:["data.assignments"],s:'_0?"Hide assignments":"Show assignments"'},p:[111,47,3338]}]}," ",{p:[112,2,3415],t:7,e:"div",a:{"class":"item"},f:[{p:[113,4,3438],t:7,e:"span",a:{id:"allvalue.jobsslot"},f:[]}]}," ",{p:[117,2,3495],t:7,e:"div",a:{"class":"item"},f:[{t:4,f:[{p:[119,4,3547],t:7,e:"div",a:{id:"all-value.jobs"},f:[{p:[120,3,3576],t:7,e:"table",f:[{p:[121,5,3589],t:7,e:"tr",f:[{p:[122,4,3598],t:7,e:"th",f:["Command"]}," ",{p:[123,4,3619],t:7,e:"td",f:[{p:[124,6,3630],t:7,e:"ui-button",a:{action:"PRG_assign",params:'{"assign_target" : "Captain"}',state:[{t:2,x:{r:["data.id_rank"],s:'_0=="Captain"?"selected":null'},p:[124,83,3707]}]},f:["Captain"]}]}]}," ",{p:[127,5,3804],t:7,e:"tr",f:[{p:[128,4,3813],t:7,e:"th",f:["Special"]}," ",{p:[129,4,3834],t:7,e:"td",f:[{p:[130,6,3845],t:7,e:"ui-button",a:{action:"PRG_assign",params:'{"assign_target" : "Custom"}'},f:["Custom"]}]}]}," ",{p:[133,5,3959],t:7,e:"tr",f:[{p:[134,4,3968],t:7,e:"th",a:{style:"color: '#FFA500';"},f:["Engineering"]}," ",{p:[135,4,4019],t:7,e:"td",f:[{t:4,f:[{p:[137,5,4067],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[137,64,4126]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[137,82,4144]}]},f:[{t:2,r:"display_name",p:[137,127,4189]}]}],n:52,r:"data.engineering_jobs",p:[136,6,4030]}]}]}," ",{p:[141,5,4260],t:7,e:"tr",f:[{p:[142,4,4269],t:7,e:"th",a:{style:"color: '#008000';"},f:["Medical"]}," ",{p:[143,4,4316],t:7,e:"td",f:[{t:4,f:[{p:[145,5,4360],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[145,64,4419]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[145,82,4437]}]},f:[{t:2,r:"display_name",p:[145,127,4482]}]}],n:52,r:"data.medical_jobs",p:[144,6,4327]}]}]}," ",{p:[149,5,4553],t:7,e:"tr",f:[{p:[150,4,4562],t:7,e:"th",a:{style:"color: '#800080';"},f:["Science"]}," ",{p:[151,4,4609],t:7,e:"td",f:[{t:4,f:[{p:[153,5,4653],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[153,64,4712]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[153,82,4730]}]},f:[{t:2,r:"display_name",p:[153,127,4775]}]}],n:52,r:"data.science_jobs",p:[152,6,4620]}]}]}," ",{p:[157,5,4846],t:7,e:"tr",f:[{p:[158,4,4855],t:7,e:"th",a:{style:"color: '#DD0000';"},f:["Security"]}," ",{p:[159,4,4903],t:7,e:"td",f:[{t:4,f:[{p:[161,5,4948],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[161,64,5007]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[161,82,5025]}]},f:[{t:2,r:"display_name",p:[161,127,5070]}]}],n:52,r:"data.security_jobs",p:[160,6,4914]}]}]}," ",{p:[165,5,5141],t:7,e:"tr",f:[{p:[166,4,5150],t:7,e:"th",a:{style:"color: '#cc6600';"},f:["Cargo"]}," ",{p:[167,4,5195],t:7,e:"td",f:[{t:4,f:[{p:[169,5,5237],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[169,64,5296]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[169,82,5314]}]},f:[{t:2,r:"display_name",p:[169,127,5359]}]}],n:52,r:"data.cargo_jobs",p:[168,6,5206]}]}]}," ",{p:[173,5,5430],t:7,e:"tr",f:[{p:[174,4,5439],t:7,e:"th",a:{style:"color: '#808080';"},f:["Civilian"]}," ",{p:[175,4,5487],t:7,e:"td",f:[{t:4,f:[{p:[177,5,5532],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[177,64,5591]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[177,82,5609]}]},f:[{t:2,r:"display_name",p:[177,127,5654]}]}],n:52,r:"data.civilian_jobs",p:[176,6,5498]}]}]}," ",{t:4,f:[{p:[182,4,5757],t:7,e:"tr",f:[{p:[183,6,5768],t:7,e:"th",a:{style:"color: '#A52A2A';"},f:["CentCom"]}," ",{p:[184,6,5817],t:7,e:"td",f:[{t:4,f:[{p:[186,7,5862],t:7,e:"ui-button",a:{action:"PRG_assign",params:['{"assign_target" : "',{t:2,r:"job",p:[186,66,5921]},'"}'],state:[{t:2,x:{r:["data.id_rank","job"],s:'_0==_1?"selected":null'},p:[186,84,5939]}]},f:[{t:2,r:"display_name",p:[186,129,5984]}]}],n:52,r:"data.centcom_jobs",p:[185,5,5827]}]}]}],n:50,r:"data.centcom_access",p:[181,5,5725]}]}]}],n:50,r:"data.assignments",p:[118,4,3518]}]}],r:"data.minor"}," ",{t:4,f:[{p:[198,4,6153],t:7,e:"div",a:{"class":"item"},f:[{p:[199,3,6175],t:7,e:"h2",f:["Central Command"]}]}," ",{p:[201,4,6215],t:7,e:"div",a:{"class":"item",style:"width: 100%"},f:[{t:4,f:[{p:[203,5,6296],t:7,e:"div",a:{"class":"itemContentWide"},f:[{p:[204,5,6331],t:7,e:"ui-button",a:{action:"PRG_access",params:['{"access_target" : "',{t:2,r:"ref",p:[204,64,6390]},'", "allowed" : "',{t:2,r:"allowed",p:[204,87,6413]},'"}'],state:[{t:2,x:{r:["allowed"],s:'_0?"toggle":null'},p:[204,109,6435]}]},f:[{t:2,r:"desc",p:[204,140,6466]}]}]}],n:52,r:"data.all_centcom_access",p:[202,3,6257]}]}],n:50,r:"data.centcom_access",p:[197,2,6121]},{t:4,n:51,f:[{p:[209,4,6538],t:7,e:"div",a:{"class":"item"},f:[{p:[210,3,6560],t:7,e:"h2",f:[{t:2,r:"data.station_name",p:[210,7,6564]}]}]}," ",{p:[212,4,6606],t:7,e:"div",a:{"class":"item",style:"width: 100%"},f:[{t:4,f:[{p:[214,5,6676],t:7,e:"div",a:{style:"float: left; width: 175px; min-height: 250px"},f:[{p:[215,4,6739],t:7,e:"div",a:{"class":"average"},f:[{p:[215,25,6760],t:7,e:"ui-button",a:{action:"PRG_regsel",state:[{t:2,x:{r:["selected"],s:'_0?"toggle":null'},p:[215,63,6798]}],params:['{"region" : "',{t:2,r:"regid",p:[215,116,6851]},'"}']},f:[{p:[215,129,6864],t:7,e:"b",f:[{t:2,r:"name",p:[215,132,6867]}]}]}]}," ",{p:[216,4,6902],t:7,e:"br"}," ",{t:4,f:[{p:[218,6,6938],t:7,e:"div",a:{"class":"itemContentWide"},f:[{p:[219,5,6973],t:7,e:"ui-button",a:{action:"PRG_access",params:['{"access_target" : "',{t:2,r:"ref",p:[219,64,7032]},'", "allowed" : "',{t:2,r:"allowed",p:[219,87,7055]},'"}'],state:[{t:2,x:{r:["allowed"],s:'_0?"toggle":null'},p:[219,109,7077]}]},f:[{t:2,r:"desc",p:[219,140,7108]}]}]}],n:52,r:"accesses",p:[217,6,6913]}]}],n:52,r:"data.regions",p:[213,3,6648]}]}],r:"data.centcom_access"}],n:50,r:"data.has_id",p:[67,3,2340]}],n:50,r:"data.authenticated",p:[66,1,2310]}]}],x:{r:["data.mmode"],s:"!_0"}}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],418:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargeState:function(t){var e=this.get("data.battery.max");return t>e/2?"good":t>e/4?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[15,1,311],t:7,e:"ntosheader"}," ",{p:[17,1,328],t:7,e:"ui-display",f:[{p:[18,2,343],t:7,e:"i",f:["Welcome to computer configuration utility. Please consult your system administrator if you have any questions about your device."]},{p:[18,137,478],t:7,e:"hr"}," ",{p:[19,2,485],t:7,e:"ui-display",a:{title:"Power Supply"},f:[{p:[20,3,522],t:7,e:"ui-section",a:{label:"Power Usage"},f:[{t:2,r:"data.power_usage",p:[21,4,559]},"W"]}," ",{t:4,f:[{p:[25,4,630],t:7,e:"ui-section",a:{label:"Battery Status"},f:["Active"]}," ",{p:[28,4,701],t:7,e:"ui-section",a:{label:"Battery Rating"},f:[{t:2,r:"data.battery.max",p:[29,5,742]}]}," ",{p:[31,4,785],t:7,e:"ui-section",a:{label:"Battery Charge"},f:[{p:[32,5,826],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.battery.max",p:[32,26,847]}],value:[{t:2,r:"adata.battery.charge",p:[32,56,877]}],state:[{t:2,x:{r:["chargeState","adata.battery.charge"],s:"_0(_1)"},p:[32,89,910]}]},f:[{t:2,x:{r:["adata.battery.charge"],s:"Math.round(_0)"},p:[32,128,949]},"/",{t:2,r:"adata.battery.max",p:[32,165,986]}]}]}],n:50,r:"data.battery",p:[24,3,605]},{t:4,n:51,f:[{p:[35,4,1051],t:7,e:"ui-section",a:{label:"Battery Status"},f:["Not Available"]}],r:"data.battery"}]}," ",{p:[41,2,1156],t:7,e:"ui-display",a:{title:"File System"},f:[{p:[42,3,1192],t:7,e:"ui-section",a:{label:"Used Capacity"},f:[{p:[43,4,1231],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.disk_size",p:[43,25,1252]}],value:[{t:2,r:"adata.disk_used",p:[43,53,1280]}],state:"good"},f:[{t:2,x:{r:["adata.disk_used"],s:"Math.round(_0)"},p:[43,87,1314]},"GQ / ",{t:2,r:"adata.disk_size",p:[43,123,1350]},"GQ"]}]}]}," ",{p:[47,2,1419],t:7,e:"ui-display",a:{title:"Computer Components"},f:[{t:4,f:[{p:[49,4,1491],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"name",p:[49,26,1513]}]},f:[{p:[50,5,1529],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"desc",p:[50,59,1583]}]}," ",{p:[52,5,1605],t:7,e:"ui-section",a:{label:"State"},f:[{p:[53,6,1638],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["critical"],s:'_0?"disabled":null'},p:[53,24,1656]}],action:"PC_toggle_component",params:['{"name": "',{t:2,r:"name",p:[53,105,1737]},'"}']},f:[{t:2,x:{r:["enabled"],s:'_0?"Enabled":"Disabled"'},p:[54,7,1757]}]}]}," ",{t:4,f:[{p:[59,6,1868],t:7,e:"ui-section",a:{label:"Power Usage"},f:[{t:2,r:"powerusage",p:[60,7,1908]},"W"]}],n:50,r:"powerusage",p:[58,5,1843]}]}," ",{p:[64,4,1985],t:7,e:"br"}],n:52,r:"data.hardware",p:[48,3,1463]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],419:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{t:4,f:[{p:[7,3,103],t:7,e:"h2",f:["An error has occurred and this program can not continue."]}," Additional information: ",{t:2,r:"data.error",p:[8,27,196]},{p:[8,41,210],t:7,e:"br"}," ",{p:[9,3,218],t:7,e:"i",f:["Please try again. If the problem persists contact your system administrator for assistance."]}," ",{p:[10,3,320],t:7,e:"ui-button",a:{action:"PRG_closefile"},f:["Restart program"]}],n:50,r:"data.error",p:[6,2,81]},{t:4,n:51,f:[{t:4,f:[{p:[13,4,422],t:7,e:"h2",f:["Viewing file ",{t:2,r:"data.filename",p:[13,21,439]}]}," ",{p:[14,4,466],t:7,e:"div",a:{"class":"item"},f:[{p:[15,4,489],t:7,e:"ui-button",a:{action:"PRG_closefile"},f:["CLOSE"]}," ",{p:[16,4,545],t:7,e:"ui-button",a:{action:"PRG_edit"},f:["EDIT"]}," ",{p:[17,4,595],t:7,e:"ui-button",a:{action:"PRG_printfile"},f:["PRINT"]}," "]},{p:[18,10,657],t:7,e:"hr"}," ",{t:3,r:"data.filedata",p:[19,4,666]}],n:50,r:"data.filename",p:[12,3,396]},{t:4,n:51,f:[{p:[21,4,702],t:7,e:"h2",f:["Available files (local):"]}," ",{p:[22,4,740],t:7,e:"table",f:[{p:[23,5,753],t:7,e:"tr",f:[{p:[24,6,764],t:7,e:"th",f:["File name"]}," ",{p:[25,6,789],t:7,e:"th",f:["File type"]}," ",{p:[26,6,814],t:7,e:"th",f:["File size (GQ)"]}," ",{p:[27,6,844],t:7,e:"th",f:["Operations"]}]}," ",{t:4,f:[{p:[30,6,907],t:7,e:"tr",f:[{p:[31,7,919],t:7,e:"td",f:[{t:2,r:"name",p:[31,11,923]}]}," ",{p:[32,7,944],t:7,e:"td",f:[".",{t:2,r:"type",p:[32,12,949]}]}," ",{p:[33,7,970],t:7,e:"td",f:[{t:2,r:"size",p:[33,11,974]},"GQ"]}," ",{p:[34,7,997],t:7,e:"td",f:[{p:[35,8,1010],t:7,e:"ui-button",a:{action:"PRG_openfile",params:['{"name": "',{t:2,r:"name",p:[35,59,1061]},'"}']},f:["VIEW"]}," ",{p:[36,8,1098],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[36,26,1116]}],action:"PRG_deletefile",params:['{"name": "',{t:2,r:"name",p:[36,105,1195]},'"}']},f:["DELETE"]}," ",{p:[37,8,1234],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[37,26,1252]}],action:"PRG_rename",params:['{"name": "',{t:2,r:"name",p:[37,101,1327]},'"}']},f:["RENAME"]}," ",{p:[38,8,1366],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[38,26,1384]}],action:"PRG_clone",params:['{"name": "',{t:2,r:"name",p:[38,100,1458]},'"}']},f:["CLONE"]}," ",{t:4,f:[{p:[40,9,1531],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[40,27,1549]}],action:"PRG_copytousb",params:['{"name": "',{t:2,r:"name",p:[40,105,1627]},'"}']},f:["EXPORT"]}],n:50,r:"data.usbconnected",p:[39,8,1496]}]}]}],n:52,r:"data.files",p:[29,5,880]}]}," ",{t:4,f:[{p:[47,4,1761],t:7,e:"h2",f:["Available files (portable device):"]}," ",{p:[48,4,1809],t:7,e:"table",f:[{p:[49,5,1822],t:7,e:"tr",f:[{p:[50,6,1833],t:7,e:"th",f:["File name"]}," ",{p:[51,6,1858],t:7,e:"th",f:["File type"]}," ",{p:[52,6,1883],t:7,e:"th",f:["File size (GQ)"]}," ",{p:[53,6,1913],t:7,e:"th",f:["Operations"]}]}," ",{t:4,f:[{p:[56,6,1979],t:7,e:"tr",f:[{p:[57,7,1991],t:7,e:"td",f:[{t:2,r:"name",p:[57,11,1995]}]}," ",{p:[58,7,2016],t:7,e:"td",f:[".",{t:2,r:"type",p:[58,12,2021]}]}," ",{p:[59,7,2042],t:7,e:"td",f:[{t:2,r:"size",p:[59,11,2046]},"GQ"]}," ",{p:[60,7,2069],t:7,e:"td",f:[{p:[61,8,2082],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[61,26,2100]}],action:"PRG_usbdeletefile",params:['{"name": "',{t:2,r:"name",p:[61,108,2182]},'"}']},f:["DELETE"]}," ",{t:4,f:[{p:[63,9,2256],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["undeletable"],s:'_0?"disabled":null'},p:[63,27,2274]}],action:"PRG_copyfromusb",params:['{"name": "',{t:2,r:"name",p:[63,107,2354]},'"}']},f:["IMPORT"]}],n:50,r:"data.usbconnected",p:[62,8,2221]}]}]}],n:52,r:"data.usbfiles",p:[55,5,1949]}]}],n:50,r:"data.usbconnected",p:[46,4,1731]}," ",{p:[70,4,2470],t:7,e:"ui-button",a:{action:"PRG_newtextfile"},f:["NEW DATA FILE"]}],r:"data.filename"}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],420:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{p:[5,2,79],t:7,e:"i",f:["No program loaded. Please select program from list below."]}," ",{p:[6,2,146],t:7,e:"table",f:[{t:4,f:[{p:[8,4,185],t:7,e:"tr",f:[{p:[8,8,189],t:7,e:"td",f:[{p:[8,12,193],t:7,e:"ui-button",a:{action:"PC_runprogram",params:['{"name": "',{t:2,r:"name",p:[8,64,245]},'"}']},f:[{t:2,r:"desc",p:[9,5,263]}]}]},{p:[11,4,293],t:7,e:"td",f:[{p:[11,8,297],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["running"],s:'_0?null:"disabled"'},p:[11,26,315]}],icon:"close",action:"PC_killprogram",params:['{"name": "',{t:2,r:"name",p:[11,114,403]},'"}']}}]}]}],n:52,r:"data.programs",p:[7,3,157]}]}," ",{p:[14,2,454],t:7,e:"br"},{p:[14,6,458],t:7,e:"br"}," ",{t:4,f:[{p:[16,3,491],t:7,e:"ui-button",a:{action:"PC_toggle_light",style:[{t:2,x:{r:["data.light_on"],s:'_0?"selected":null'},p:[16,46,534]}]},f:["Toggle Flashlight"]},{p:[16,114,602],t:7,e:"br"}," ",{p:[17,3,610],t:7,e:"ui-button",a:{action:"PC_light_color"},f:["Change Flashlight Color ",{p:[17,62,669],t:7,e:"span",a:{style:["border:1px solid #161616; background-color: ",{t:2,r:"data.comp_light_color",p:[17,119,726]},";"]},f:["   "]}]}],n:50,r:"data.has_light",p:[15,2,465]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],421:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{t:4,f:[{p:[6,3,105],t:7,e:"h1",f:["ADMINISTRATIVE MODE"]}],n:50,r:"data.adminmode",p:[5,2,79]}," ",{t:4,f:[{p:[10,3,170],t:7,e:"div",a:{"class":"itemLabel"},f:["Current channel:"]}," ",{p:[13,3,229],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.title",p:[14,4,259]}]}," ",{p:[16,3,287],t:7,e:"div",a:{"class":"itemLabel"},f:["Operator access:"]}," ",{p:[19,3,346],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:[{p:[21,5,406],t:7,e:"b",f:["Enabled"]}],n:50,r:"data.is_operator",p:[20,4,376]},{t:4,n:51,f:[{p:[23,5,439],t:7,e:"b",f:["Disabled"]}],r:"data.is_operator"}]}," ",{p:[26,3,480],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[29,3,532],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[30,4,562],t:7,e:"table",f:[{p:[31,5,575],t:7,e:"tr",f:[{p:[31,9,579],t:7,e:"td",f:[{p:[31,13,583],t:7,e:"ui-button",a:{action:"PRG_speak"},f:["Send message"]}]}]},{p:[32,5,643],t:7,e:"tr",f:[{p:[32,9,647],t:7,e:"td",f:[{p:[32,13,651],t:7,e:"ui-button",a:{action:"PRG_changename"},f:["Change nickname"]}]}]},{p:[33,5,719],t:7,e:"tr",f:[{p:[33,9,723],t:7,e:"td",f:[{p:[33,13,727],t:7,e:"ui-button",a:{action:"PRG_toggleadmin"},f:["Toggle administration mode"]}]}]},{p:[34,5,807],t:7,e:"tr",f:[{p:[34,9,811],t:7,e:"td",f:[{p:[34,13,815],t:7,e:"ui-button",a:{action:"PRG_leavechannel"},f:["Leave channel"]}]}]},{p:[35,5,883],t:7,e:"tr",f:[{p:[35,9,887],t:7,e:"td",f:[{p:[35,13,891],t:7,e:"ui-button",a:{action:"PRG_savelog"},f:["Save log to local drive"]}," ",{t:4,f:[{p:[37,6,995],t:7,e:"tr",f:[{p:[37,10,999],t:7,e:"td",f:[{p:[37,14,1003],t:7,e:"ui-button",a:{action:"PRG_renamechannel"},f:["Rename channel"]}]}]},{p:[38,6,1074],t:7,e:"tr",f:[{p:[38,10,1078],t:7,e:"td",f:[{p:[38,14,1082],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}]}]},{p:[39,6,1149],t:7,e:"tr",f:[{p:[39,10,1153],t:7,e:"td",f:[{p:[39,14,1157],t:7,e:"ui-button",a:{action:"PRG_deletechannel"},f:["Delete channel"]}]}]}],n:50,r:"data.is_operator",p:[36,5,964]}]}]}]}]}," ",{p:[43,3,1263],t:7,e:"b",f:["Chat Window"]}," ",{p:[44,4,1286],t:7,e:"div",a:{"class":"statusDisplay",style:"overflow: auto;"},f:[{p:[45,4,1342],t:7,e:"div",a:{"class":"item"},f:[{p:[46,5,1366],t:7,e:"div",a:{"class":"itemContent",style:"width: 100%;"},f:[{t:4,f:[{t:2,r:"msg",p:[48,7,1450]},{p:[48,14,1457],t:7,e:"br"}],n:52,r:"data.messages",p:[47,6,1419]}]}]}]}," ",{p:[53,3,1516],t:7,e:"b",f:["Connected Users"]},{p:[53,25,1538],t:7,e:"br"}," ",{t:4,f:[{t:2,r:"name",p:[55,4,1573]},{p:[55,12,1581],t:7,e:"br"}],n:52,r:"data.clients",p:[54,3,1546]}],n:50,r:"data.title",p:[9,2,148]},{t:4,n:51,f:[{p:[58,3,1613],t:7,e:"b",f:["Controls:"]}," ",{p:[59,3,1633],t:7,e:"table",f:[{p:[60,4,1645],t:7,e:"tr",f:[{p:[60,8,1649],t:7,e:"td",f:[{p:[60,12,1653],t:7,e:"ui-button",a:{action:"PRG_changename"},f:["Change nickname"]}]}]},{p:[61,4,1720],t:7,e:"tr",f:[{p:[61,8,1724],t:7,e:"td",f:[{p:[61,12,1728],t:7,e:"ui-button",a:{action:"PRG_newchannel"},f:["New Channel"]}]}]},{p:[62,4,1791],t:7,e:"tr",f:[{p:[62,8,1795],t:7,e:"td",f:[{p:[62,12,1799],t:7,e:"ui-button",a:{action:"PRG_toggleadmin"},f:["Toggle administration mode"]}]}]}]}," ",{p:[64,3,1889],t:7,e:"b",f:["Available channels:"]}," ",{p:[65,3,1919],t:7,e:"table",f:[{t:4,f:[{p:[67,4,1964],t:7,e:"tr",f:[{p:[67,8,1968],t:7,e:"td",f:[{p:[67,12,1972],t:7,e:"ui-button",a:{action:"PRG_joinchannel",params:['{"id": "',{t:2,r:"id",p:[67,64,2024]},'"}']},f:[{t:2,r:"chan",p:[67,74,2034]}]},{p:[67,94,2054],t:7,e:"br"}]}]}],n:52,r:"data.all_channels",p:[66,3,1930]}]}],r:"data.title"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],422:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{t:4,f:["##SYSTEM ERROR: ",{t:2,r:"data.error",p:[6,19,117]},{p:[6,33,131],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["RESET"]}],n:50,r:"data.error",p:[5,2,79]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.target"],s:"_0"},f:["##DoS traffic generator active. Tx: ",{t:2,r:"data.speed",p:[8,39,243]},"GQ/s",{p:[8,57,261],t:7,e:"br"}," ",{t:4,f:[{t:2,r:"nums",p:[10,4,300]},{p:[10,12,308],t:7,e:"br"}],n:52,r:"data.dos_strings",p:[9,3,269]}," ",{p:[12,3,329],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["ABORT"]}]},{t:4,n:50,x:{r:["data.target"],s:"!(_0)"},f:[" ##DoS traffic generator ready. Select target device.",{p:[14,55,443],t:7,e:"br"}," ",{t:4,f:["Targeted device ID: ",{t:2,r:"data.focus",p:[16,24,494]}],n:50,r:"data.focus",p:[15,3,451]},{t:4,n:51,f:["Targeted device ID: None"],r:"data.focus"}," ",{p:[20,3,564],t:7,e:"ui-button",a:{action:"PRG_execute"},f:["EXECUTE"]},{p:[20,54,615],t:7,e:"div",a:{style:"clear:both"}}," Detected devices on network:",{p:[21,31,677],t:7,e:"br"}," ",{t:4,f:[{p:[23,4,711],t:7,e:"ui-button",a:{action:"PRG_target_relay",params:['{"targid": "',{t:2,r:"id",p:[23,61,768]},'"}']},f:[{t:2,r:"id",p:[23,71,778]}]}],n:52,r:"data.relays",p:[22,3,685]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],423:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{p:[5,2,79],t:7,e:"i",f:["Welcome to software download utility. Please select which software you wish to download."]},{p:[5,97,174],t:7,e:"hr"}," ",{t:4,f:[{p:[7,3,203],t:7,e:"ui-display",a:{title:"Download Error"},f:[{p:[8,4,243],t:7,e:"ui-section",a:{label:"Information"},f:[{t:2,r:"data.error",p:[9,5,281]}]}," ",{p:[11,4,318],t:7,e:"ui-section",a:{label:"Reset Program"},f:[{p:[12,5,358],t:7,e:"ui-button",a:{icon:"times",action:"PRG_reseterror"},f:["RESET"]}]}]}],n:50,r:"data.error",p:[6,2,181]},{t:4,n:51,f:[{t:4,f:[{p:[19,4,516],t:7,e:"ui-display",a:{title:"Download Running"},f:[{p:[20,5,559],t:7,e:"i",f:["Please wait..."]}," ",{p:[21,5,586],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"data.downloadname",p:[22,6,623]}]}," ",{p:[24,5,669],t:7,e:"ui-section",a:{label:"File description"},f:[{t:2,r:"data.downloaddesc",p:[25,6,713]}]}," ",{p:[27,5,759],t:7,e:"ui-section",a:{label:"File size"},f:[{t:2,r:"data.downloadsize",p:[28,6,796]},"GQ"]}," ",{p:[30,5,844],t:7,e:"ui-section",a:{label:"Transfer Rate"},f:[{t:2,r:"data.downloadspeed",p:[31,6,885]}," GQ/s"]}," ",{p:[33,5,937],t:7,e:"ui-section",a:{label:"Download progress"},f:[{p:[34,6,982],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.downloadsize",p:[34,27,1003]}],value:[{t:2,r:"adata.downloadcompletion",p:[34,58,1034]}],state:"good"},f:[{t:2,x:{r:["adata.downloadcompletion"],s:"Math.round(_0)"},p:[34,101,1077]},"GQ / ",{t:2,r:"adata.downloadsize",p:[34,146,1122]},"GQ"]}]}]}],n:50,r:"data.downloadname",p:[18,3,486]}],r:"data.error"}," ",{t:4,f:[{t:4,f:[{p:[41,4,1270],t:7,e:"ui-display",a:{title:"File System"},f:[{p:[42,5,1308],t:7,e:"ui-section",a:{label:"Used Capacity"},f:[{p:[43,6,1349],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.disk_size",p:[43,27,1370]}],value:[{t:2,r:"adata.disk_used",p:[43,55,1398]}],state:"good"},f:[{t:2,x:{r:["adata.disk_used"],s:"Math.round(_0)"},p:[43,89,1432]},"GQ / ",{t:2,r:"adata.disk_size",p:[43,125,1468]},"GQ"]}]}]}," ",{p:[47,4,1545],t:7,e:"ui-display",a:{title:"Primary Software Repository"},f:[{t:4,f:[{p:[49,6,1642],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"filedesc",p:[49,28,1664]}]},f:[{p:[50,7,1686],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"fileinfo",p:[50,61,1740]}]}," ",{p:[52,7,1774],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"filename", +p:[53,8,1813]}," (",{t:2,r:"size",p:[53,22,1827]}," GQ)"]}," ",{p:[55,7,1868],t:7,e:"ui-section",a:{label:"Compatibility"},f:[{t:2,r:"compatibility",p:[56,8,1911]}]}," ",{p:[58,7,1957],t:7,e:"ui-button",a:{icon:"signal",action:"PRG_downloadfile",params:['{"filename": "',{t:2,r:"filename",p:[58,80,2030]},'"}']},f:["DOWNLOAD"]}]}," ",{p:[62,6,2113],t:7,e:"br"}],n:52,r:"data.downloadable_programs",p:[48,5,1599]}]}," ",{t:4,f:[{p:[67,5,2194],t:7,e:"ui-display",a:{title:"UNKNOWN Software Repository"},f:[{p:[68,6,2249],t:7,e:"i",f:["Please note that Nanotrasen does not recommend download of software from non-official servers."]}," ",{t:4,f:[{p:[70,7,2395],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"filedesc",p:[70,29,2417]}]},f:[{p:[71,8,2440],t:7,e:"div",a:{style:"display: table-caption; margin-left: 3px"},f:[{t:2,r:"fileinfo",p:[71,62,2494]}]}," ",{p:[73,8,2530],t:7,e:"ui-section",a:{label:"File name"},f:[{t:2,r:"filename",p:[74,9,2570]}," (",{t:2,r:"size",p:[74,23,2584]}," GQ)"]}," ",{p:[76,8,2627],t:7,e:"ui-section",a:{label:"Compatibility"},f:[{t:2,r:"compatibility",p:[77,9,2671]}]}," ",{p:[79,8,2719],t:7,e:"ui-button",a:{icon:"signal",action:"PRG_downloadfile",params:['{"filename": "',{t:2,r:"filename",p:[79,81,2792]},'"}']},f:["DOWNLOAD"]}]}," ",{p:[83,7,2879],t:7,e:"br"}],n:52,r:"data.hacked_programs",p:[69,6,2357]}]}],n:50,r:"data.hackedavailable",p:[66,4,2160]}],n:50,x:{r:["data.error"],s:"!_0"},p:[40,3,1246]}],n:50,x:{r:["data.downloadname"],s:"!_0"},p:[39,2,1216]}," ",{p:[89,2,2954],t:7,e:"br"},{p:[89,6,2958],t:7,e:"br"},{p:[89,10,2962],t:7,e:"hr"},{p:[89,14,2966],t:7,e:"i",f:["NTOS v2.0.4b Copyright Nanotrasen 2557 - 2559"]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],424:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{p:[6,2,81],t:7,e:"ui-display",a:{title:"WIRELESS CONNECTIVITY"},f:[{p:[8,3,129],t:7,e:"ui-section",a:{label:"Active NTNetRelays"},f:[{p:[9,4,173],t:7,e:"b",f:[{t:2,r:"data.ntnetrelays",p:[9,7,176]}]}]}," ",{t:4,f:[{p:[12,4,250],t:7,e:"ui-section",a:{label:"System status"},f:[{p:[13,6,291],t:7,e:"b",f:[{t:2,x:{r:["data.ntnetstatus"],s:'_0?"ENABLED":"DISABLED"'},p:[13,9,294]}]}]}," ",{p:[15,4,366],t:7,e:"ui-section",a:{label:"Control"},f:[{p:[17,4,401],t:7,e:"ui-button",a:{icon:"plus",action:"toggleWireless"},f:["TOGGLE"]}]}," ",{p:[21,4,500],t:7,e:"br"},{p:[21,8,504],t:7,e:"br"}," ",{p:[22,4,513],t:7,e:"i",f:["Caution - Disabling wireless transmitters when using wireless device may prevent you from re-enabling them again!"]}],n:50,r:"data.ntnetrelays",p:[11,3,221]},{t:4,n:51,f:[{p:[24,4,650],t:7,e:"br"},{p:[24,8,654],t:7,e:"p",f:["Wireless coverage unavailable, no relays are connected."]}],r:"data.ntnetrelays"}]}," ",{p:[29,2,750],t:7,e:"ui-display",a:{title:"FIREWALL CONFIGURATION"},f:[{p:[31,2,798],t:7,e:"table",f:[{p:[32,3,809],t:7,e:"tr",f:[{p:[33,4,818],t:7,e:"th",f:["PROTOCOL"]},{p:[34,4,835],t:7,e:"th",f:["STATUS"]},{p:[35,4,850],t:7,e:"th",f:["CONTROL"]}]},{p:[36,3,865],t:7,e:"tr",f:[" ",{p:[37,4,874],t:7,e:"td",f:["Software Downloads"]},{p:[38,4,901],t:7,e:"td",f:[{t:2,x:{r:["data.config_softwaredownload"],s:'_0?"ENABLED":"DISABLED"'},p:[38,8,905]}]},{p:[39,4,967],t:7,e:"td",f:[" ",{p:[39,9,972],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "1"}'},f:["TOGGLE"]}]}]},{p:[40,3,1051],t:7,e:"tr",f:[" ",{p:[41,4,1060],t:7,e:"td",f:["Peer to Peer Traffic"]},{p:[42,4,1089],t:7,e:"td",f:[{t:2,x:{r:["data.config_peertopeer"],s:'_0?"ENABLED":"DISABLED"'},p:[42,8,1093]}]},{p:[43,4,1149],t:7,e:"td",f:[{p:[43,8,1153],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "2"}'},f:["TOGGLE"]}]}]},{p:[44,3,1232],t:7,e:"tr",f:[" ",{p:[45,4,1241],t:7,e:"td",f:["Communication Systems"]},{p:[46,4,1271],t:7,e:"td",f:[{t:2,x:{r:["data.config_communication"],s:'_0?"ENABLED":"DISABLED"'},p:[46,8,1275]}]},{p:[47,4,1334],t:7,e:"td",f:[{p:[47,8,1338],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "3"}'},f:["TOGGLE"]}]}]},{p:[48,3,1417],t:7,e:"tr",f:[" ",{p:[49,4,1426],t:7,e:"td",f:["Remote System Control"]},{p:[50,4,1456],t:7,e:"td",f:[{t:2,x:{r:["data.config_systemcontrol"],s:'_0?"ENABLED":"DISABLED"'},p:[50,8,1460]}]},{p:[51,4,1519],t:7,e:"td",f:[{p:[51,8,1523],t:7,e:"ui-button",a:{action:"toggle_function",params:'{"id": "4"}'},f:["TOGGLE"]}]}]}]}]}," ",{p:[55,2,1630],t:7,e:"ui-display",a:{title:"SECURITY SYSTEMS"},f:[{t:4,f:[{p:[58,4,1699],t:7,e:"ui-notice",f:[{p:[59,5,1716],t:7,e:"h1",f:["NETWORK INCURSION DETECTED"]}]}," ",{p:[61,5,1774],t:7,e:"i",f:["An abnormal activity has been detected in the network. Please verify system logs for more information"]}],n:50,r:"data.idsalarm",p:[57,3,1673]}," ",{p:[64,3,1902],t:7,e:"ui-section",a:{label:"Intrusion Detection System"},f:[{p:[65,4,1954],t:7,e:"b",f:[{t:2,x:{r:["data.idsstatus"],s:'_0?"ENABLED":"DISABLED"'},p:[65,7,1957]}]}]}," ",{p:[68,3,2029],t:7,e:"ui-section",a:{label:"Maximal Log Count"},f:[{p:[69,4,2072],t:7,e:"b",f:[{t:2,r:"data.ntnetmaxlogs",p:[69,7,2075]}]}]}," ",{p:[72,3,2125],t:7,e:"ui-section",a:{label:"Controls"},f:[]}," ",{p:[74,4,2176],t:7,e:"table",f:[{p:[75,4,2188],t:7,e:"tr",f:[{p:[75,8,2192],t:7,e:"td",f:[{p:[75,12,2196],t:7,e:"ui-button",a:{action:"resetIDS"},f:["RESET IDS"]}]}]},{p:[76,4,2251],t:7,e:"tr",f:[{p:[76,8,2255],t:7,e:"td",f:[{p:[76,12,2259],t:7,e:"ui-button",a:{action:"toggleIDS"},f:["TOGGLE IDS"]}]}]},{p:[77,4,2316],t:7,e:"tr",f:[{p:[77,8,2320],t:7,e:"td",f:[{p:[77,12,2324],t:7,e:"ui-button",a:{action:"updatemaxlogs"},f:["SET LOG LIMIT"]}]}]},{p:[78,4,2388],t:7,e:"tr",f:[{p:[78,8,2392],t:7,e:"td",f:[{p:[78,12,2396],t:7,e:"ui-button",a:{action:"purgelogs"},f:["PURGE LOGS"]}]}]}]}," ",{p:[81,3,2467],t:7,e:"ui-subdisplay",a:{title:"System Logs"},f:[{p:[82,3,2506],t:7,e:"div",a:{"class":"statusDisplay",style:"overflow: auto;"},f:[{p:[83,3,2561],t:7,e:"div",a:{"class":"item"},f:[{p:[84,4,2584],t:7,e:"div",a:{"class":"itemContent",style:"width: 100%;"},f:[{t:4,f:[{t:2,r:"entry",p:[86,6,2667]},{p:[86,15,2676],t:7,e:"br"}],n:52,r:"data.ntnetlogs",p:[85,5,2636]}]}]}]}]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],425:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{t:4,f:[{p:[7,2,102],t:7,e:"div",a:{"class":"item"},f:[{p:[8,3,124],t:7,e:"h2",f:["An error has occurred during operation..."]}," ",{p:[9,3,178],t:7,e:"b",f:["Additional information:"]},{t:2,r:"data.error",p:[9,34,209]},{p:[9,48,223],t:7,e:"br"}," ",{p:[10,3,231],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Clear"]}]}],n:50,r:"data.error",p:[6,2,81]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.downloading"],s:"_0"},f:[{p:[13,3,321],t:7,e:"h2",f:["Download in progress..."]}," ",{p:[14,3,357],t:7,e:"div",a:{"class":"itemLabel"},f:["Downloaded file:"]}," ",{p:[17,3,416],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_name",p:[18,4,446]}]}," ",{p:[20,3,483],t:7,e:"div",a:{"class":"itemLabel"},f:["Download progress:"]}," ",{p:[23,3,544],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_progress",p:[24,4,574]}," / ",{t:2,r:"data.download_size",p:[24,33,603]}," GQ"]}," ",{p:[26,3,642],t:7,e:"div",a:{"class":"itemLabel"},f:["Transfer speed:"]}," ",{p:[29,3,700],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.download_netspeed",p:[30,4,730]},"GQ/s"]}," ",{p:[32,3,774],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[35,3,826],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[36,4,856],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Abort download"]}]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading"],s:"(!(_0))&&(_1)"},f:[" ",{p:[39,3,954],t:7,e:"h2",f:["Server enabled"]}," ",{p:[40,3,981],t:7,e:"div",a:{"class":"itemLabel"},f:["Connected clients:"]}," ",{p:[43,3,1042],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.upload_clients",p:[44,4,1072]}]}," ",{p:[46,3,1109],t:7,e:"div",a:{"class":"itemLabel"},f:["Provided file:"]}," ",{p:[49,3,1166],t:7,e:"div",a:{"class":"itemContent"},f:[{t:2,r:"data.upload_filename",p:[50,4,1196]}]}," ",{p:[52,3,1234],t:7,e:"div",a:{"class":"itemLabel"},f:["Server password:"]}," ",{p:[55,3,1293],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["ENABLED"],n:50,r:"data.upload_haspassword",p:[56,4,1323]},{t:4,n:51,f:["DISABLED"],r:"data.upload_haspassword"}]}," ",{p:[62,3,1420],t:7,e:"div",a:{"class":"itemLabel"},f:["Commands:"]}," ",{p:[65,3,1472],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[66,4,1502],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}," ",{p:[67,4,1567],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Exit server"]}]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading","data.upload_filelist"],s:"(!(_0))&&((!(_1))&&(_2))"},f:[" ",{p:[70,3,1668],t:7,e:"h2",f:["File transfer server ready. Select file to upload:"]}," ",{p:[71,3,1732],t:7,e:"table",f:[{p:[72,3,1743],t:7,e:"tr",f:[{p:[72,7,1747],t:7,e:"th",f:["File name"]},{p:[72,20,1760],t:7,e:"th",f:["File size"]},{p:[72,33,1773],t:7,e:"th",f:["Controls ",{t:4,f:[{p:[74,4,1824],t:7,e:"tr",f:[{p:[74,8,1828],t:7,e:"td",f:[{t:2,r:"filename",p:[74,12,1832]}]},{p:[75,4,1849],t:7,e:"td",f:[{t:2,r:"size",p:[75,8,1853]},"GQ"]},{p:[76,4,1868],t:7,e:"td",f:[{p:[76,8,1872],t:7,e:"ui-button",a:{action:"PRG_uploadfile",params:['{"id": "',{t:2,r:"uid",p:[76,59,1923]},'"}']},f:["Select"]}]}]}],n:52,r:"data.upload_filelist",p:[73,3,1789]}]}]}]}," ",{p:[79,3,1981],t:7,e:"hr"}," ",{p:[80,3,1989],t:7,e:"ui-button",a:{action:"PRG_setpassword"},f:["Set password"]}," ",{p:[81,3,2053],t:7,e:"ui-button",a:{action:"PRG_reset"},f:["Return"]}]},{t:4,n:50,x:{r:["data.downloading","data.uploading","data.upload_filelist"],s:"(!(_0))&&((!(_1))&&(!(_2)))"},f:[" ",{p:[83,3,2116],t:7,e:"h2",f:["Available files:"]}," ",{p:[84,3,2145],t:7,e:"table",a:{border:"1",style:"border-collapse: collapse"},f:[{p:[84,55,2197],t:7,e:"tr",f:[{p:[84,59,2201],t:7,e:"th",f:["Server UID"]},{p:[84,73,2215],t:7,e:"th",f:["File Name"]},{p:[84,86,2228],t:7,e:"th",f:["File Size"]},{p:[84,99,2241],t:7,e:"th",f:["Password Protection"]},{p:[84,122,2264],t:7,e:"th",f:["Operations ",{t:4,f:[{p:[86,5,2311],t:7,e:"tr",f:[{p:[86,9,2315],t:7,e:"td",f:[{t:2,r:"uid",p:[86,13,2319]}]},{p:[87,5,2332],t:7,e:"td",f:[{t:2,r:"filename",p:[87,9,2336]}]},{p:[88,5,2354],t:7,e:"td",f:[{t:2,r:"size",p:[88,9,2358]},"GQ ",{t:4,f:[{p:[90,6,2400],t:7,e:"td",f:["Enabled"]}],n:50,r:"haspassword",p:[89,5,2374]}," ",{t:4,f:[{p:[93,6,2457],t:7,e:"td",f:["Disabled"]}],n:50,x:{r:["haspassword"],s:"!_0"},p:[92,5,2430]}]},{p:[96,5,2494],t:7,e:"td",f:[{p:[96,9,2498],t:7,e:"ui-button",a:{action:"PRG_downloadfile",params:['{"id": "',{t:2,r:"uid",p:[96,62,2551]},'"}']},f:["Download"]}]}]}],n:52,r:"data.servers",p:[85,4,2283]}]}]}]}," ",{p:[99,3,2612],t:7,e:"hr"}," ",{p:[100,3,2620],t:7,e:"ui-button",a:{action:"PRG_uploadmenu"},f:["Send file"]}]}],r:"data.error"}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],426:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargingState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},chargingMode:function(t){return 2==t?"Full":1==t?"Charging":"Draining"},channelState:function(t){return t>=2?"good":"bad"},channelPower:function(t){return t>=2?"On":"Off"},channelMode:function(t){return 1==t||3==t?"Auto":"Manual"}},computed:{graphData:function(){var t=this.get("data.history");return Object.keys(t).map(function(e){return t[e].map(function(t,e){return{x:e,y:t}})})}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[43,1,1082],t:7,e:"ntosheader"}," ",{p:[45,1,1099],t:7,e:"ui-display",a:{title:"Network"},f:[{t:4,f:[{p:[47,5,1157],t:7,e:"ui-linegraph",a:{points:[{t:2,r:"graphData",p:[47,27,1179]}],height:"500",legend:'["Available", "Load"]',colors:'["rgb(0, 102, 0)", "rgb(153, 0, 0)"]',xunit:"seconds ago",xfactor:[{t:2,r:"data.interval",p:[49,38,1331]}],yunit:"W",yfactor:"1",xinc:[{t:2,x:{r:["data.stored"],s:"_0/10"},p:[50,15,1387]}],yinc:"9"}}],n:50,r:"config.fancy",p:[46,3,1131]},{t:4,n:51,f:[{p:[52,5,1437],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[53,7,1475],t:7,e:"span",f:[{t:2,r:"data.supply",p:[53,13,1481]}]}]}," ",{p:[55,5,1528],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[56,9,1563],t:7,e:"span",f:[{t:2,r:"data.demand",p:[56,15,1569]}]}]}],r:"config.fancy"}]}," ",{p:[60,1,1638],t:7,e:"ui-display",a:{title:"Areas"},f:[{p:[61,3,1668],t:7,e:"ui-section",a:{nowrap:0},f:[{p:[62,5,1693],t:7,e:"div",a:{"class":"content"},f:["Area"]}," ",{p:[63,5,1730],t:7,e:"div",a:{"class":"content"},f:["Charge"]}," ",{p:[64,5,1769],t:7,e:"div",a:{"class":"content"},f:["Load"]}," ",{p:[65,5,1806],t:7,e:"div",a:{"class":"content"},f:["Status"]}," ",{p:[66,5,1845],t:7,e:"div",a:{"class":"content"},f:["Equipment"]}," ",{p:[67,5,1887],t:7,e:"div",a:{"class":"content"},f:["Lighting"]}," ",{p:[68,5,1928],t:7,e:"div",a:{"class":"content"},f:["Environment"]}]}," ",{t:4,f:[{p:[71,5,2013],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[71,24,2032]}],nowrap:0},f:[{p:[72,7,2057],t:7,e:"div",a:{"class":"content"},f:[{t:2,x:{r:["@index","adata.areas"],s:"Math.round(_1[_0].charge)"},p:[72,28,2078]}," %"]}," ",{p:[73,7,2136],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.areas",m:[{t:30,n:"@index"},"load"]},p:[73,28,2157]}]}," ",{p:[74,7,2199],t:7,e:"div",a:{"class":"content"},f:[{p:[74,28,2220],t:7,e:"span",a:{"class":[{t:2,x:{r:["chargingState","charging"],s:"_0(_1)"},p:[74,41,2233]}]},f:[{t:2,x:{r:["chargingMode","charging"],s:"_0(_1)"},p:[74,70,2262]}]}]}," ",{p:[75,7,2309],t:7,e:"div",a:{"class":"content"},f:[{p:[75,28,2330],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","eqp"],s:"_0(_1)"},p:[75,41,2343]}]},f:[{t:2,x:{r:["channelPower","eqp"],s:"_0(_1)"},p:[75,64,2366]}," [",{p:[75,87,2389],t:7,e:"span",f:[{t:2,x:{r:["channelMode","eqp"],s:"_0(_1)"},p:[75,93,2395]}]},"]"]}]}," ",{p:[76,7,2444],t:7,e:"div",a:{"class":"content"},f:[{p:[76,28,2465],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","lgt"],s:"_0(_1)"},p:[76,41,2478]}]},f:[{t:2,x:{r:["channelPower","lgt"],s:"_0(_1)"},p:[76,64,2501]}," [",{p:[76,87,2524],t:7,e:"span",f:[{t:2,x:{r:["channelMode","lgt"],s:"_0(_1)"},p:[76,93,2530]}]},"]"]}]}," ",{p:[77,7,2579],t:7,e:"div",a:{"class":"content"},f:[{p:[77,28,2600],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","env"],s:"_0(_1)"},p:[77,41,2613]}]},f:[{t:2,x:{r:["channelPower","env"],s:"_0(_1)"},p:[77,64,2636]}," [",{p:[77,87,2659],t:7,e:"span",f:[{t:2,x:{r:["channelMode","env"],s:"_0(_1)"},p:[77,93,2665]}]},"]"]}]}]}],n:52,r:"data.areas",p:[70,3,1987]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],427:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{p:[4,1,64],t:7,e:"ui-display",f:[{p:[5,2,79],t:7,e:"div",a:{"class":"item"},f:[{p:[6,3,101],t:7,e:"div",a:{"class":"itemLabel"},f:["Payload status:"]}," ",{p:[9,3,158],t:7,e:"div",a:{"class":"itemContent"},f:[{t:4,f:["ARMED"],n:50,r:"data.armed",p:[10,4,188]},{t:4,n:51,f:["DISARMED"],r:"data.armed"}]}," ",{p:[16,3,270],t:7,e:"div",a:{"class":"itemLabel"},f:["Controls:"]}," ",{p:[19,3,321],t:7,e:"div",a:{"class":"itemContent"},f:[{p:[20,4,351],t:7,e:"table",f:[{p:[21,4,363],t:7,e:"tr",f:[{p:[21,8,367],t:7,e:"td",f:[{p:[21,12,371],t:7,e:"ui-button",a:{action:"PRG_obfuscate"},f:["OBFUSCATE PROGRAM NAME"]}]}]},{p:[22,4,444],t:7,e:"tr",f:[{p:[22,8,448],t:7,e:"td",f:[{p:[22,12,452],t:7,e:"ui-button",a:{action:"PRG_arm",state:[{t:2,x:{r:["data.armed"],s:'_0?"danger":null'},p:[22,47,487]}]},f:[{t:2,x:{r:["data.armed"],s:'_0?"DISARM":"ARM"'},p:[22,81,521]}]}," ",{p:[23,4,571],t:7,e:"ui-button",a:{icon:"radiation",state:[{t:2,x:{r:["data.armed"],s:'_0?null:"disabled"'},p:[23,39,606]}],action:"PRG_activate"},f:["ACTIVATE"]}]}]}]}]}]}]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],428:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[2,1,47],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[5,3,95],t:7,e:"ui-display",a:{title:[{t:2,r:"class",p:[5,22,114]}," Alarms"]},f:[{p:[6,5,138],t:7,e:"ul",f:[{t:4,f:[{p:[8,9,171],t:7,e:"li",f:[{t:2,r:".",p:[8,13,175]}]}],n:52,r:".",p:[7,7,150]},{t:4,n:51,f:[{p:[10,9,211],t:7,e:"li",f:["System Nominal"]}],r:"."}]}]}],n:52,i:"class",r:"data.alarms",p:[4,1,64]}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],429:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{integState:function(t){var e=100;return t==e?"good":t>e/2?"average":"bad"},bigState:function(t,e,n){return charge>n?"bad":t>e?"average":"good"}}}}(r),r.exports.template={v:3,t:[" "," ",{p:[23,1,421],t:7,e:"ntosheader"}," ",{t:4,f:[{p:[27,2,462],t:7,e:"ui-button",a:{action:"PRG_clear"},f:["Back to Menu"]},{p:[27,56,516],t:7,e:"br"}," ",{p:[28,3,524],t:7,e:"ui-display",a:{title:"Supermatter Status:"},f:[{p:[29,3,568],t:7,e:"ui-section",a:{label:"Core Integrity"},f:[{p:[30,5,609],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"adata.SM_integrity",p:[30,38,642]}],state:[{t:2,x:{r:["integState","adata.SM_integrity"],s:"_0(_1)"},p:[30,69,673]}]},f:[{t:2,r:"data.SM_integrity",p:[30,105,709]},"%"]}]}," ",{p:[32,3,761],t:7,e:"ui-section",a:{label:"Relative EER"},f:[{p:[33,5,800],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_power"],s:"_0(_1,150,300)"},p:[33,18,813]}]},f:[{t:2,r:"data.SM_power",p:[33,55,850]}," MeV/cm3"]}]}," ",{p:[35,3,903],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[36,5,941],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_ambienttemp"],s:"_0(_1,4000,5000)"},p:[36,18,954]}]},f:[{t:2,r:"data.SM_ambienttemp",p:[36,63,999]}," K"]}]}," ",{p:[38,3,1052],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[39,5,1087],t:7,e:"span",a:{"class":[{t:2,x:{r:["bigState","data.SM_ambientpressure"],s:"_0(_1,5000,10000)"},p:[39,18,1100]}]},f:[{t:2,r:"data.SM_ambientpressure",p:[39,68,1150]}," kPa"]}]}]}," ",{p:[42,3,1227],t:7,e:"hr"},{p:[42,7,1231],t:7,e:"br"}," ",{p:[43,3,1239],t:7,e:"ui-display",a:{title:"Gas Composition:"},f:[{t:4,f:[{p:[45,5,1307],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[45,24,1326]}]},f:[{t:2,r:"amount",p:[46,6,1343]}," %"]}],n:52,r:"data.gases",p:[44,4,1281]}]}],n:50,r:"data.active",p:[26,1,440]},{t:4,n:51,f:[{p:[51,2,1418],t:7,e:"ui-button",a:{action:"PRG_refresh"},f:["Refresh"]},{p:[51,53,1469],t:7,e:"br"}," ",{p:[52,2,1476],t:7,e:"ui-display",a:{title:"Detected Supermatters"},f:[{t:4,f:[{p:[54,3,1552],t:7,e:"ui-section",a:{label:"Area"},f:[{t:2,r:"area_name",p:[55,5,1583]}," - (#",{t:2,r:"uid",p:[55,23,1601]},")"]}," ",{p:[57,3,1630],t:7,e:"ui-section",a:{label:"Integrity"},f:[{t:2,r:"integrity",p:[58,5,1666]}," %"]}," ",{p:[60,3,1702],t:7,e:"ui-section",a:{label:"Options"},f:[{p:[61,5,1736],t:7,e:"ui-button",a:{action:"PRG_set",params:['{"target" : "',{t:2,r:"uid",p:[61,54,1785]},'"}']},f:["View Details"]}]}],n:52,r:"data.supermatters",p:[53,2,1521]}]}],r:"data.active"}]},r.exports.components=r.exports.components||{};var i={ntosheader:t(430)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,430:430}],430:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"div",a:{"class":"item",style:"float: left"},f:[{p:[2,2,41],t:7,e:"table",f:[{p:[2,9,48],t:7,e:"tr",f:[{t:4,f:[{p:[4,3,113],t:7,e:"td",f:[{p:[4,7,117],t:7,e:"img",a:{src:[{t:2,r:"data.PC_batteryicon",p:[4,17,127]}]}}]}],n:50,x:{r:["data.PC_batteryicon","data.PC_showbatteryicon"],s:"_0&&_1"},p:[3,2,55]}," ",{t:4,f:[{p:[7,3,226],t:7,e:"td",f:[{p:[7,7,230],t:7,e:"b",f:[{t:2,r:"data.PC_batterypercent",p:[7,10,233]}]}]}],n:50,x:{r:["data.PC_batterypercent","data.PC_showbatteryicon"],s:"_0&&_1"},p:[6,2,165]}," ",{t:4,f:[{p:[10,3,305],t:7,e:"td",f:[{p:[10,7,309],t:7,e:"img",a:{src:[{t:2,r:"data.PC_ntneticon",p:[10,17,319]}]}}]}],n:50,r:"data.PC_ntneticon",p:[9,2,276]}," ",{t:4,f:[{p:[13,3,386],t:7,e:"td",f:[{p:[13,7,390],t:7,e:"img",a:{src:[{t:2,r:"data.PC_apclinkicon",p:[13,17,400]}]}}]}],n:50,r:"data.PC_apclinkicon",p:[12,2,355]}," ",{t:4,f:[{p:[16,3,469],t:7,e:"td",f:[{p:[16,7,473],t:7,e:"b",f:[{t:2,r:"data.PC_stationtime",p:[16,10,476]}]}]}],n:50,r:"data.PC_stationtime",p:[15,2,438]}," ",{t:4,f:[{p:[19,3,552],t:7,e:"td",f:[{p:[19,7,556],t:7,e:"img",a:{src:[{t:2,r:"icon",p:[19,17,566]}]}}]}],n:52,r:"data.PC_programheaders",p:[18,2,516]}]}]}]}," ",{p:[23,1,609],t:7,e:"div",a:{style:"float: right; margin-top: 5px"},f:[{p:[24,2,655],t:7,e:"ui-button",a:{action:"PC_shutdown"},f:["Shutdown"]}," ",{t:4,f:[{p:[26,3,745],t:7,e:"ui-button",a:{action:"PC_exit"},f:["EXIT PROGRAM"]}," ",{p:[27,3,801],t:7,e:"ui-button",a:{action:"PC_minimize"},f:["Minimize Program"]}],n:50,r:"data.PC_showexitprogram",p:[25,2,710]}]}," ",{p:[30,1,881],t:7,e:"div",a:{style:"clear: both"}}]},e.exports=a.extend(r.exports)},{341:341}],431:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Auth. Disk:"},f:[{t:4,f:[{p:[3,7,69],t:7,e:"ui-button",a:{icon:"eject",style:"selected",action:"eject_disk"},f:["++++++++++"]}],n:50,r:"data.disk_present",p:[2,3,36]},{t:4,n:51,f:[{p:[5,7,172],t:7,e:"ui-button",a:{icon:"plus",action:"insert_disk"},f:["----------"]}],r:"data.disk_present"}]}," ",{p:[8,1,266],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[9,3,297],t:7,e:"span",f:[{t:2,r:"data.status1",p:[9,9,303]},"-",{t:2,r:"data.status2",p:[9,26,320]}]}]}," ",{p:[11,1,360],t:7,e:"ui-display",a:{title:"Timer"},f:[{p:[12,3,390],t:7,e:"ui-section",a:{label:"Time to Detonation"},f:[{p:[13,5,435],t:7,e:"span",f:[{t:2,x:{r:["data.timing","data.time_left","data.timer_set"],s:"_0?_1:_2"},p:[13,11,441]}]}]}," ",{t:4,f:[{p:[16,5,540],t:7,e:"ui-section",a:{label:"Adjust Timer"},f:[{p:[17,7,581],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_default"],s:'_0&&_1&&_2?null:"disabled"'},p:[17,40,614]}],action:"timer",params:'{"change": "reset"}'},f:["Reset"]}," ",{p:[19,7,786],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_min"],s:'_0&&_1&&_2?null:"disabled"'},p:[19,38,817]}],action:"timer",params:'{"change": "decrease"}'},f:["Decrease"]}," ",{p:[21,7,991],t:7,e:"ui-button",a:{icon:"pencil",state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[21,39,1023]}],action:"timer",params:'{"change": "input"}'},f:["Set"]}," ",{p:[22,7,1155],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.timer_is_not_max"],s:'_0&&_1&&_2?null:"disabled"'},p:[22,37,1185]}],action:"timer",params:'{"change": "increase"}'},f:["Increase"]}]}],n:51,r:"data.timing",p:[15,3,518]}," ",{p:[26,3,1394],t:7,e:"ui-section",a:{label:"Timer"},f:[{p:[27,5,1426],t:7,e:"ui-button",a:{icon:"clock-o",style:[{t:2,x:{r:["data.timing"],s:'_0?"danger":"caution"'},p:[27,38,1459]}],action:"toggle_timer",state:[{t:2,x:{r:["data.disk_present","data.code_approved","data.safety"],s:'_0&&_1&&!_2?null:"disabled"'},p:[29,14,1542]}]},f:[{t:2,x:{r:["data.timing"],s:'_0?"On":"Off"'},p:[30,7,1631]}]}]}]}," ",{p:[34,1,1713],t:7,e:"ui-display",a:{title:"Anchoring"},f:[{p:[35,3,1747],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[36,12,1770]}],icon:[{t:2,x:{r:["data.anchored"],s:'_0?"lock":"unlock"'},p:[37,11,1846]}],style:[{t:2,x:{r:["data.anchored"],s:'_0?null:"caution"'},p:[38,12,1897]}],action:"anchor"},f:[{t:2,x:{r:["data.anchored"],s:'_0?"Engaged":"Off"'},p:[39,21,1956]}]}]}," ",{p:[41,1,2022],t:7,e:"ui-display",a:{title:"Safety"},f:[{p:[42,3,2053],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.disk_present","data.code_approved"],s:'_0&&_1?null:"disabled"'},p:[43,12,2076]}],icon:[{t:2,x:{r:["data.safety"],s:'_0?"lock":"unlock"'},p:[44,11,2152]}],action:"safety",style:[{t:2,x:{r:["data.safety"],s:'_0?"caution":"danger"'},p:[45,12,2217]}]},f:[{p:[46,7,2265],t:7,e:"span",f:[{t:2,x:{r:["data.safety"],s:'_0?"On":"Off"'},p:[46,13,2271]}]}]}]}," ",{p:[49,1,2341],t:7,e:"ui-display",a:{title:"Code"},f:[{p:[50,3,2370],t:7,e:"ui-section",a:{label:"Message"},f:[{t:2,r:"data.message",p:[50,31,2398]}]}," ",{p:[51,3,2431],t:7,e:"ui-section",a:{label:"Keypad"},f:[{p:[52,5,2464],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[52,39,2498]}],params:'{"digit":"1"}'},f:["1"]}," ",{p:[53,5,2583],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[53,39,2617]}],params:'{"digit":"2"}'},f:["2"]}," ",{p:[54,5,2702],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[54,39,2736]}],params:'{"digit":"3"}'},f:["3"]}," ",{p:[55,5,2821],t:7,e:"br"}," ",{p:[56,5,2831],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[56,39,2865]}],params:'{"digit":"4"}'},f:["4"]}," ",{p:[57,5,2950],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[57,39,2984]}],params:'{"digit":"5"}'},f:["5"]}," ",{p:[58,5,3069],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[58,39,3103]}],params:'{"digit":"6"}'},f:["6"]}," ",{p:[59,5,3188],t:7,e:"br"}," ",{p:[60,5,3198],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[60,39,3232]}],params:'{"digit":"7"}'},f:["7"]}," ",{p:[61,5,3317],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[61,39,3351]}],params:'{"digit":"8"}'},f:["8"]}," ",{p:[62,5,3436],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[62,39,3470]}],params:'{"digit":"9"}'},f:["9"]}," ",{p:[63,5,3555],t:7,e:"br"}," ",{p:[64,5,3565],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[64,39,3599]}],params:'{"digit":"R"}'},f:["R"]}," ",{p:[65,5,3684],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[65,39,3718]}],params:'{"digit":"0"}'},f:["0"]}," ",{p:[66,5,3803],t:7,e:"ui-button",a:{action:"keypad",state:[{t:2,x:{r:["data.disk_present"],s:'_0?null:"disabled"'},p:[66,39,3837]}],params:'{"digit":"E"}'},f:["E"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],432:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,25],t:7,e:"ui-button",a:{icon:"undo",action:"change_menu",params:'{"menu": "1"}'},f:["Return"]}," ",{p:[3,2,113],t:7,e:"ui-display",a:{title:"Advanced Surgery Procedures"},f:[{p:[4,3,165],t:7,e:"ui-button",a:{icon:"download",action:"sync"},f:["Sync with research database"]}," ",{t:4,f:[{p:[6,4,278],t:7,e:"ui-display",f:[{p:[7,6,297],t:7,e:"ui-section",f:[{p:[7,18,309],t:7,e:"b",f:[{t:2,r:"name",p:[7,21,312]}]}]}," ",{p:[8,6,344],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[8,18,356]}]}]}],n:52,r:"data.surgeries",p:[5,3,249]}]}],n:50,x:{r:["data.menu"],s:"_0==2"},p:[1,1,0]},{t:4,n:51,f:[{p:[13,2,437],t:7,e:"ui-button",a:{action:"change_menu",params:'{"menu": "2"}'},f:["View Surgery Procedures"]}," ",{t:4,f:[{p:[15,3,556],t:7,e:"ui-notice",f:["No table detected!"]}],n:51,r:"data.table",p:[14,2,530]}," ",{p:[19,2,623],t:7,e:"ui-display",f:[{p:[20,3,639],t:7,e:"ui-display",a:{title:"Patient State"},f:[{t:4,f:[{p:[22,5,704],t:7,e:"ui-section",a:{label:"State"},f:[{p:[23,6,737],t:7,e:"span",a:{"class":[{t:2,r:"data.patient.statstate",p:[23,19,750]}]},f:[{t:2,r:"data.patient.stat",p:[23,47,778]}]}]}," ",{p:[25,5,831],t:7,e:"ui-section",a:{label:"Blood Type"},f:[{p:[26,6,869],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"data.patient.blood_type",p:[26,28,891]}]}]}," ",{p:[28,5,950],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[29,6,984],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.patient.minHealth",p:[29,19,997]}],max:[{t:2,r:"data.patient.maxHealth",p:[29,52,1030]}],value:[{t:2,r:"data.patient.health",p:[29,87,1065]}],state:[{t:2,x:{r:["data.patient.health"],s:'_0>=0?"good":"average"'},p:[30,13,1103]}]},f:[{t:2,x:{r:["adata.patient.health"],s:"Math.round(_0)"},p:[30,64,1154]}]}]}," ",{t:4,f:[{p:[33,6,1389],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[33,25,1408]}]},f:[{p:[34,7,1427],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.patient.maxHealth",p:[34,28,1448]}],value:[{t:2,rx:{r:"data.patient",m:[{t:30,n:"type"}]},p:[34,63,1483]}],state:"bad"},f:[{t:2,x:{r:["type","adata.patient"],s:"Math.round(_1[_0])"},p:[34,99,1519]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Burn",type:"fireLoss"},{label:"Toxin",type:"toxLoss"},{label:"Respiratory",type:"oxyLoss"}]'},p:[32,5,1224]}],n:50,r:"data.patient",p:[21,4,678]},{t:4,n:51,f:["No patient detected."],r:"data.patient"}]}," ",{p:[41,3,1670],t:7,e:"ui-display",a:{title:"Initiated Procedures"},f:[{t:4,f:[{t:4,f:[{p:[44,6,1777],t:7,e:"ui-subdisplay",a:{title:[{t:2,r:"name",p:[44,28,1799]}]},f:[{p:[45,7,1817],t:7,e:"ui-section",a:{label:"Next Step"},f:[{p:[46,8,1856],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"next_step",p:[46,30,1878]}]}," ",{t:4,f:[{p:[48,9,1937],t:7,e:"span",a:{"class":"content"},f:[{p:[48,31,1959],t:7,e:"b",f:["Required chemicals:"]},{p:[48,57,1985],t:7,e:"br"}," ",{t:2,r:"chems_needed",p:[48,62,1990]}]}],n:50,r:"chems_needed",p:[47,8,1907]}]}," ",{t:4,f:[{p:[52,8,2091],t:7,e:"ui-section",a:{label:"Alternative Step"},f:[{p:[53,9,2138],t:7,e:"span",a:{"class":"content"},f:[{t:2,r:"alternative_step",p:[53,31,2160]}]}," ",{t:4,f:[{p:[55,10,2232],t:7,e:"span",a:{"class":"content"},f:[{p:[55,32,2254],t:7,e:"b",f:["Required chemicals:"]},{p:[55,58,2280],t:7,e:"br"}," ",{t:2,r:"chems_needed",p:[55,63,2285]}]}],n:50,r:"alt_chems_needed",p:[54,9,2197]}]}],n:50,r:"alternative_step",p:[51,7,2058]}]}],n:52,r:"data.procedures",p:[43,5,1745]}],n:50,r:"data.procedures",p:[42,4,1716]},{t:4,n:51,f:["No active procedures."],r:"data.procedures"}]}]}],x:{r:["data.menu"],s:"_0==2"}}]},e.exports=a.extend(r.exports)},{341:341}],433:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,2,15],t:7,e:"ui-section",f:["This machine only accepts ore. Gibtonite and Slag are not accepted."]}," ",{p:[5,2,117],t:7,e:"ui-section",f:["Current unclaimed credits: ",{t:2,r:"data.unclaimedPoints",p:[6,30,160]}," ",{p:[7,4,189],t:7,e:"ui-button",a:{action:"Claim"},f:["Claim"]}]}]}," ",{p:[12,1,276],t:7,e:"ui-display",f:[{t:4,f:[{p:[14,3,315],t:7,e:"ui-section",f:[{p:[15,4,332],t:7,e:"ui-button",a:{action:"diskEject",icon:"eject"},f:["Eject Disk"]}]}," ",{t:4,f:[{p:[20,4,460],t:7,e:"ui-section",a:{"class":"candystripe"},f:[{p:[21,5,496],t:7,e:"ui-button",a:{action:"diskUpload",state:[{t:2,x:{r:["canupload"],s:'(_0)?null:"disabled"'},p:[21,42,533]}],icon:"upload",align:"right",params:['{ "design" : "',{t:2,r:"index",p:[21,129,620]},'" }']},f:["Upload"]}," File ",{t:2,r:"index",p:[24,10,676]},": ",{t:2,r:"name",p:[24,21,687]}]}],n:52,r:"data.diskDesigns",p:[19,3,429]}],n:50,r:"data.hasDisk",p:[13,2,291]},{t:4,n:51,f:[{p:[28,3,741],t:7,e:"ui-section",f:[{p:[29,4,758],t:7,e:"ui-button",a:{action:"diskInsert",icon:"floppy-o"},f:["Insert Disk"]}]}],r:"data.hasDisk" +}]}," ",{t:4,f:[{p:[36,2,911],t:7,e:"ui-display",f:[{p:[37,3,927],t:7,e:"ui-section",f:[{p:[38,4,944],t:7,e:"b",f:["Warning"]},": ",{t:2,r:"data.disconnected",p:[38,20,960]},". Please contact the quartermaster."]}]}],n:50,r:"data.disconnected",p:[35,1,883]},{t:4,f:[{p:[43,2,1100],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[44,3,1133],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[45,5,1168],t:7,e:"section",a:{"class":"cell"},f:["Mineral"]}," ",{p:[48,5,1226],t:7,e:"section",a:{"class":"cell"},f:["Sheets"]}," ",{p:[51,5,1283],t:7,e:"section",a:{"class":"cell"},f:[]}," ",{p:[53,5,1327],t:7,e:"section",a:{"class":"cell"},f:[]}," ",{p:[55,5,1371],t:7,e:"section",a:{"class":"cell"},f:["Ore Value"]}]}," ",{t:4,f:[{p:[60,4,1473],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[61,5,1508],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[62,6,1537]}]}," ",{p:[64,5,1567],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[65,6,1610]}]}," ",{p:[67,5,1642],t:7,e:"section",a:{"class":"cell"},f:[{p:[68,6,1671],t:7,e:"input",a:{value:[{t:2,r:"sheets",p:[68,19,1684]}],placeholder:"###","class":"number"}}]}," ",{p:[70,5,1751],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{p:[71,6,1794],t:7,e:"ui-button",a:{"class":"center",grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[71,60,1848]}],params:['{ "id" : ',{t:2,r:"id",p:[71,115,1903]},', "sheets" : ',{t:2,r:"sheets",p:[71,134,1922]}," }"]},f:["Release"]}]}," ",{p:[75,5,1993],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"value",p:[76,6,2036]}]}]}],n:52,r:"data.materials",p:[59,3,1444]}," ",{t:4,f:[{p:[81,4,2119],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[82,5,2154],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[83,6,2183]}]}," ",{p:[85,5,2213],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[86,6,2256]}]}," ",{p:[88,5,2288],t:7,e:"section",a:{"class":"cell"},f:[{p:[89,6,2317],t:7,e:"input",a:{value:[{t:2,r:"sheets",p:[89,19,2330]}],placeholder:"###","class":"number"}}]}," ",{p:[91,5,2397],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{p:[92,6,2440],t:7,e:"ui-button",a:{"class":"center",grid:0,action:"Smelt",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[92,58,2492]}],params:['{ "id" : ',{t:2,r:"id",p:[92,114,2548]},', "sheets" : ',{t:2,r:"sheets",p:[92,133,2567]}," }"]},f:["Smelt"]}]}," ",{p:[96,5,2635],t:7,e:"section",a:{"class":"cell",align:"right"},f:[]}]}],n:52,r:"data.alloys",p:[80,3,2093]}]}],n:50,x:{r:["data.materials","data.alloys"],s:"_0||_1"},p:[42,1,1060]}]},e.exports=a.extend(r.exports)},{341:341}],434:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:{button:[{p:[4,4,87],t:7,e:"ui-button",a:{icon:"remove",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[4,36,119]}],action:"empty_eject_beaker"},f:["Empty and eject"]}," ",{p:[7,4,231],t:7,e:"ui-button",a:{icon:"trash",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[7,35,262]}],action:"empty_beaker"},f:["Empty"]}," ",{p:[10,4,358],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.has_beaker"],s:'_0?null:"disabled"'},p:[10,35,389]}],action:"eject_beaker"},f:["Eject"]}]},t:7,e:"ui-display",a:{title:"Beaker",button:0},f:[" ",{t:4,f:[{p:[15,4,528],t:7,e:"ui-section",f:[{t:4,f:[{p:[17,6,578],t:7,e:"span",a:{"class":"bad"},f:["The beaker is empty!"]}],n:50,r:"data.beaker_empty",p:[16,5,546]},{t:4,n:51,f:[{p:[19,6,644],t:7,e:"ui-subdisplay",a:{title:"Blood"},f:[{t:4,f:[{p:[21,8,712],t:7,e:"ui-section",a:{label:"Blood DNA"},f:[{t:2,r:"data.blood.dna",p:[21,38,742]}]}," ",{p:[22,8,782],t:7,e:"ui-section",a:{label:"Blood type"},f:[{t:2,r:"data.blood.type",p:[22,39,813]}]}],n:50,r:"data.has_blood",p:[20,7,681]},{t:4,n:51,f:[{p:[24,8,870],t:7,e:"ui-section",f:[{p:[25,9,892],t:7,e:"span",a:{"class":"average"},f:["No blood sample detected."]}]}],r:"data.has_blood"}]}],r:"data.beaker_empty"}]}],n:50,r:"data.has_beaker",p:[14,3,500]},{t:4,n:51,f:[{p:[32,4,1054],t:7,e:"ui-section",f:[{p:[33,5,1072],t:7,e:"span",a:{"class":"bad"},f:["No beaker loaded."]}]}],r:"data.has_beaker"}]}," ",{t:4,f:[{p:[38,3,1188],t:7,e:"ui-display",a:{title:"Diseases"},f:[{t:4,f:[{p:{button:[{t:4,f:[{p:[43,8,1343],t:7,e:"ui-button",a:{icon:"pencil",action:"rename_disease",state:[{t:2,x:{r:["can_rename"],s:'_0?"":"disabled"'},p:[43,64,1399]}],params:['{"index": ',{t:2,r:"index",p:[43,116,1451]},"}"]},f:["Name advanced disease"]}],n:50,r:"is_adv",p:[42,7,1320]}," ",{p:[47,7,1538],t:7,e:"ui-button",a:{icon:"flask",action:"create_culture_bottle",state:[{t:2,x:{r:["data.is_ready"],s:'_0?"":"disabled"'},p:[47,69,1600]}],params:['{"index": ',{t:2,r:"index",p:[47,124,1655]},"}"]},f:["Create virus culture bottle"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[40,24,1269]}],button:0},f:[" ",{p:[51,6,1749],t:7,e:"ui-section",a:{label:"Disease agent"},f:[{t:2,r:"agent",p:[51,40,1783]}]}," ",{p:[52,6,1812],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"description",p:[52,38,1844]}]}," ",{p:[53,6,1879],t:7,e:"ui-section",a:{label:"Spread"},f:[{t:2,r:"spread",p:[53,33,1906]}]}," ",{p:[54,6,1936],t:7,e:"ui-section",a:{label:"Possible cure"},f:[{t:2,r:"cure",p:[54,40,1970]}]}," ",{t:4,f:[{p:[56,7,2021],t:7,e:"ui-section",a:{label:"Symptoms"},f:[{t:4,f:[{p:[58,9,2087],t:7,e:"ui-button",a:{action:"symptom_details",state:"",params:['{"picked_symptom": ',{t:2,r:"sym_index",p:[58,81,2159]},', "index": ',{t:2,r:"index",p:[58,105,2183]},"}"]},f:[{t:2,r:"name",p:[59,10,2206]}," "]},{p:[60,21,2236],t:7,e:"br"}],n:52,r:"symptoms",p:[57,8,2059]}]}," ",{p:[63,7,2289],t:7,e:"ui-section",a:{label:"Resistance"},f:[{t:2,r:"resistance",p:[63,38,2320]}]}," ",{p:[64,7,2355],t:7,e:"ui-section",a:{label:"Stealth"},f:[{t:2,r:"stealth",p:[64,35,2383]}]}," ",{p:[65,7,2415],t:7,e:"ui-section",a:{label:"Stage speed"},f:[{t:2,r:"stage_speed",p:[65,39,2447]}]}," ",{p:[66,7,2483],t:7,e:"ui-section",a:{label:"Transmittability"},f:[{t:2,r:"transmission",p:[66,44,2520]}]}],n:50,r:"is_adv",p:[55,6,1999]}]}],n:52,r:"data.viruses",p:[39,4,1222]},{t:4,n:51,f:[{p:[70,5,2601],t:7,e:"ui-section",f:[{p:[71,6,2620],t:7,e:"span",a:{"class":"average"},f:["No detectable virus in the blood sample."]}]}],r:"data.viruses"}]}," ",{p:[75,3,2743],t:7,e:"ui-display",a:{title:"Antibodies"},f:[{t:4,f:[{p:[77,5,2811],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[77,24,2830]}]},f:[{p:[78,7,2848],t:7,e:"ui-button",a:{icon:"eyedropper",state:[{t:2,x:{r:["data.is_ready"],s:'_0?"":"disabled"'},p:[78,43,2884]}],action:"create_vaccine_bottle",params:['{"index": ',{t:2,r:"id",p:[78,129,2970]},"}"]},f:["Create vaccine bottle"]}]}],n:52,r:"data.resistances",p:[76,4,2779]},{t:4,n:51,f:[{p:[83,5,3067],t:7,e:"ui-section",f:[{p:[84,6,3086],t:7,e:"span",a:{"class":"average"},f:["No antibodies detected in the blood sample."]}]}],r:"data.resistances"}]}],n:50,r:"data.has_blood",p:[37,2,1162]}],n:50,x:{r:["data.mode"],s:"_0==1"},p:[1,1,0]},{t:4,n:51,f:[{p:[90,2,3231],t:7,e:"ui-button",a:{icon:"undo",state:"",action:"back"},f:["Back"]}," ",{t:4,f:[{p:[94,4,3330],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[94,23,3349]}]},f:[{p:[95,4,3364],t:7,e:"ui-section",f:[{t:2,r:"desc",p:[96,5,3382]}," ",{t:4,f:[{p:[98,5,3417],t:7,e:"br"}," ",{p:[99,5,3428],t:7,e:"b",f:["This symptom has been neutered, and has no effect. It will still affect the virus' statistics."]}],n:50,r:"neutered",p:[97,4,3395]}]}," ",{p:[102,4,3564],t:7,e:"ui-section",f:[{p:[103,5,3582],t:7,e:"ui-section",a:{label:"Level"},f:[{t:2,r:"level",p:[103,31,3608]}]}," ",{p:[104,5,3636],t:7,e:"ui-section",a:{label:"Resistance"},f:[{t:2,r:"resistance",p:[104,36,3667]}]}," ",{p:[105,5,3700],t:7,e:"ui-section",a:{label:"Stealth"},f:[{t:2,r:"stealth",p:[105,33,3728]}]}," ",{p:[106,5,3758],t:7,e:"ui-section",a:{label:"Stage speed"},f:[{t:2,r:"stage_speed",p:[106,37,3790]}]}," ",{p:[107,5,3824],t:7,e:"ui-section",a:{label:"Transmittability"},f:[{t:2,r:"transmission",p:[107,42,3861]}]}]}," ",{p:[109,4,3913],t:7,e:"ui-subdisplay",a:{title:"Effect Thresholds"},f:[{p:[110,5,3960],t:7,e:"ui-section",f:[{t:3,r:"threshold_desc",p:[110,17,3972]}]}]}]}],n:53,r:"data.symptom",p:[93,2,3303]}],x:{r:["data.mode"],s:"_0==1"}}]},e.exports=a.extend(r.exports)},{341:341}],435:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(483);e.exports={data:{filter:"",tooltiptext:function(t,e,n){var a="";return t&&(a+="REQUIREMENTS: "+t+" "),e&&(a+="CATALYSTS: "+e+" "),n&&(a+="TOOLS: "+n),a}},oninit:function(){var t=this;this.on({hover:function(t){this.set("hovered",t.context.params)},unhover:function(t){this.set("hovered")}}),this.observe("filter",function(e,a,r){var i=null;i=t.get("data.display_compact")?t.findAll(".section"):t.findAll(".display:not(:first-child)"),(0,n.filterMulti)(i,t.get("filter").toLowerCase())},{init:!1})}}}(r),r.exports.template={v:3,t:[" ",{p:[48,1,1342],t:7,e:"ui-display",a:{title:[{t:2,r:"data.category",p:[48,20,1361]},{t:4,f:[" : ",{t:2,r:"data.subcategory",p:[48,64,1405]}],n:50,r:"data.subcategory",p:[48,37,1378]}]},f:[{t:4,f:[{p:[50,3,1459],t:7,e:"ui-section",f:["Crafting... ",{p:[51,16,1488],t:7,e:"i",a:{"class":"fa-spin fa fa-spinner"}}]}],n:50,r:"data.busy",p:[49,2,1438]},{t:4,n:51,f:[{p:[54,3,1557],t:7,e:"ui-section",f:[{p:[55,4,1574],t:7,e:"table",a:{style:"width:100%"},f:[{p:[56,5,1606],t:7,e:"tr",f:[{p:[57,6,1617],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[58,7,1659],t:7,e:"ui-button",a:{icon:"arrow-left",action:"backwardCat"},f:[{t:2,r:"data.prev_cat",p:[59,8,1718]}]}]}," ",{p:[62,6,1774],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[63,7,1816],t:7,e:"ui-button",a:{icon:"arrow-right",action:"forwardCat"},f:[{t:2,r:"data.next_cat",p:[64,7,1874]}]}]}," ",{p:[67,6,1930],t:7,e:"td",a:{style:"float:right!important"},f:[{t:4,f:[{p:[69,7,2014],t:7,e:"ui-button",a:{icon:"lock",action:"toggle_recipes"},f:["Showing Craftable Recipes"]}],n:50,r:"data.display_craftable_only",p:[68,6,1971]},{t:4,n:51,f:[{p:[73,7,2138],t:7,e:"ui-button",a:{icon:"unlock",action:"toggle_recipes"},f:["Showing All Recipes"]}],r:"data.display_craftable_only"}]}," ",{p:[78,6,2268],t:7,e:"td",a:{style:"float:right!important"},f:[{p:[79,7,2310],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.display_compact"],s:'_0?"check-square-o":"square-o"'},p:[79,24,2327]}],action:"toggle_compact"},f:["Compact"]}]}]}," ",{p:[84,5,2474],t:7,e:"tr",f:[{t:4,f:[{p:[86,6,2515],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[87,7,2557],t:7,e:"ui-button",a:{icon:"arrow-left",action:"backwardSubCat"},f:[{t:2,r:"data.prev_subcat",p:[88,8,2619]}]}]}," ",{p:[91,6,2678],t:7,e:"td",a:{style:"width:150px!important"},f:[{p:[92,7,2720],t:7,e:"ui-button",a:{icon:"arrow-right",action:"forwardSubCat"},f:[{t:2,r:"data.next_subcat",p:[93,8,2782]}]}]}],n:50,r:"data.subcategory",p:[85,5,2484]}]}]}," ",{t:4,f:[{t:4,f:[" ",{p:[101,6,2992],t:7,e:"ui-input",a:{value:[{t:2,r:"filter",p:[101,23,3009]}],placeholder:"Filter.."}}],n:51,r:"data.display_compact",p:[100,5,2902]}],n:50,r:"config.fancy",p:[99,4,2876]}]}," ",{t:4,f:[{p:[106,5,3144],t:7,e:"ui-display",f:[{t:4,f:[{p:[108,6,3193],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[108,25,3212]}]},f:[{p:[109,7,3230],t:7,e:"ui-button",a:{tooltip:[{t:2,x:{r:["tooltiptext","req_text","catalyst_text","tool_text"],s:"_0(_1,_2,_3)"},p:[109,27,3250]}],"tooltip-side":"right",action:"make",params:['{"recipe": "',{t:2,r:"ref",p:[109,135,3358]},'"}'],icon:"gears"},v:{hover:"hover",unhover:"unhover"},f:["Craft"]}]}],n:52,r:"data.can_craft",p:[107,5,3162]}," ",{t:4,f:[{t:4,f:[{p:[116,7,3567],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[116,26,3586]}]},f:[{p:[117,8,3605],t:7,e:"ui-button",a:{tooltip:[{t:2,x:{r:["tooltiptext","req_text","catalyst_text","tool_text"],s:"_0(_1,_2,_3)"},p:[117,28,3625]}],"tooltip-side":"right",state:"disabled",icon:"gears"},v:{hover:"hover",unhover:"unhover"},f:["Craft"]}]}],n:52,r:"data.cant_craft",p:[115,6,3534]}],n:51,r:"data.display_craftable_only",p:[114,5,3495]}]}],n:50,r:"data.display_compact",p:[105,4,3110]},{t:4,n:51,f:[{t:4,f:[{p:[126,6,3947],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[126,25,3966]}]},f:[{t:4,f:[{p:[128,8,4009],t:7,e:"ui-section",a:{label:"Requirements"},f:[{t:2,r:"req_text",p:[129,9,4052]}]}],n:50,r:"req_text",p:[127,7,3984]}," ",{t:4,f:[{p:[133,8,4139],t:7,e:"ui-section",a:{label:"Catalysts"},f:[{t:2,r:"catalyst_text",p:[134,9,4179]}]}],n:50,r:"catalyst_text",p:[132,7,4109]}," ",{t:4,f:[{p:[138,8,4267],t:7,e:"ui-section",a:{label:"Tools"},f:[{t:2,r:"tool_text",p:[139,9,4303]}]}],n:50,r:"tool_text",p:[137,7,4241]}," ",{p:[142,7,4361],t:7,e:"ui-section",f:[{p:[143,8,4382],t:7,e:"ui-button",a:{icon:"gears",action:"make",params:['{"recipe": "',{t:2,r:"ref",p:[143,66,4440]},'"}']},f:["Craft"]}]}]}],n:52,r:"data.can_craft",p:[125,5,3916]}," ",{t:4,f:[{t:4,f:[{p:[151,7,4621],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[151,26,4640]}]},f:[{t:4,f:[{p:[153,9,4685],t:7,e:"ui-section",a:{label:"Requirements"},f:[{t:2,r:"req_text",p:[154,10,4729]}]}],n:50,r:"req_text",p:[152,8,4659]}," ",{t:4,f:[{p:[158,9,4820],t:7,e:"ui-section",a:{label:"Catalysts"},f:[{t:2,r:"catalyst_text",p:[159,10,4861]}]}],n:50,r:"catalyst_text",p:[157,8,4789]}," ",{t:4,f:[{p:[163,9,4953],t:7,e:"ui-section",a:{label:"Tools"},f:[{t:2,r:"tool_text",p:[164,10,4990]}]}],n:50,r:"tool_text",p:[162,8,4926]}]}],n:52,r:"data.cant_craft",p:[150,6,4588]}],n:51,r:"data.display_craftable_only",p:[149,5,4549]}],r:"data.display_compact"}],r:"data.busy"}]}]},e.exports=a.extend(r.exports)},{341:341,483:483}],436:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-notice",f:[{p:[2,3,15],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.holding"],s:'_0?"is":"is not"'},p:[2,23,35]}," connected to a tank."]}]}," ",{p:[4,1,113],t:7,e:"ui-display",a:{title:"Status",button:0},f:[{p:[5,3,151],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[6,5,186],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[6,11,192]}," kPa"]}]}," ",{p:[8,3,254],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[9,5,285],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected"],s:'_0?"good":"average"'},p:[9,18,298]}]},f:[{t:2,x:{r:["data.connected"],s:'_0?"Connected":"Not Connected"'},p:[9,59,339]}]}]}]}," ",{p:[12,1,430],t:7,e:"ui-display",a:{title:"Pump"},f:[{p:[13,3,459],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[14,5,491],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[14,22,508]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":"null"'},p:[15,14,559]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[16,22,616]}]}]}," ",{p:[18,3,675],t:7,e:"ui-section",a:{label:"Direction"},f:[{p:[19,5,711],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.direction"],s:'_0=="out"?"sign-out":"sign-in"'},p:[19,22,728]}],action:"direction"},f:[{t:2,x:{r:["data.direction"],s:'_0=="out"?"Out":"In"'},p:[20,26,808]}]}]}," ",{p:[22,3,883],t:7,e:"ui-section",a:{label:"Target Pressure"},f:[{p:[23,5,925],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.min_pressure",p:[23,18,938]}],max:[{t:2,r:"data.max_pressure",p:[23,46,966]}],value:[{t:2,r:"data.target_pressure",p:[24,14,1003]}]},f:[{t:2,x:{r:["adata.target_pressure"],s:"Math.round(_0)"},p:[24,40,1029]}," kPa"]}]}," ",{p:[26,3,1100],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[27,5,1145],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.target_pressure","data.default_pressure"],s:'_0!=_1?null:"disabled"'},p:[27,38,1178]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[29,5,1328],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.target_pressure","data.min_pressure"],s:'_0>_1?null:"disabled"'},p:[29,36,1359]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[31,5,1500],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[32,5,1595],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.target_pressure","data.max_pressure"],s:'_0<_1?null:"disabled"'},p:[32,35,1625]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}]}," ",{p:{button:[{t:4,f:[{p:[39,7,1891],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.on"],s:'_0?"danger":null'},p:[39,38,1922]}],action:"eject"},f:["Eject"]}],n:50,r:"data.holding",p:[38,5,1863]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[43,3,2042],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holding.name",p:[44,4,2073]}]}," ",{p:[46,3,2115],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holding.pressure"],s:"Math.round(_0)"},p:[47,4,2149]}," kPa"]}],n:50,r:"data.holding",p:[42,3,2018]},{t:4,n:51,f:[{p:[50,3,2223],t:7,e:"ui-section",f:[{p:[51,4,2240],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.holding"}]}]},e.exports=a.extend(r.exports)},{341:341}],437:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" ",{p:[3,1,69],t:7,e:"ui-notice",f:[{p:[4,3,84],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.holding"],s:'_0?"is":"is not"'},p:[4,23,104]}," connected to a tank."]}]}," ",{p:[6,1,182],t:7,e:"ui-display",a:{title:"Status",button:0},f:[{p:[7,3,220],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[8,5,255],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.round(_0)"},p:[8,11,261]}," kPa"]}]}," ",{p:[10,3,323],t:7,e:"ui-section",a:{label:"Port"},f:[{p:[11,5,354],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected"],s:'_0?"good":"average"'},p:[11,18,367]}]},f:[{t:2,x:{r:["data.connected"],s:'_0?"Connected":"Not Connected"'},p:[11,59,408]}]}]}]}," ",{p:[14,1,499],t:7,e:"ui-display",a:{title:"Filter"},f:[{p:[15,3,530],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[16,5,562],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[16,22,579]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":"null"'},p:[17,14,630]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[18,22,687]}]}]}]}," ",{p:{button:[{t:4,f:[{p:[24,7,856],t:7,e:"ui-button",a:{icon:"eject",style:[{t:2,x:{r:["data.on"],s:'_0?"danger":null'},p:[24,38,887]}],action:"eject"},f:["Eject"]}],n:50,r:"data.holding",p:[23,5,828]}]},t:7,e:"ui-display",a:{title:"Holding Tank",button:0},f:[" ",{t:4,f:[{p:[28,3,1007],t:7,e:"ui-section",a:{label:"Label"},f:[{t:2,r:"data.holding.name",p:[29,4,1038]}]}," ",{p:[31,3,1080],t:7,e:"ui-section",a:{label:"Pressure"},f:[{t:2,x:{r:["adata.holding.pressure"],s:"Math.round(_0)"},p:[32,4,1114]}," kPa"]}],n:50,r:"data.holding",p:[27,3,983]},{t:4,n:51,f:[{p:[35,3,1188],t:7,e:"ui-section",f:[{p:[36,4,1205],t:7,e:"span",a:{"class":"average"},f:["No Holding Tank"]}]}],r:"data.holding"}]}," ",{p:[40,1,1293],t:7,e:"ui-display",a:{title:"Filters"},f:[{t:4,f:[{p:[42,5,1345],t:7,e:"filters"}],n:53,r:"data",p:[41,3,1325]}]}]},r.exports.components=r.exports.components||{};var i={filters:t(456)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,456:456}],438:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{chargingState:function(t){switch(t){case 2:return"good";case 1:return"average";default:return"bad"}},chargingMode:function(t){return 2==t?"Full":1==t?"Charging":"Draining"},channelState:function(t){return t>=2?"good":"bad"},channelPower:function(t){return t>=2?"On":"Off"},channelMode:function(t){return 1==t||3==t?"Auto":"Manual"}},computed:{graphData:function(){var t=this.get("data.history");return Object.keys(t).map(function(e){return t[e].map(function(t,e){return{x:e,y:t}})})}}}}(r),r.exports.template={v:3,t:[" ",{p:[42,1,1035],t:7,e:"ui-display",a:{title:"Network"},f:[{t:4,f:[{p:[44,5,1093],t:7,e:"ui-linegraph",a:{points:[{t:2,r:"graphData",p:[44,27,1115]}],height:"500",legend:'["Available", "Load"]',colors:'["rgb(0, 102, 0)", "rgb(153, 0, 0)"]',xunit:"seconds ago",xfactor:[{t:2,r:"data.interval",p:[46,38,1267]}],yunit:"W",yfactor:"1",xinc:[{t:2,x:{r:["data.stored"],s:"_0/10"},p:[47,15,1323]}],yinc:"9"}}],n:50,r:"config.fancy",p:[43,3,1067]},{t:4,n:51,f:[{p:[49,5,1373],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[50,7,1411],t:7,e:"span",f:[{t:2,r:"data.supply",p:[50,13,1417]}]}]}," ",{p:[52,5,1464],t:7,e:"ui-section",a:{label:"Load"},f:[{p:[53,9,1499],t:7,e:"span",f:[{t:2,r:"data.demand",p:[53,15,1505]}]}]}],r:"config.fancy"}]}," ",{p:[57,1,1574],t:7,e:"ui-display",a:{title:"Areas"},f:[{p:[58,3,1604],t:7,e:"ui-section",a:{nowrap:0},f:[{p:[59,5,1629],t:7,e:"div",a:{"class":"content"},f:["Area"]}," ",{p:[60,5,1666],t:7,e:"div",a:{"class":"content"},f:["Charge"]}," ",{p:[61,5,1705],t:7,e:"div",a:{"class":"content"},f:["Load"]}," ",{p:[62,5,1742],t:7,e:"div",a:{"class":"content"},f:["Status"]}," ",{p:[63,5,1781],t:7,e:"div",a:{"class":"content"},f:["Equipment"]}," ",{p:[64,5,1823],t:7,e:"div",a:{"class":"content"},f:["Lighting"]}," ",{p:[65,5,1864],t:7,e:"div",a:{"class":"content"},f:["Environment"]}]}," ",{t:4,f:[{p:[68,5,1949],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[68,24,1968]}],nowrap:0},f:[{p:[69,7,1993],t:7,e:"div",a:{"class":"content"},f:[{t:2,x:{r:["@index","adata.areas"],s:"Math.round(_1[_0].charge)"},p:[69,28,2014]}," %"]}," ",{p:[70,7,2072],t:7,e:"div",a:{"class":"content"},f:[{t:2,rx:{r:"adata.areas",m:[{t:30,n:"@index"},"load"]},p:[70,28,2093]}]}," ",{p:[71,7,2135],t:7,e:"div",a:{"class":"content"},f:[{p:[71,28,2156],t:7,e:"span",a:{"class":[{t:2,x:{r:["chargingState","charging"],s:"_0(_1)"},p:[71,41,2169]}]},f:[{t:2,x:{r:["chargingMode","charging"],s:"_0(_1)"},p:[71,70,2198]}]}]}," ",{p:[72,7,2245],t:7,e:"div",a:{"class":"content"},f:[{p:[72,28,2266],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","eqp"],s:"_0(_1)"},p:[72,41,2279]}]},f:[{t:2,x:{r:["channelPower","eqp"],s:"_0(_1)"},p:[72,64,2302]}," [",{p:[72,87,2325],t:7,e:"span",f:[{t:2,x:{r:["channelMode","eqp"],s:"_0(_1)"},p:[72,93,2331]}]},"]"]}]}," ",{p:[73,7,2380],t:7,e:"div",a:{"class":"content"},f:[{p:[73,28,2401],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","lgt"],s:"_0(_1)"},p:[73,41,2414]}]},f:[{t:2,x:{r:["channelPower","lgt"],s:"_0(_1)"},p:[73,64,2437]}," [",{p:[73,87,2460],t:7,e:"span",f:[{t:2,x:{r:["channelMode","lgt"],s:"_0(_1)"},p:[73,93,2466]}]},"]"]}]}," ",{p:[74,7,2515],t:7,e:"div",a:{"class":"content"},f:[{p:[74,28,2536],t:7,e:"span",a:{"class":[{t:2,x:{r:["channelState","env"],s:"_0(_1)"},p:[74,41,2549]}]},f:[{t:2,x:{r:["channelPower","env"],s:"_0(_1)"},p:[74,64,2572]}," [",{p:[74,87,2595],t:7,e:"span",f:[{t:2,x:{r:["channelMode","env"],s:"_0(_1)"},p:[74,93,2601]}]},"]"]}]}]}],n:52,r:"data.areas",p:[67,3,1923]}]}]},e.exports=a.extend(r.exports)},{341:341}],439:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{readableFrequency:function(){return Math.round(this.get("adata.frequency"))/10}}}}(r),r.exports.template={v:3,t:[" ",{p:[11,1,177],t:7,e:"ui-display",a:{title:"Settings"},f:[{t:4,f:[{p:[13,5,236],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[14,7,270],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.listening"],s:'_0?"power-off":"close"'},p:[14,24,287]}],style:[{t:2,x:{r:["data.listening"],s:'_0?"selected":null'},p:[14,75,338]}],action:"listen"},f:[{t:2,x:{r:["data.listening"],s:'_0?"On":"Off"'},p:[16,9,413]}]}]}],n:50,r:"data.headset",p:[12,3,210]},{t:4,n:51,f:[{p:[19,5,494],t:7,e:"ui-section",a:{label:"Microphone"},f:[{p:[20,7,533],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.broadcasting"],s:'_0?"power-off":"close"'},p:[20,24,550]}],style:[{t:2,x:{r:["data.broadcasting"],s:'_0?"selected":null'},p:[20,78,604]}],action:"broadcast"},f:[{t:2,x:{r:["data.broadcasting"],s:'_0?"Engaged":"Disengaged"'},p:[22,9,685]}]}]}," ",{p:[24,5,769],t:7,e:"ui-section",a:{label:"Speaker"},f:[{p:[25,7,805],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.listening"],s:'_0?"power-off":"close"'},p:[25,24,822]}],style:[{t:2,x:{r:["data.listening"],s:'_0?"selected":null'},p:[25,75,873]}],action:"listen"},f:[{t:2,x:{r:["data.listening"],s:'_0?"Engaged":"Disengaged"'},p:[27,9,948]}]}]}],r:"data.headset"}," ",{t:4,f:[{p:[31,5,1064],t:7,e:"ui-section",a:{label:"High Volume"},f:[{p:[32,7,1104],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.useCommand"],s:'_0?"power-off":"close"'},p:[32,24,1121]}],style:[{t:2,x:{r:["data.useCommand"],s:'_0?"selected":null'},p:[32,76,1173]}],action:"command"},f:[{t:2,x:{r:["data.useCommand"],s:'_0?"On":"Off"'},p:[34,9,1250]}]}]}],n:50,r:"data.command",p:[30,3,1038]}]}," ",{p:[38,1,1342],t:7,e:"ui-display",a:{title:"Channel"},f:[{p:[39,3,1374],t:7,e:"ui-section",a:{label:"Frequency"},f:[{t:4,f:[{p:[41,7,1439],t:7,e:"span",f:[{t:2,r:"readableFrequency",p:[41,13,1445]}]}],n:50,r:"data.freqlock",p:[40,5,1410]},{t:4,n:51,f:[{p:[43,7,1495],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.frequency","data.minFrequency"],s:'_0==_1?"disabled":null'},p:[43,46,1534]}],action:"frequency",params:'{"adjust": -1}'}}," ",{p:[44,7,1646],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.frequency","data.minFrequency"],s:'_0==_1?"disabled":null'},p:[44,41,1680]}],action:"frequency",params:'{"adjust": -.2}'}}," ",{p:[45,7,1793],t:7,e:"ui-button",a:{icon:"pencil",action:"frequency",params:'{"tune": "input"}'},f:[{t:2,r:"readableFrequency",p:[45,78,1864]}]}," ",{p:[46,7,1905],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.frequency","data.maxFrequency"],s:'_0==_1?"disabled":null'},p:[46,40,1938]}],action:"frequency",params:'{"adjust": .2}'}}," ",{p:[47,7,2050],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.frequency","data.maxFrequency"],s:'_0==_1?"disabled":null'},p:[47,45,2088]}],action:"frequency",params:'{"adjust": 1}'}}],r:"data.freqlock"}]}," ",{t:4,f:[{p:[51,5,2262],t:7,e:"ui-section",a:{label:"Subspace Transmission"},f:[{p:[52,7,2312],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.subspace"],s:'_0?"power-off":"close"'},p:[52,24,2329]}],style:[{t:2,x:{r:["data.subspace"],s:'_0?"selected":null'},p:[52,74,2379]}],action:"subspace"},f:[{t:2,x:{r:["data.subspace"],s:'_0?"Active":"Inactive"'},p:[53,29,2447]}]}]}],n:50,r:"data.subspaceSwitchable",p:[50,3,2225]}," ",{t:4,f:[{p:[57,5,2578],t:7,e:"ui-section",a:{label:"Channels"},f:[{t:4,f:[{p:[59,9,2656],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["."],s:'_0?"check-square-o":"square-o"'},p:[59,26,2673]}],style:[{t:2,x:{r:["."],s:'_0?"selected":null'},p:[60,18,2730]}],action:"channel",params:['{"channel": "',{t:2,r:"channel",p:[61,49,2806]},'"}']},f:[{t:2,r:"channel",p:[62,11,2833]}]},{p:[62,34,2856],t:7,e:"br"}],n:52,i:"channel",r:"data.channels",p:[58,7,2615]}]}],n:50,x:{r:["data.subspace","data.channels"],s:"_0&&_1"},p:[56,3,2534]}]}]},e.exports=a.extend(r.exports)},{341:341}],440:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," "," "," "," "," "," "," "," ",{p:[11,1,560],t:7,e:"rdheader"}," ",{t:4,f:[{p:[13,2,595],t:7,e:"ui-display",a:{title:"CONSOLE LOCKED"},f:[{p:[14,3,634],t:7,e:"ui-button",a:{action:"Unlock"},f:["Unlock"]}]}],n:50,r:"data.locked",p:[12,1,573]},{t:4,f:[{p:[18,2,729],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.tabs",p:[18,17,744]}]},f:[{p:[19,3,763],t:7,e:"tab",a:{name:"Technology"},f:[{p:[20,4,791],t:7,e:"techweb"}]}," ",{p:[22,3,815],t:7,e:"tab",a:{name:"View Node"},f:[{p:[23,4,842],t:7,e:"nodeview"}]}," ",{p:[25,3,867],t:7,e:"tab",a:{name:"View Design"},f:[{p:[26,4,896],t:7,e:"designview"}]}," ",{p:[28,3,923],t:7,e:"tab",a:{name:"Disk Operations - Design"},f:[{p:[29,4,965],t:7,e:"diskopsdesign"}]}," ",{p:[31,3,995],t:7,e:"tab",a:{name:"Disk Operations - Technology"},f:[{p:[32,4,1041],t:7,e:"diskopstech"}]}," ",{p:[34,3,1069],t:7,e:"tab",a:{name:"Deconstructive Analyzer"},f:[{p:[35,4,1110],t:7,e:"destruct"}]}," ",{p:[37,3,1135],t:7,e:"tab",a:{name:"Protolathe"},f:[{p:[38,4,1163],t:7,e:"protolathe"}]}," ",{p:[40,3,1190],t:7,e:"tab",a:{name:"Circuit Imprinter"},f:[{p:[41,4,1225],t:7,e:"circuit"}]}," ",{p:[43,3,1249],t:7,e:"tab",a:{name:"Settings"},f:[{p:[44,4,1275],t:7,e:"settings"}]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[17,1,706]}]},r.exports.components=r.exports.components||{};var i={settings:t(449),circuit:t(441),protolathe:t(447),destruct:t(443),diskopsdesign:t(444),diskopstech:t(445),designview:t(442),nodeview:t(446),techweb:t(450),rdheader:t(448)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,441:441,442:442,443:443,444:444,445:445,446:446,447:447,448:448,449:449,450:450}],441:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[3,3,58],t:7,e:"ui-display",a:{title:"Circuit Imprinter Busy!"}}],n:50,r:"data.circuitbusy",p:[2,2,30]},{t:4,n:51,f:[{p:[5,3,130],t:7,e:"ui-display",f:[{p:[6,4,147],t:7,e:"ui-section",f:["Search Available Designs: ",{p:[7,4,189],t:7,e:"input",a:{value:[{t:2,r:"textsearch",p:[7,17,202]}],placeholder:"Type Here","class":"text"}}," ",{p:[8,5,261],t:7,e:"ui-button",a:{action:"textSearch",params:['{"latheType" : "circuit", "inputText" : ',{t:2,r:"textsearch",p:[8,84,340]},"}"]},f:["Search"]}]}," ",{p:[10,4,398],t:7,e:"ui-section",f:["Materials: ",{t:2,r:"data.circuitmats",p:[10,27,421]}," / ",{t:2,r:"data.circuitmaxmats",p:[10,50,444]}]}," ",{p:[11,4,485],t:7,e:"ui-section",f:["Reagents: ",{t:2,r:"data.circuitchems",p:[11,26,507]}," / ",{t:2,r:"data.circuitmaxchems",p:[11,50,531]}]}," ",{p:[12,3,572],t:7,e:"ui-display",f:[{p:[14,3,590],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.lathe_tabs",p:[14,18,605]}]},f:[{p:[15,4,631],t:7,e:"tab",a:{name:"Category List"},f:[{t:4,f:[{p:[17,6,696],t:7,e:"ui-button",a:{action:"switchcat",state:[{t:2,x:{r:["data.circuitcat"],s:'_0=="{{name}}"?"selected":null'},p:[17,43,733]}],params:['{"type" : "circuit", "cat" : "',{t:2,r:"name",p:[17,135,825]},'"}']},f:[{t:2,r:"name",p:[17,147,837]}]}],n:52,r:"data.circuitcats",p:[16,5,663]}]}," ",{p:[20,4,888],t:7,e:"tab",a:{name:"Selected Category"},f:[{t:4,f:[{p:[22,6,956],t:7,e:"ui-section",f:[{t:2,r:"name",p:[22,18,968]},{t:2,r:"matstring",p:[22,26,976]}," ",{p:[23,7,997],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[23,40,1030]}],params:['{"latheType" : "circuit", "id" : "',{t:2,r:"id",p:[23,119,1109]},'"}']},f:["Print"]}]}],n:52,r:"data.circuitdes",p:[21,5,924]}]}," ",{p:[27,4,1187],t:7,e:"tab",a:{name:"Search Results"},f:[{t:4,f:[{p:[29,6,1254],t:7,e:"ui-section",f:[{t:2,r:"name",p:[29,18,1266]},{t:2,r:"matstring",p:[29,26,1274]}," ",{p:[30,7,1295],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[30,40,1328]}],params:['{"latheType" : "circuit", "id" : "',{t:2,r:"id",p:[30,119,1407]},'"}']},f:["Print"]}]}],n:52,r:"data.circuitmatch",p:[28,5,1220]}]}," ",{p:[34,4,1485],t:7,e:"tab",a:{name:"Materials"},f:[{t:4,f:[{p:[36,6,1550],t:7,e:"ui-section",f:[{t:2,r:"name",p:[36,18,1562]}," : ",{t:2,r:"amount",p:[36,29,1573]}," cm3 - ",{t:4,f:[{p:[38,7,1623],t:7,e:"input",a:{value:[{t:2,r:"number",p:[38,20,1636]}],placeholder:["1-",{t:2,r:"sheets",p:[38,46,1662]}],"class":"number"}}," ",{p:[39,7,1698],t:7,e:"ui-button",a:{action:"releasemats",params:['{"latheType" : "circuit", "mat_id" : ',{t:2,r:"mat_id",p:[39,84,1775]},', "sheets" : ',{t:2,r:"number",p:[39,107,1798]},"}"]},f:["Release"]}],n:50,x:{r:["sheets"],s:"_0>0"},p:[37,6,1597]}]}],n:52,r:"data.circuitmat_list",p:[35,5,1513]}]}," ",{p:[44,4,1895],t:7,e:"tab",a:{name:"Chemicals"},f:[{t:4,f:[{p:[46,6,1961],t:7,e:"ui-section",f:[{t:2,r:"name",p:[46,18,1973]}," : ",{t:2,r:"amount",p:[46,29,1984]}," - ",{p:[47,7,2005],t:7,e:"ui-button",a:{action:"purgechem",params:['{"latheType" : "circuit", "name" : ',{t:2,r:"name",p:[47,80,2078]},', "id" : ',{t:2,r:"reagentid",p:[47,97,2095]},"}"]},f:["Purge"]}]}],n:52,r:"data.circuitchem_list",p:[45,5,1923]}]}]}]}]}],r:"data.circuitbusy"}],n:50,r:"data.circuit_linked",p:[1,1,0]},{t:4,n:51,f:[{p:[55,2,2216],t:7,e:"ui-display",a:{title:"No Linked Circuit Imprinter"}}],r:"data.circuit_linked"}]},e.exports=a.extend(r.exports)},{341:341}],442:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,31],t:7,e:"ui-display",a:{title:[{t:2,r:"data.sdesign_name",p:[2,21,50] +}]},f:[{p:[3,3,77],t:7,e:"ui-section",a:{title:"Description"},f:[{t:2,r:"data.sdesign_desc",p:[3,35,109]}]}]}," ",{p:[5,2,162],t:7,e:"ui-display",a:{title:"Lathe Types"},f:[{t:4,f:[{p:[7,4,239],t:7,e:"ui-section",a:{title:"Circuit Imprinter"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&1"},p:[6,3,198]}," ",{t:4,f:[{p:[10,4,346],t:7,e:"ui-section",a:{title:"Protolathe"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&2"},p:[9,3,305]}," ",{t:4,f:[{p:[13,4,446],t:7,e:"ui-section",a:{title:"Autolathe"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&4"},p:[12,3,405]}," ",{t:4,f:[{p:[16,4,545],t:7,e:"ui-section",a:{title:"Crafting Fabricator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&8"},p:[15,3,504]}," ",{t:4,f:[{p:[19,4,655],t:7,e:"ui-section",a:{title:"Exosuit Fabricator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&16"},p:[18,3,613]}," ",{t:4,f:[{p:[22,4,764],t:7,e:"ui-section",a:{title:"Biogenerator"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&32"},p:[21,3,722]}," ",{t:4,f:[{p:[25,4,867],t:7,e:"ui-section",a:{title:"Limb Grower"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&64"},p:[24,3,825]}," ",{t:4,f:[{p:[28,4,970],t:7,e:"ui-section",a:{title:"Ore Smelter"}}],n:50,x:{r:["data.sdesign_buildtype"],s:"_0&128"},p:[27,3,927]}]}," ",{p:[31,2,1045],t:7,e:"ui-display",a:{title:"Materials"},f:[{t:4,f:[{p:[33,4,1116],t:7,e:"ui-section",a:{title:[{t:2,r:"matname",p:[33,23,1135]}]},f:[{t:2,r:"matamt",p:[33,36,1148]}," cm^3"]}],n:52,r:"data.sdesign_materials",p:[32,3,1079]}]}],n:50,r:"data.design_selected",p:[1,1,0]},{t:4,f:[{p:[38,2,1248],t:7,e:"ui-display",a:{title:"No Design Selected."}}],n:50,x:{r:["data.design_selected"],s:"!_0"},p:[37,1,1216]}]},e.exports=a.extend(r.exports)},{341:341}],443:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[4,3,60],t:7,e:"ui-display",a:{title:"Destructive Analyzer Busy!"}}],n:50,r:"data.destroybusy",p:[3,2,32]},{t:4,n:51,f:[{t:4,f:[{p:[7,4,168],t:7,e:"ui-display",a:{title:"Destructive Analyzer Unloaded"}}],n:50,x:{r:["data.destroy_loaded"],s:"!_0"},p:[6,3,135]},{t:4,n:51,f:[{p:[9,4,248],t:7,e:"ui-display",a:{title:"Loaded Item"},f:[{p:[10,4,285],t:7,e:"ui-section",a:{title:"Name"},f:[{t:2,r:"data.destroy_name",p:[10,29,310]}]}]}," ",{p:[12,4,367],t:7,e:"ui-display",a:{title:"Boost Nodes"},f:[{t:4,f:[{p:[14,6,438],t:7,e:"ui-section",a:{title:[{t:2,r:"name",p:[14,25,457]}," | ",{t:2,r:"value",p:[14,36,468]}]},f:[{p:[15,7,487],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["allow"],s:'_0?null:"disabled"'},p:[15,25,505]}],action:"deconstruct",params:['{"id":',{t:2,r:"id",p:[15,90,570]},"}"]},f:["Deconstruct and Boost"]}]}],n:52,r:"data.boost_paths",p:[13,5,405]}]}," ",{p:[19,4,670],t:7,e:"ui-button",a:{action:"eject_da"},f:["Eject Item"]}],x:{r:["data.destroy_loaded"],s:"!_0"}}],r:"data.destroybusy"}],n:50,r:"data.destroy_linked",p:[2,1,2]},{t:4,n:51,f:[{p:[23,2,755],t:7,e:"ui-display",a:{title:"No Linked Destructive Analyzer"}}],r:"data.destroy_linked"}]},e.exports=a.extend(r.exports)},{341:341}],444:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[3,2,24],t:7,e:"ui-display",a:{title:"No Design Disk Loaded"}}],n:50,x:{r:["data.ddisk"],s:"!_0"},p:[2,1,2]},{t:4,n:51,f:[{t:4,f:[{p:[6,3,121],t:7,e:"ui-display",a:{title:"Design Disk Updating"}}],n:50,r:"data.ddisk_update",p:[5,2,92]},{t:4,n:51,f:[{t:4,f:[{p:[9,4,221],t:7,e:"ui-display",a:{title:"Design Disk"},f:[{p:[10,5,259],t:7,e:"ui-section",a:{title:"Disk Space"},f:["Disk Capacity: ",{t:2,r:"data.ddisk_size",p:[10,51,305]}," blueprints."]}," ",{p:[11,5,355],t:7,e:"ui-section",a:{title:"Disk IO"},f:[{p:[11,33,383],t:7,e:"ui-button",a:{action:"ddisk_upall"},f:["Upload all designs"]}]}," ",{p:[12,5,464],t:7,e:"ui-section",a:{title:"Clear Disk"},f:[{p:[12,36,495],t:7,e:"ui-button",a:{action:"clear_designdisk",style:"danger"},f:["WIPE ALL DATA"]}]}," ",{p:[13,5,591],t:7,e:"ui-section",a:{title:"Eject Disk"},f:[{p:[13,36,622],t:7,e:"ui-button",a:{action:"eject_designdisk"},f:["Eject Disk"]}]}]}," ",{p:[15,4,717],t:7,e:"ui-display",a:{title:"Disk Contents"},f:[{t:4,f:[{p:[17,6,792],t:7,e:"ui-section",a:{title:"Number"},f:["#",{t:2,r:"pos",p:[17,34,820]},": ",{t:4,f:[{p:[19,8,866],t:7,e:"ui-button",a:{action:"upload_empty_ddisk_slot",params:['{"slot": "',{t:2,r:"pos",p:[19,70,928]},'"}']},f:["Upload to Empty Slot"]}],n:50,x:{r:["id"],s:'_0=="null"'},p:[18,7,837]},{t:4,n:51,f:[{p:[21,8,996],t:7,e:"ui-button",a:{action:"select_design",params:['{"id": "',{t:2,r:"id",p:[21,58,1046]},'"}'],state:[{t:2,x:{r:["data.sdesign_id","id"],s:'_0==_1?"selected":null'},p:[21,75,1063]}]},f:[{t:2,r:"name",p:[21,122,1110]}]}," ",{p:[22,8,1139],t:7,e:"ui-button",a:{action:"ddisk_erasepos",style:"danger",params:['{"id": "',{t:2,r:"id",p:[22,74,1205]},'"}'],state:[{t:2,x:{r:["id"],s:'_0=="null"?"disabled":null'},p:[22,91,1222]}]},f:["Delete Slot"]}],x:{r:["id"],s:'_0=="null"'}}]}],n:52,r:"data.ddisk_designs",p:[16,5,757]}]}],n:50,x:{r:["data.ddisk_upload"],s:"!_0"},p:[8,3,190]},{t:4,n:51,f:[{p:[28,4,1367],t:7,e:"ui-display",a:{title:"Upload Design to Disk"},f:[{p:[28,46,1409],t:7,e:"ui-section",f:["Available Designs:"]}]}," ",{t:4,f:[{p:[30,5,1513],t:7,e:"ui-section",f:[{p:[30,17,1525],t:7,e:"ui-button",a:{action:"ddisk_uploaddesign",params:['{"id": "',{t:2,r:"id",p:[30,72,1580]},'"}']},f:[{t:2,r:"name",p:[30,82,1590]}]}]}],n:52,r:"data.ddisk_possible_designs",p:[29,4,1470]}],x:{r:["data.ddisk_upload"],s:"!_0"}}],r:"data.ddisk_update"}],x:{r:["data.ddisk"],s:"!_0"}}]},e.exports=a.extend(r.exports)},{341:341}],445:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[3,2,24],t:7,e:"ui-display",a:{title:"No Technology Disk Loaded"}}],n:50,x:{r:["data.tdisk"],s:"!_0"},p:[2,1,2]},{t:4,n:51,f:[{t:4,f:[{p:[6,3,125],t:7,e:"ui-display",a:{title:"Technology Disk Updating"}}],n:50,r:"data.tdisk_update",p:[5,2,96]},{t:4,n:51,f:[{p:[8,3,198],t:7,e:"ui-display",a:{title:"Technology Disk"},f:[{p:[9,4,239],t:7,e:"ui-section",a:{title:"Disk IO"},f:[{p:[9,32,267],t:7,e:"ui-button",a:{action:"tdisk_down"},f:["Download Research to Disk"]},{p:[9,100,335],t:7,e:"ui-button",a:{action:"tdisk_up"},f:["Upload Research from Disk"]}," ",{p:[10,4,406],t:7,e:"ui-section",a:{title:"Clear Disk"},f:[{p:[10,35,437],t:7,e:"ui-button",a:{action:"clear_techdisk",style:"danger"},f:["WIPE ALL DATA"]}]}," ",{p:[11,4,530],t:7,e:"ui-section",a:{title:"Eject Disk"},f:[{p:[11,35,561],t:7,e:"ui-button",a:{action:"eject_techdisk"},f:["Eject Disk"]}]}]}]}," ",{p:[13,3,652],t:7,e:"ui-display",a:{title:"Disk Contents"},f:[{t:4,f:[{p:[15,5,723],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[15,53,771]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[15,70,788]}]},f:[{t:2,r:"display_name",p:[15,115,833]}]}],n:52,r:"data.tdisk_nodes",p:[14,4,691]}]}],r:"data.tdisk_update"}],x:{r:["data.tdisk"],s:"!_0"}}]},e.exports=a.extend(r.exports)},{341:341}],446:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,2,29],t:7,e:"ui-display",a:{title:[{t:2,r:"data.snode_name",p:[2,21,48]}]},f:[{p:[3,3,73],t:7,e:"ui-section",a:{title:"Description"},f:["Description: ",{t:2,r:"data.snode_desc",p:[3,48,118]}]}," ",{p:[4,3,154],t:7,e:"ui-section",a:{title:"Point Cost"},f:["Point Cost: ",{t:2,r:"data.snode_cost",p:[4,46,197]}]}," ",{p:[5,3,233],t:7,e:"ui-section",a:{title:"Export Price"},f:["Export Price: ",{t:2,r:"data.snode_export",p:[5,50,280]}]}," ",{p:[6,3,318],t:7,e:"ui-button",a:{action:"research_node",params:['{"id"="',{t:2,r:"id",p:[6,52,367]},'"}'],state:[{t:2,x:{r:["data.snode_researched"],s:'_0?"disabled":null'},p:[6,69,384]}]},f:[{t:2,x:{r:["data.snode_researched"],s:'_0?"Researched":"Research Node"'},p:[6,115,430]}]}]}," ",{p:[8,2,518],t:7,e:"ui-display",a:{title:"Prerequisites"},f:[{t:4,f:[{p:[10,4,588],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[10,52,636]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[10,69,653]}]},f:[{t:2,r:"display_name",p:[10,114,698]}]}],n:52,r:"data.node_prereqs",p:[9,3,556]}]}," ",{p:[13,2,759],t:7,e:"ui-display",a:{title:"Unlocks"},f:[{t:4,f:[{p:[15,4,823],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[15,52,871]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[15,69,888]}]},f:[{t:2,r:"display_name",p:[15,114,933]}]}],n:52,r:"data.node_unlocks",p:[14,3,791]}]}," ",{p:[18,2,994],t:7,e:"ui-display",a:{title:"Designs"},f:[{t:4,f:[{p:[20,4,1058],t:7,e:"ui-button",a:{action:"select_design",params:['{"id": "',{t:2,r:"id",p:[20,54,1108]},'"}'],state:[{t:2,x:{r:["data.sdesign_id","id"],s:'_0==_1?"selected":null'},p:[20,71,1125]}]},f:[{t:2,r:"name",p:[20,118,1172]}]}],n:52,r:"data.node_designs",p:[19,3,1026]}]}],n:50,r:"data.node_selected",p:[1,1,0]},{t:4,f:[{p:[25,2,1263],t:7,e:"ui-display",a:{title:"No Node Selected."}}],n:50,x:{r:["data.node_selected"],s:"!_0"},p:[24,1,1233]}]},e.exports=a.extend(r.exports)},{341:341}],447:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{t:4,f:[{p:[3,3,59],t:7,e:"ui-display",a:{title:"Protolathe Busy!"}}],n:50,r:"data.protobusy",p:[2,2,33]},{t:4,n:51,f:[{p:[5,3,124],t:7,e:"ui-display",f:[{p:[6,4,141],t:7,e:"ui-section",f:["Search Available Designs: ",{p:[7,4,183],t:7,e:"input",a:{value:[{t:2,r:"textsearch",p:[7,17,196]}],placeholder:"Type Here","class":"text"}}," ",{p:[8,5,255],t:7,e:"ui-button",a:{action:"textSearch",params:['{"latheType" : "proto", "inputText" : ',{t:2,r:"textsearch",p:[8,82,332]},"}"]},f:["Search"]}]}," ",{p:[10,4,390],t:7,e:"ui-section",f:["Materials: ",{t:2,r:"data.protomats",p:[10,27,413]}," / ",{t:2,r:"data.protomaxmats",p:[10,48,434]}]}," ",{p:[11,4,473],t:7,e:"ui-section",f:["Reagents: ",{t:2,r:"data.protochems",p:[11,26,495]}," / ",{t:2,r:"data.protomaxchems",p:[11,48,517]}]}," ",{p:[12,3,556],t:7,e:"ui-display",f:[{p:[14,3,574],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.lathe_tabs",p:[14,18,589]}]},f:[{p:[15,4,615],t:7,e:"tab",a:{name:"Category List"},f:[{t:4,f:[{p:[17,6,678],t:7,e:"ui-button",a:{action:"switchcat",state:[{t:2,x:{r:["data.protocat","name"],s:'_0==_1?"selected":null'},p:[17,43,715]}],params:['{"type" : "proto", "cat" : "',{t:2,r:"name",p:[17,125,797]},'"}']},f:[{t:2,r:"name",p:[17,137,809]}]}],n:52,r:"data.protocats",p:[16,5,647]}]}," ",{p:[20,4,860],t:7,e:"tab",a:{name:"Selected Category"},f:[{t:4,f:[{p:[22,6,926],t:7,e:"ui-section",f:[{t:2,r:"name",p:[22,18,938]},{t:2,r:"matstring",p:[22,26,946]}," ",{t:4,f:[{p:[24,8,996],t:7,e:"input",a:{value:[{t:2,r:"number",p:[24,21,1009]}],placeholder:["1-",{t:2,x:{r:["canprint"],s:"_0>10?10:_0"},p:[24,47,1035]}],"class":"number"}}],n:50,x:{r:["canprint"],s:"_0>1"},p:[23,7,967]}," ",{p:[26,7,1108],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[26,40,1141]}],params:['{"latheType" : "proto", "id" : "',{t:2,r:"id",p:[26,117,1218]},'", "amount" : "',{t:2,r:"number",p:[26,138,1239]},'"}']},f:["Print"]}]}],n:52,r:"data.protodes",p:[21,5,896]}]}," ",{p:[30,4,1321],t:7,e:"tab",a:{name:"Search Results"},f:[{t:4,f:[{p:[32,6,1386],t:7,e:"ui-section",f:[{t:2,r:"name",p:[32,18,1398]},{t:2,r:"matstring",p:[32,26,1406]}," ",{t:4,f:[{p:[34,8,1456],t:7,e:"input",a:{value:[{t:2,r:"number",p:[34,21,1469]}],placeholder:["1-",{t:2,x:{r:["canprint"],s:"_0>10?10:_0"},p:[34,47,1495]}],"class":"number"}}],n:50,x:{r:["canprint"],s:"_0>1"},p:[33,7,1427]}," ",{p:[36,7,1568],t:7,e:"ui-button",a:{action:"print",state:[{t:2,x:{r:["canprint"],s:'_0>1?null:"disabled"'},p:[36,40,1601]}],params:['{"latheType" : "proto", "id" : "',{t:2,r:"id",p:[36,117,1678]},'", "amount" : "',{t:2,r:"number",p:[36,138,1699]},'"}']},f:["Print"]}]}],n:52,r:"data.protomatch",p:[31,5,1354]}]}," ",{p:[40,4,1781],t:7,e:"tab",a:{name:"Materials"},f:[{t:4,f:[{p:[42,6,1844],t:7,e:"ui-section",f:[{t:2,r:"name",p:[42,18,1856]}," : ",{t:2,r:"amount",p:[42,29,1867]}," cm3 - ",{t:4,f:[{p:[44,7,1917],t:7,e:"input",a:{value:[{t:2,r:"number",p:[44,20,1930]}],placeholder:["1-",{t:2,r:"sheets",p:[44,46,1956]}],"class":"number"}}," ",{p:[45,7,1992],t:7,e:"ui-button",a:{action:"releasemats",params:['{"latheType" : "proto", "mat_id" : ',{t:2,r:"mat_id",p:[45,82,2067]},', "sheets" : ',{t:2,r:"number",p:[45,105,2090]},"}"]},f:["Release"]}],n:50,x:{r:["sheets"],s:"_0>0"},p:[43,6,1891]}]}],n:52,r:"data.protomat_list",p:[41,5,1809]}]}," ",{p:[50,4,2187],t:7,e:"tab",a:{name:"Chemicals"},f:[{t:4,f:[{p:[52,6,2251],t:7,e:"ui-section",f:[{t:2,r:"name",p:[52,18,2263]}," : ",{t:2,r:"amount",p:[52,29,2274]}," - ",{p:[53,7,2295],t:7,e:"ui-button",a:{action:"purgechem",params:['{"latheType" : "proto", "name" : ',{t:2,r:"name",p:[53,78,2366]},', "id" : ',{t:2,r:"reagentid",p:[53,95,2383]},"}"]},f:["Purge"]}]}],n:52,r:"data.protochem_list",p:[51,5,2215]}]}]}]}]}],r:"data.protobusy"}],n:50,r:"data.protolathe_linked",p:[1,1,0]},{t:4,n:51,f:[{p:[61,2,2504],t:7,e:"ui-display",a:{title:"No Linked Protolathe"}}],r:"data.protolathe_linked"}]},e.exports=a.extend(r.exports)},{341:341}],448:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,1,14],t:7,e:"span",a:{"class":"memoedit"},f:["Nanotrasen R&D Console"]},{p:[2,53,66],t:7,e:"br"}," Available Points: ",{p:[3,19,91],t:7,e:"ui-section",a:{title:"Research Points"},f:[{t:2,r:"data.research_points_stored",p:[3,55,127]}]}," ",{p:[4,1,173],t:7,e:"ui-section",a:{title:["Page Selection - ",{t:2,r:"page",p:[4,37,209]}]},f:[{p:[4,47,219],t:7,e:"input",a:{value:[{t:2,r:"pageselect",p:[4,60,232]}],placeholder:"1","class":"number"}}," Select Page: ",{p:[5,14,294],t:7,e:"ui-button",a:{action:"page",params:['{"num" : "',{t:2,r:"pageselect",p:[5,57,337]},'"}']},f:["[Go]"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],449:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"span",a:{"class":"bad"},f:["Settings"]},{p:[1,34,33],t:7,e:"br"},{p:[1,39,38],t:7,e:"br"}," ",{p:[2,1,45],t:7,e:"ui-button",a:{action:"Resync"},f:["RESYNC MACHINERY"]},{p:[2,56,100],t:7,e:"br"}," ",{p:[3,1,107],t:7,e:"ui-button",a:{action:"Lock"},f:["LOCK"]}," ",{p:[4,1,150],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "destroy"}',state:[{t:2,x:{r:["data.destroy_linked"],s:'_0?null:"disabled"'},p:[4,71,220]}]},f:["Disconnect Destructive Analyzer"]}," ",{p:[5,1,309],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "lathe"}',state:[{t:2,x:{r:["data.protolathe_linked"],s:'_0?null:"disabled"'},p:[5,69,377]}]},f:["Disconnect Protolathe"]}," ",{p:[6,1,459],t:7,e:"ui-button",a:{action:"disconnect",params:'{"type" : "imprinter"}',state:[{t:2,x:{r:["data.circuit_linked"],s:'_0?null:"disabled"'},p:[6,73,531]}]},f:["Disconnect Circuit Imprinter"]}]},e.exports=a.extend(r.exports)},{341:341}],450:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Available for Research"},f:[{t:4,f:[{p:[3,3,78],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[3,51,126]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[3,68,143]}]},f:[{t:2,r:"display_name",p:[3,113,188]}]}],n:52,r:"data.techweb_avail",p:[2,2,46]}]}," ",{p:[6,1,245],t:7,e:"ui-display",a:{title:"Locked Nodes"},f:[{t:4,f:[{p:[8,3,314],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[8,51,362]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[8,68,379]}]},f:[{t:2,r:"display_name",p:[8,113,424]}]}],n:52,r:"data.techweb_locked",p:[7,2,281]}]}," ",{p:[11,1,482],t:7,e:"ui-display",a:{title:"Researched Nodes"},f:[{t:4,f:[{p:[13,3,559],t:7,e:"ui-button",a:{action:"select_node",params:['{"id": "',{t:2,r:"id",p:[13,51,607]},'"}'],state:[{t:2,x:{r:["data.snode_id","id"],s:'_0==_1?"selected":null'},p:[13,68,624]}]},f:[{t:2,r:"display_name",p:[13,113,669]}]}],n:52,r:"data.techweb_researched",p:[12,2,522]}]}]},e.exports=a.extend(r.exports)},{341:341}],451:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,1,25],t:7,e:"ui-notice",f:[{p:[3,3,40],t:7,e:"span",f:["The grinder is currently processing and cannot be used."]}]}],n:50,r:"data.processing",p:[1,1,0]},{p:{button:[{p:[8,5,208],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.operating","data.contents"],s:'(_0==0)&&_1?null:"disabled"'},p:[8,36,239]}],action:"eject"},f:["Eject Contents"]}]},t:7,e:"ui-display",a:{title:"Processing Chamber",button:0},f:[" ",{p:[10,3,364],t:7,e:"ui-section",a:{label:"Grinding"},f:[{p:[11,5,399],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.operating"],s:'_0?"average":"good"'},p:[11,18,412]}]},f:[{t:2,x:{r:["data.operating"],s:'_0?"Busy":"Ready"'},p:[11,59,453]}]}," ",{p:[12,2,500],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.operating","data.contents"],s:'(_0==0)&&_1?null:"disabled"'},p:[12,35,533]}],action:"grind"},f:["Activate"]}]}," ",{p:[14,3,653],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{t:4,f:[{p:[17,9,755],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:["The ",{t:2,r:"name",p:[17,56,802]}]},{p:[17,71,817],t:7,e:"br"}],n:52,r:"adata.contentslist",p:[16,7,717]},{t:4,n:51,f:[{p:[19,9,848],t:7,e:"span",f:["No Contents"]}],r:"adata.contentslist"}],n:50,r:"data.contents",p:[15,5,688]},{t:4,n:51,f:[{p:[22,7,911],t:7,e:"span",f:["No Contents"]}],r:"data.contents"}]}]}," ",{p:{button:[{p:[28,5,1047],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.operating","data.isBeakerLoaded"],s:'(_0==0)&&_1?null:"disabled"'},p:[28,36,1078]}],action:"detach"},f:["Detach"]}]},t:7,e:"ui-display",a:{title:"Container",button:0},f:[" ",{p:[30,3,1202],t:7,e:"ui-section",a:{label:"Reagents"},f:[{t:4,f:[{p:[32,7,1272],t:7,e:"span",f:[{t:2,x:{r:["adata.beakerCurrentVolume"],s:"Math.round(_0)"},p:[32,13,1278]},"/",{t:2,r:"data.beakerMaxVolume",p:[32,55,1320]}," Units"]}," ",{p:[33,7,1365],t:7,e:"br"}," ",{t:4,f:[{p:[35,9,1418],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[35,52,1461]}," units of ",{t:2,r:"name",p:[35,87,1496]}]},{p:[35,102,1511],t:7,e:"br"}],n:52,r:"adata.beakerContents",p:[34,7,1378]},{t:4,n:51,f:[{p:[37,9,1542],t:7,e:"span",a:{"class":"bad"},f:["Container Empty"]}],r:"adata.beakerContents"}],n:50,r:"data.isBeakerLoaded",p:[31,5,1237]},{t:4,n:51,f:[{p:[40,7,1621],t:7,e:"span",a:{"class":"average"},f:["No Container"]}],r:"data.isBeakerLoaded"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],452:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Direction"},f:[{t:4,f:[{p:[3,3,64],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,5,105],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[5,23,123]}],action:"setdir",params:['{"dir": ',{t:2,r:"dir",p:[6,22,195]},', "flipped": ',{t:2,r:"flipped",p:[6,42,215]},"}"]},f:[{p:[6,56,229],t:7,e:"span",a:{"class":["pipes32x32 ",{t:2,r:"dir",p:[6,80,253]},"-",{t:2,r:"icon_state",p:[6,88,261]}],title:[{t:2,r:"dir_name",p:[6,111,284]}]}}]}],n:52,r:"previews",p:[4,4,81]}]}],n:52,r:"data.preview_rows",p:[2,2,33]}]}," ",{t:4,f:[{p:[12,2,406],t:7,e:"ui-display",a:{title:"Color"},f:[{t:4,f:[{p:[14,4,468],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["@key","data.selected_color"],s:'_0==_1?"selected":null'},p:[14,22,486]}],action:"color",params:['{"paint_color": ',{t:2,r:"@key",p:[15,44,583]},"}"]},f:[{t:2,r:"@key",p:[15,55,594]}]}],n:52,r:"data.paint_colors",p:[13,3,436]}]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[11,1,377]},{p:[19,1,654],t:7,e:"ui-display",a:{title:"Utilities"},f:[{p:[20,2,687],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&1?"check-square-o":"square-o"'},p:[20,19,704]}],action:"mode",params:'{"mode": 1}'},f:["Build"]}," ",{p:[22,2,813],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&2?"check-square-o":"square-o"'},p:[22,19,830]}],action:"mode",params:'{"mode": 2}'},f:["Wrench"]}," ",{p:[24,2,940],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&4?"check-square-o":"square-o"'},p:[24,19,957]}],action:"mode",params:'{"mode": 4}'},f:["Destroy"]}," ",{t:4,f:[{p:[27,3,1098],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mode"],s:'_0&8?"check-square-o":"square-o"'},p:[27,20,1115]}],action:"mode",params:'{"mode": 8}'},f:["Paint"]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[26,2,1068]}]}," ",{p:[31,1,1249],t:7,e:"ui-display",a:{title:"Category"},f:[{p:[32,2,1281],t:7,e:"ui-section",f:[{p:[33,3,1297],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==0?"check-square-o":"square-o"'},p:[33,20,1314]}],state:[{t:2,x:{r:["data.category"],s:'_0<=0?"selected":null'},p:[33,83,1377]}],action:"category",params:'{"category": 0}'},f:["Atmospherics"]}," ",{p:[35,3,1496],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==1?"check-square-o":"square-o"'},p:[35,20,1513]}],state:[{t:2,x:{r:["data.category"],s:'_0==1?"selected":null'},p:[35,83,1576]}],action:"category",params:'{"category": 1}'},f:["Disposals"]}," ",{p:[37,3,1692],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.category"],s:'_0==2?"check-square-o":"square-o"'},p:[37,20,1709]}],state:[{t:2,x:{r:["data.category"],s:'_0==2?"selected":null'},p:[37,83,1772]}],action:"category",params:'{"category": 2}'},f:["Transit Tubes"]}]}," ",{t:4,f:[{p:[41,3,1937],t:7,e:"ui-section",a:{label:"Piping Layer"},f:[{p:[42,4,1975],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==1?"selected":null'},p:[42,22,1993]}],action:"piping_layer",params:'{"piping_layer": 1}'},f:["1"]}," ",{p:[44,4,2115],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==2?"selected":null'},p:[44,22,2133]}],action:"piping_layer",params:'{"piping_layer": 2}'},f:["2"]}," ",{p:[46,4,2255],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.piping_layer"],s:'_0==3?"selected":null'},p:[46,22,2273]}],action:"piping_layer",params:'{"piping_layer": 3}'},f:["3"]}]}],n:50,x:{r:["data.category"],s:"_0==0"},p:[40,2,1907]}]}," ",{t:4,f:[{p:[52,2,2462],t:7,e:"ui-display",a:{title:[{t:2,r:"cat_name",p:[52,21,2481]}]},f:[{t:4,f:[{p:[54,4,2521],t:7,e:"ui-section",f:[{p:[55,5,2539],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[55,23,2557]}],action:"pipe_type",params:['{"pipe_type": ',{t:2,r:"pipe_index",p:[56,28,2638]},', "category": ',{t:2,r:"cat_name",p:[56,56,2666]},"}"]},f:[{t:2,r:"pipe_name",p:[56,71,2681]}]}]}],n:52,r:"recipes",p:[53,3,2499]}]}],n:52,r:"data.categories",p:[51,1,2434]}]},e.exports=a.extend(r.exports)},{341:341}],453:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Color"},f:[{t:4,f:[{p:[3,3,60],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[3,21,78]}],action:"color",params:['{"paint_color": ',{t:2,r:"color_name",p:[4,28,155]},"}"]},f:[{t:2,r:"color_name",p:[4,45,172]}]}],n:52,r:"data.paint_colors",p:[2,2,29]}]}]},e.exports=a.extend(r.exports)},{341:341}],454:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Direction"},f:[{t:4,f:[{p:[3,3,64],t:7,e:"ui-section",f:[{t:4,f:[{p:[5,5,105],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["selected"],s:'_0?"selected":null'},p:[5,23,123]}],action:"setdir",params:['{"dir": ',{t:2,r:"dir",p:[6,22,195]},', "flipped": ',{t:2,r:"flipped",p:[6,42,215]},"}"]},f:[{p:[6,56,229],t:7,e:"img",a:{src:["pipe.",{t:2,r:"dir",p:[6,71,244]},".",{t:2,r:"icon_state",p:[6,79,252]},".png"],title:[{t:2,r:"dir_name",p:[6,106,279]}]}}]}],n:52,r:"previews",p:[4,4,81]}]}],n:52,r:"data.preview_rows",p:[2,2,33]}]}]},e.exports=a.extend(r.exports)},{341:341}],455:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,23],t:7,e:"ui-notice",f:[{t:2,r:"data.notice",p:[3,5,40]}]}],n:50,r:"data.notice",p:[1,1,0]},{p:[6,1,82],t:7,e:"ui-display",a:{title:"Satellite Network Control",button:0},f:[{t:4,f:[{p:[8,4,168],t:7,e:"ui-section",a:{candystripe:0,nowrap:0},f:[{p:[9,9,209],t:7,e:"div",a:{"class":"content"},f:["#",{t:2,r:"id",p:[9,31,231]}]}," ",{p:[10,9,253],t:7,e:"div",a:{"class":"content"},f:[{t:2,r:"mode",p:[10,30,274]}]}," ",{p:[11,9,298],t:7,e:"div",a:{"class":"content"},f:[{p:[12,11,331],t:7,e:"ui-button",a:{action:"toggle",params:['{"id": "',{t:2,r:"id",p:[12,54,374]},'"}']},f:[{t:2,x:{r:["active"],s:'_0?"Deactivate":"Activate"'},p:[12,64,384]}]}]}]}],n:52,r:"data.satellites",p:[7,2,138]}]}," ",{t:4,f:[{p:[18,1,528],t:7,e:"ui-display",a:{title:"Station Shield Coverage"},f:[{p:[19,3,576],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.meteor_shield_coverage_max",p:[19,24,597]}],value:[{t:2,r:"data.meteor_shield_coverage",p:[19,68,641]}]},f:[{t:2,x:{r:["data.meteor_shield_coverage","data.meteor_shield_coverage_max"],s:"100*_0/_1"},p:[19,101,674]}," %"]}," ",{p:[20,1,758],t:7,e:"ui-display",f:[]}]}],n:50,r:"data.meteor_shield",p:[17,1,500]}]},e.exports=a.extend(r.exports)},{341:341}],456:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,26],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["enabled"],s:'_0?"check-square-o":"square-o"'},p:[2,20,43]}],style:[{t:2,x:{r:["enabled"],s:'_0?"selected":null'},p:[2,72,95]}],action:"toggle_filter",params:['{"id_tag": "',{t:2,r:"id_tag",p:[3,48,176]},'", "val": ',{t:2,r:"gas_id",p:[3,68,196]},"}"]},f:[{t:2,r:"gas_name",p:[3,81,209]}]}],n:52,r:"filter_types",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],457:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[" "," "," ",{p:[5,1,200],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.tabs",p:[5,16,215]}]},f:[{p:[6,2,233],t:7,e:"tab",a:{name:"Status"},f:[{p:[7,3,256],t:7,e:"status"}]}," ",{p:[9,2,277],t:7,e:"tab",a:{name:"Templates"},f:[{p:[10,3,303],t:7,e:"templates"}]}," ",{p:[12,2,327],t:7,e:"tab",a:{name:"Modification"},f:[{t:4,f:[{p:[14,3,381],t:7,e:"modification"}],n:50,r:"data.selected",p:[13,3,356]}," ",{t:4,f:[{p:[17,3,437],t:7,e:"span",a:{"class":"bad"},f:["No shuttle selected."]}],n:50,x:{r:["data.selected"],s:"!_0"},p:[16,3,411]}]}]}]},r.exports.components=r.exports.components||{};var i={modification:t(458),templates:t(460),status:t(459)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{341:341,458:458,459:459,460:460}],458:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:["Selected: ",{t:2,r:"data.selected.name",p:[1,30,29]}]},f:[{t:4,f:[{p:[3,5,96],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"data.selected.description",p:[3,37,128]}]}],n:50,r:"data.selected.description",p:[2,3,57]}," ",{t:4,f:[{p:[6,5,224],t:7,e:"ui-section",a:{label:"Admin Notes"},f:[{t:2,r:"data.selected.admin_notes",p:[6,37,256]}]}],n:50,r:"data.selected.admin_notes",p:[5,3,185]}]}," ",{t:4,f:[{p:[11,3,361],t:7,e:"ui-display",a:{title:["Existing Shuttle: ",{t:2,r:"data.existing_shuttle.name",p:[11,40,398]}]},f:["Status: ",{t:2,r:"data.existing_shuttle.status",p:[12,13,444]}," ",{t:4,f:["(",{t:2,r:"data.existing_shuttle.timeleft",p:[14,8,526]},")"],n:50,r:"data.existing_shuttle.timer",p:[13,5,482]}," ",{p:[16,5,580],t:7,e:"ui-button",a:{action:"jump_to",params:['{"type": "mobile", "id": "',{t:2,r:"data.existing_shuttle.id",p:[17,41,649]},'"}']},f:["Jump To"]}]}],n:50,r:"data.existing_shuttle",p:[10,1,328]},{t:4,f:[{p:[24,3,778],t:7,e:"ui-display",a:{title:"Existing Shuttle: None"}}],n:50,x:{r:["data.existing_shuttle"],s:"!_0"},p:[23,1,744]},{p:[27,1,847],t:7,e:"ui-button",a:{action:"preview",params:['{"shuttle_id": "',{t:2,r:"data.selected.shuttle_id",p:[28,27,902]},'"}']},f:["Preview"]}," ",{p:[31,1,961],t:7,e:"ui-button",a:{action:"load",params:['{"shuttle_id": "',{t:2,r:"data.selected.shuttle_id",p:[32,27,1013]},'"}'],style:"danger"},f:["Load"]}," ",{p:[37,1,1089],t:7,e:"ui-display",a:{title:"Status"},f:[]}]},e.exports=a.extend(r.exports)},{341:341}],459:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"table",a:{width:"100%"},f:[{t:4,f:[{p:[3,3,49],t:7,e:"tr",f:[{p:[4,5,59],t:7,e:"td",f:[{p:[5,7,71],t:7,e:"ui-button",a:{action:"jump_to",params:['{"type": "mobile", "id": "',{t:2,r:"id",p:[5,69,133]},'"}']},f:["JMP"]}]}," ",{p:[9,5,193],t:7,e:"td",f:[{p:[10,7,205],t:7,e:"ui-button",a:{action:"fly",params:['{"id": "',{t:2,r:"id",p:[10,47,245]},'"}'],state:[{t:2,x:{r:["can_fly"],s:'_0?null:"disabled"'},p:[10,64,262]}]},f:["Fly"]}]}," ",{p:[14,5,345],t:7,e:"td",f:[{t:2,r:"name",p:[15,7,357]}," (",{p:[15,17,367],t:7,e:"code",f:[{t:2,r:"id",p:[15,23,373]}]},")"]}," ",{p:[17,5,404],t:7,e:"td",f:[{t:2,r:"status",p:[18,7,416]}]}," ",{p:[20,5,443],t:7,e:"td",f:[{t:4,f:[{t:2,r:"mode",p:[22,9,477]}],n:50,r:"mode",p:[21,7,455]}," ",{t:4,f:["(",{t:2,r:"timeleft",p:[25,10,532]},") ",{p:[26,9,555],t:7,e:"ui-button",a:{action:"fast_travel",params:['{"id": "',{t:2,r:"id",p:[26,57,603]},'"}'],state:[{t:2,x:{r:["can_fast_travel"],s:'_0?null:"disabled"'},p:[26,74,620]}]},f:["Fast Travel"]}],n:50,r:"timer",p:[24,7,508]}]}]}],n:52,r:"data.shuttles",p:[2,1,22]}]}]},e.exports=a.extend(r.exports)},{341:341}],460:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-tabs",a:{tabs:[{t:2,r:"data.templates_tabs",p:[1,16,15]}]},f:[{t:4,f:[{p:[3,5,74],t:7,e:"tab",a:{name:[{t:2,r:"port_id",p:[3,16,85]}]},f:[{t:4,f:[{p:[5,9,135],t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[5,28,154]}]},f:[{t:4,f:[{p:[7,13,209],t:7,e:"ui-section",a:{label:"Description"},f:[{t:2,r:"description",p:[7,45,241]}]}],n:50,r:"description",p:[6,11,176]}," ",{t:4,f:[{p:[10,13,333],t:7,e:"ui-section",a:{label:"Admin Notes"},f:[{t:2,r:"admin_notes",p:[10,45,365]}]}],n:50,r:"admin_notes",p:[9,11,300]}," ",{p:[13,11,426],t:7,e:"ui-button",a:{action:"select_template",params:['{"shuttle_id": "',{t:2,r:"shuttle_id",p:[14,37,499]},'"}'],state:[{t:2,x:{r:["data.selected.shuttle_id","shuttle_id"],s:'_0==_1?"selected":null'},p:[15,20,537]}]},f:[{t:2,x:{r:["data.selected.shuttle_id","shuttle_id"],s:'_0==_1?"Selected":"Select"'},p:[17,13,630]}]}]}],n:52,r:"templates",p:[4,7,106]}]}],n:52,r:"data.templates",p:[2,3,44]}]}]},e.exports=a.extend(r.exports)},{341:341}],461:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Occupant"},f:[{p:[2,3,33],t:7,e:"ui-section",a:{label:"Occupant"},f:[{p:[3,3,66],t:7,e:"span",f:[{t:2,x:{r:["data.occupant.name"],s:'_0?_0:"No Occupant"'},p:[3,9,72]}]}]}," ",{t:4,f:[{p:[6,5,186],t:7,e:"ui-section",a:{label:"State"},f:[{p:[7,7,220],t:7,e:"span",a:{"class":[{t:2,r:"data.occupant.statstate",p:[7,20,233]}]},f:[{t:2,r:"data.occupant.stat",p:[7,49,262]}]}]}," ",{p:[9,5,315],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[10,7,350],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.occupant.minHealth",p:[10,20,363]}],max:[{t:2,r:"data.occupant.maxHealth",p:[10,54,397]}],value:[{t:2,r:"data.occupant.health",p:[10,90,433]}],state:[{t:2,x:{r:["data.occupant.health"],s:'_0>=0?"good":"average"'},p:[11,16,475]}]},f:[{t:2,x:{r:["adata.occupant.health"],s:"Math.round(_0)"},p:[11,68,527]}]}]}," ",{t:4,f:[{p:[14,7,764],t:7,e:"ui-section",a:{label:[{t:2,r:"label",p:[14,26,783]}]},f:[{p:[15,9,804],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.maxHealth",p:[15,30,825]}],value:[{t:2,rx:{r:"data.occupant",m:[{t:30,n:"type"}]},p:[15,66,861]}],state:"bad"},f:[{t:2,x:{r:["type","adata.occupant"],s:"Math.round(_1[_0])"},p:[15,103,898]}]}]}],n:52,x:{r:[],s:'[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}]'},p:[13,5,598]}," ",{t:4,f:[{p:[19,7,1020],t:7,e:"ui-section",a:{label:"Blood"},f:[{p:[20,9,1056],t:7,e:"ui-section",a:{label:"Volume"},f:[{p:[21,11,1095],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.occupant.blood.maxBloodVolume",p:[21,32,1116]}],value:[{t:2,r:"data.occupant.blood.currentBloodVolume",p:[21,79,1163]}],state:[{t:2,x:{r:["data.occupant.blood.currentBloodVolume","data.occupant.blood.dangerBloodVolume"],s:'_0<=_1?"bad":"good"'},p:[21,130,1214]}]},f:[{t:3,x:{r:["data.occupant.blood.currentBloodVolume","data.occupant.blood.dangerBloodVolume"], +s:'_0<=_1?"LOW":"OK"'},p:[21,232,1316]}," - ",{t:2,x:{r:["data.occupant.blood.currentBloodVolume"],s:"Math.round(_0)"},p:[21,342,1426]}," cl"]}]}," ",{p:[23,9,1525],t:7,e:"ui-section",a:{label:"Type"},f:[{p:[24,11,1562],t:7,e:"span",a:{"class":"highlight"},f:[{t:2,r:"data.occupant.blood.bloodType",p:[24,35,1586]}]}]}]}],n:50,r:"data.occupant.blood",p:[18,5,985]}," ",{p:[28,5,1689],t:7,e:"ui-section",a:{label:"Cells"},f:[{p:[29,9,1725],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"bad":"good"'},p:[29,22,1738]}]},f:[{t:2,x:{r:["data.occupant.cloneLoss"],s:'_0?"Damaged":"Healthy"'},p:[29,68,1784]}]}]}," ",{p:[31,5,1867],t:7,e:"ui-section",a:{label:"Brain"},f:[{p:[32,9,1903],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"bad":"good"'},p:[32,22,1916]}]},f:[{t:2,x:{r:["data.occupant.brainLoss"],s:'_0?"Abnormal":"Healthy"'},p:[32,68,1962]}]}]}," ",{t:4,f:[{p:[35,3,2083],t:7,e:"ui-section",a:{label:"Failing Organs"},f:[{t:4,f:[{p:[37,5,2167],t:7,e:"span",a:{"class":"bad"},f:[{t:2,r:"name",p:[37,24,2186]}]}],n:52,r:"data.occupant.failing_organs",p:[36,4,2123]}]}],n:50,r:"data.occupant.failing_organs",p:[34,2,2043]}," ",{p:[41,5,2249],t:7,e:"ui-section",a:{label:"Bloodstream"},f:[{t:4,f:[{p:[43,11,2336],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,1)"},p:[43,54,2379]}," units of ",{t:2,r:"name",p:[43,89,2414]}]},{p:[43,104,2429],t:7,e:"br"}],n:52,r:"adata.occupant.reagents",p:[42,9,2291]},{t:4,n:51,f:[{p:[45,11,2464],t:7,e:"span",a:{"class":"good"},f:["Pure"]}],r:"adata.occupant.reagents"}]}],n:50,r:"data.occupied",p:[5,3,159]}]}," ",{p:[50,1,2560],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[51,2,2592],t:7,e:"ui-section",a:{label:"Door"},f:[{p:[52,5,2623],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"unlock":"lock"'},p:[52,22,2640]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Open":"Closed"'},p:[52,71,2689]}]}]}," ",{p:[55,3,2756],t:7,e:"ui-section",a:{label:"Synthesize"},f:[{t:4,f:[{p:[57,7,2826],t:7,e:"ui-button",a:{grid:0,state:[{t:2,x:{r:["synth_allowed"],s:'_0?null:"disabled"'},p:[57,30,2849]}],action:"synth",params:['{"chem": "',{t:2,r:"id",p:[57,102,2921]},'"}']},f:[{t:2,r:"name",p:[57,112,2931]}]}],n:52,r:"data.synthchems",p:[56,5,2793]}]}," ",{p:[61,3,2989],t:7,e:"ui-section",a:{label:"Inject"},f:[{p:[62,2,3019],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[63,3,3052],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[64,4,3086],t:7,e:"section",a:{"class":"compressedcell"},f:["Name"]}," ",{p:[68,4,3150],t:7,e:"section",a:{"class":"compressedcell"},f:["Volume"]}," ",{t:4,f:[{p:[73,5,3250],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[74,6,3289],t:7,e:"span",f:["Purity"]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=4"},p:[72,4,3216]}," ",{t:4,f:[{p:[79,5,3377],t:7,e:"section",a:{"class":"compressedcell"},f:[]}],n:50,x:{r:["data.efficiency"],s:"_0>=3"},p:[78,4,3343]}," ",{t:4,f:[{p:[84,5,3478],t:7,e:"section",a:{"class":"compressedcell"},f:[]}],n:50,x:{r:["data.efficiency"],s:"_0>=2"},p:[83,4,3444]}," ",{p:[88,4,3545],t:7,e:"section",a:{"class":"compressedcell"},f:[]}," ",{p:[91,4,3599],t:7,e:"section",a:{"class":"compressedcell"},f:[]}]}," ",{t:4,f:[{p:[96,4,3691],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[97,5,3726],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[98,6,3765],t:7,e:"span",f:[{p:[98,12,3771],t:7,e:"b",f:[{t:2,r:"name",p:[98,15,3774]}]}]}]}," ",{p:[101,5,3817],t:7,e:"section",a:{"class":"compressedcell",align:"center"},f:[{p:[102,6,3871],t:7,e:"span",f:[{t:2,r:"vol",p:[102,12,3877]},"u"]}]}," ",{t:4,f:[{p:[106,6,3953],t:7,e:"section",a:{"class":"compressedcell",align:"center"},f:[{p:[107,7,4008],t:7,e:"span",f:[{t:2,r:"purity",p:[107,13,4014]}]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=4"},p:[105,7,3918]}," ",{t:4,f:[{p:[112,6,4106],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[113,7,4146],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[113,25,4164]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[113,109,4248]},'", "volume": 1}']},f:["1"]}]}],n:50,x:{r:["data.efficiency"],s:"_0>=3"},p:[111,5,4071]}," ",{t:4,f:[{p:[118,6,4358],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[119,7,4398],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[119,25,4416]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[119,109,4500]},'", "volume": 5}']},f:["5"]}]}],n:50,x:{r:["adata.efficiency"],s:"_0>=2"},p:[117,5,4322]}," ",{p:[123,5,4574],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[124,6,4613],t:7,e:"ui-button",a:{state:[{t:2,x:{r:["data.occupied","allowed"],s:'_0&&_1?null:"disabled"'},p:[124,24,4631]}],action:"inject",params:['{"chem": "',{t:2,r:"id",p:[124,108,4715]},'", "volume": 10}']},f:["10"]}]}," ",{p:[127,5,4777],t:7,e:"section",a:{"class":"compressedcell"},f:[{p:[128,6,4816],t:7,e:"ui-button",a:{action:"purge",params:['{"chem": "',{t:2,r:"id",p:[128,50,4860]},'"}']},f:["Purge"]},{p:[128,77,4887],t:7,e:"br"}]}]}],n:52,r:"data.chems",p:[95,3,3666]}]}]}," ",{p:[135,3,4968],t:7,e:"ui-section",a:{label:"Capacity"},f:[{p:[136,5,5003],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.tot_capacity",p:[136,24,5022]}],value:[{t:2,r:"data.current_vol",p:[136,54,5052]}],state:[{t:2,r:"data.current_vol",p:[137,12,5086]}]},f:[{t:2,r:"data.current_vol",p:[137,34,5108]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],462:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,25],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[2,22,44]}],labelcolor:[{t:2,r:"htmlcolor",p:[2,44,66]}],candystripe:0,right:0},f:[{p:[3,5,105],t:7,e:"ui-section",a:{label:"Status"},f:[{p:[3,32,132],t:7,e:"span",a:{"class":[{t:2,x:{r:["status"],s:'_0=="Dead"?"bad bold":_0=="Unconscious"?"average bold":"good"'},p:[3,45,145]}]},f:[{t:2,r:"status",p:[3,132,232]}]}]}," ",{p:[4,5,268],t:7,e:"ui-section",a:{label:"Jelly"},f:[{t:2,r:"exoticblood",p:[4,31,294]}]}," ",{p:[5,5,328],t:7,e:"ui-section",a:{label:"Location"},f:[{t:2,r:"area",p:[5,34,357]}]}," ",{p:[7,5,386],t:7,e:"ui-button",a:{state:[{t:2,r:"swap_button_state",p:[8,14,411]}],action:"swap",params:['{"ref": "',{t:2,r:"ref",p:[9,38,472]},'"}']},f:[{t:4,f:["You Are Here"],n:50,x:{r:["occupied"],s:'_0=="owner"'},p:[10,7,491]},{t:4,n:51,f:[{t:4,f:["Occupied"],n:50,x:{r:["occupied"],s:'_0=="stranger"'},p:[13,9,566]},{t:4,n:51,f:["Swap"],x:{r:["occupied"],s:'_0=="stranger"'}}],x:{r:["occupied"],s:'_0=="owner"'}}]}]}],n:52,r:"data.bodies",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],463:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{t:4,f:[{p:[4,23,82],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.drying"],s:'_0?"stop":"tint"'},p:[4,40,99]}],action:"Dry"},f:[{t:2,x:{r:["data.drying"],s:'_0?"Stop drying":"Dry"'},p:[4,88,147]}]}],n:50,r:"data.isdryer",p:[4,3,62]}]},t:7,e:"ui-display",a:{title:"Storage",button:0},f:[" ",{t:4,f:[{p:[7,3,258],t:7,e:"ui-notice",f:[{p:[8,5,275],t:7,e:"span",f:["Unfortunately, this ",{t:2,r:"data.name",p:[8,31,301]}," is empty."]}]}],n:50,x:{r:["data.contents.length"],s:"_0==0"},p:[6,1,221]},{t:4,n:51,f:[{p:[11,1,359],t:7,e:"div",a:{"class":"display tabular"},f:[{p:[12,2,391],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[13,4,425],t:7,e:"section",a:{"class":"cell bold"},f:["Item"]}," ",{p:[16,4,482],t:7,e:"section",a:{"class":"cell bold"},f:["Quantity"]}," ",{p:[19,4,543],t:7,e:"section",a:{"class":"cell bold",align:"center"},f:[{t:4,f:[{t:2,r:"data.verb",p:[20,22,608]}],n:50,r:"data.verb",p:[20,5,591]},{t:4,n:51,f:["Dispense"],r:"data.verb"}]}]}," ",{t:4,f:[{p:[24,3,703],t:7,e:"section",a:{"class":"candystripe"},f:[{p:[25,4,737],t:7,e:"section",a:{"class":"cell"},f:[{t:2,r:"name",p:[26,5,765]}]}," ",{p:[28,4,793],t:7,e:"section",a:{"class":"cell",align:"right"},f:[{t:2,r:"amount",p:[29,5,835]}]}," ",{p:[31,4,865],t:7,e:"section",a:{"class":"table",alight:"right"},f:[{p:[32,5,909],t:7,e:"section",a:{"class":"cell"}}," ",{p:[33,5,947],t:7,e:"section",a:{"class":"cell"},f:[{p:[34,6,976],t:7,e:"ui-button",a:{grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>=1)?null:"disabled"'},p:[34,45,1015]}],params:['{ "name" : ',{t:2,r:"name",p:[34,102,1072]},', "amount" : 1 }']},f:["One"]}]}," ",{p:[38,5,1151],t:7,e:"section",a:{"class":"cell"},f:[{p:[39,6,1180],t:7,e:"ui-button",a:{grid:0,action:"Release",state:[{t:2,x:{r:["amount"],s:'(_0>1)?null:"disabled"'},p:[39,45,1219]}],params:['{ "name" : ',{t:2,r:"name",p:[39,101,1275]}," }"]},f:["Many"]}]}]}]}],n:52,r:"data.contents",p:[23,2,676]}]}],x:{r:["data.contents.length"],s:"_0==0"}}]}]},e.exports=a.extend(r.exports)},{341:341}],464:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{capacityPercentState:function(){var t=this.get("data.capacityPercent");return t>50?"good":t>15?"average":"bad"},inputState:function(){return this.get("data.capacityPercent")>=100?"good":this.get("data.inputting")?"average":"bad"},outputState:function(){return this.get("data.outputting")?"good":this.get("data.charge")>0?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[24,1,663],t:7,e:"ui-display",a:{title:"Storage"},f:[{p:[25,3,695],t:7,e:"ui-section",a:{label:"Stored Energy"},f:[{p:[26,5,735],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.capacityPercent",p:[26,38,768]}],state:[{t:2,r:"capacityPercentState",p:[26,71,801]}]},f:[{t:2,x:{r:["adata.capacityPercent"],s:"Math.fixed(_0)"},p:[26,97,827]},"%"]}]}]}," ",{p:[29,1,908],t:7,e:"ui-display",a:{title:"Input"},f:[{p:[30,3,938],t:7,e:"ui-section",a:{label:"Charge Mode"},f:[{p:[31,5,976],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"refresh":"close"'},p:[31,22,993]}],style:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"selected":null'},p:[31,74,1045]}],action:"tryinput"},f:[{t:2,x:{r:["data.inputAttempt"],s:'_0?"Auto":"Off"'},p:[32,25,1113]}]},"   [",{p:[34,6,1182],t:7,e:"span",a:{"class":[{t:2,r:"inputState",p:[34,19,1195]}]},f:[{t:2,x:{r:["data.capacityPercent","data.inputting"],s:'_0>=100?"Fully Charged":_1?"Charging":"Not Charging"'},p:[34,35,1211]}]},"]"]}," ",{p:[36,3,1335],t:7,e:"ui-section",a:{label:"Target Input"},f:[{p:[37,5,1374],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.inputLevelMax",p:[37,26,1395]}],value:[{t:2,r:"data.inputLevel",p:[37,57,1426]}]},f:[{t:2,r:"adata.inputLevel_text",p:[37,78,1447]}]}]}," ",{p:[39,3,1501],t:7,e:"ui-section",a:{label:"Adjust Input"},f:[{p:[40,5,1540],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.inputLevel"],s:'_0==0?"disabled":null'},p:[40,44,1579]}],action:"input",params:'{"target": "min"}'}}," ",{p:[41,5,1674],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.inputLevel"],s:'_0==0?"disabled":null'},p:[41,39,1708]}],action:"input",params:'{"adjust": -10000}'}}," ",{p:[42,5,1804],t:7,e:"ui-button",a:{icon:"pencil",action:"input",params:'{"target": "input"}'},f:["Set"]}," ",{p:[43,5,1894],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.inputLevel","data.inputLevelMax"],s:'_0==_1?"disabled":null'},p:[43,38,1927]}],action:"input",params:'{"adjust": 10000}'}}," ",{p:[44,5,2039],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.inputLevel","data.inputLevelMax"],s:'_0==_1?"disabled":null'},p:[44,43,2077]}],action:"input",params:'{"target": "max"}'}}]}," ",{p:[46,3,2204],t:7,e:"ui-section",a:{label:"Available"},f:[{p:[47,3,2238],t:7,e:"span",f:[{t:2,r:"adata.inputAvailable",p:[47,9,2244]}]}]}]}," ",{p:[50,1,2308],t:7,e:"ui-display",a:{title:"Output"},f:[{p:[51,3,2339],t:7,e:"ui-section",a:{label:"Output Mode"},f:[{p:[52,5,2377],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"power-off":"close"'},p:[52,22,2394]}],style:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"selected":null'},p:[52,77,2449]}],action:"tryoutput"},f:[{t:2,x:{r:["data.outputAttempt"],s:'_0?"On":"Off"'},p:[53,26,2519]}]},"   [",{p:[55,6,2587],t:7,e:"span",a:{"class":[{t:2,r:"outputState",p:[55,19,2600]}]},f:[{t:2,x:{r:["data.outputting","data.charge"],s:'_0?"Sending":_1>0?"Not Sending":"No Charge"'},p:[55,36,2617]}]},"]"]}," ",{p:[57,3,2724],t:7,e:"ui-section",a:{label:"Target Output"},f:[{p:[58,5,2764],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"data.outputLevelMax",p:[58,26,2785]}],value:[{t:2,r:"data.outputLevel",p:[58,58,2817]}]},f:[{t:2,r:"adata.outputLevel_text",p:[58,80,2839]}]}]}," ",{p:[60,3,2894],t:7,e:"ui-section",a:{label:"Adjust Output"},f:[{p:[61,5,2934],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.outputLevel"],s:'_0==0?"disabled":null'},p:[61,44,2973]}],action:"output",params:'{"target": "min"}'}}," ",{p:[62,5,3070],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.outputLevel"],s:'_0==0?"disabled":null'},p:[62,39,3104]}],action:"output",params:'{"adjust": -10000}'}}," ",{p:[63,5,3202],t:7,e:"ui-button",a:{icon:"pencil",action:"output",params:'{"target": "input"}'},f:["Set"]}," ",{p:[64,5,3293],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.outputLevel","data.outputLevelMax"],s:'_0==_1?"disabled":null'},p:[64,38,3326]}],action:"output",params:'{"adjust": 10000}'}}," ",{p:[65,5,3441],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.outputLevel","data.outputLevelMax"],s:'_0==_1?"disabled":null'},p:[65,43,3479]}],action:"output",params:'{"target": "max"}'}}]}," ",{p:[67,3,3609],t:7,e:"ui-section",a:{label:"Outputting"},f:[{p:[68,3,3644],t:7,e:"span",f:[{t:2,r:"adata.outputUsed",p:[68,9,3650]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],465:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:["\ufeff",{t:4,f:[" ",{p:[2,2,33],t:7,e:"ui-display",a:{title:"Dispersal Tank"},f:[{p:[3,3,73],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[4,4,104],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.active"],s:'_0?"power-off":"close"'},p:[4,21,121]}],style:[{t:2,x:{r:["data.active"],s:'_0?"selected":null'},p:[5,12,174]}],state:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?null:"disabled"'},p:[6,12,223]}],action:"power"},f:[{t:2,x:{r:["data.active"],s:'_0?"On":"Off"'},p:[7,20,286]}]}]}," ",{p:[10,3,354],t:7,e:"ui-section",a:{label:"Smoke Radius Setting"},f:[{p:[11,5,401],t:7,e:"div",a:{"class":"content",style:"float:left"},f:[{p:[12,6,448],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=1?null:"disabled"'},p:[12,36,478]}],style:[{t:2,x:{r:["data.setting"],s:'_0==1?"selected":null'},p:[12,89,531]}],action:"setting",params:'{"amount": 1}'},f:["3"]}," ",{p:[13,6,634],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=2?null:"disabled"'},p:[13,36,664]}],style:[{t:2,x:{r:["data.setting"],s:'_0==2?"selected":null'},p:[13,89,717]}],action:"setting",params:'{"amount": 2}'},f:["6"]}," ",{p:[14,6,820],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=3?null:"disabled"'},p:[14,36,850]}],style:[{t:2,x:{r:["data.setting"],s:'_0==3?"selected":null'},p:[14,89,903]}],action:"setting",params:'{"amount": 3}'},f:["9"]}," ",{p:[15,6,1006],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=4?null:"disabled"'},p:[15,36,1036]}],style:[{t:2,x:{r:["data.setting"],s:'_0==4?"selected":null'},p:[15,89,1089]}],action:"setting",params:'{"amount": 4}'},f:["12"]}," ",{p:[16,6,1193],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.maxSetting"],s:'_0>=5?null:"disabled"'},p:[16,36,1223]}],style:[{t:2,x:{r:["data.setting"],s:'_0==5?"selected":null'},p:[16,89,1276]}],action:"setting",params:'{"amount": 5}'},f:["15"]}]}]}," ",{p:[19,3,1410],t:7,e:"ui-section",a:{label:"Contents"},f:[{t:4,f:[{p:[21,6,1476],t:7,e:"span",f:[{t:2,x:{r:["adata.TankCurrentVolume"],s:"Math.round(_0)"},p:[21,12,1482]},"/",{t:2,r:"data.TankMaxVolume",p:[21,52,1522]}," Units"]}," ",{p:[22,6,1564],t:7,e:"br"}," ",{p:[23,5,1575],t:7,e:"br"}," ",{t:4,f:[{p:[25,7,1623],t:7,e:"span",a:{"class":"highlight"},t0:"fade",f:[{t:2,x:{r:["volume"],s:"Math.fixed(_0,2)"},p:[25,50,1666]}," units of ",{t:2,r:"name",p:[25,85,1701]}]},{p:[25,100,1716],t:7,e:"br"}],n:52,r:"adata.TankContents",p:[24,6,1587]}],n:50,r:"data.isTankLoaded",p:[20,4,1444]},{t:4,n:51,f:[{p:[28,6,1757],t:7,e:"span",a:{"class":"bad"},f:["Tank Empty"]}],r:"data.isTankLoaded"}," ",{p:[30,4,1809],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"Eject":"Close"'},p:[30,21,1826]}],style:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"selected":null'},p:[31,12,1881]}],state:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?null:"disabled"'},p:[32,12,1936]}],action:"purge"},f:[{t:2,x:{r:["data.isTankLoaded"],s:'_0?"Purge Contents":"No chemicals detected"'},p:[33,20,1999]}]}]}]}],n:50,x:{r:["data.screen"],s:'_0=="home"'},p:[1,2,1]}]},e.exports=a.extend(r.exports)},{341:341}],466:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,3,31],t:7,e:"ui-section",a:{label:"Generated Power"},f:[{t:2,x:{r:["adata.generated"],s:"Math.round(_0)"},p:[3,5,73]},"W"]}," ",{p:[5,3,126],t:7,e:"ui-section",a:{label:"Orientation"},f:[{p:[6,5,164],t:7,e:"span",f:[{t:2,x:{r:["adata.angle"],s:"Math.round(_0)"},p:[6,11,170]},"° (",{t:2,r:"data.direction",p:[6,45,204]},")"]}]}," ",{p:[8,3,251],t:7,e:"ui-section",a:{label:"Adjust Angle"},f:[{p:[9,5,290],t:7,e:"ui-button",a:{icon:"step-backward",action:"angle",params:'{"adjust": -15}'},f:["15°"]}," ",{p:[10,5,387],t:7,e:"ui-button",a:{icon:"backward",action:"angle",params:'{"adjust": -5}'},f:["5°"]}," ",{p:[11,5,477],t:7,e:"ui-button",a:{icon:"forward",action:"angle",params:'{"adjust": 5}'},f:["5°"]}," ",{p:[12,5,565],t:7,e:"ui-button",a:{icon:"step-forward",action:"angle",params:'{"adjust": 15}'},f:["15°"]}]}]}," ",{p:[15,1,687],t:7,e:"ui-display",a:{title:"Tracking"},f:[{p:[16,3,720],t:7,e:"ui-section",a:{label:"Tracker Mode"},f:[{p:[17,5,759],t:7,e:"ui-button",a:{icon:"close",state:[{t:2,x:{r:["data.tracking_state"],s:'_0==0?"selected":null'},p:[17,36,790]}],action:"tracking",params:'{"mode": 0}'},f:["Off"]}," ",{p:[19,5,907],t:7,e:"ui-button",a:{icon:"clock-o",state:[{t:2,x:{r:["data.tracking_state"],s:'_0==1?"selected":null'},p:[19,38,940]}],action:"tracking",params:'{"mode": 1}'},f:["Timed"]}," ",{p:[21,5,1059],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.connected_tracker","data.tracking_state"],s:'_0?_1==2?"selected":null:"disabled"'},p:[21,38,1092]}],action:"tracking",params:'{"mode": 2}'},f:["Auto"]}]}," ",{p:[24,3,1262],t:7,e:"ui-section",a:{label:"Tracking Rate"},f:[{p:[25,3,1300],t:7,e:"span",f:[{t:2,x:{r:["adata.tracking_rate"],s:"Math.round(_0)"},p:[25,9,1306]},"°/h (",{t:2,r:"data.rotating_way",p:[25,53,1350]},")"]}]}," ",{p:[27,3,1399],t:7,e:"ui-section",a:{label:"Adjust Rate"},f:[{p:[28,5,1437],t:7,e:"ui-button",a:{icon:"fast-backward",action:"rate",params:'{"adjust": -180}'},f:["180°"]}," ",{p:[29,5,1535],t:7,e:"ui-button",a:{icon:"step-backward",action:"rate",params:'{"adjust": -30}'},f:["30°"]}," ",{p:[30,5,1631],t:7,e:"ui-button",a:{icon:"backward",action:"rate",params:'{"adjust": -5}'},f:["5°"]}," ",{p:[31,5,1720],t:7,e:"ui-button",a:{icon:"forward",action:"rate",params:'{"adjust": 5}'},f:["5°"]}," ",{p:[32,5,1807],t:7,e:"ui-button",a:{icon:"step-forward",action:"rate",params:'{"adjust": 30}'},f:["30°"]}," ",{p:[33,5,1901],t:7,e:"ui-button",a:{icon:"fast-forward",action:"rate",params:'{"adjust": 180}'},f:["180°"]}]}]}," ",{p:{button:[{p:[38,5,2088],t:7,e:"ui-button",a:{icon:"refresh",action:"refresh"},f:["Refresh"]}]},t:7,e:"ui-display",a:{title:"Devices",button:0},f:[" ",{p:[40,2,2169],t:7,e:"ui-section",a:{label:"Solar Tracker"},f:[{p:[41,5,2209],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected_tracker"],s:'_0?"good":"bad"'},p:[41,18,2222]}]},f:[{t:2,x:{r:["data.connected_tracker"],s:'_0?"":"Not "'},p:[41,63,2267]},"Found"]}]}," ",{p:[43,2,2338],t:7,e:"ui-section",a:{label:"Solar Panels"},f:[{p:[44,3,2375],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.connected_panels"],s:'_0?"good":"bad"'},p:[44,16,2388]}]},f:[{t:2,x:{r:["adata.connected_panels"],s:"Math.round(_0)"},p:[44,60,2432]}," Panels Connected"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],467:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:{button:[{t:4,f:[{p:[4,7,87],t:7,e:"ui-button",a:{icon:"eject",state:[{t:2,x:{r:["data.hasPowercell"],s:'_0?null:"disabled"'},p:[4,38,118]}],action:"eject"},f:["Eject"]}],n:50,r:"data.open",p:[3,5,62]}]},t:7,e:"ui-display",a:{title:"Power",button:0},f:[" ",{p:[7,3,226],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[8,5,258],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[8,22,275]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[9,14,326]}],state:[{t:2,x:{r:["data.hasPowercell"],s:'_0?null:"disabled"'},p:[9,54,366]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[10,22,431]}]}]}," ",{p:[12,3,490],t:7,e:"ui-section",a:{label:"Cell"},f:[{t:4,f:[{p:[14,7,554],t:7,e:"ui-bar",a:{min:"0",max:"100",value:[{t:2,r:"data.powerLevel",p:[14,40,587]}]},f:[{t:2,x:{r:["adata.powerLevel"],s:"Math.fixed(_0)"},p:[14,61,608]},"%"]}],n:50,r:"data.hasPowercell",p:[13,5,521]},{t:4,n:51,f:[{p:[16,4,667],t:7,e:"span",a:{"class":"bad"},f:["No Cell"]}],r:"data.hasPowercell"}]}]}," ",{p:[20,1,744],t:7,e:"ui-display",a:{title:"Thermostat"},f:[{p:[21,3,779],t:7,e:"ui-section",a:{label:"Current Temperature"},f:[{p:[22,3,823],t:7,e:"span",f:[{t:2,x:{r:["adata.currentTemp"],s:"Math.round(_0)"},p:[22,9,829]},"°C"]}]}," ",{p:[24,2,894],t:7,e:"ui-section",a:{label:"Target Temperature"},f:[{p:[25,3,937],t:7,e:"span",f:[{t:2,x:{r:["adata.targetTemp"],s:"Math.round(_0)"},p:[25,9,943]},"°C"]}]}," ",{t:4,f:[{p:[28,5,1031],t:7,e:"ui-section",a:{label:"Adjust Target"},f:[{p:[29,7,1073],t:7,e:"ui-button",a:{icon:"fast-backward",state:[{t:2,x:{r:["data.targetTemp","data.minTemp"],s:'_0>_1?null:"disabled"'},p:[29,46,1112]}],action:"target",params:'{"adjust": -20}'}}," ",{p:[30,7,1218],t:7,e:"ui-button",a:{icon:"backward",state:[{t:2,x:{r:["data.targetTemp","data.minTemp"],s:'_0>_1?null:"disabled"'},p:[30,41,1252]}],action:"target",params:'{"adjust": -5}'}}," ",{p:[31,7,1357],t:7,e:"ui-button",a:{icon:"pencil",action:"target",params:'{"target": "input"}'},f:["Set"]}," ",{p:[32,7,1450],t:7,e:"ui-button",a:{icon:"forward",state:[{t:2,x:{r:["data.targetTemp","data.maxTemp"],s:'_0<_1?null:"disabled"'},p:[32,40,1483]}],action:"target",params:'{"adjust": 5}'}}," ",{p:[33,7,1587],t:7,e:"ui-button",a:{icon:"fast-forward",state:[{t:2,x:{r:["data.targetTemp","data.maxTemp"],s:'_0<_1?null:"disabled"'},p:[33,45,1625]}],action:"target",params:'{"adjust": 20}'}}]}],n:50,r:"data.open",p:[27,3,1008]}," ",{p:[36,3,1754],t:7,e:"ui-section",a:{label:"Mode"},f:[{t:4,f:[{p:[38,7,1808],t:7,e:"ui-button",a:{icon:"long-arrow-up",state:[{t:2,x:{r:["data.mode"],s:'_0=="heat"?"selected":null'},p:[38,46,1847]}],action:"mode",params:'{"mode": "heat"}'},f:["Heat"]}," ",{p:[39,7,1956],t:7,e:"ui-button",a:{icon:"long-arrow-down",state:[{t:2,x:{r:["data.mode"],s:'_0=="cool"?"selected":null'},p:[39,48,1997]}],action:"mode",params:'{"mode": "cool"}'},f:["Cool"]}," ",{p:[40,7,2106],t:7,e:"ui-button",a:{icon:"arrows-v",state:[{t:2,x:{r:["data.mode"],s:'_0=="auto"?"selected":null'},p:[40,41,2140]}],action:"mode",params:'{"mode": "auto"}'},f:["Auto"]}],n:50,r:"data.open",p:[37,3,1783]},{t:4,n:51,f:[{p:[42,4,2258],t:7,e:"span",f:[{t:2,x:{r:["text","data.mode"],s:"_0.titleCase(_1)"},p:[42,10,2264]}]}],r:"data.open"}]}]}]},e.exports=a.extend(r.exports)},{341:341}],468:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:{button:[{p:[4,8,97],t:7,e:"ui-button",a:{action:"jump",params:['{"name" : ',{t:2,r:"name",p:[4,51,140]},"}"]},f:["Jump"]}," ",{p:[7,9,195],t:7,e:"ui-button",a:{action:"spawn",params:['{"name" : ',{t:2,r:"name",p:[7,53,239]},"}"]},f:["Spawn"]}]},t:7,e:"ui-display",a:{title:[{t:2,r:"name",p:[2,22,46]}],button:0},f:[" ",{p:[11,3,308],t:7,e:"ui-section",a:{label:"Description"},f:[{p:[12,5,346],t:7,e:"span",f:[{t:3,r:"desc",p:[12,11,352]}]}]}," ",{p:[14,3,390],t:7,e:"ui-section",a:{label:"Spawners left"},f:[{p:[15,5,430],t:7,e:"span",f:[{t:2,r:"amount_left",p:[15,11,436]}]}]}]}],n:52,r:"data.spawners",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],469:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,31],t:7,e:"ui-display",a:{title:[{t:2,r:"class",p:[2,22,50]}," Alarms"]},f:[{p:[3,5,74],t:7,e:"ul",f:[{t:4,f:[{p:[5,9,107],t:7,e:"li",f:[{t:2,r:".",p:[5,13,111]}]}],n:52,r:".",p:[4,7,86]},{t:4,n:51,f:[{p:[7,9,147],t:7,e:"li",f:["System Nominal"]}],r:"."}]}]}],n:52,i:"class",r:"data.alarms",p:[1,1,0]}]},e.exports=a.extend(r.exports)},{341:341}],470:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{t:4,f:[{p:[2,3,42],t:7,e:"ui-notice",f:[{p:[3,5,59],t:7,e:"span",f:["Biological entity detected in contents. Please remove."]}]}],n:50,x:{r:["data.occupied","data.safeties"],s:"_0&&_1"},p:[1,1,0]},{t:4,f:[{p:[7,3,179],t:7,e:"ui-notice",f:[{p:[8,5,196],t:7,e:"span",f:["Contents are being disinfected. Please wait."]}]}],n:50,r:"data.uv_active",p:[6,1,153]},{t:4,n:51,f:[{p:{button:[{t:4,f:[{p:[13,25,369],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.locked"],s:'_0?"unlock":"lock"'},p:[13,42,386]}],action:"lock"},f:[{t:2,x:{r:["data.locked"],s:'_0?"Unlock":"Lock"'},p:[13,93,437]}]}],n:50,x:{r:["data.open"],s:"!_0"},p:[13,7,351]}," ",{t:4,f:[{p:[14,27,519],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.open"],s:'_0?"sign-out":"sign-in"'},p:[14,44,536]}],action:"door"},f:[{t:2,x:{r:["data.open"],s:'_0?"Close":"Open"'},p:[14,98,590]}]}],n:50,x:{r:["data.locked"],s:"!_0"},p:[14,7,499]}]},t:7,e:"ui-display",a:{title:"Storage",button:0},f:[" ",{t:4,f:[{p:[17,7,692],t:7,e:"ui-notice",f:[{p:[18,9,713],t:7,e:"span",f:["Unit Locked"]}]}],n:50,r:"data.locked",p:[16,5,665]},{t:4,n:51,f:[{t:4,n:50,x:{r:["data.open"],s:"_0"},f:[{p:[21,9,793],t:7,e:"ui-section",a:{label:"Helmet"},f:[{p:[22,11,832],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.helmet"],s:'_0?"square":"square-o"'},p:[22,28,849]}],state:[{t:2,x:{r:["data.helmet"],s:'_0?null:"disabled"'},p:[22,75,896]}],action:"dispense",params:'{"item": "helmet"}'},f:[{t:2,x:{r:["data.helmet"],s:'_0||"Empty"'},p:[23,59,992]}]}]}," ",{p:[25,9,1063],t:7,e:"ui-section",a:{label:"Suit"},f:[{p:[26,11,1100],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.suit"],s:'_0?"square":"square-o"'},p:[26,28,1117]}],state:[{t:2,x:{r:["data.suit"],s:'_0?null:"disabled"'},p:[26,74,1163]}],action:"dispense",params:'{"item": "suit"}'},f:[{t:2,x:{r:["data.suit"],s:'_0||"Empty"'},p:[27,57,1255]}]}]}," ",{p:[29,9,1324],t:7,e:"ui-section",a:{label:"Mask"},f:[{p:[30,11,1361],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.mask"],s:'_0?"square":"square-o"'},p:[30,28,1378]}],state:[{t:2,x:{r:["data.mask"],s:'_0?null:"disabled"'},p:[30,74,1424]}],action:"dispense",params:'{"item": "mask"}'},f:[{t:2,x:{r:["data.mask"],s:'_0||"Empty"'},p:[31,57,1516]}]}]}," ",{p:[33,9,1585],t:7,e:"ui-section",a:{label:"Storage"},f:[{p:[34,11,1625],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.storage"],s:'_0?"square":"square-o"'},p:[34,28,1642]}],state:[{t:2,x:{r:["data.storage"],s:'_0?null:"disabled"'},p:[34,77,1691]}],action:"dispense",params:'{"item": "storage"}'},f:[{t:2,x:{r:["data.storage"],s:'_0||"Empty"'},p:[35,60,1789]}]}]}]},{t:4,n:50,x:{r:["data.open"],s:"!(_0)"},f:[" ",{p:[38,7,1873],t:7,e:"ui-button",a:{icon:"recycle",state:[{t:2,x:{r:["data.occupied","data.safeties"],s:'_0&&_1?"disabled":null'},p:[38,40,1906]}],action:"uv"},f:["Disinfect"]}]}],r:"data.locked"}]}],r:"data.uv_active"}]},e.exports=a.extend(r.exports)},{341:341}],471:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{p:[2,5,18],t:7,e:"ui-section",a:{label:"Dispense"},f:[{p:[3,9,57],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.plasma"],s:'_0?"square":"square-o"'},p:[3,26,74]}],state:[{t:2,x:{r:["data.plasma"],s:'_0?null:"disabled"'},p:[3,74,122]}],action:"plasma"},f:["Plasma (",{t:2,x:{r:["adata.plasma"],s:"Math.round(_0)"},p:[4,37,196]},")"]}," ",{p:[5,9,247],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.oxygen"],s:'_0?"square":"square-o"'},p:[5,26,264]}],state:[{t:2,x:{r:["data.oxygen"],s:'_0?null:"disabled"'},p:[5,74,312]}],action:"oxygen"},f:["Oxygen (",{t:2,x:{r:["adata.oxygen"],s:"Math.round(_0)"},p:[6,37,386]},")"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],472:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={computed:{tankPressureState:function(){var t=this.get("data.tankPressure");return t>=200?"good":t>=100?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[14,1,295],t:7,e:"ui-notice",f:[{p:[15,3,310],t:7,e:"span",f:["The regulator ",{t:2,x:{r:["data.connected"],s:'_0?"is":"is not"'},p:[15,23,330]}," connected to a mask."]}]}," ",{p:[17,1,409],t:7,e:"ui-display",f:[{p:[18,3,425],t:7,e:"ui-section",a:{label:"Tank Pressure"},f:[{p:[19,7,467],t:7,e:"ui-bar",a:{min:"0",max:"1013",value:[{t:2,r:"data.tankPressure",p:[19,41,501]}],state:[{t:2,r:"tankPressureState",p:[20,16,540]}]},f:[{t:2,x:{r:["adata.tankPressure"],s:"Math.round(_0)"},p:[20,39,563]}," kPa"]}]}," ",{p:[22,3,631],t:7,e:"ui-section",a:{label:"Release Pressure"},f:[{p:[23,5,674],t:7,e:"ui-bar",a:{min:[{t:2,r:"data.minReleasePressure",p:[23,18,687]}],max:[{t:2,r:"data.maxReleasePressure",p:[23,52,721]}],value:[{t:2,r:"data.releasePressure",p:[24,14,764]}]},f:[{t:2,x:{r:["adata.releasePressure"],s:"Math.round(_0)"},p:[24,40,790]}," kPa"]}]}," ",{p:[26,3,861],t:7,e:"ui-section",a:{label:"Pressure Regulator"},f:[{p:[27,5,906],t:7,e:"ui-button",a:{icon:"refresh",state:[{t:2,x:{r:["data.releasePressure","data.defaultReleasePressure"],s:'_0!=_1?null:"disabled"'},p:[27,38,939]}],action:"pressure",params:'{"pressure": "reset"}'},f:["Reset"]}," ",{p:[29,5,1095],t:7,e:"ui-button",a:{icon:"minus",state:[{t:2,x:{r:["data.releasePressure","data.minReleasePressure"],s:'_0>_1?null:"disabled"'},p:[29,36,1126]}],action:"pressure",params:'{"pressure": "min"}'},f:["Min"]}," ",{p:[31,5,1273],t:7,e:"ui-button",a:{icon:"pencil",action:"pressure",params:'{"pressure": "input"}'},f:["Set"]}," ",{p:[32,5,1368],t:7,e:"ui-button",a:{icon:"plus",state:[{t:2,x:{r:["data.releasePressure","data.maxReleasePressure"],s:'_0<_1?null:"disabled"'},p:[32,35,1398]}],action:"pressure",params:'{"pressure": "max"}'},f:["Max"]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],473:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[2,5,33],t:7,e:"ui-section",a:{label:"Temperature"},f:[{p:[3,9,75],t:7,e:"span",f:[{t:2,x:{r:["adata.temperature"],s:"Math.fixed(_0,2)"},p:[3,15,81]}," K"]}]}," ",{p:[5,5,151],t:7,e:"ui-section",a:{label:"Pressure"},f:[{p:[6,9,190],t:7,e:"span",f:[{t:2,x:{r:["adata.pressure"],s:"Math.fixed(_0,2)"},p:[6,15,196]}," kPa"]}]}]}," ",{p:[9,1,276],t:7,e:"ui-display",a:{title:"Controls"},f:[{p:[10,5,311],t:7,e:"ui-section",a:{label:"Power"},f:[{p:[11,9,347],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.on"],s:'_0?"power-off":"close"'},p:[11,26,364]}],style:[{t:2,x:{r:["data.on"],s:'_0?"selected":null'},p:[11,70,408]}],action:"power"},f:[{t:2,x:{r:["data.on"],s:'_0?"On":"Off"'},p:[12,28,469]}]}]}," ",{p:[14,5,531],t:7,e:"ui-section",a:{label:"Target Temperature"},f:[{p:[15,9,580],t:7,e:"ui-button",a:{icon:"fast-backward",style:[{t:2,x:{r:["data.target","data.min"],s:'_0==_1?"disabled":null'},p:[15,48,619]}],action:"target",params:'{"adjust": -20}'}}," ",{p:[17,9,733],t:7,e:"ui-button",a:{icon:"backward",style:[{t:2,x:{r:["data.target","data.min"],s:'_0==_1?"disabled":null'},p:[17,43,767]}],action:"target",params:'{"adjust": -5}'}}," ",{p:[19,9,880],t:7,e:"ui-button",a:{icon:"pencil",action:"target",params:'{"target": "input"}'},f:[{t:2,x:{r:["adata.target"],s:"Math.fixed(_0,2)"},p:[19,79,950]}]}," ",{p:[20,9,1003],t:7,e:"ui-button",a:{icon:"forward",style:[{t:2,x:{r:["data.target","data.max"],s:'_0==_1?"disabled":null'},p:[20,42,1036]}],action:"target",params:'{"adjust": 5}'} +}," ",{p:[22,9,1148],t:7,e:"ui-button",a:{icon:"fast-forward",style:[{t:2,x:{r:["data.target","data.max"],s:'_0==_1?"disabled":null'},p:[22,47,1186]}],action:"target",params:'{"adjust": 20}'}}]}]}]},e.exports=a.extend(r.exports)},{341:341}],474:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{powerState:function(t){switch(t){case 1:return"good";default:return"bad"}}}}}(r),r.exports.template={v:3,t:[" ",{p:[13,1,173],t:7,e:"ui-notice",f:[{p:[14,2,187],t:7,e:"ui-section",a:{label:"Reconnect"},f:[{p:[15,3,221],t:7,e:"div",a:{style:"float:right"},f:[{p:[16,4,251],t:7,e:"ui-button",a:{icon:"refresh",action:"reconnect"},f:["Reconnect"]}]}]}]}," ",{p:[20,1,359],t:7,e:"ui-display",a:{title:"Turbine Controller"},f:[{p:[21,2,401],t:7,e:"ui-section",a:{label:"Status"},f:[{t:4,f:[{p:[23,4,456],t:7,e:"span",a:{"class":"bad"},f:["Broken"]}],n:50,r:"data.broken",p:[22,3,432]},{t:4,n:51,f:[{p:[25,4,504],t:7,e:"span",a:{"class":[{t:2,x:{r:["powerState","data.online"],s:"_0(_1)"},p:[25,17,517]}]},f:[{t:2,x:{r:["data.online","data.compressor_broke","data.turbine_broke"],s:'_0&&!(_1||_2)?"Online":"Offline"'},p:[25,46,546]}]}],r:"data.broken"}," ",{p:[27,3,656],t:7,e:"div",a:{style:"float:right"},f:[{p:[28,4,686],t:7,e:"ui-button",a:{icon:"power-off",action:"power-on",state:[{t:2,r:"data.broken",p:[28,57,739]}],style:[{t:2,x:{r:["data.online"],s:'_0?"selected":""'},p:[28,81,763]}]},f:["On"]}," ",{p:[29,4,817],t:7,e:"ui-button",a:{icon:"close",action:"power-off",state:[{t:2,r:"data.broken",p:[29,54,867]}],style:[{t:2,x:{r:["data.online"],s:'_0?"":"selected"'},p:[29,78,891]}]},f:["Off"]}]}," ",{t:4,f:[{p:[32,4,989],t:7,e:"br"}," [ ",{p:[33,6,1e3],t:7,e:"span",a:{"class":"bad"},f:["Compressor is inoperable"]}," ]"],n:50,r:"data.compressor_broke",p:[31,3,955]}," ",{t:4,f:[{p:[36,4,1097],t:7,e:"br"}," [ ",{p:[37,6,1108],t:7,e:"span",a:{"class":"bad"},f:["Turbine is inoperable"]}," ]"],n:50,r:"data.turbine_broke",p:[35,3,1066]}]}]}," ",{p:[41,1,1200],t:7,e:"ui-display",a:{title:"Status"},f:[{p:[42,2,1230],t:7,e:"ui-section",a:{label:"Turbine Speed"},f:[{p:[43,3,1268],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.rpm"],s:'_0?"--":_1'},p:[43,9,1274]}," RPM"]}]}," ",{p:[45,2,1337],t:7,e:"ui-section",a:{label:"Internal Temp"},f:[{p:[46,3,1375],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.temp"],s:'_0?"--":_1'},p:[46,9,1381]}," K"]}]}," ",{p:[48,2,1443],t:7,e:"ui-section",a:{label:"Generated Power"},f:[{p:[49,3,1483],t:7,e:"span",f:[{t:2,x:{r:["data.broken","data.power"],s:'_0?"--":_1'},p:[49,9,1489]}]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],475:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{},oninit:function(){this.on({hover:function(t){var e=this.get("data.telecrystals");e>=t.context.params.cost&&this.set("hovered",t.context.params)},unhover:function(t){this.set("hovered")}})}}}(r),r.exports.template={v:3,t:[" ",{p:{button:[{t:4,f:[{p:[23,7,482],t:7,e:"ui-button",a:{icon:"lock",action:"lock"},f:["Lock"]}],n:50,r:"data.lockable",p:[22,5,453]}]},t:7,e:"ui-display",a:{title:"Uplink",button:0},f:[" ",{p:[26,3,568],t:7,e:"ui-section",a:{label:"Telecrystals",right:0},f:[{p:[27,5,613],t:7,e:"span",a:{"class":[{t:2,x:{r:["data.telecrystals"],s:'_0>0?"good":"bad"'},p:[27,18,626]}]},f:[{t:2,r:"data.telecrystals",p:[27,62,670]}," TC"]}]}]}," ",{t:4,f:[{p:[31,3,764],t:7,e:"ui-display",f:[{p:[32,2,779],t:7,e:"ui-button",a:{action:"select",params:['{"category": "',{t:2,r:"name",p:[32,51,828]},'"}']},f:[{t:2,r:"name",p:[32,63,840]}]}," ",{t:4,f:[{p:[34,4,883],t:7,e:"ui-section",a:{label:[{t:2,r:"name",p:[34,23,902]}],candystripe:0,right:0},f:[{p:[35,3,934],t:7,e:"ui-button",a:{tooltip:[{t:2,r:"name",p:[35,23,954]},": ",{t:2,r:"desc",p:[35,33,964]}],"tooltip-side":"left",state:[{t:2,x:{r:["data.telecrystals","hovered.cost","cost","hovered.item","name"],s:'_0<_2||(_0-_1<_2&&_3!=_4)?"disabled":null'},p:[36,12,1006]}],action:"buy",params:['{"category": "',{t:2,r:"category",p:[37,40,1165]},'", "item": ',{t:2,r:"name",p:[37,63,1188]},', "cost": ',{t:2,r:"cost",p:[37,81,1206]},"}"]},v:{hover:"hover",unhover:"unhover"},f:[{t:2,r:"cost",p:[38,43,1260]}," TC"]}]}],n:52,r:"items",p:[33,2,863]}]}],n:52,r:"data.categories",p:[30,1,735]}]},e.exports=a.extend(r.exports)},{341:341}],476:[function(t,e,n){var a=t(341),r={exports:{}};!function(t){"use strict";t.exports={data:{healthState:function(t){var e=this.get("data.vr_avatar.maxhealth");return t>e/1.5?"good":t>e/3?"average":"bad"}}}}(r),r.exports.template={v:3,t:[" ",{p:[14,1,292],t:7,e:"ui-display",f:[{t:4,f:[{p:[16,3,331],t:7,e:"ui-notice",f:[{p:[17,4,347],t:7,e:"span",f:["Safety restraints disabled."]}]}],n:50,r:"data.emagged",p:[15,2,307]}," ",{t:4,f:[{p:[21,3,442],t:7,e:"ui-display",a:{title:"Virtual Avatar"},f:[{p:[22,4,482],t:7,e:"ui-section",a:{label:"Name"},f:[{t:2,r:"data.vr_avatar.name",p:[23,5,513]}]}," ",{t:4,f:[{p:[26,5,586],t:7,e:"ui-section",a:{label:"Status"},f:[{t:2,r:"data.vr_avatar.status",p:[27,6,620]}]}," ",{p:[29,5,670],t:7,e:"ui-section",a:{label:"Health"},f:[{p:[30,6,704],t:7,e:"ui-bar",a:{min:"0",max:[{t:2,r:"adata.vr_avatar.maxhealth",p:[30,27,725]}],value:[{t:2,r:"adata.vr_avatar.health",p:[30,65,763]}],state:[{t:2,x:{r:["healthState","adata.vr_avatar.health"],s:"_0(_1)"},p:[30,100,798]}]},f:[{t:2,x:{r:["adata.vr_avatar.health"],s:"Math.round(_0)"},p:[30,141,839]},"/",{t:2,r:"adata.vr_avatar.maxhealth",p:[30,180,878]}]}]}],n:50,r:"data.isliving",p:[25,4,559]}]}],n:50,r:"data.vr_avatar",p:[20,2,416]},{t:4,n:51,f:[{p:[35,3,979],t:7,e:"ui-display",a:{title:"Virtual Avatar"},f:["No Virtual Avatar detected"]}],r:"data.vr_avatar"}," ",{p:[39,2,1075],t:7,e:"ui-display",a:{title:"VR Commands"},f:[{p:[40,3,1111],t:7,e:"ui-button",a:{icon:[{t:2,x:{r:["data.toggle_open"],s:'_0?"times":"plus"'},p:[40,20,1128]}],action:"toggle_open"},f:[{t:2,x:{r:["data.toggle_open"],s:'_0?"Close":"Open"'},p:[41,4,1195]}," the VR Sleeper"]}," ",{t:4,f:[{p:[44,4,1297],t:7,e:"ui-button",a:{icon:"signal",action:"vr_connect"},f:["Connect to VR"]}],n:50,r:"data.isoccupant",p:[43,3,1269]}," ",{t:4,f:[{p:[49,4,1420],t:7,e:"ui-button",a:{icon:"ban",action:"delete_avatar"},f:["Delete Virtual Avatar"]}],n:50,r:"data.vr_avatar",p:[48,3,1393]}]}]}]},e.exports=a.extend(r.exports)},{341:341}],477:[function(t,e,n){var a=t(341),r={exports:{}};r.exports.template={v:3,t:[{p:[1,1,0],t:7,e:"ui-display",f:[{t:4,f:[{p:[3,5,42],t:7,e:"ui-section",a:{label:[{t:2,r:"color",p:[3,24,61]},{t:2,x:{r:["wire"],s:'_0?" ("+_0+")":""'},p:[3,33,70]}],labelcolor:[{t:2,r:"color",p:[3,80,117]}],candystripe:0,right:0},f:[{p:[4,7,154],t:7,e:"ui-button",a:{action:"cut",params:['{"wire":"',{t:2,r:"color",p:[4,48,195]},'"}']},f:[{t:2,x:{r:["cut"],s:'_0?"Mend":"Cut"'},p:[4,61,208]}]}," ",{p:[5,7,252],t:7,e:"ui-button",a:{action:"pulse",params:['{"wire":"',{t:2,r:"color",p:[5,50,295]},'"}']},f:["Pulse"]}," ",{p:[6,7,333],t:7,e:"ui-button",a:{action:"attach",params:['{"wire":"',{t:2,r:"color",p:[6,51,377]},'"}']},f:[{t:2,x:{r:["attached"],s:'_0?"Detach":"Attach"'},p:[6,64,390]}]}]}],n:52,r:"data.wires",p:[2,3,16]}]}," ",{t:4,f:[{p:[11,3,508],t:7,e:"ui-display",f:[{t:4,f:[{p:[13,7,555],t:7,e:"ui-section",f:[{t:2,r:".",p:[13,19,567]}]}],n:52,r:"data.status",p:[12,5,526]}]}],n:50,r:"data.status",p:[10,1,485]}]},e.exports=a.extend(r.exports)},{341:341}],478:[function(t,e,n){(function(e){"use strict";var n=t(341),a=e.interopRequireDefault(n);t(331),t(1),t(327),t(330);var r=t(479),i=e.interopRequireDefault(r),o=t(480),s=t(328),p=t(329),u=e.interopRequireDefault(p);a["default"].DEBUG=/minified/.test(function(){}),Object.assign(Math,t(484)),window.initialize=function(e){window.tgui=window.tgui||new i["default"]({el:"#container",data:function(){var n=JSON.parse(e);return{constants:t(481),text:t(485),config:n.config,data:n.data,adata:n.data}}})};var c=document.getElementById("data"),l=c.textContent,d=c.getAttribute("data-ref");"{}"!==l&&(window.initialize(l),c.remove()),(0,o.act)(d,"tgui:initialize"),(0,s.loadCSS)("font-awesome.min.css");var f=new u["default"]("FontAwesome");f.check("").then(function(){return document.body.classList.add("icons")})["catch"](function(){return document.body.classList.add("no-icons")})}).call(this,t("babel/external-helpers"))},{1:1,327:327,328:328,329:329,330:330,331:331,341:341,479:479,480:480,481:481,484:484,485:485,"babel/external-helpers":"babel/external-helpers"}],479:[function(t,e,n){var a=t(341),r={exports:{}};!function(e){"use strict";var n=t(480),a=t(482);e.exports={components:{"ui-bar":t(342),"ui-button":t(343),"ui-display":t(344),"ui-input":t(345),"ui-linegraph":t(346),"ui-notice":t(347),"ui-section":t(349),"ui-subdisplay":t(350),"ui-tabs":t(351)},events:{enter:t(339).enter,space:t(339).space},transitions:{fade:t(340)},onconfig:function(){var e=this.get("config.interface"),n={ai_airlock:t(355),airalarm:t(356),"airalarm/back":t(357),"airalarm/modes":t(358),"airalarm/scrubbers":t(359),"airalarm/status":t(360),"airalarm/thresholds":t(361),"airalarm/vents":t(362),airlock_electronics:t(363),apc:t(364),atmos_alert:t(365),atmos_control:t(366),atmos_filter:t(367),atmos_mixer:t(368),atmos_pump:t(369),borgopanel:t(370),brig_timer:t(371),bsa:t(372),canister:t(373),cargo:t(374),cargo_express:t(375),cellular_emporium:t(376),centcom_podlauncher:t(377),chem_dispenser:t(378),chem_heater:t(379),chem_master:t(380),chem_synthesizer:t(381),clockwork_slab:t(382),codex_gigas:t(383),computer_fabricator:t(384),crayon:t(385),crew:t(386),cryo:t(387),disposal_unit:t(388),dna_vault:t(389),dogborg_sleeper:t(390),eightball:t(391),emergency_shuttle_console:t(392),engraved_message:t(393),error:t(394),"exofab - Copia":t(395),exonet_node:t(396),gps:t(397),gulag_console:t(398),gulag_item_reclaimer:t(399),holodeck:t(400),implantchair:t(401),intellicard:t(402),keycard_auth:t(403),labor_claim_console:t(404),language_menu:t(405),launchpad_remote:t(406),mech_bay_power_console:t(407),mulebot:t(408),nanite_chamber_control:t(409),nanite_cloud_control:t(410),nanite_program_hub:t(411),nanite_programmer:t(412),nanite_remote:t(413),notificationpanel:t(414),ntnet_relay:t(415),ntos_ai_restorer:t(416),ntos_card:t(417),ntos_configuration:t(418),ntos_file_manager:t(419),ntos_main:t(420),ntos_net_chat:t(421),ntos_net_dos:t(422),ntos_net_downloader:t(423),ntos_net_monitor:t(424),ntos_net_transfer:t(425),ntos_power_monitor:t(426),ntos_revelation:t(427),ntos_station_alert:t(428),ntos_supermatter_monitor:t(429),ntosheader:t(430),nuclear_bomb:t(431),operating_computer:t(432),ore_redemption_machine:t(433),pandemic:t(434),personal_crafting:t(435),portable_pump:t(436),portable_scrubber:t(437),power_monitor:t(438),radio:t(439),rdconsole:t(440),"rdconsole/circuit":t(441),"rdconsole/designview":t(442),"rdconsole/destruct":t(443),"rdconsole/diskopsdesign":t(444),"rdconsole/diskopstech":t(445),"rdconsole/nodeview":t(446),"rdconsole/protolathe":t(447),"rdconsole/rdheader":t(448),"rdconsole/settings":t(449),"rdconsole/techweb":t(450),reagentgrinder:t(451),rpd:t(452),"rpd/colorsel":t(453),"rpd/dirsel":t(454),sat_control:t(455),scrubbing_types:t(456),shuttle_manipulator:t(457),"shuttle_manipulator/modification":t(458),"shuttle_manipulator/status":t(459),"shuttle_manipulator/templates":t(460),sleeper:t(461),slime_swap_body:t(462),smartvend:t(463),smes:t(464),smoke_machine:t(465),solar_control:t(466),space_heater:t(467),spawners_menu:t(468),station_alert:t(469),suit_storage_unit:t(470),tank_dispenser:t(471),tanks:t(472),thermomachine:t(473),turbine_computer:t(474),uplink:t(475),vr_sleeper:t(476),wires:t(477)};e in n?this.components["interface"]=n[e]:this.components["interface"]=n.error},oninit:function(){this.observe("config.style",function(t,e,n){t&&document.body.classList.add(t),e&&document.body.classList.remove(e)})},oncomplete:function(){if(this.get("config.locked")){var t=(0,a.lock)(window.screenLeft,window.screenTop),e=t.x,r=t.y;(0,n.winset)(this.get("config.window"),"pos",e+","+r)}(0,n.winset)("mapwindow.map","focus",!0)}}}(r),r.exports.template={v:3,t:[" "," "," "," ",{p:[56,1,1874],t:7,e:"titlebar",f:[{t:3,r:"config.title",p:[56,11,1884]}]}," ",{p:[57,1,1915],t:7,e:"main",f:[{p:[58,3,1925],t:7,e:"warnings"}," ",{p:[59,3,1940],t:7,e:"interface"}]}," ",{t:4,f:[{p:[62,3,1990],t:7,e:"resize"}],n:50,r:"config.titlebar",p:[61,1,1963]}]},r.exports.components=r.exports.components||{};var i={warnings:t(354),titlebar:t(353),resize:t(348)};for(var o in i)i.hasOwnProperty(o)&&(r.exports.components[o]=i[o]);e.exports=a.extend(r.exports)},{339:339,340:340,341:341,342:342,343:343,344:344,345:345,346:346,347:347,348:348,349:349,350:350,351:351,353:353,354:354,355:355,356:356,357:357,358:358,359:359,360:360,361:361,362:362,363:363,364:364,365:365,366:366,367:367,368:368,369:369,370:370,371:371,372:372,373:373,374:374,375:375,376:376,377:377,378:378,379:379,380:380,381:381,382:382,383:383,384:384,385:385,386:386,387:387,388:388,389:389,390:390,391:391,392:392,393:393,394:394,395:395,396:396,397:397,398:398,399:399,400:400,401:401,402:402,403:403,404:404,405:405,406:406,407:407,408:408,409:409,410:410,411:411,412:412,413:413,414:414,415:415,416:416,417:417,418:418,419:419,420:420,421:421,422:422,423:423,424:424,425:425,426:426,427:427,428:428,429:429,430:430,431:431,432:432,433:433,434:434,435:435,436:436,437:437,438:438,439:439,440:440,441:441,442:442,443:443,444:444,445:445,446:446,447:447,448:448,449:449,450:450,451:451,452:452,453:453,454:454,455:455,456:456,457:457,458:458,459:459,460:460,461:461,462:462,463:463,464:464,465:465,466:466,467:467,468:468,469:469,470:470,471:471,472:472,473:473,474:474,475:475,476:476,477:477,480:480,482:482}],480:[function(t,e,n){"use strict";function a(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"byond://"+e+"?"+Object.keys(t).map(function(e){return o(e)+"="+o(t[e])}).join("&")}function r(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};window.location.href=a(Object.assign({src:t,action:e},n))}function i(t,e,n){var r;window.location.href=a((r={},r[t+"."+e]=n,r),"winset")}n.__esModule=!0,n.href=a,n.act=r,n.winset=i;var o=encodeURIComponent},{}],481:[function(t,e,n){"use strict";n.__esModule=!0;n.UI_INTERACTIVE=2,n.UI_UPDATE=1,n.UI_DISABLED=0,n.UI_CLOSE=-1},{}],482:[function(t,e,n){"use strict";function a(t,e){return 0>t?t=0:t+window.innerWidth>window.screen.availWidth&&(t=window.screen.availWidth-window.innerWidth),0>e?e=0:e+window.innerHeight>window.screen.availHeight&&(e=window.screen.availHeight-window.innerHeight),{x:t,y:e}}function r(t){if(t.preventDefault(),this.get("drag")){if(this.get("x")){var e=t.screenX-this.get("x")+window.screenLeft,n=t.screenY-this.get("y")+window.screenTop;if(this.get("config.locked")){var r=a(e,n);e=r.x,n=r.y}(0,s.winset)(this.get("config.window"),"pos",e+","+n)}this.set({x:t.screenX,y:t.screenY})}}function i(t,e){return t=Math.clamp(100,window.screen.width,t),e=Math.clamp(100,window.screen.height,e),{x:t,y:e}}function o(t){if(t.preventDefault(),this.get("resize")){if(this.get("x")){var e=t.screenX-this.get("x")+window.innerWidth,n=t.screenY-this.get("y")+window.innerHeight,a=i(e,n);e=a.x,n=a.y,(0,s.winset)(this.get("config.window"),"size",e+","+n)}this.set({x:t.screenX,y:t.screenY})}}n.__esModule=!0,n.lock=a,n.drag=r,n.sane=i,n.resize=o;var s=t(480)},{480:480}],483:[function(t,e,n){"use strict";function a(t,e){for(var n=t,a=Array.isArray(n),i=0,n=a?n:n[Symbol.iterator]();;){var o;if(a){if(i>=n.length)break;o=n[i++]}else{if(i=n.next(),i.done)break;o=i.value}var s=o;s.textContent.toLowerCase().includes(e)?(s.style.display="",r(s,e)):s.style.display="none"}}function r(t,e){for(var n=t.queryAll("section"),a=t.query("header").textContent.toLowerCase().includes(e),r=n,i=Array.isArray(r),o=0,r=i?r:r[Symbol.iterator]();;){var s;if(i){if(o>=r.length)break;s=r[o++]}else{if(o=r.next(),o.done)break;s=o.value}var p=s;a||p.textContent.toLowerCase().includes(e)?p.style.display="":p.style.display="none"}}n.__esModule=!0,n.filterMulti=a,n.filter=r},{}],484:[function(t,e,n){"use strict";function a(t,e,n){return Math.max(t,Math.min(n,e))}function r(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return+(Math.round(t+"e"+e)+"e-"+e)}n.__esModule=!0,n.clamp=a,n.fixed=r},{}],485:[function(t,e,n){"use strict";function a(t){return t[0].toUpperCase()+t.slice(1).toLowerCase()}function r(t){return t.replace(/\w\S*/g,a)}function i(t,e){for(t=""+t;t.length1){for(var p=Array(o),u=0;o>u;u++)p[u]=arguments[u+3];n.children=p}return{$$typeof:t,type:e,key:void 0===a?null:""+a,ref:null,props:n,_owner:null}}}(),e.asyncIterator=function(t){if("function"==typeof Symbol){if(Symbol.asyncIterator){var e=t[Symbol.asyncIterator];if(null!=e)return e.call(t)}if(Symbol.iterator)return t[Symbol.iterator]()}throw new TypeError("Object is not async iterable")},e.asyncGenerator=function(){function t(t){this.value=t}function e(e){function n(t,e){return new Promise(function(n,r){var s={key:t,arg:e,resolve:n,reject:r,next:null};o?o=o.next=s:(i=o=s,a(t,e))})}function a(n,i){try{var o=e[n](i),s=o.value;s instanceof t?Promise.resolve(s.value).then(function(t){a("next",t)},function(t){a("throw",t)}):r(o.done?"return":"normal",o.value)}catch(p){r("throw",p)}}function r(t,e){switch(t){case"return":i.resolve({value:e,done:!0});break;case"throw":i.reject(e);break;default:i.resolve({value:e,done:!1})}i=i.next,i?a(i.key,i.arg):o=null}var i,o;this._invoke=n,"function"!=typeof e["return"]&&(this["return"]=void 0)}return"function"==typeof Symbol&&Symbol.asyncIterator&&(e.prototype[Symbol.asyncIterator]=function(){return this}),e.prototype.next=function(t){return this._invoke("next",t)},e.prototype["throw"]=function(t){return this._invoke("throw",t)},e.prototype["return"]=function(t){return this._invoke("return",t)},{wrap:function(t){return function(){return new e(t.apply(this,arguments))}},await:function(e){return new t(e)}}}(),e.asyncGeneratorDelegate=function(t,e){function n(n,a){return r=!0,a=new Promise(function(e){e(t[n](a))}),{done:!1,value:e(a)}}var a={},r=!1;return"function"==typeof Symbol&&Symbol.iterator&&(a[Symbol.iterator]=function(){return this}),a.next=function(t){return r?(r=!1,t):n("next",t)},"function"==typeof t["throw"]&&(a["throw"]=function(t){if(r)throw r=!1,t;return n("throw",t)}),"function"==typeof t["return"]&&(a["return"]=function(t){return n("return",t)}),a},e.asyncToGenerator=function(t){return function(){var e=t.apply(this,arguments);return new Promise(function(t,n){function a(r,i){try{var o=e[r](i),s=o.value}catch(p){return void n(p)}return o.done?void t(s):Promise.resolve(s).then(function(t){a("next",t)},function(t){a("throw",t)})}return a("next")})}},e.classCallCheck=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},e.createClass=function(){function t(t,e){for(var n=0;n=0||Object.prototype.hasOwnProperty.call(t,a)&&(n[a]=t[a]);return n},e.possibleConstructorReturn=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e},e.selfGlobal=void 0===t?self:t,e.set=function a(t,e,n,r){var i=Object.getOwnPropertyDescriptor(t,e);if(void 0===i){var o=Object.getPrototypeOf(t);null!==o&&a(o,e,n,r)}else if("value"in i&&i.writable)i.value=n;else{var s=i.set;void 0!==s&&s.call(r,n)}return n},e.slicedToArray=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),e.slicedToArrayLoose=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t)){for(var n,a=[],r=t[Symbol.iterator]();!(n=r.next()).done&&(a.push(n.value),!e||a.length!==e););return a}throw new TypeError("Invalid attempt to destructure non-iterable instance")},e.taggedTemplateLiteral=function(t,e){return Object.freeze(Object.defineProperties(t,{raw:{value:Object.freeze(e)}}))},e.taggedTemplateLiteralLoose=function(t,e){return t.raw=e,t},e.temporalRef=function(t,e,n){if(t===n)throw new ReferenceError(e+" is not defined - temporal dead zone");return t},e.temporalUndefined={},e.toArray=function(t){return Array.isArray(t)?t:Array.from(t)},e.toConsumableArray=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e - {{#if data.locked && !data.siliconUser}} + {{#if data.locked && !data.siliconUser && data.lock_nightshift}} {{data.nightshiftLights ? "Enabled" : "Disabled"}} {{else}} {{data.nightshiftLights ? "Enabled" : "Disabled"}} From 38c4060bfc52c2f9535f4b5415bc136bf19a5639 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Fri, 3 Jan 2020 00:04:58 -0800 Subject: [PATCH 029/409] compile --- code/modules/power/apc.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 8e6deb4659..2c860b9f25 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1404,7 +1404,7 @@ /obj/machinery/power/apc/proc/nightshift_toggle_requires_auth() if(!area) return FALSE - var/configured_level = CONFIG_GET(number/nightshift_public_areas_only) + var/configured_level = CONFIG_GET(number/night_shift_public_areas_only) var/our_level = area.nightshift_public_area var/public_requires_auth = CONFIG_GET(flag/nightshift_toggle_public_requires_auth) var/normal_requires_auth = CONFIG_GET(flag/nightshift_toggle_requires_auth) From 3f5d4ad83519e8c7a2dd8e20a0c1be86792adecf Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 03:13:03 -0500 Subject: [PATCH 030/409] remove a duplicate comment --- code/modules/research/designs/misc_designs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 5ae33a4752..a75a8697fd 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -444,7 +444,7 @@ desc = "A tool that can construct and deconstruct pipes on the fly." id = "rpd" build_type = PROTOLATHE - materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) // costs more than what it did in the autolathe, this one comes loaded. + materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) build_path = /obj/item/construction/rcd/loaded category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING From aedf634355766059c1aa42a77a7cc2c872aeb778 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 03:15:30 -0500 Subject: [PATCH 031/409] Fix mats. --- code/modules/research/designs/misc_designs.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index a75a8697fd..ebc1f8a39c 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -434,7 +434,7 @@ desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly." id = "rcd_loaded" build_type = PROTOLATHE - materials = list(/datum/material/iron = 60000, /datum/material/glass = 5000) // costs more than what it did in the autolathe, this one comes loaded. + materials = list(MAT_METAL = 60000, MAT_GLASS = 5000) // costs more than what it did in the autolathe, this one comes loaded. build_path = /obj/item/construction/rcd/loaded category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING @@ -444,7 +444,7 @@ desc = "A tool that can construct and deconstruct pipes on the fly." id = "rpd" build_type = PROTOLATHE - materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) + materials = list(MAT_METAL = 75000, MAT_GLASS = 37500) build_path = /obj/item/construction/rcd/loaded category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING From 880db10033685e0d0bcc9b27aa400fb4d3593857 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 03:22:18 -0500 Subject: [PATCH 032/409] Forgot some more mats --- code/modules/research/designs/misc_designs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index ebc1f8a39c..ae19b6d053 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -394,7 +394,7 @@ desc = "Adds the simple circuits to the RCD." id = "rcd_upgrade_simple_circuits" build_type = PROTOLATHE - materials = list(/datum/material/iron = 5000, /datum/material/glass = 2500, /datum/material/silver = 1500, /datum/material/titanium = 2000) + materials = list(/AT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) build_path = /obj/item/rcd_upgrade/simple_circuits category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING From 221cb980d61a3595b7beee8ac853859037cc16fa Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 03:25:53 -0500 Subject: [PATCH 033/409] forgot a / --- code/modules/research/designs/misc_designs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index ae19b6d053..a49dd76ede 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -394,7 +394,7 @@ desc = "Adds the simple circuits to the RCD." id = "rcd_upgrade_simple_circuits" build_type = PROTOLATHE - materials = list(/AT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) + materials = list(AT_METAL = 5000, MAT_GLASS = 2500, MAT_SILVER = 1500, MAT_TITANIUM = 2000) build_path = /obj/item/rcd_upgrade/simple_circuits category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING From 62ea644dd0155fba3c05a22f9c24c39cbba46f15 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 16:26:53 -0500 Subject: [PATCH 034/409] ugh, make rcds that are able to remove r-wall be able to remvoe r-doors too. THERE I DID GRAY YOU CAN NOW SHUT UP!! --- code/game/machinery/doors/airlock.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 6959ab971c..3e88223037 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1408,7 +1408,7 @@ /obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) if(RCD_DECONSTRUCT) - if(security_level != AIRLOCK_SECURITY_NONE) + if(security_level != AIRLOCK_SECURITY_NONE && the_rcd.canRturf != TRUE) to_chat(user, "[src]'s reinforcement needs to be removed first.") return FALSE return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 32) From a0768120c141d93dc2a5be150f75b55374691e40 Mon Sep 17 00:00:00 2001 From: r4d6 Date: Fri, 3 Jan 2020 21:04:16 -0500 Subject: [PATCH 035/409] Fix conflict --- icons/obj/clothing/suits.dmi | Bin 137267 -> 137169 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 2e53bb24db696bdb6ded2c0f4f090ba9ec8f6b51..5220814218e3428672659736727123447aa81d79 100644 GIT binary patch delta 101710 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

Other content prefs

" @@ -1015,6 +1016,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
" dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
" dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
" + dat += "" dat += "
" @@ -2234,6 +2236,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("ass_slap") cit_toggles ^= NO_ASS_SLAP + + if("bimbo") + cit_toggles ^= BIMBOFICATION //END CITADEL EDIT diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 2fa012ae87..ba4fe4909e 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -969,9 +969,10 @@ if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(5)) for(var/obj/item/organ/genital/G in M.internal_organs) if(!G.aroused_state && prob(5*G.sensitivity)) - G.aroused_state = TRUE + G.set_aroused_state(TRUE) G.update_appearance() - to_chat(M, "You feel like playing with your [G.name]!") + if(G.aroused_state) + to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index dc39c433eb..a39746519a 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2284,7 +2284,8 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state && prob(2*G.sensitivity)) - G.aroused_state = TRUE + G.set_aroused_state(TRUE) G.update_appearance() - to_chat(M, "You feel like playing with your [G.name]!") + if(G.aroused_state) + to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index af9646fa51..3ea8bf8013 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -6,7 +6,8 @@ var/genital_flags //see citadel_defines.dm var/masturbation_verb = "masturbate" var/orgasm_verb = "cumming" //present continous - var/arousal_verb = "feel aroused" + var/arousal_verb = "You feel aroused" + var/unarousal_verb = "You no longer feel aroused" var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? var/size = 2 //can vary between num or text, just used in icon_state strings var/fluid_id = null @@ -38,6 +39,11 @@ Remove(owner, TRUE)//this should remove references to it, so it can be GCd correctly return ..() +/obj/item/organ/genital/proc/set_aroused_state(new_state) + if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state)) + aroused_state = new_state + return aroused_state + /obj/item/organ/genital/proc/update(removing = FALSE) if(QDELETED(src)) return @@ -126,8 +132,12 @@ var/obj/item/organ/genital/picked_organ picked_organ = input(src, "Choose which genitalia to toggle arousal on", "Set genital arousal", null) in genital_list if(picked_organ) - picked_organ.aroused_state = !picked_organ.aroused_state - to_chat(src,"You [picked_organ.arousal_verb].") + var/original_state = picked_organ.aroused_state + picked_organ.set_aroused_state(!picked_organ.aroused_state) + if(original_state != picked_organ.aroused_state) + to_chat(src,"[picked_organ.aroused_state ? picked_organ.arousal_verb : picked_organ.unarousal_verb].") + else + to_chat(src,"You can't make that genital [picked_organ.aroused_state ? "unaroused" : "aroused"]!") picked_organ.update_appearance() return diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 19c3ff80a9..6b4887c094 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -11,7 +11,8 @@ shape = "pair" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION masturbation_verb = "massage" - arousal_verb = "feel very sensitive in your breasts" + arousal_verb = "Your breasts start feeling sensitive" + unarousal_verb = "Your breasts no longer feel sensitive" orgasm_verb = "leaking" fluid_transfer_factor = 0.5 var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0) diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index d2d827e66d..c6d3c764ac 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -6,7 +6,8 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS masturbation_verb = "stroke" - arousal_verb = "pop a boner" + arousal_verb = "You pop a boner" + unarousal_verb = "Your boner goes down" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH linked_organ_slot = ORGAN_SLOT_TESTICLES fluid_transfer_factor = 0.5 diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 547674a5f1..a2a9f8eb05 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -6,6 +6,8 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TESTICLES size = BALLS_SIZE_MIN + arousal_verb = "Your balls ache a little" + unarousal_verb = "Your balls finally stop aching, again" linked_organ_slot = ORGAN_SLOT_PENIS genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION var/size_name = "average" diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index 7ecc0c155c..31d116b48e 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -8,7 +8,8 @@ size = 1 //There is only 1 size right now genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH masturbation_verb = "finger" - arousal_verb = "feel wet" + arousal_verb = "You feel wetness on your crotch." + unarousal_verb = "You no longer feel wet." fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS layer_index = VAGINA_LAYER_INDEX var/cap_length = 8//D E P T H (cap = capacity) diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index 50dee539e3..9ec1c8b010 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -110,9 +110,10 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state && prob(current_cycle*G.sensitivity)) - G.aroused_state = TRUE + G.set_aroused_state(TRUE) G.update_appearance() - to_chat(M, "You suddenly [G.arousal_verb]!") + if(G.aroused_state) + to_chat(M, "[G.arousal_verb]!") ..() /datum/reagent/drug/aphrodisiacplus @@ -145,9 +146,10 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state) - G.aroused_state = TRUE + G.set_aroused_state(TRUE) G.update_appearance() - to_chat(M, "You suddenly [G.arousal_verb]!") + if(G.aroused_state) + to_chat(M, "[G.arousal_verb]!") ..() /datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) @@ -166,9 +168,9 @@ /datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) - if(prob(5) && ishuman(M) && M.has_dna()) - if(prob(5)) //Less spam - to_chat(M, "Your libido is going haywire!") + if(prob(5) && ishuman(M) && M.has_dna() && (M.client?.prefs.cit_toggles & BIMBOFICATION)) + if(!HAS_TRAIT(M,TRAIT_PERMABONER)) //Less spam + to_chat(M, "Your libido is going haywire!") ADD_TRAIT(M,TRAIT_PERMABONER,"aphro") ..() @@ -189,9 +191,9 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) if(G.aroused_state) - G.aroused_state = FALSE + G.set_aroused_state(FALSE) G.update_appearance() - unboner = TRUE + unboner = (G.aroused_state == FALSE) if(unboner) to_chat(M, "You no longer feel aroused.") ..() @@ -213,9 +215,9 @@ var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) if(G.aroused_state) - G.aroused_state = FALSE + G.set_aroused_state(FALSE) G.update_appearance() - unboner = TRUE + unboner = (G.aroused_state == FALSE) if(unboner) to_chat(M, "You no longer feel aroused.") ..() From 35cd77d43380339909bfedd8ceec9d1e822ed146 Mon Sep 17 00:00:00 2001 From: keronshb Date: Mon, 6 Jan 2020 15:17:26 -0500 Subject: [PATCH 053/409] Adds the nanite remote for some programs Adds a new remote function from tg --- code/__DEFINES/components.dm | 1 + code/datums/components/nanites.dm | 622 ++--- .../research/designs/electronics_designs.dm | 10 + .../research/designs/nanite_designs.dm | 6 +- .../nanites/nanite_programs/suppression.dm | 94 +- .../nanites/nanite_programs/utility.dm | 9 + .../modules/research/nanites/nanite_remote.dm | 103 + code/modules/research/techweb/all_nodes.dm | 2274 ++++++++--------- icons/obj/device.dmi | Bin 49032 -> 51443 bytes tgui/assets/tgui.js | 42 +- tgui/src/interfaces/nanite_comm_remote.ract | 41 + 11 files changed, 1712 insertions(+), 1490 deletions(-) create mode 100644 tgui/src/interfaces/nanite_comm_remote.ract diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index b0cc9030cb..2f270e6861 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -300,6 +300,7 @@ #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_COMM_SIGNAL "nanite_comm_signal" //(comm_code(1-9999), comm_message) Called when sending a nanite comm 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 diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index 89c4deb2e9..9a18609060 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -1,307 +1,315 @@ -/datum/component/nanites - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - - var/mob/living/host_mob - var/nanite_volume = 50 //amount of nanites in the system, used as fuel for nanite programs - var/max_nanites = 250 //maximum amount of nanites in the system - var/regen_rate = 0.5 //nanites generated per second - var/safety_threshold = 25 //how low nanites will get before they stop processing/triggering - var/cloud_id = 0 //0 if not connected to the cloud, 1-100 to set a determined cloud backup to draw from - var/next_sync = 0 - var/list/datum/nanite_program/programs = list() - var/max_programs = NANITE_PROGRAM_LIMIT - - var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans - var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners - -/datum/component/nanites/Initialize(amount = 100, cloud = 0) - if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup)) - return COMPONENT_INCOMPATIBLE - - nanite_volume = amount - cloud_id = cloud - - //Nanites without hosts are non-interactive through normal means - if(isliving(parent)) - host_mob = parent - - if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) //Shouldn't happen, but this avoids HUD runtimes in case a silicon gets them somehow. - return COMPONENT_INCOMPATIBLE - - host_mob.hud_set_nanite_indicator() - START_PROCESSING(SSnanites, src) - - if(cloud_id) - cloud_sync() - -/datum/component/nanites/RegisterWithParent() - . = ..() - RegisterSignal(parent, COMSIG_HAS_NANITES, .proc/confirm_nanites) - RegisterSignal(parent, COMSIG_NANITE_UI_DATA, .proc/nanite_ui_data) - RegisterSignal(parent, COMSIG_NANITE_GET_PROGRAMS, .proc/get_programs) - RegisterSignal(parent, COMSIG_NANITE_SET_VOLUME, .proc/set_volume) - RegisterSignal(parent, COMSIG_NANITE_ADJUST_VOLUME, .proc/adjust_nanites) - RegisterSignal(parent, COMSIG_NANITE_SET_MAX_VOLUME, .proc/set_max_volume) - RegisterSignal(parent, COMSIG_NANITE_SET_CLOUD, .proc/set_cloud) - RegisterSignal(parent, COMSIG_NANITE_SET_SAFETY, .proc/set_safety) - RegisterSignal(parent, COMSIG_NANITE_SET_REGEN, .proc/set_regen) - RegisterSignal(parent, COMSIG_NANITE_ADD_PROGRAM, .proc/add_program) - RegisterSignal(parent, COMSIG_NANITE_SCAN, .proc/nanite_scan) - RegisterSignal(parent, COMSIG_NANITE_SYNC, .proc/sync) - RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp) - - if(isliving(parent)) - RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/on_death) - RegisterSignal(parent, COMSIG_MOB_ALLOWED, .proc/check_access) - RegisterSignal(parent, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_shock) - RegisterSignal(parent, COMSIG_LIVING_MINOR_SHOCK, .proc/on_minor_shock) - RegisterSignal(parent, COMSIG_SPECIES_GAIN, .proc/check_viable_biotype) - RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal) - -/datum/component/nanites/UnregisterFromParent() - . = ..() - UnregisterSignal(parent, list(COMSIG_HAS_NANITES, - COMSIG_NANITE_UI_DATA, - COMSIG_NANITE_GET_PROGRAMS, - COMSIG_NANITE_SET_VOLUME, - COMSIG_NANITE_ADJUST_VOLUME, - COMSIG_NANITE_SET_MAX_VOLUME, - COMSIG_NANITE_SET_CLOUD, - COMSIG_NANITE_SET_SAFETY, - COMSIG_NANITE_SET_REGEN, - COMSIG_NANITE_ADD_PROGRAM, - COMSIG_NANITE_SCAN, - COMSIG_NANITE_SYNC, - COMSIG_ATOM_EMP_ACT, - COMSIG_MOB_DEATH, - COMSIG_MOB_ALLOWED, - COMSIG_LIVING_ELECTROCUTE_ACT, - COMSIG_LIVING_MINOR_SHOCK, - COMSIG_MOVABLE_HEAR, - COMSIG_SPECIES_GAIN, - COMSIG_NANITE_SIGNAL)) - -/datum/component/nanites/Destroy() - STOP_PROCESSING(SSnanites, src) - set_nanite_bar(TRUE) - QDEL_LIST(programs) - if(host_mob) - host_mob.hud_set_nanite_indicator() - host_mob = null - return ..() - -/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments) - if(new_nanites) - adjust_nanites(null, new_nanites.nanite_volume) - else - adjust_nanites(null, arguments[1]) //just add to the nanite volume - -/datum/component/nanites/process() - adjust_nanites(null, regen_rate) - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.on_process() - set_nanite_bar() - if(cloud_id && world.time > next_sync) - cloud_sync() - next_sync = world.time + NANITE_SYNC_DELAY - -//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status) -/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE) - var/list/programs_to_remove = programs.Copy() - var/list/programs_to_add = source.programs.Copy() - for(var/X in programs) - var/datum/nanite_program/NP = X - for(var/Y in programs_to_add) - var/datum/nanite_program/SNP = Y - if(NP.type == SNP.type) - programs_to_remove -= NP - programs_to_add -= SNP - SNP.copy_programming(NP, copy_activation) - break - if(full_overwrite) - for(var/X in programs_to_remove) - qdel(X) - for(var/X in programs_to_add) - var/datum/nanite_program/SNP = X - add_program(null, SNP.copy()) - -/datum/component/nanites/proc/cloud_sync() - if(!cloud_id) - return - var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id) - if(backup) - var/datum/component/nanites/cloud_copy = backup.nanites - if(cloud_copy) - sync(null, cloud_copy) - -/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program) - for(var/X in programs) - var/datum/nanite_program/NP = X - if(NP.unique && NP.type == new_program.type) - qdel(NP) - if(programs.len >= max_programs) - return COMPONENT_PROGRAM_NOT_INSTALLED - if(source_program) - source_program.copy_programming(new_program) - programs += new_program - new_program.on_add(src) - return COMPONENT_PROGRAM_INSTALLED - -/datum/component/nanites/proc/consume_nanites(amount, force = FALSE) - if(!force && safety_threshold && (nanite_volume - amount < safety_threshold)) - return FALSE - adjust_nanites(null, -amount) - return (nanite_volume > 0) - -/datum/component/nanites/proc/adjust_nanites(datum/source, amount) - nanite_volume = CLAMP(nanite_volume + amount, 0, max_nanites) - if(nanite_volume <= 0) //oops we ran out - qdel(src) - -/datum/component/nanites/proc/set_nanite_bar(remove = FALSE) - var/image/holder = host_mob.hud_list[DIAG_NANITE_FULL_HUD] - var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir) - holder.pixel_y = I.Height() - world.icon_size - holder.icon_state = null - if(remove || stealth) - return //bye icon - var/nanite_percent = (nanite_volume / max_nanites) * 100 - nanite_percent = CLAMP(CEILING(nanite_percent, 10), 10, 100) - holder.icon_state = "nanites[nanite_percent]" - -/datum/component/nanites/proc/on_emp(datum/source, severity) - adjust_nanites(null, -(nanite_volume * 0.3 + 50)) //Lose 30% variable and 50 flat nanite volume. - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.on_emp(severity) - -/datum/component/nanites/proc/on_shock(datum/source, shock_damage) - adjust_nanites(null, -(nanite_volume * (shock_damage * 0.005) + shock_damage)) //0.5% of shock damage (@ 50 damage it'd drain 25%) + shock damage flat volume - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.on_shock(shock_damage) - -/datum/component/nanites/proc/on_minor_shock(datum/source) - adjust_nanites(null, -25) - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.on_minor_shock() - -/datum/component/nanites/proc/on_death(datum/source, gibbed) - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.on_death(gibbed) - -/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source") - for(var/X in programs) - var/datum/nanite_program/NP = X - NP.receive_signal(code, source) - -/datum/component/nanites/proc/check_viable_biotype() - if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) - qdel(src) //bodytype no longer sustains nanites - -/datum/component/nanites/proc/check_access(datum/source, obj/O) - for(var/datum/nanite_program/triggered/access/access_program in programs) - if(access_program.activated) - return O.check_access_list(access_program.access) - else - return FALSE - return FALSE - -/datum/component/nanites/proc/set_volume(datum/source, amount) - nanite_volume = CLAMP(amount, 0, max_nanites) - -/datum/component/nanites/proc/set_max_volume(datum/source, amount) - max_nanites = max(1, max_nanites) - -/datum/component/nanites/proc/set_cloud(datum/source, amount) - cloud_id = CLAMP(amount, 0, 100) - -/datum/component/nanites/proc/set_safety(datum/source, amount) - safety_threshold = CLAMP(amount, 0, max_nanites) - -/datum/component/nanites/proc/set_regen(datum/source, amount) - regen_rate = amount - -/datum/component/nanites/proc/confirm_nanites() - return TRUE //yup i exist - -/datum/component/nanites/proc/get_data(list/nanite_data) - nanite_data["nanite_volume"] = nanite_volume - nanite_data["max_nanites"] = max_nanites - nanite_data["cloud_id"] = cloud_id - nanite_data["regen_rate"] = regen_rate - nanite_data["safety_threshold"] = safety_threshold - nanite_data["stealth"] = stealth - -/datum/component/nanites/proc/get_programs(datum/source, list/nanite_programs) - nanite_programs |= programs - -/datum/component/nanites/proc/nanite_scan(datum/source, mob/user, full_scan) - if(!full_scan) - if(!stealth) - to_chat(user, "Nanites Detected") - to_chat(user, "Saturation: [nanite_volume]/[max_nanites]") - return TRUE - else - to_chat(user, "NANITES DETECTED") - to_chat(user, "================") - to_chat(user, "Saturation: [nanite_volume]/[max_nanites]") - to_chat(user, "Safety Threshold: [safety_threshold]") - to_chat(user, "Cloud ID: [cloud_id ? cloud_id : "Disabled"]") - to_chat(user, "================") - to_chat(user, "Program List:") - if(!diagnostics) - to_chat(user, "Diagnostics Disabled") - else - for(var/X in programs) - var/datum/nanite_program/NP = X - to_chat(user, "[NP.name] | [NP.activated ? "Active" : "Inactive"]") - return TRUE - -/datum/component/nanites/proc/nanite_ui_data(datum/source, list/data, scan_level) - data["has_nanites"] = TRUE - data["nanite_volume"] = nanite_volume - data["regen_rate"] = regen_rate - data["safety_threshold"] = safety_threshold - data["cloud_id"] = cloud_id - var/list/mob_programs = list() - var/id = 1 - for(var/X in programs) - var/datum/nanite_program/P = X - var/list/mob_program = list() - mob_program["name"] = P.name - mob_program["desc"] = P.desc - mob_program["id"] = id - - if(scan_level >= 2) - mob_program["activated"] = P.activated - mob_program["use_rate"] = P.use_rate - mob_program["can_trigger"] = P.can_trigger - mob_program["trigger_cost"] = P.trigger_cost - mob_program["trigger_cooldown"] = P.trigger_cooldown / 10 - - if(scan_level >= 3) - mob_program["activation_delay"] = P.activation_delay - mob_program["timer"] = P.timer - mob_program["timer_type"] = P.get_timer_type_text() - var/list/extra_settings = list() - for(var/Y in P.extra_settings) - var/list/setting = list() - setting["name"] = Y - setting["value"] = P.get_extra_setting(Y) - extra_settings += list(setting) - mob_program["extra_settings"] = extra_settings - if(LAZYLEN(extra_settings)) - mob_program["has_extra_settings"] = TRUE - - if(scan_level >= 4) - mob_program["activation_code"] = P.activation_code - mob_program["deactivation_code"] = P.deactivation_code - mob_program["kill_code"] = P.kill_code - mob_program["trigger_code"] = P.trigger_code - id++ - mob_programs += list(mob_program) - data["mob_programs"] = mob_programs +/datum/component/nanites + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + var/mob/living/host_mob + var/nanite_volume = 50 //amount of nanites in the system, used as fuel for nanite programs + var/max_nanites = 250 //maximum amount of nanites in the system + var/regen_rate = 0.5 //nanites generated per second + var/safety_threshold = 25 //how low nanites will get before they stop processing/triggering + var/cloud_id = 0 //0 if not connected to the cloud, 1-100 to set a determined cloud backup to draw from + var/next_sync = 0 + var/list/datum/nanite_program/programs = list() + var/max_programs = NANITE_PROGRAM_LIMIT + + var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans + var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners + +/datum/component/nanites/Initialize(amount = 100, cloud = 0) + if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup)) + return COMPONENT_INCOMPATIBLE + + nanite_volume = amount + cloud_id = cloud + + //Nanites without hosts are non-interactive through normal means + if(isliving(parent)) + host_mob = parent + + if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) //Shouldn't happen, but this avoids HUD runtimes in case a silicon gets them somehow. + return COMPONENT_INCOMPATIBLE + + host_mob.hud_set_nanite_indicator() + START_PROCESSING(SSnanites, src) + + if(cloud_id) + cloud_sync() + +/datum/component/nanites/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_HAS_NANITES, .proc/confirm_nanites) + RegisterSignal(parent, COMSIG_NANITE_UI_DATA, .proc/nanite_ui_data) + RegisterSignal(parent, COMSIG_NANITE_GET_PROGRAMS, .proc/get_programs) + RegisterSignal(parent, COMSIG_NANITE_SET_VOLUME, .proc/set_volume) + RegisterSignal(parent, COMSIG_NANITE_ADJUST_VOLUME, .proc/adjust_nanites) + RegisterSignal(parent, COMSIG_NANITE_SET_MAX_VOLUME, .proc/set_max_volume) + RegisterSignal(parent, COMSIG_NANITE_SET_CLOUD, .proc/set_cloud) + RegisterSignal(parent, COMSIG_NANITE_SET_SAFETY, .proc/set_safety) + RegisterSignal(parent, COMSIG_NANITE_SET_REGEN, .proc/set_regen) + RegisterSignal(parent, COMSIG_NANITE_ADD_PROGRAM, .proc/add_program) + RegisterSignal(parent, COMSIG_NANITE_SCAN, .proc/nanite_scan) + RegisterSignal(parent, COMSIG_NANITE_SYNC, .proc/sync) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp) + + if(isliving(parent)) + RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/on_death) + RegisterSignal(parent, COMSIG_MOB_ALLOWED, .proc/check_access) + RegisterSignal(parent, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_shock) + RegisterSignal(parent, COMSIG_LIVING_MINOR_SHOCK, .proc/on_minor_shock) + RegisterSignal(parent, COMSIG_SPECIES_GAIN, .proc/check_viable_biotype) + RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal) + RegisterSignal(parent, COMSIG_NANITE_COMM_SIGNAL, .proc/receive_comm_signal) + +/datum/component/nanites/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list(COMSIG_HAS_NANITES, + COMSIG_NANITE_UI_DATA, + COMSIG_NANITE_GET_PROGRAMS, + COMSIG_NANITE_SET_VOLUME, + COMSIG_NANITE_ADJUST_VOLUME, + COMSIG_NANITE_SET_MAX_VOLUME, + COMSIG_NANITE_SET_CLOUD, + COMSIG_NANITE_SET_SAFETY, + COMSIG_NANITE_SET_REGEN, + COMSIG_NANITE_ADD_PROGRAM, + COMSIG_NANITE_SCAN, + COMSIG_NANITE_SYNC, + COMSIG_ATOM_EMP_ACT, + COMSIG_MOB_DEATH, + COMSIG_MOB_ALLOWED, + COMSIG_LIVING_ELECTROCUTE_ACT, + COMSIG_LIVING_MINOR_SHOCK, + COMSIG_MOVABLE_HEAR, + COMSIG_SPECIES_GAIN, + COMSIG_NANITE_SIGNAL, + COMSIG_NANITE_COMM_SIGNAL)) + +/datum/component/nanites/Destroy() + STOP_PROCESSING(SSnanites, src) + set_nanite_bar(TRUE) + QDEL_LIST(programs) + if(host_mob) + host_mob.hud_set_nanite_indicator() + host_mob = null + return ..() + +/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments) + if(new_nanites) + adjust_nanites(null, new_nanites.nanite_volume) + else + adjust_nanites(null, arguments[1]) //just add to the nanite volume + +/datum/component/nanites/process() + adjust_nanites(null, regen_rate) + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.on_process() + set_nanite_bar() + if(cloud_id && world.time > next_sync) + cloud_sync() + next_sync = world.time + NANITE_SYNC_DELAY + +//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status) +/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE) + var/list/programs_to_remove = programs.Copy() + var/list/programs_to_add = source.programs.Copy() + for(var/X in programs) + var/datum/nanite_program/NP = X + for(var/Y in programs_to_add) + var/datum/nanite_program/SNP = Y + if(NP.type == SNP.type) + programs_to_remove -= NP + programs_to_add -= SNP + SNP.copy_programming(NP, copy_activation) + break + if(full_overwrite) + for(var/X in programs_to_remove) + qdel(X) + for(var/X in programs_to_add) + var/datum/nanite_program/SNP = X + add_program(null, SNP.copy()) + +/datum/component/nanites/proc/cloud_sync() + if(!cloud_id) + return + var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id) + if(backup) + var/datum/component/nanites/cloud_copy = backup.nanites + if(cloud_copy) + sync(null, cloud_copy) + +/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program) + for(var/X in programs) + var/datum/nanite_program/NP = X + if(NP.unique && NP.type == new_program.type) + qdel(NP) + if(programs.len >= max_programs) + return COMPONENT_PROGRAM_NOT_INSTALLED + if(source_program) + source_program.copy_programming(new_program) + programs += new_program + new_program.on_add(src) + return COMPONENT_PROGRAM_INSTALLED + +/datum/component/nanites/proc/consume_nanites(amount, force = FALSE) + if(!force && safety_threshold && (nanite_volume - amount < safety_threshold)) + return FALSE + adjust_nanites(null, -amount) + return (nanite_volume > 0) + +/datum/component/nanites/proc/adjust_nanites(datum/source, amount) + nanite_volume = CLAMP(nanite_volume + amount, 0, max_nanites) + if(nanite_volume <= 0) //oops we ran out + qdel(src) + +/datum/component/nanites/proc/set_nanite_bar(remove = FALSE) + var/image/holder = host_mob.hud_list[DIAG_NANITE_FULL_HUD] + var/icon/I = icon(host_mob.icon, host_mob.icon_state, host_mob.dir) + holder.pixel_y = I.Height() - world.icon_size + holder.icon_state = null + if(remove || stealth) + return //bye icon + var/nanite_percent = (nanite_volume / max_nanites) * 100 + nanite_percent = CLAMP(CEILING(nanite_percent, 10), 10, 100) + holder.icon_state = "nanites[nanite_percent]" + +/datum/component/nanites/proc/on_emp(datum/source, severity) + adjust_nanites(null, -(nanite_volume * 0.3 + 50)) //Lose 30% variable and 50 flat nanite volume. + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.on_emp(severity) + +/datum/component/nanites/proc/on_shock(datum/source, shock_damage) + adjust_nanites(null, -(nanite_volume * (shock_damage * 0.005) + shock_damage)) //0.5% of shock damage (@ 50 damage it'd drain 25%) + shock damage flat volume + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.on_shock(shock_damage) + +/datum/component/nanites/proc/on_minor_shock(datum/source) + adjust_nanites(null, -25) + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.on_minor_shock() + +/datum/component/nanites/proc/on_death(datum/source, gibbed) + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.on_death(gibbed) + +/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source") + for(var/X in programs) + var/datum/nanite_program/NP = X + NP.receive_signal(code, source) + +/datum/component/nanites/proc/receive_comm_signal(datum/source, comm_code, comm_message, comm_source = "an unidentified source") + for(var/X in programs) + if(istype(X, /datum/nanite_program/triggered/comm)) + var/datum/nanite_program/triggered/comm/NP = X + NP.receive_comm_signal(comm_code, comm_message, comm_source) + +/datum/component/nanites/proc/check_viable_biotype() + if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) + qdel(src) //bodytype no longer sustains nanites + +/datum/component/nanites/proc/check_access(datum/source, obj/O) + for(var/datum/nanite_program/triggered/access/access_program in programs) + if(access_program.activated) + return O.check_access_list(access_program.access) + else + return FALSE + return FALSE + +/datum/component/nanites/proc/set_volume(datum/source, amount) + nanite_volume = CLAMP(amount, 0, max_nanites) + +/datum/component/nanites/proc/set_max_volume(datum/source, amount) + max_nanites = max(1, max_nanites) + +/datum/component/nanites/proc/set_cloud(datum/source, amount) + cloud_id = CLAMP(amount, 0, 100) + +/datum/component/nanites/proc/set_safety(datum/source, amount) + safety_threshold = CLAMP(amount, 0, max_nanites) + +/datum/component/nanites/proc/set_regen(datum/source, amount) + regen_rate = amount + +/datum/component/nanites/proc/confirm_nanites() + return TRUE //yup i exist + +/datum/component/nanites/proc/get_data(list/nanite_data) + nanite_data["nanite_volume"] = nanite_volume + nanite_data["max_nanites"] = max_nanites + nanite_data["cloud_id"] = cloud_id + nanite_data["regen_rate"] = regen_rate + nanite_data["safety_threshold"] = safety_threshold + nanite_data["stealth"] = stealth + +/datum/component/nanites/proc/get_programs(datum/source, list/nanite_programs) + nanite_programs |= programs + +/datum/component/nanites/proc/nanite_scan(datum/source, mob/user, full_scan) + if(!full_scan) + if(!stealth) + to_chat(user, "Nanites Detected") + to_chat(user, "Saturation: [nanite_volume]/[max_nanites]") + return TRUE + else + to_chat(user, "NANITES DETECTED") + to_chat(user, "================") + to_chat(user, "Saturation: [nanite_volume]/[max_nanites]") + to_chat(user, "Safety Threshold: [safety_threshold]") + to_chat(user, "Cloud ID: [cloud_id ? cloud_id : "Disabled"]") + to_chat(user, "================") + to_chat(user, "Program List:") + if(!diagnostics) + to_chat(user, "Diagnostics Disabled") + else + for(var/X in programs) + var/datum/nanite_program/NP = X + to_chat(user, "[NP.name] | [NP.activated ? "Active" : "Inactive"]") + return TRUE + +/datum/component/nanites/proc/nanite_ui_data(datum/source, list/data, scan_level) + data["has_nanites"] = TRUE + data["nanite_volume"] = nanite_volume + data["regen_rate"] = regen_rate + data["safety_threshold"] = safety_threshold + data["cloud_id"] = cloud_id + var/list/mob_programs = list() + var/id = 1 + for(var/X in programs) + var/datum/nanite_program/P = X + var/list/mob_program = list() + mob_program["name"] = P.name + mob_program["desc"] = P.desc + mob_program["id"] = id + + if(scan_level >= 2) + mob_program["activated"] = P.activated + mob_program["use_rate"] = P.use_rate + mob_program["can_trigger"] = P.can_trigger + mob_program["trigger_cost"] = P.trigger_cost + mob_program["trigger_cooldown"] = P.trigger_cooldown / 10 + + if(scan_level >= 3) + mob_program["activation_delay"] = P.activation_delay + mob_program["timer"] = P.timer + mob_program["timer_type"] = P.get_timer_type_text() + var/list/extra_settings = list() + for(var/Y in P.extra_settings) + var/list/setting = list() + setting["name"] = Y + setting["value"] = P.get_extra_setting(Y) + extra_settings += list(setting) + mob_program["extra_settings"] = extra_settings + if(LAZYLEN(extra_settings)) + mob_program["has_extra_settings"] = TRUE + + if(scan_level >= 4) + mob_program["activation_code"] = P.activation_code + mob_program["deactivation_code"] = P.deactivation_code + mob_program["kill_code"] = P.kill_code + mob_program["trigger_code"] = P.trigger_code + id++ + mob_programs += list(mob_program) + data["mob_programs"] = mob_programs diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm index 818e80beea..18d90ea12e 100644 --- a/code/modules/research/designs/electronics_designs.dm +++ b/code/modules/research/designs/electronics_designs.dm @@ -36,6 +36,16 @@ category = list("Electronics") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE +/datum/design/nanite_comm_remote + name = "Nanite Communication Remote" + desc = "Allows for the construction of a nanite communication remote." + id = "nanite_comm_remote" + build_type = PROTOLATHE + materials = list(MAT_GLASS = 500, MAT_METAL = 500) + build_path = /obj/item/nanite_remote/comm + category = list("Electronics") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE + /datum/design/nanite_scanner name = "Nanite Scanner" desc = "Allows for the construction of a nanite scanner." diff --git a/code/modules/research/designs/nanite_designs.dm b/code/modules/research/designs/nanite_designs.dm index 09fe1d9c9b..85e34e5234 100644 --- a/code/modules/research/designs/nanite_designs.dm +++ b/code/modules/research/designs/nanite_designs.dm @@ -445,21 +445,21 @@ name = "Skull Echo" desc = "The nanites echo a synthesized message inside the host's skull." id = "voice_nanites" - program_type = /datum/nanite_program/triggered/voice + program_type = /datum/nanite_program/triggered/comm/voice category = list("Suppression Nanites") /datum/design/nanites/speech name = "Forced Speech" desc = "The nanites force the host to say a pre-programmed sentence when triggered." id = "speech_nanites" - program_type = /datum/nanite_program/triggered/speech + program_type = /datum/nanite_program/triggered/comm/speech category = list("Suppression Nanites") /datum/design/nanites/hallucination name = "Hallucination" desc = "The nanites make the host see and hear things that aren't real." id = "hallucination_nanites" - program_type = /datum/nanite_program/triggered/hallucination + program_type = /datum/nanite_program/triggered/comm/hallucination category = list("Suppression Nanites") ////////////////////SENSOR NANITES////////////////////////////////////// diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm index a6225fd337..300f54ba11 100644 --- a/code/modules/research/nanites/nanite_programs/suppression.dm +++ b/code/modules/research/nanites/nanite_programs/suppression.dm @@ -114,7 +114,19 @@ . = ..() host_mob.cure_fakedeath("nanites") -/datum/nanite_program/triggered/speech +//Can receive transmissions from a nanite communication remote for customized messages +/datum/nanite_program/triggered/comm + var/comm_code = 0 + var/comm_message = "" + +/datum/nanite_program/triggered/comm/proc/receive_comm_signal(signal_comm_code, comm_message, comm_source) + if(!activated || !comm_code) + return + if(signal_comm_code == comm_code) + host_mob.investigate_log("'s [name] nanite program was messaged by [comm_source] with comm code [signal_comm_code] and message '[comm_message]'.", INVESTIGATE_NANITES) + trigger(comm_message) + +/datum/nanite_program/triggered/comm/speech name = "Forced Speech" desc = "The nanites force the host to say a pre-programmed sentence when triggered." unique = FALSE @@ -122,10 +134,10 @@ trigger_cooldown = 20 rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay) - extra_settings = list("Sentence") + extra_settings = list("Sentence","Comm Code") var/sentence = "" -/datum/nanite_program/triggered/speech/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/speech/set_extra_setting(user, setting) if(setting == "Sentence") var/new_sentence = stripped_input(user, "Choose the sentence that the host will be forced to say.", "Sentence", sentence, MAX_MESSAGE_LEN) if(!new_sentence) @@ -133,23 +145,34 @@ if(copytext(new_sentence, 1, 2) == "*") //emotes are abusable, like surrender return sentence = new_sentence + if(setting == "Comm Code") + var/new_code = input(user, "Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) -/datum/nanite_program/triggered/speech/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/speech/get_extra_setting(setting) if(setting == "Sentence") return sentence + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/speech/copy_extra_settings_to(datum/nanite_program/triggered/speech/target) +/datum/nanite_program/triggered/comm/speech/copy_extra_settings_to(datum/nanite_program/triggered/comm/speech/target) target.sentence = sentence + target.comm_code = comm_code -/datum/nanite_program/triggered/speech/trigger() +/datum/nanite_program/triggered/comm/speech/trigger(comm_message) if(!..()) return + var/sent_message = comm_message + if(!comm_message) + sent_message = sentence if(host_mob.stat == DEAD) return to_chat(host_mob, "You feel compelled to speak...") - host_mob.say(sentence, forced = "nanite speech") + host_mob.say(sent_message, forced = "nanite speech") -/datum/nanite_program/triggered/voice +/datum/nanite_program/triggered/comm/voice name = "Skull Echo" desc = "The nanites echo a synthesized message inside the host's skull." unique = FALSE @@ -157,44 +180,62 @@ trigger_cooldown = 20 rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay) - extra_settings = list("Message") + extra_settings = list("Message","Comm Code") var/message = "" -/datum/nanite_program/triggered/voice/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/voice/set_extra_setting(user, setting) if(setting == "Message") var/new_message = stripped_input(user, "Choose the message sent to the host.", "Message", message, MAX_MESSAGE_LEN) if(!new_message) return message = new_message + if(setting == "Comm Code") + var/new_code = input(user, "Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) -/datum/nanite_program/triggered/voice/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/voice/get_extra_setting(setting) if(setting == "Message") return message + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/voice/copy_extra_settings_to(datum/nanite_program/triggered/voice/target) +/datum/nanite_program/triggered/comm/voice/copy_extra_settings_to(datum/nanite_program/triggered/comm/voice/target) target.message = message + target.comm_code = comm_code -/datum/nanite_program/triggered/voice/trigger() +/datum/nanite_program/triggered/comm/voice/trigger(comm_message) if(!..()) return + var/sent_message = comm_message + if(!comm_message) + sent_message = message if(host_mob.stat == DEAD) return - to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[message]\"") + to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[sent_message]\"") -/datum/nanite_program/triggered/hallucination +/datum/nanite_program/triggered/comm/hallucination name = "Hallucination" desc = "The nanites make the host hallucinate something when triggered." trigger_cost = 4 trigger_cooldown = 80 unique = FALSE rogue_types = list(/datum/nanite_program/brain_misfire) - extra_settings = list("Hallucination Type") + extra_settings = list("Hallucination Type", "Comm Code") var/hal_type var/hal_details -/datum/nanite_program/triggered/hallucination/trigger() +/datum/nanite_program/triggered/comm/hallucination/trigger(comm_message) if(!..()) return + + if(comm_message && (hal_type != "Message")) //Triggered via comm remote, but not set to a message hallucination + return + var/sent_message = comm_message //Comm remotes can send custom hallucination messages for the chat hallucination + if(!sent_message) + sent_message = hal_details + if(!iscarbon(host_mob)) return var/mob/living/carbon/C = host_mob @@ -203,7 +244,7 @@ else switch(hal_type) if("Message") - new /datum/hallucination/chat(C, TRUE, null, hal_details) + new /datum/hallucination/chat(C, TRUE, null, sent_message) if("Battle") new /datum/hallucination/battle(C, TRUE, hal_details) if("Sound") @@ -223,7 +264,13 @@ if("Plasma Flood") new /datum/hallucination/fake_flood(C, TRUE) -/datum/nanite_program/triggered/hallucination/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/hallucination/set_extra_setting(user, setting) + if(setting == "Comm Code") + var/new_code = input(user, "(Only for Message) Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) + if(setting == "Hallucination Type") var/list/possible_hallucinations = list("Random","Message","Battle","Sound","Weird Sound","Station Message","Health","Alert","Fire","Shock","Plasma Flood") var/hal_type_choice = input("Choose the hallucination type", name) as null|anything in possible_hallucinations @@ -299,13 +346,16 @@ if("Plasma Flood") hal_type = "Plasma Flood" -/datum/nanite_program/triggered/hallucination/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/hallucination/get_extra_setting(setting) if(setting == "Hallucination Type") if(!hal_type) return "Random" else return hal_type + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/hallucination/copy_extra_settings_to(datum/nanite_program/triggered/hallucination/target) +/datum/nanite_program/triggered/comm/hallucination/copy_extra_settings_to(datum/nanite_program/triggered/comm/hallucination/target) target.hal_type = hal_type - target.hal_details = hal_details \ No newline at end of file + target.hal_details = hal_details + target.comm_code = comm_code \ No newline at end of file diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index 3db482d989..3e3ff52f47 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -197,6 +197,15 @@ return SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, code, source) +/datum/nanite_program/relay/proc/relay_comm_signal(comm_code, relay_code, comm_message) + if(!activated) + return + if(!host_mob) + return + if(relay_code != relay_channel) + return + SEND_SIGNAL(host_mob, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message) + /datum/nanite_program/metabolic_synthesis name = "Metabolic Synthesis" desc = "The nanites use the metabolic cycle of the host to speed up their replication rate, using their extra nutrition as fuel." diff --git a/code/modules/research/nanites/nanite_remote.dm b/code/modules/research/nanites/nanite_remote.dm index a7c8533521..e10d8f8c4b 100644 --- a/code/modules/research/nanites/nanite_remote.dm +++ b/code/modules/research/nanites/nanite_remote.dm @@ -168,6 +168,109 @@ . = TRUE +/obj/item/nanite_remote/comm + name = "nanite communication remote" + desc = "A device that can send text messages to specific programs." + icon_state = "nanite_comm_remote" + var/comm_code = 0 + var/comm_message = "" + +/obj/item/nanite_remote/comm/afterattack(atom/target, mob/user, etc) + switch(mode) + if(REMOTE_MODE_OFF) + return + if(REMOTE_MODE_SELF) + to_chat(user, "You activate [src], signaling the nanites in your bloodstream.") + signal_mob(user, comm_code, comm_message) + if(REMOTE_MODE_TARGET) + if(isliving(target) && (get_dist(target, get_turf(src)) <= 7)) + to_chat(user, "You activate [src], signaling the nanites inside [target].") + signal_mob(target, code, comm_message, key_name(user)) + if(REMOTE_MODE_AOE) + to_chat(user, "You activate [src], signaling the nanites inside every host around you.") + for(var/mob/living/L in view(user, 7)) + signal_mob(L, code, comm_message, key_name(user)) + if(REMOTE_MODE_RELAY) + to_chat(user, "You activate [src], signaling all connected relay nanites.") + signal_relay(code, relay_code, comm_message, key_name(user)) + +/obj/item/nanite_remote/comm/signal_mob(mob/living/M, code, source) + SEND_SIGNAL(M, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message) + +/obj/item/nanite_remote/comm/signal_relay(code, relay_code, source) + for(var/X in SSnanites.nanite_relays) + var/datum/nanite_program/relay/N = X + N.relay_comm_signal(comm_code, relay_code, comm_message) + +/obj/item/nanite_remote/comm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) + SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "nanite_comm_remote", name, 420, 800, master_ui, state) + ui.open() + +/obj/item/nanite_remote/comm/ui_data() + var/list/data = list() + data["comm_code"] = comm_code + data["relay_code"] = relay_code + data["comm_message"] = comm_message + data["mode"] = mode + data["locked"] = locked + data["saved_settings"] = saved_settings + + return data + +/obj/item/nanite_remote/comm/ui_act(action, params) + if(..()) + return + switch(action) + if("set_comm_code") + if(locked) + return + var/new_code = input("Set comm code (0000-9999):", name, code) as null|num + if(!isnull(new_code)) + new_code = CLAMP(round(new_code, 1),0,9999) + comm_code = new_code + . = TRUE + if("set_message") + if(locked) + return + var/new_message = stripped_input(usr, "Set the message (Max 300 characters):", "Set Message", null , 300) + if(!new_message) + return + comm_message = new_message + . = TRUE + if("comm_save") + if(locked) + return + var/code_name = stripped_input(usr, "Set the setting name", "Set Name", null , 15) + if(!code_name) + return + var/new_save = list() + new_save["id"] = last_id + 1 + last_id++ + new_save["name"] = code_name + new_save["code"] = comm_code + new_save["mode"] = mode + new_save["relay_code"] = relay_code + new_save["message"] = comm_message + + saved_settings += list(new_save) + . = TRUE + if("comm_load") + var/code_id = params["save_id"] + var/list/setting + for(var/list/X in saved_settings) + if(X["id"] == text2num(code_id)) + setting = X + break + if(setting) + comm_code = setting["code"] + mode = setting["mode"] + relay_code = setting["relay_code"] + comm_message = setting["message"] + . = TRUE + + #undef REMOTE_MODE_OFF #undef REMOTE_MODE_SELF #undef REMOTE_MODE_TARGET diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index af4148d194..ee065eb21f 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1,1137 +1,1137 @@ - -//Current rate: 132500 research points in 90 minutes - -//Base Nodes -/datum/techweb_node/base - id = "base" - starting_node = TRUE - display_name = "Basic Research Technology" - description = "NT default research technologies." - // Default research tech, prevents bricking - design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", - "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", - "space_heater", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal", - "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass") - -/datum/techweb_node/mmi - id = "mmi" - starting_node = TRUE - display_name = "Man Machine Interface" - description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs." - design_ids = list("mmi") - -/datum/techweb_node/cyborg - id = "cyborg" - starting_node = TRUE - display_name = "Cyborg Construction" - description = "Sapient robots with preloaded tool modules and programmable laws." - design_ids = list("robocontrol", "sflash", "borg_suit", "borg_head", "borg_chest", "borg_r_arm", "borg_l_arm", "borg_r_leg", "borg_l_leg", "borgupload", - "cyborgrecharger", "borg_upgrade_restart", "borg_upgrade_rename") - -/datum/techweb_node/mech - id = "mecha" - starting_node = TRUE - display_name = "Mechanical Exosuits" - description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." - design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg", - "ripley_main", "ripley_peri", "mech_hydraulic_clamp") - -/datum/techweb_node/mech_tools - id = "mech_tools" - starting_node = TRUE - display_name = "Basic Exosuit Equipment" - description = "Various tools fit for basic mech units" - design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") - -/datum/techweb_node/surplus_lims - id = "surplus_lims" - display_name = "Basic Prosthetics" - description = "Basic fragile lims for the impaired." - starting_node = TRUE - prereq_ids = list("biotech") - design_ids = list("basic_l_arm", "basic_r_arm", "basic_r_leg", "basic_l_leg") - -/datum/techweb_node/blueprinted_bottles - id = "blueprinted_bottles" - display_name = "License Bottling" - description = "Some Branded bottles to print and export." - starting_node = TRUE - design_ids = list("gin", "wine", "whiskey", "vodka", "tequila", "patron", "rum", "kahlua", "vermouth", "goldschlager", "hcider", "cognac", "absinthe", "grappa", "sake", "fernet", "applejack", "champagne", "blazaam", "trappist", "grenadine", "autobottler") - -/datum/techweb_node/blueprinted_exports - id = "blueprinted_exports" - display_name = "License Exports" - description = "Some Branded bottles to print and export." - starting_node = TRUE - design_ids = list("gin_export", "wine_export", "whiskey_export", "vodka_export", "tequila_export", "patron_export", "rum_export", "kahlua_export", "vermouth_export", "goldschlager_export", "hcider_export", "cognac_export", "absinthe_export", "grappa_export", "sake_export", "fernet_export", "applejack_export", "champagne_export", "blazaam_export", "trappist_export", "grenadine_export") - -/////////////////////////Biotech///////////////////////// -/datum/techweb_node/biotech - id = "biotech" - display_name = "Biological Technology" - description = "What makes us tick." //the MC, silly! - prereq_ids = list("base") - design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/adv_biotech - id = "adv_biotech" - display_name = "Advanced Biotechnology" - description = "Advanced Biotechnology" - prereq_ids = list("biotech") - design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/bio_process - id = "bio_process" - display_name = "Biological Processing" - description = "From slimes to kitchens." - prereq_ids = list("biotech") - design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave", "reagentgrinder", "dish_drive") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/bottle_exports - id = "bottle_exports" - display_name = "Legal Bottling" - prereq_ids = list("blueprinted_bottles") - description = "New bottles for printing and selling." - design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 250) - -/datum/techweb_node/advance_lims - id = "advance_lims" - display_name = "Upgraded Prosthetics" - description = "Reinforced prosthetics for the impaired." - prereq_ids = list("adv_biotech", "surplus_lims") - design_ids = list("adv_l_arm", "adv_r_arm", "adv_r_leg", "adv_l_leg") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) - export_price = 5000 - -/datum/techweb_node/advance_surgerytools - id = "advance_surgerytools" - display_name = "Advanced Surgery Tools" - description = "Refined and improved redesigns for the run-of-the-mill medical utensils." - prereq_ids = list("adv_biotech", "adv_surgery") - design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/adv_defibrillator_tec - id = "adv_defibrillator_tec" - display_name = "Defibrillator Upgrades" - description = "More ways to bring back the newly dead." - prereq_ids = list("adv_biotech", "exp_surgery", "adv_engi", "adv_power") - design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/////////////////////////Advanced Surgery///////////////////////// -/datum/techweb_node/imp_wt_surgery - id = "imp_wt_surgery" - display_name = "Improved Wound-Tending Surgery" - description = "Who would have known being more gentle with a hemostat decreases patient pain?" - prereq_ids = list("biotech") - design_ids = list("surgery_heal_brute_upgrade","surgery_heal_burn_upgrade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - export_price = 1000 - -/datum/techweb_node/adv_surgery - id = "adv_surgery" - display_name = "Advanced Surgery" - description = "When simple medicine doesn't cut it." - prereq_ids = list("imp_wt_surgery") - design_ids = list("surgery_revival", "surgery_lobotomy", "surgery_heal_brute_upgrade_femto","surgery_heal_burn_upgrade_femto", "surgery_heal_combo", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/exp_surgery - id = "exp_surgery" - display_name = "Experimental Surgery" - description = "When evolution isn't fast enough." - prereq_ids = list("adv_surgery") - design_ids = list("surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection", "surgery_heal_combo_upgrade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -/datum/techweb_node/alien_surgery - id = "alien_surgery" - display_name = "Alien Surgery" - description = "Abductors did nothing wrong." - prereq_ids = list("exp_surgery", "alientech") - design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection", "surgery_heal_combo_upgrade_femto") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - export_price = 5000 - -/////////////////////////data theory tech///////////////////////// -/datum/techweb_node/datatheory //Computer science - id = "datatheory" - display_name = "Data Theory" - description = "Big Data, in space!" - prereq_ids = list("base") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/adv_datatheory - id = "adv_datatheory" - display_name = "Advanced Data Theory" - description = "Better insight into programming and data." - prereq_ids = list("datatheory") - design_ids = list("icprinter", "icupgadv", "icupgclo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/////////////////////////engineering tech///////////////////////// -/datum/techweb_node/engineering - id = "engineering" - display_name = "Industrial Engineering" - description = "A refresher course on modern engineering technology." - prereq_ids = list("base") - design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", - "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", - "apc_control", "cell_charger", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000) - export_price = 5000 - -/datum/techweb_node/adv_engi - id = "adv_engi" - display_name = "Advanced Engineering" - description = "Pushing the boundaries of physics, one chainsaw-fist at a time." - prereq_ids = list("engineering", "emp_basic") - design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - export_price = 5000 - -/datum/techweb_node/anomaly - id = "anomaly_research" - display_name = "Anomaly Research" - description = "Unlock the potential of the mysterious anomalies that appear on station." - prereq_ids = list("adv_engi", "practical_bluespace") - design_ids = list("reactive_armour", "anomaly_neutralizer") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - export_price = 5000 - -/datum/techweb_node/high_efficiency - id = "high_efficiency" - display_name = "High Efficiency Parts" - description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." - prereq_ids = list("engineering", "datatheory") - design_ids = list("pico_mani", "super_matter_bin") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -/datum/techweb_node/adv_power - id = "adv_power" - display_name = "Advanced Power Manipulation" - description = "How to get more zap." - prereq_ids = list("engineering") - design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor", "circulator", "teg") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/datum/techweb_node/basic_meteor_defense - id = "basic_meteor_defense" - display_name = "Meteor Defense Research" - description = "Unlock the potential of the mysterious of why CC decided to not build these around the station themselves." - prereq_ids = list("adv_engi", "high_efficiency") - design_ids = list("meteor_defence", "meteor_console") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -//datum/techweb_node/adv_meteor_defense - //id = "adv_meteor_defense" - //display_name = "Meteor Defense Research" - //description = "New and improved coding and lock on tech for meteor defence!" - //prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") - //design_ids = list("meteor_disk") - //research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - //export_price = 5000 - -/datum/techweb_node/computer_board_gaming - id = "computer_board_gaming" - display_name = "Games and Toys" - description = "For the slackers on the station." - prereq_ids = list("comptech") - design_ids = list("arcade_battle", "arcade_orion", "slotmachine", "autoylathe") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - export_price = 5000 - -/////////////////////////Bluespace tech///////////////////////// -/datum/techweb_node/bluespace_basic //Bluespace-memery - id = "bluespace_basic" - display_name = "Basic Bluespace Theory" - description = "Basic studies into the mysterious alternate dimension known as bluespace." - prereq_ids = list("base", "datatheory") - design_ids = list("beacon", "xenobioconsole", "telesci_gps", "xenobio_monkeys") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/practical_bluespace - id = "practical_bluespace" - display_name = "Applied Bluespace Research" - description = "Using bluespace to make things faster and better." - prereq_ids = list("bluespace_basic", "engineering") - design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -/datum/techweb_node/adv_bluespace - id = "adv_bluespace" - display_name = "Advanced Bluespace Research" - description = "Deeper understanding of how the Bluespace dimension works" - prereq_ids = list("practical_bluespace", "high_efficiency") - design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - export_price = 5000 - -/datum/techweb_node/bluespace_power - id = "bluespace_power" - display_name = "Bluespace Power Technology" - description = "Even more powerful.. power!" - prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("bluespace_cell", "quadratic_capacitor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/bluespace_holding - id = "bluespace_holding" - display_name = "Bluespace Pockets" - description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality." - prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma") - design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500) - export_price = 5000 - -/datum/techweb_node/bluespace_portal - id = "bluespace_portal" - display_name = "Bluespace Portals" - description = "Allows for Bluespace Tech to be used tandem with Wormhole tech." - prereq_ids = list("adv_weaponry", "adv_bluespace") - design_ids = list("wormholeprojector") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/bluespace_warping - id = "bluespace_warping" - display_name = "Bluespace Travel" - description = "Application of Bluespace for static teleportation technology." - prereq_ids = list("adv_power", "adv_bluespace") - design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/unregulated_bluespace - id = "unregulated_bluespace" - display_name = "Unregulated Bluespace Research" - description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." - prereq_ids = list("bluespace_warping", "syndicate_basic") - design_ids = list("desynchronizer") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 2500 - -/////////////////////////plasma tech///////////////////////// -/datum/techweb_node/basic_plasma - id = "basic_plasma" - display_name = "Basic Plasma Research" - description = "Research into the mysterious and dangerous substance, plasma." - prereq_ids = list("engineering") - design_ids = list("mech_generator") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/adv_plasma - id = "adv_plasma" - display_name = "Advanced Plasma Research" - description = "Research on how to fully exploit the power of plasma." - prereq_ids = list("basic_plasma") - design_ids = list("mech_plasma_cutter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/////////////////////////robotics tech///////////////////////// -/datum/techweb_node/robotics - id = "robotics" - display_name = "Basic Robotics Research" - description = "Programmable machines that make our lives lazier." - prereq_ids = list("base") - design_ids = list("paicard", "drone_shell") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/adv_robotics - id = "adv_robotics" - display_name = "Advanced Robotics Research" - description = "It can even do the dishes!" - prereq_ids = list("robotics") - design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/datum/techweb_node/neural_programming - id = "neural_programming" - display_name = "Neural Programming" - description = "Study into networks of processing units that mimic our brains." - prereq_ids = list("biotech", "datatheory") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/posibrain - id = "posibrain" - display_name = "Positronic Brain" - description = "Applied usage of neural technology allowing for autonomous AI units based on special metallic cubes with conductive and processing circuits." - prereq_ids = list("neural_programming") - design_ids = list("mmi_posi") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/cyborg_upg_util - id = "cyborg_upg_util" - display_name = "Cyborg Upgrades: Utility" - description = "Utility upgrades for cyborgs." - prereq_ids = list("engineering", "robotics") - design_ids = list("borg_upgrade_holding", "borg_upgrade_lavaproof", "borg_upgrade_thrusters", "borg_upgrade_selfrepair", "borg_upgrade_expand", "borg_upgrade_rped") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/cyborg_upg_med - id = "cyborg_upg_med" - display_name = "Cyborg Upgrades: Medical" - description = "Medical upgrades for cyborgs." - prereq_ids = list("adv_biotech", "robotics") - design_ids = list("borg_upgrade_advhealth", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser", "borg_upgrade_pinpointer", "borg_upgrade_surgicalprocessor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/cyborg_upg_combat - id = "cyborg_upg_combat" - display_name = "Cyborg Upgrades: Combat" - description = "Military grade upgrades for cyborgs." - prereq_ids = list("adv_robotics", "adv_engi" , "weaponry") - design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -/datum/techweb_node/ai - id = "ai" - display_name = "Artificial Intelligence" - description = "AI unit research." - prereq_ids = list("robotics", "posibrain") - design_ids = list("aifixer", "aicore", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", - "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "paladin_module", "tyrant_module", "corporate_module", - "default_module", "borg_ai_control", "mecha_tracking_ai_control", "aiupload", "intellicard") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/////////////////////////EMP tech///////////////////////// -/datum/techweb_node/emp_basic //EMP tech for some reason - id = "emp_basic" - display_name = "Electromagnetic Theory" - description = "Study into usage of frequencies in the electromagnetic spectrum." - prereq_ids = list("base") - design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "inducer", "tray_goggles", "holopad") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/emp_adv - id = "emp_adv" - display_name = "Advanced Electromagnetic Theory" - description = "Determining whether reversing the polarity will actually help in a given situation." - prereq_ids = list("emp_basic") - design_ids = list("ultra_micro_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/datum/techweb_node/emp_super - id = "emp_super" - display_name = "Quantum Electromagnetic Technology" //bs - description = "Even better electromagnetic technology." - prereq_ids = list("emp_adv") - design_ids = list("quadultra_micro_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/////////////////////////Clown tech///////////////////////// -/datum/techweb_node/clown - id = "clown" - display_name = "Clown Technology" - description = "Honk?!" - prereq_ids = list("base") - design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", - "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone", "borg_transform_clown") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -////////////////////////Computer tech//////////////////////// -/datum/techweb_node/comptech - id = "comptech" - display_name = "Computer Consoles" - description = "Computers and how they work." - prereq_ids = list("datatheory") - design_ids = list("cargo", "cargorequest", "libraryconsole", "mining", "miningshuttle", "crewconsole", "rdcamera", "comconsole", "idcardconsole", "seccamera") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. - id = "computer_hardware_basic" - display_name = "Computer Hardware" - description = "How computer hardware are made." - prereq_ids = list("comptech") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) //they are really kinda shitty - export_price = 2000 - design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", - "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", - "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") - -/datum/techweb_node/comp_recordkeeping - id = "comp_recordkeeping" - display_name = "Computerized Recordkeeping" - description = "Organized record databases and how they're used." - prereq_ids = list("comptech") - design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) - export_price = 2000 - -/datum/techweb_node/telecomms - id = "telecomms" - display_name = "Telecommunications Technology" - description = "Subspace transmission technology for near-instant communications devices." - prereq_ids = list("comptech", "bluespace_basic") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - export_price = 5000 - design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", - "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter", "message_monitor") - -/datum/techweb_node/integrated_HUDs - id = "integrated_HUDs" - display_name = "Integrated HUDs" - description = "The usefulness of computerized records, projected straight onto your eyepiece!" - prereq_ids = list("comp_recordkeeping", "emp_basic") - design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles", "health_hud_prescription", "security_hud_prescription", "diagnostic_hud_prescription") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - export_price = 5000 - -/datum/techweb_node/NVGtech - id = "NVGtech" - display_name = "Night Vision Technology" - description = "Allows seeing in the dark without actual light!" - prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") - design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons", "night_visision_goggles_glasses") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 5000 - -////////////////////////Medical//////////////////////// -/datum/techweb_node/cloning - id = "cloning" - display_name = "Genetic Engineering" - description = "We have the technology to make him." - prereq_ids = list("biotech") - design_ids = list("clonecontrol", "clonepod", "clonescanner", "scan_console", "cloning_disk") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/cryotech - id = "cryotech" - display_name = "Cryostasis Technology" - description = "Smart freezing of objects to preserve them!" - prereq_ids = list("adv_engi", "biotech") - design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 4000 - -/datum/techweb_node/subdermal_implants - id = "subdermal_implants" - display_name = "Subdermal Implants" - description = "Electronic implants buried beneath the skin." - prereq_ids = list("biotech", "datatheory") - design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator", "c38_trac") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/cyber_organs - id = "cyber_organs" - display_name = "Cybernetic Organs" - description = "We have the technology to rebuild him." - prereq_ids = list("adv_biotech") - design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - export_price = 5000 - -/datum/techweb_node/cyber_organs_upgraded - id = "cyber_organs_upgraded" - display_name = "Upgraded Cybernetic Organs" - description = "We have the technology to upgrade him." - prereq_ids = list("cyber_organs") - design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - export_price = 5000 - -/datum/techweb_node/cyber_implants - id = "cyber_implants" - display_name = "Cybernetic Implants" - description = "Electronic implants that improve humans." - prereq_ids = list("adv_biotech", "adv_datatheory") - design_ids = list("ci-nutriment", "ci-breather", "ci-gloweyes", "ci-welding", "ci-medhud", "ci-sechud") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/adv_cyber_implants - id = "adv_cyber_implants" - display_name = "Advanced Cybernetic Implants" - description = "Upgraded and more powerful cybernetic implants." - prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") - design_ids = list("ci-toolset", "ci-surgery", "ci-reviver", "ci-nutrimentplus") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/combat_cyber_implants - id = "combat_cyber_implants" - display_name = "Combat Cybernetic Implants" - description = "Military grade combat implants to improve performance." - prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") - design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -////////////////////////Tools//////////////////////// -/datum/techweb_node/basic_mining - id = "basic_mining" - display_name = "Mining Technology" - description = "Better than Efficiency V." - prereq_ids = list("engineering", "basic_plasma") - design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter")//e a r l y g a m e) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/adv_mining - id = "adv_mining" - display_name = "Advanced Mining Technology" - description = "Efficiency Level 127" //dumb mc references - prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma") - design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/janitor - id = "janitor" - display_name = "Advanced Sanitation Technology" - description = "Clean things better, faster, stronger, and harder!" - prereq_ids = list("adv_engi") - design_ids = list("advmop", "buffer", "light_replacer") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1750) // No longer has its bag - export_price = 5000 - -/datum/techweb_node/botany - id = "botany" - display_name = "Botanical Engineering" - description = "Botanical tools." - prereq_ids = list("adv_engi", "biotech") - design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - export_price = 5000 - -/datum/techweb_node/exp_tools - id = "exp_tools" - display_name = "Experimental Tools" - description = "Highly advanced construction tools." - design_ids = list("exwelder", "jawsoflife", "handdrill") - prereq_ids = list("adv_engi") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - export_price = 5000 - -/////////////////////////weaponry tech///////////////////////// -/datum/techweb_node/weaponry - id = "weaponry" - display_name = "Weapon Development Technology" - description = "Our researchers have found new to weaponize just about everything now." - prereq_ids = list("engineering") - design_ids = list("pin_testing", "tele_shield", "lasercarbine") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - export_price = 5000 - -/datum/techweb_node/adv_weaponry - id = "adv_weaponry" - display_name = "Advanced Weapon Development Technology" - description = "Our weapons are breaking the rules of reality by now." - prereq_ids = list("adv_engi", "weaponry") - design_ids = list("pin_loyalty") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - export_price = 5000 - -/datum/techweb_node/electric_weapons - id = "electronic_weapons" - display_name = "Electric Weapons" - description = "Weapons using electric technology" - prereq_ids = list("weaponry", "adv_power" , "emp_basic") - design_ids = list("stunrevolver", "stunshell", "ioncarbine") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - export_price = 5000 - -/datum/techweb_node/radioactive_weapons - id = "radioactive_weapons" - display_name = "Radioactive Weaponry" - description = "Weapons using radioactive technology." - prereq_ids = list("adv_engi", "adv_weaponry") - design_ids = list("nuclear_gun") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/medical_weapons - id = "medical_weapons" - display_name = "Medical Weaponry" - description = "Weapons using medical technology." - prereq_ids = list("adv_biotech", "adv_weaponry") - design_ids = list("rapidsyringe", "shotgundartcryostatis") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/beam_weapons - id = "beam_weapons" - display_name = "Beam Weaponry" - description = "Various basic beam weapons" - prereq_ids = list("adv_weaponry") - design_ids = list("temp_gun", "xray_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/adv_beam_weapons - id = "adv_beam_weapons" - display_name = "Advanced Beam Weaponry" - description = "Various advanced beam weapons" - prereq_ids = list("beam_weapons") - design_ids = list("beamrifle") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3250) // Sniper - export_price = 5000 - -/datum/techweb_node/explosive_weapons - id = "explosive_weapons" - display_name = "Explosive & Pyrotechnical Weaponry" - description = "If the light stuff just won't do it." - prereq_ids = list("adv_weaponry") - design_ids = list("large_Grenade", "pyro_Grenade", "adv_Grenade") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - export_price = 5000 - -/datum/techweb_node/ballistic_weapons - id = "ballistic_weapons" - display_name = "Ballistic Weaponry" - description = "This isn't research.. This is reverse-engineering!" - prereq_ids = list("weaponry") - design_ids = list("mag_oldsmg", "mag_oldsmg_ap", "mag_oldsmg_ic", "mag_oldsmg_rubber", "mag_oldsmg_tx") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - export_price = 5000 - -/datum/techweb_node/exotic_ammo - id = "exotic_ammo" - display_name = "Exotic Ammunition" - description = "They won't know what hit em." - prereq_ids = list("weaponry", "ballistic_weapons") - design_ids = list("techshotshell", "c38_hotshot", "c38_iceblox") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - export_price = 5000 - -/datum/techweb_node/gravity_gun - id = "gravity_gun" - display_name = "One-point Bluespace-gravitational Manipulator" - description = "Fancy wording for gravity gun." - prereq_ids = list("adv_weaponry", "adv_bluespace") - design_ids = list("gravitygun", "mech_gravcatapult") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -////////////////////////mech technology//////////////////////// -/datum/techweb_node/adv_mecha - id = "adv_mecha" - display_name = "Advanced Exosuits" - description = "For when you just aren't Gundam enough." - prereq_ids = list("adv_robotics") - design_ids = list("mech_repair_droid") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/odysseus - id = "mecha_odysseus" - display_name = "EXOSUIT: Odysseus" - description = "Odysseus exosuit designs" - prereq_ids = list("base") - design_ids = list("odysseus_chassis", "odysseus_torso", "odysseus_head", "odysseus_left_arm", "odysseus_right_arm" ,"odysseus_left_leg", "odysseus_right_leg", - "odysseus_main", "odysseus_peri") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/gygax - id = "mech_gygax" - display_name = "EXOSUIT: Gygax" - description = "Gygax exosuit designs" - prereq_ids = list("adv_mecha", "weaponry") - design_ids = list("gygax_chassis", "gygax_torso", "gygax_head", "gygax_left_arm", "gygax_right_arm", "gygax_left_leg", "gygax_right_leg", "gygax_main", - "gygax_peri", "gygax_targ", "gygax_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/durand - id = "mech_durand" - display_name = "EXOSUIT: Durand" - description = "Durand exosuit designs" - prereq_ids = list("adv_mecha", "adv_weaponry") - design_ids = list("durand_chassis", "durand_torso", "durand_head", "durand_left_arm", "durand_right_arm", "durand_left_leg", "durand_right_leg", "durand_main", - "durand_peri", "durand_targ", "durand_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) - export_price = 5000 - -/datum/techweb_node/phazon - id = "mecha_phazon" - display_name = "EXOSUIT: Phazon" - description = "Phazon exosuit designs" - prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace") - design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main", - "phazon_peri", "phazon_targ", "phazon_armor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - export_price = 5000 - -/datum/techweb_node/adv_mecha_tools - id = "adv_mecha_tools" - display_name = "Advanced Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_mecha") - design_ids = list("mech_rcd") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/med_mech_tools - id = "med_mech_tools" - display_name = "Medical Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_biotech") - design_ids = list("mech_sleeper", "mech_syringe_gun", "mech_medi_beam") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 5000 - -/datum/techweb_node/mech_modules - id = "adv_mecha_modules" - display_name = "Simple Exosuit Modules" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_mecha", "bluespace_power") - design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_scattershot - id = "mecha_tools" - display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_scattershot") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_seedscatter - id = "mech_seedscatter" - display_name = "Exosuit Weapon (Melon Seed \"Scattershot\")" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_seedscatter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_carbine - id = "mech_carbine" - display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_carbine") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_ion - id = "mmech_ion" - display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "emp_adv") - design_ids = list("mech_ion") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_tesla - id = "mech_tesla" - display_name = "Exosuit Weapon (MKI Tesla Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "adv_power") - design_ids = list("mech_tesla") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_laser - id = "mech_laser" - display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)" - description = "A basic piece of mech weaponry" - prereq_ids = list("beam_weapons") - design_ids = list("mech_laser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_laser_heavy - id = "mech_laser_heavy" - display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_beam_weapons") - design_ids = list("mech_laser_heavy") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_grenade_launcher - id = "mech_grenade_launcher" - display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("mech_grenade_launcher") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_missile_rack - id = "mech_missile_rack" - display_name = "Exosuit Weapon (SRM-8 Missile Rack)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("mech_missile_rack") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/clusterbang_launcher - id = "clusterbang_launcher" - display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list("clusterbang_launcher") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_teleporter - id = "mech_teleporter" - display_name = "Exosuit Module (Teleporter Module)" - description = "An advanced piece of mech Equipment" - prereq_ids = list("adv_bluespace") - design_ids = list("mech_teleporter") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_wormhole_gen - id = "mech_wormhole_gen" - display_name = "Exosuit Module (Localized Wormhole Generator)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_bluespace") - design_ids = list("mech_wormhole_gen") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_taser - id = "mech_taser" - display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)" - description = "A basic piece of mech weaponry" - prereq_ids = list("electronic_weapons") - design_ids = list("mech_taser") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_lmg - id = "mech_lmg" - display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("ballistic_weapons") - design_ids = list("mech_lmg") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/mech_diamond_drill - id = "mech_diamond_drill" - display_name = "Exosuit Diamond Drill" - description = "A diamond drill fit for a large exosuit" - prereq_ids = list("adv_mining") - design_ids = list("mech_diamond_drill") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/////////////////////////Nanites///////////////////////// -/datum/techweb_node/nanite_base - id = "nanite_base" - display_name = "Basic Nanite Programming" - description = "The basics of nanite construction and programming." - prereq_ids = list("datatheory","robotics") - design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\ - "nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\ - "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/nanite_smart - id = "nanite_smart" - display_name = "Smart Nanite Programming" - description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets." - prereq_ids = list("nanite_base","adv_robotics") - design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - export_price = 4000 - -/datum/techweb_node/nanite_mesh - id = "nanite_mesh" - display_name = "Mesh Nanite Programming" - description = "Nanite programs that require static structures and membranes." - prereq_ids = list("nanite_base","engineering") - design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/nanite_bio - id = "nanite_bio" - display_name = "Biological Nanite Programming" - description = "Nanite programs that require complex biological interaction." - prereq_ids = list("nanite_base","biotech") - design_ids = list("regenerative_nanites", "bloodheal_nanites", "coagulating_nanites","poison_nanites","flesheating_nanites",\ - "sensor_crit_nanites","sensor_death_nanites", "sensor_health_nanites", "sensor_damage_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/nanite_neural - id = "nanite_neural" - display_name = "Neural Nanite Programming" - description = "Nanite programs affecting nerves and brain matter." - prereq_ids = list("nanite_bio") - design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/nanite_synaptic - id = "nanite_synaptic" - display_name = "Synaptic Nanite Programming" - description = "Nanite programs affecting mind and thoughts." - prereq_ids = list("nanite_neural","neural_programming") - design_ids = list("mindshield_nanites", "pacifying_nanites", "blinding_nanites", "sleep_nanites", "mute_nanites", "speech_nanites","hallucination_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - export_price = 5000 - -/datum/techweb_node/nanite_harmonic - id = "nanite_harmonic" - display_name = "Harmonic Nanite Programming" - description = "Nanite programs that require seamless integration between nanites and biology." - prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh") - design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - export_price = 8000 - -/datum/techweb_node/nanite_combat - id = "nanite_military" - display_name = "Military Nanite Programming" - description = "Nanite programs that perform military-grade functions." - prereq_ids = list("nanite_harmonic", "syndicate_basic") - design_ids = list("explosive_nanites","pyro_nanites","meltdown_nanites","viral_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - export_price = 12500 - -/datum/techweb_node/nanite_hazard - id = "nanite_hazard" - display_name = "Hazard Nanite Programs" - description = "Extremely advanced Nanite programs with the potential of being extremely dangerous." - prereq_ids = list("nanite_harmonic", "alientech") - design_ids = list("spreading_nanites","mindcontrol_nanites","mitosis_nanites") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - export_price = 15000 - -////////////////////////Alien technology//////////////////////// -/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech - id = "alientech" - display_name = "Alien Technology" - description = "Things used by the greys." - prereq_ids = list("biotech","engineering") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 20000 - hidden = TRUE - design_ids = list("alienalloy") - -/datum/techweb_node/alientech/New() - . = ..() - boost_item_paths = typesof(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, - /obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/cautery/alien, - /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, - /obj/item/crowbar/abductor, /obj/item/multitool/abductor, - /obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor, - /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, - /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor) - -/datum/techweb_node/alien_bio - id = "alien_bio" - display_name = "Alien Biological Tools" - description = "Advanced biological tools." - prereq_ids = list("alientech", "advance_surgerytools") - design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery", "ayyplantgenes") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 10000 - -/datum/techweb_node/alien_engi - id = "alien_engi" - display_name = "Alien Engineering" - description = "Alien engineering tools." - prereq_ids = list("alientech", "exp_tools") - design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - export_price = 10000 - -/datum/techweb_node/syndicate_basic - id = "syndicate_basic" - display_name = "Illegal Technology" - description = "Dangerous research used to create dangerous objects." - prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") - design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow", "donksofttoyvendor") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - export_price = 5000 - hidden = TRUE - -/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. - . = ..() - boost_item_paths = list() - for(var/path in GLOB.uplink_items) - var/datum/uplink_item/UI = new path - if(!UI.item || !UI.illegal_tech) - continue - boost_item_paths |= UI.item //allows deconning to unlock. - -/datum/techweb_node/advanced_illegal_ballistics - id = "advanced_illegal_ballistics" - display_name = "Advanced Non-Standard Ballistics" - description = "Ballistic ammunition for non-standard firearms. Usually the ones you don't have nor want to be involved with." - design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","pistolm9mm","m45","bolt_clip") - prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns from traitors, space, or anything in between. - export_price = 7000 - -//Helpers for debugging/balancing the techweb in its entirety! -/proc/total_techweb_exports() - var/list/datum/techweb_node/processing = list() - for(var/i in subtypesof(/datum/techweb_node)) - processing += new i - . = 0 - for(var/i in processing) - var/datum/techweb_node/TN = i - . += TN.export_price - -/proc/total_techweb_points() - var/list/datum/techweb_node/processing = list() - for(var/i in subtypesof(/datum/techweb_node)) - processing += new i - var/datum/techweb/TW = new - TW.research_points = list() - for(var/i in processing) - var/datum/techweb_node/TN = i - TW.add_point_list(TN.research_costs) - return TW.research_points - -/proc/total_techweb_points_printout() - var/list/datum/techweb_node/processing = list() - for(var/i in subtypesof(/datum/techweb_node)) - processing += new i - var/datum/techweb/TW = new - TW.research_points = list() - for(var/i in processing) - var/datum/techweb_node/TN = i - TW.add_point_list(TN.research_costs) - return TW.printout_points() + +//Current rate: 132500 research points in 90 minutes + +//Base Nodes +/datum/techweb_node/base + id = "base" + starting_node = TRUE + display_name = "Basic Research Technology" + description = "NT default research technologies." + // Default research tech, prevents bricking + design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", + "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", + "space_heater", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal", + "rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass") + +/datum/techweb_node/mmi + id = "mmi" + starting_node = TRUE + display_name = "Man Machine Interface" + description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs." + design_ids = list("mmi") + +/datum/techweb_node/cyborg + id = "cyborg" + starting_node = TRUE + display_name = "Cyborg Construction" + description = "Sapient robots with preloaded tool modules and programmable laws." + design_ids = list("robocontrol", "sflash", "borg_suit", "borg_head", "borg_chest", "borg_r_arm", "borg_l_arm", "borg_r_leg", "borg_l_leg", "borgupload", + "cyborgrecharger", "borg_upgrade_restart", "borg_upgrade_rename") + +/datum/techweb_node/mech + id = "mecha" + starting_node = TRUE + display_name = "Mechanical Exosuits" + description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." + design_ids = list("mecha_tracking", "mechacontrol", "mechapower", "mech_recharger", "ripley_chassis", "firefighter_chassis", "ripley_torso", "ripley_left_arm", "ripley_right_arm", "ripley_left_leg", "ripley_right_leg", + "ripley_main", "ripley_peri", "mech_hydraulic_clamp") + +/datum/techweb_node/mech_tools + id = "mech_tools" + starting_node = TRUE + display_name = "Basic Exosuit Equipment" + description = "Various tools fit for basic mech units" + design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer") + +/datum/techweb_node/surplus_lims + id = "surplus_lims" + display_name = "Basic Prosthetics" + description = "Basic fragile lims for the impaired." + starting_node = TRUE + prereq_ids = list("biotech") + design_ids = list("basic_l_arm", "basic_r_arm", "basic_r_leg", "basic_l_leg") + +/datum/techweb_node/blueprinted_bottles + id = "blueprinted_bottles" + display_name = "License Bottling" + description = "Some Branded bottles to print and export." + starting_node = TRUE + design_ids = list("gin", "wine", "whiskey", "vodka", "tequila", "patron", "rum", "kahlua", "vermouth", "goldschlager", "hcider", "cognac", "absinthe", "grappa", "sake", "fernet", "applejack", "champagne", "blazaam", "trappist", "grenadine", "autobottler") + +/datum/techweb_node/blueprinted_exports + id = "blueprinted_exports" + display_name = "License Exports" + description = "Some Branded bottles to print and export." + starting_node = TRUE + design_ids = list("gin_export", "wine_export", "whiskey_export", "vodka_export", "tequila_export", "patron_export", "rum_export", "kahlua_export", "vermouth_export", "goldschlager_export", "hcider_export", "cognac_export", "absinthe_export", "grappa_export", "sake_export", "fernet_export", "applejack_export", "champagne_export", "blazaam_export", "trappist_export", "grenadine_export") + +/////////////////////////Biotech///////////////////////// +/datum/techweb_node/biotech + id = "biotech" + display_name = "Biological Technology" + description = "What makes us tick." //the MC, silly! + prereq_ids = list("base") + design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/adv_biotech + id = "adv_biotech" + display_name = "Advanced Biotechnology" + description = "Advanced Biotechnology" + prereq_ids = list("biotech") + design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "defibrillator", "meta_beaker", "healthanalyzer_advanced","harvester","holobarrier_med","smartdartgun","medicinalsmartdart", "pHmeter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/bio_process + id = "bio_process" + display_name = "Biological Processing" + description = "From slimes to kitchens." + prereq_ids = list("biotech") + design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave", "reagentgrinder", "dish_drive") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/bottle_exports + id = "bottle_exports" + display_name = "Legal Bottling" + prereq_ids = list("blueprinted_bottles") + description = "New bottles for printing and selling." + design_ids = list("minikeg", "blooddrop", "slim_gold", "white_bloodmoon", "greenroad") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 250) + +/datum/techweb_node/advance_lims + id = "advance_lims" + display_name = "Upgraded Prosthetics" + description = "Reinforced prosthetics for the impaired." + prereq_ids = list("adv_biotech", "surplus_lims") + design_ids = list("adv_l_arm", "adv_r_arm", "adv_r_leg", "adv_l_leg") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + export_price = 5000 + +/datum/techweb_node/advance_surgerytools + id = "advance_surgerytools" + display_name = "Advanced Surgery Tools" + description = "Refined and improved redesigns for the run-of-the-mill medical utensils." + prereq_ids = list("adv_biotech", "adv_surgery") + design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/adv_defibrillator_tec + id = "adv_defibrillator_tec" + display_name = "Defibrillator Upgrades" + description = "More ways to bring back the newly dead." + prereq_ids = list("adv_biotech", "exp_surgery", "adv_engi", "adv_power") + design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/////////////////////////Advanced Surgery///////////////////////// +/datum/techweb_node/imp_wt_surgery + id = "imp_wt_surgery" + display_name = "Improved Wound-Tending Surgery" + description = "Who would have known being more gentle with a hemostat decreases patient pain?" + prereq_ids = list("biotech") + design_ids = list("surgery_heal_brute_upgrade","surgery_heal_burn_upgrade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + export_price = 1000 + +/datum/techweb_node/adv_surgery + id = "adv_surgery" + display_name = "Advanced Surgery" + description = "When simple medicine doesn't cut it." + prereq_ids = list("imp_wt_surgery") + design_ids = list("surgery_revival", "surgery_lobotomy", "surgery_heal_brute_upgrade_femto","surgery_heal_burn_upgrade_femto", "surgery_heal_combo", "surgery_toxinhealing", "organbox", "surgery_adv_dissection") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/exp_surgery + id = "exp_surgery" + display_name = "Experimental Surgery" + description = "When evolution isn't fast enough." + prereq_ids = list("adv_surgery") + design_ids = list("surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection", "surgery_heal_combo_upgrade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +/datum/techweb_node/alien_surgery + id = "alien_surgery" + display_name = "Alien Surgery" + description = "Abductors did nothing wrong." + prereq_ids = list("exp_surgery", "alientech") + design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection", "surgery_heal_combo_upgrade_femto") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + export_price = 5000 + +/////////////////////////data theory tech///////////////////////// +/datum/techweb_node/datatheory //Computer science + id = "datatheory" + display_name = "Data Theory" + description = "Big Data, in space!" + prereq_ids = list("base") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/adv_datatheory + id = "adv_datatheory" + display_name = "Advanced Data Theory" + description = "Better insight into programming and data." + prereq_ids = list("datatheory") + design_ids = list("icprinter", "icupgadv", "icupgclo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/////////////////////////engineering tech///////////////////////// +/datum/techweb_node/engineering + id = "engineering" + display_name = "Industrial Engineering" + description = "A refresher course on modern engineering technology." + prereq_ids = list("base") + design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin", + "atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod", + "apc_control", "cell_charger", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6000) + export_price = 5000 + +/datum/techweb_node/adv_engi + id = "adv_engi" + display_name = "Advanced Engineering" + description = "Pushing the boundaries of physics, one chainsaw-fist at a time." + prereq_ids = list("engineering", "emp_basic") + design_ids = list("engine_goggles", "magboots", "forcefield_projector", "weldingmask", "tray_goggles_prescription", "engine_goggles_prescription", "mesons_prescription", "rcd_upgrade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) + export_price = 5000 + +/datum/techweb_node/anomaly + id = "anomaly_research" + display_name = "Anomaly Research" + description = "Unlock the potential of the mysterious anomalies that appear on station." + prereq_ids = list("adv_engi", "practical_bluespace") + design_ids = list("reactive_armour", "anomaly_neutralizer") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + export_price = 5000 + +/datum/techweb_node/high_efficiency + id = "high_efficiency" + display_name = "High Efficiency Parts" + description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." + prereq_ids = list("engineering", "datatheory") + design_ids = list("pico_mani", "super_matter_bin") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +/datum/techweb_node/adv_power + id = "adv_power" + display_name = "Advanced Power Manipulation" + description = "How to get more zap." + prereq_ids = list("engineering") + design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor", "circulator", "teg") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/datum/techweb_node/basic_meteor_defense + id = "basic_meteor_defense" + display_name = "Meteor Defense Research" + description = "Unlock the potential of the mysterious of why CC decided to not build these around the station themselves." + prereq_ids = list("adv_engi", "high_efficiency") + design_ids = list("meteor_defence", "meteor_console") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +//datum/techweb_node/adv_meteor_defense + //id = "adv_meteor_defense" + //display_name = "Meteor Defense Research" + //description = "New and improved coding and lock on tech for meteor defence!" + //prereq_ids = list("basic_meteor_defense", "adv_datatheory", "emp_adv") + //design_ids = list("meteor_disk") + //research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + //export_price = 5000 + +/datum/techweb_node/computer_board_gaming + id = "computer_board_gaming" + display_name = "Games and Toys" + description = "For the slackers on the station." + prereq_ids = list("comptech") + design_ids = list("arcade_battle", "arcade_orion", "slotmachine", "autoylathe") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + export_price = 5000 + +/////////////////////////Bluespace tech///////////////////////// +/datum/techweb_node/bluespace_basic //Bluespace-memery + id = "bluespace_basic" + display_name = "Basic Bluespace Theory" + description = "Basic studies into the mysterious alternate dimension known as bluespace." + prereq_ids = list("base", "datatheory") + design_ids = list("beacon", "xenobioconsole", "telesci_gps", "xenobio_monkeys") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/practical_bluespace + id = "practical_bluespace" + display_name = "Applied Bluespace Research" + description = "Using bluespace to make things faster and better." + prereq_ids = list("bluespace_basic", "engineering") + design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +/datum/techweb_node/adv_bluespace + id = "adv_bluespace" + display_name = "Advanced Bluespace Research" + description = "Deeper understanding of how the Bluespace dimension works" + prereq_ids = list("practical_bluespace", "high_efficiency") + design_ids = list("bluespace_matter_bin", "femto_mani", "triphasic_scanning", "bluespace_crystal", "xenobio_slimeadv") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + export_price = 5000 + +/datum/techweb_node/bluespace_power + id = "bluespace_power" + display_name = "Bluespace Power Technology" + description = "Even more powerful.. power!" + prereq_ids = list("adv_power", "adv_bluespace") + design_ids = list("bluespace_cell", "quadratic_capacitor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/bluespace_holding + id = "bluespace_holding" + display_name = "Bluespace Pockets" + description = "Studies into the mysterious alternate dimension known as bluespace and how to place items in the threads of reality." + prereq_ids = list("adv_power", "adv_bluespace", "adv_biotech", "adv_plasma") + design_ids = list( "bluespacebodybag","bag_holding", "bluespace_pod", "borg_upgrade_trashofholding", "blutrash", "satchel_holding", "bsblood_bag") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5500) + export_price = 5000 + +/datum/techweb_node/bluespace_portal + id = "bluespace_portal" + display_name = "Bluespace Portals" + description = "Allows for Bluespace Tech to be used tandem with Wormhole tech." + prereq_ids = list("adv_weaponry", "adv_bluespace") + design_ids = list("wormholeprojector") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/bluespace_warping + id = "bluespace_warping" + display_name = "Bluespace Travel" + description = "Application of Bluespace for static teleportation technology." + prereq_ids = list("adv_power", "adv_bluespace") + design_ids = list("tele_station", "tele_hub", "quantumpad", "quantum_keycard", "launchpad", "launchpad_console", "teleconsole", "roastingstick") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/unregulated_bluespace + id = "unregulated_bluespace" + display_name = "Unregulated Bluespace Research" + description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." + prereq_ids = list("bluespace_warping", "syndicate_basic") + design_ids = list("desynchronizer") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 2500 + +/////////////////////////plasma tech///////////////////////// +/datum/techweb_node/basic_plasma + id = "basic_plasma" + display_name = "Basic Plasma Research" + description = "Research into the mysterious and dangerous substance, plasma." + prereq_ids = list("engineering") + design_ids = list("mech_generator") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/adv_plasma + id = "adv_plasma" + display_name = "Advanced Plasma Research" + description = "Research on how to fully exploit the power of plasma." + prereq_ids = list("basic_plasma") + design_ids = list("mech_plasma_cutter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/////////////////////////robotics tech///////////////////////// +/datum/techweb_node/robotics + id = "robotics" + display_name = "Basic Robotics Research" + description = "Programmable machines that make our lives lazier." + prereq_ids = list("base") + design_ids = list("paicard", "drone_shell") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/adv_robotics + id = "adv_robotics" + display_name = "Advanced Robotics Research" + description = "It can even do the dishes!" + prereq_ids = list("robotics") + design_ids = list("borg_upgrade_diamonddrill", "borg_upgrade_advancedmop") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/datum/techweb_node/neural_programming + id = "neural_programming" + display_name = "Neural Programming" + description = "Study into networks of processing units that mimic our brains." + prereq_ids = list("biotech", "datatheory") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/posibrain + id = "posibrain" + display_name = "Positronic Brain" + description = "Applied usage of neural technology allowing for autonomous AI units based on special metallic cubes with conductive and processing circuits." + prereq_ids = list("neural_programming") + design_ids = list("mmi_posi") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/cyborg_upg_util + id = "cyborg_upg_util" + display_name = "Cyborg Upgrades: Utility" + description = "Utility upgrades for cyborgs." + prereq_ids = list("engineering", "robotics") + design_ids = list("borg_upgrade_holding", "borg_upgrade_lavaproof", "borg_upgrade_thrusters", "borg_upgrade_selfrepair", "borg_upgrade_expand", "borg_upgrade_rped") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/cyborg_upg_med + id = "cyborg_upg_med" + display_name = "Cyborg Upgrades: Medical" + description = "Medical upgrades for cyborgs." + prereq_ids = list("adv_biotech", "robotics") + design_ids = list("borg_upgrade_advhealth", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser", "borg_upgrade_pinpointer", "borg_upgrade_surgicalprocessor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/cyborg_upg_combat + id = "cyborg_upg_combat" + display_name = "Cyborg Upgrades: Combat" + description = "Military grade upgrades for cyborgs." + prereq_ids = list("adv_robotics", "adv_engi" , "weaponry") + design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +/datum/techweb_node/ai + id = "ai" + display_name = "Artificial Intelligence" + description = "AI unit research." + prereq_ids = list("robotics", "posibrain") + design_ids = list("aifixer", "aicore", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", + "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "paladin_module", "tyrant_module", "corporate_module", + "default_module", "borg_ai_control", "mecha_tracking_ai_control", "aiupload", "intellicard") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/////////////////////////EMP tech///////////////////////// +/datum/techweb_node/emp_basic //EMP tech for some reason + id = "emp_basic" + display_name = "Electromagnetic Theory" + description = "Study into usage of frequencies in the electromagnetic spectrum." + prereq_ids = list("base") + design_ids = list("holosign", "holosignsec", "holosignengi", "holosignatmos", "inducer", "tray_goggles", "holopad") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/emp_adv + id = "emp_adv" + display_name = "Advanced Electromagnetic Theory" + description = "Determining whether reversing the polarity will actually help in a given situation." + prereq_ids = list("emp_basic") + design_ids = list("ultra_micro_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/datum/techweb_node/emp_super + id = "emp_super" + display_name = "Quantum Electromagnetic Technology" //bs + description = "Even better electromagnetic technology." + prereq_ids = list("emp_adv") + design_ids = list("quadultra_micro_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/////////////////////////Clown tech///////////////////////// +/datum/techweb_node/clown + id = "clown" + display_name = "Clown Technology" + description = "Honk?!" + prereq_ids = list("base") + design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm", + "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone", "borg_transform_clown") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +////////////////////////Computer tech//////////////////////// +/datum/techweb_node/comptech + id = "comptech" + display_name = "Computer Consoles" + description = "Computers and how they work." + prereq_ids = list("datatheory") + design_ids = list("cargo", "cargorequest", "libraryconsole", "mining", "miningshuttle", "crewconsole", "rdcamera", "comconsole", "idcardconsole", "seccamera") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get. + id = "computer_hardware_basic" + display_name = "Computer Hardware" + description = "How computer hardware are made." + prereq_ids = list("comptech") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) //they are really kinda shitty + export_price = 2000 + design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired", + "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced", + "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small") + +/datum/techweb_node/comp_recordkeeping + id = "comp_recordkeeping" + display_name = "Computerized Recordkeeping" + description = "Organized record databases and how they're used." + prereq_ids = list("comptech") + design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1250) + export_price = 2000 + +/datum/techweb_node/telecomms + id = "telecomms" + display_name = "Telecommunications Technology" + description = "Subspace transmission technology for near-instant communications devices." + prereq_ids = list("comptech", "bluespace_basic") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + export_price = 5000 + design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", + "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter", "message_monitor") + +/datum/techweb_node/integrated_HUDs + id = "integrated_HUDs" + display_name = "Integrated HUDs" + description = "The usefulness of computerized records, projected straight onto your eyepiece!" + prereq_ids = list("comp_recordkeeping", "emp_basic") + design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles", "health_hud_prescription", "security_hud_prescription", "diagnostic_hud_prescription") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + export_price = 5000 + +/datum/techweb_node/NVGtech + id = "NVGtech" + display_name = "Night Vision Technology" + description = "Allows seeing in the dark without actual light!" + prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") + design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons", "night_visision_goggles_glasses") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 5000 + +////////////////////////Medical//////////////////////// +/datum/techweb_node/cloning + id = "cloning" + display_name = "Genetic Engineering" + description = "We have the technology to make him." + prereq_ids = list("biotech") + design_ids = list("clonecontrol", "clonepod", "clonescanner", "scan_console", "cloning_disk") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/cryotech + id = "cryotech" + display_name = "Cryostasis Technology" + description = "Smart freezing of objects to preserve them!" + prereq_ids = list("adv_engi", "biotech") + design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 4000 + +/datum/techweb_node/subdermal_implants + id = "subdermal_implants" + display_name = "Subdermal Implants" + description = "Electronic implants buried beneath the skin." + prereq_ids = list("biotech", "datatheory") + design_ids = list("implanter", "implantcase", "implant_chem", "implant_tracking", "locator", "c38_trac") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/cyber_organs + id = "cyber_organs" + display_name = "Cybernetic Organs" + description = "We have the technology to rebuild him." + prereq_ids = list("adv_biotech") + design_ids = list("cybernetic_ears", "cybernetic_heart", "cybernetic_liver", "cybernetic_lungs", "cybernetic_tongue") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + export_price = 5000 + +/datum/techweb_node/cyber_organs_upgraded + id = "cyber_organs_upgraded" + display_name = "Upgraded Cybernetic Organs" + description = "We have the technology to upgrade him." + prereq_ids = list("cyber_organs") + design_ids = list("cybernetic_ears_u", "cybernetic_heart_u", "cybernetic_liver_u", "cybernetic_lungs_u") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + export_price = 5000 + +/datum/techweb_node/cyber_implants + id = "cyber_implants" + display_name = "Cybernetic Implants" + description = "Electronic implants that improve humans." + prereq_ids = list("adv_biotech", "adv_datatheory") + design_ids = list("ci-nutriment", "ci-breather", "ci-gloweyes", "ci-welding", "ci-medhud", "ci-sechud") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/adv_cyber_implants + id = "adv_cyber_implants" + display_name = "Advanced Cybernetic Implants" + description = "Upgraded and more powerful cybernetic implants." + prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") + design_ids = list("ci-toolset", "ci-surgery", "ci-reviver", "ci-nutrimentplus") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/combat_cyber_implants + id = "combat_cyber_implants" + display_name = "Combat Cybernetic Implants" + description = "Military grade combat implants to improve performance." + prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") + design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +////////////////////////Tools//////////////////////// +/datum/techweb_node/basic_mining + id = "basic_mining" + display_name = "Mining Technology" + description = "Better than Efficiency V." + prereq_ids = list("engineering", "basic_plasma") + design_ids = list("drill", "superresonator", "triggermod", "damagemod", "cooldownmod", "rangemod", "ore_redemption", "mining_equipment_vendor", "cargoexpress", "plasmacutter")//e a r l y g a m e) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/adv_mining + id = "adv_mining" + display_name = "Advanced Mining Technology" + description = "Efficiency Level 127" //dumb mc references + prereq_ids = list("basic_mining", "adv_engi", "adv_power", "adv_plasma") + design_ids = list("drill_diamond", "jackhammer", "hypermod", "plasmacutter_adv", "ore_silo") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/janitor + id = "janitor" + display_name = "Advanced Sanitation Technology" + description = "Clean things better, faster, stronger, and harder!" + prereq_ids = list("adv_engi") + design_ids = list("advmop", "buffer", "light_replacer") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1750) // No longer has its bag + export_price = 5000 + +/datum/techweb_node/botany + id = "botany" + display_name = "Botanical Engineering" + description = "Botanical tools." + prereq_ids = list("adv_engi", "biotech") + design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + export_price = 5000 + +/datum/techweb_node/exp_tools + id = "exp_tools" + display_name = "Experimental Tools" + description = "Highly advanced construction tools." + design_ids = list("exwelder", "jawsoflife", "handdrill") + prereq_ids = list("adv_engi") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + export_price = 5000 + +/////////////////////////weaponry tech///////////////////////// +/datum/techweb_node/weaponry + id = "weaponry" + display_name = "Weapon Development Technology" + description = "Our researchers have found new to weaponize just about everything now." + prereq_ids = list("engineering") + design_ids = list("pin_testing", "tele_shield", "lasercarbine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + export_price = 5000 + +/datum/techweb_node/adv_weaponry + id = "adv_weaponry" + display_name = "Advanced Weapon Development Technology" + description = "Our weapons are breaking the rules of reality by now." + prereq_ids = list("adv_engi", "weaponry") + design_ids = list("pin_loyalty") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + export_price = 5000 + +/datum/techweb_node/electric_weapons + id = "electronic_weapons" + display_name = "Electric Weapons" + description = "Weapons using electric technology" + prereq_ids = list("weaponry", "adv_power" , "emp_basic") + design_ids = list("stunrevolver", "stunshell", "ioncarbine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + export_price = 5000 + +/datum/techweb_node/radioactive_weapons + id = "radioactive_weapons" + display_name = "Radioactive Weaponry" + description = "Weapons using radioactive technology." + prereq_ids = list("adv_engi", "adv_weaponry") + design_ids = list("nuclear_gun") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/medical_weapons + id = "medical_weapons" + display_name = "Medical Weaponry" + description = "Weapons using medical technology." + prereq_ids = list("adv_biotech", "adv_weaponry") + design_ids = list("rapidsyringe", "shotgundartcryostatis") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/beam_weapons + id = "beam_weapons" + display_name = "Beam Weaponry" + description = "Various basic beam weapons" + prereq_ids = list("adv_weaponry") + design_ids = list("temp_gun", "xray_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/adv_beam_weapons + id = "adv_beam_weapons" + display_name = "Advanced Beam Weaponry" + description = "Various advanced beam weapons" + prereq_ids = list("beam_weapons") + design_ids = list("beamrifle") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3250) // Sniper + export_price = 5000 + +/datum/techweb_node/explosive_weapons + id = "explosive_weapons" + display_name = "Explosive & Pyrotechnical Weaponry" + description = "If the light stuff just won't do it." + prereq_ids = list("adv_weaponry") + design_ids = list("large_Grenade", "pyro_Grenade", "adv_Grenade") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + export_price = 5000 + +/datum/techweb_node/ballistic_weapons + id = "ballistic_weapons" + display_name = "Ballistic Weaponry" + description = "This isn't research.. This is reverse-engineering!" + prereq_ids = list("weaponry") + design_ids = list("mag_oldsmg", "mag_oldsmg_ap", "mag_oldsmg_ic", "mag_oldsmg_rubber", "mag_oldsmg_tx") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + export_price = 5000 + +/datum/techweb_node/exotic_ammo + id = "exotic_ammo" + display_name = "Exotic Ammunition" + description = "They won't know what hit em." + prereq_ids = list("weaponry", "ballistic_weapons") + design_ids = list("techshotshell", "c38_hotshot", "c38_iceblox") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) + export_price = 5000 + +/datum/techweb_node/gravity_gun + id = "gravity_gun" + display_name = "One-point Bluespace-gravitational Manipulator" + description = "Fancy wording for gravity gun." + prereq_ids = list("adv_weaponry", "adv_bluespace") + design_ids = list("gravitygun", "mech_gravcatapult") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +////////////////////////mech technology//////////////////////// +/datum/techweb_node/adv_mecha + id = "adv_mecha" + display_name = "Advanced Exosuits" + description = "For when you just aren't Gundam enough." + prereq_ids = list("adv_robotics") + design_ids = list("mech_repair_droid") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/odysseus + id = "mecha_odysseus" + display_name = "EXOSUIT: Odysseus" + description = "Odysseus exosuit designs" + prereq_ids = list("base") + design_ids = list("odysseus_chassis", "odysseus_torso", "odysseus_head", "odysseus_left_arm", "odysseus_right_arm" ,"odysseus_left_leg", "odysseus_right_leg", + "odysseus_main", "odysseus_peri") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/gygax + id = "mech_gygax" + display_name = "EXOSUIT: Gygax" + description = "Gygax exosuit designs" + prereq_ids = list("adv_mecha", "weaponry") + design_ids = list("gygax_chassis", "gygax_torso", "gygax_head", "gygax_left_arm", "gygax_right_arm", "gygax_left_leg", "gygax_right_leg", "gygax_main", + "gygax_peri", "gygax_targ", "gygax_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/durand + id = "mech_durand" + display_name = "EXOSUIT: Durand" + description = "Durand exosuit designs" + prereq_ids = list("adv_mecha", "adv_weaponry") + design_ids = list("durand_chassis", "durand_torso", "durand_head", "durand_left_arm", "durand_right_arm", "durand_left_leg", "durand_right_leg", "durand_main", + "durand_peri", "durand_targ", "durand_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) + export_price = 5000 + +/datum/techweb_node/phazon + id = "mecha_phazon" + display_name = "EXOSUIT: Phazon" + description = "Phazon exosuit designs" + prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace") + design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main", + "phazon_peri", "phazon_targ", "phazon_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + export_price = 5000 + +/datum/techweb_node/adv_mecha_tools + id = "adv_mecha_tools" + display_name = "Advanced Exosuit Equipment" + description = "Tools for high level mech suits" + prereq_ids = list("adv_mecha") + design_ids = list("mech_rcd") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/med_mech_tools + id = "med_mech_tools" + display_name = "Medical Exosuit Equipment" + description = "Tools for high level mech suits" + prereq_ids = list("adv_biotech") + design_ids = list("mech_sleeper", "mech_syringe_gun", "mech_medi_beam") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 5000 + +/datum/techweb_node/mech_modules + id = "adv_mecha_modules" + display_name = "Simple Exosuit Modules" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_mecha", "bluespace_power") + design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_scattershot + id = "mecha_tools" + display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_scattershot") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_seedscatter + id = "mech_seedscatter" + display_name = "Exosuit Weapon (Melon Seed \"Scattershot\")" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_seedscatter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_carbine + id = "mech_carbine" + display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_carbine") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_ion + id = "mmech_ion" + display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("electronic_weapons", "emp_adv") + design_ids = list("mech_ion") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_tesla + id = "mech_tesla" + display_name = "Exosuit Weapon (MKI Tesla Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("electronic_weapons", "adv_power") + design_ids = list("mech_tesla") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_laser + id = "mech_laser" + display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)" + description = "A basic piece of mech weaponry" + prereq_ids = list("beam_weapons") + design_ids = list("mech_laser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_laser_heavy + id = "mech_laser_heavy" + display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_beam_weapons") + design_ids = list("mech_laser_heavy") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_grenade_launcher + id = "mech_grenade_launcher" + display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("mech_grenade_launcher") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_missile_rack + id = "mech_missile_rack" + display_name = "Exosuit Weapon (SRM-8 Missile Rack)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("mech_missile_rack") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/clusterbang_launcher + id = "clusterbang_launcher" + display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("explosive_weapons") + design_ids = list("clusterbang_launcher") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_teleporter + id = "mech_teleporter" + display_name = "Exosuit Module (Teleporter Module)" + description = "An advanced piece of mech Equipment" + prereq_ids = list("adv_bluespace") + design_ids = list("mech_teleporter") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_wormhole_gen + id = "mech_wormhole_gen" + display_name = "Exosuit Module (Localized Wormhole Generator)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_bluespace") + design_ids = list("mech_wormhole_gen") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_taser + id = "mech_taser" + display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)" + description = "A basic piece of mech weaponry" + prereq_ids = list("electronic_weapons") + design_ids = list("mech_taser") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_lmg + id = "mech_lmg" + display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("ballistic_weapons") + design_ids = list("mech_lmg") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/mech_diamond_drill + id = "mech_diamond_drill" + display_name = "Exosuit Diamond Drill" + description = "A diamond drill fit for a large exosuit" + prereq_ids = list("adv_mining") + design_ids = list("mech_diamond_drill") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/////////////////////////Nanites///////////////////////// +/datum/techweb_node/nanite_base + id = "nanite_base" + display_name = "Basic Nanite Programming" + description = "The basics of nanite construction and programming." + prereq_ids = list("datatheory","robotics") + design_ids = list("nanite_disk","nanite_remote","nanite_comm_remote","nanite_scanner",\ + "nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\ + "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/nanite_smart + id = "nanite_smart" + display_name = "Smart Nanite Programming" + description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets." + prereq_ids = list("nanite_base","adv_robotics") + design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + export_price = 4000 + +/datum/techweb_node/nanite_mesh + id = "nanite_mesh" + display_name = "Mesh Nanite Programming" + description = "Nanite programs that require static structures and membranes." + prereq_ids = list("nanite_base","engineering") + design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/nanite_bio + id = "nanite_bio" + display_name = "Biological Nanite Programming" + description = "Nanite programs that require complex biological interaction." + prereq_ids = list("nanite_base","biotech") + design_ids = list("regenerative_nanites", "bloodheal_nanites", "coagulating_nanites","poison_nanites","flesheating_nanites",\ + "sensor_crit_nanites","sensor_death_nanites", "sensor_health_nanites", "sensor_damage_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/nanite_neural + id = "nanite_neural" + display_name = "Neural Nanite Programming" + description = "Nanite programs affecting nerves and brain matter." + prereq_ids = list("nanite_bio") + design_ids = list("nervous_nanites", "brainheal_nanites", "paralyzing_nanites", "stun_nanites", "selfscan_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/nanite_synaptic + id = "nanite_synaptic" + display_name = "Synaptic Nanite Programming" + description = "Nanite programs affecting mind and thoughts." + prereq_ids = list("nanite_neural","neural_programming") + design_ids = list("mindshield_nanites", "pacifying_nanites", "blinding_nanites", "sleep_nanites", "mute_nanites", "speech_nanites","hallucination_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + export_price = 5000 + +/datum/techweb_node/nanite_harmonic + id = "nanite_harmonic" + display_name = "Harmonic Nanite Programming" + description = "Nanite programs that require seamless integration between nanites and biology." + prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh") + design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) + export_price = 8000 + +/datum/techweb_node/nanite_combat + id = "nanite_military" + display_name = "Military Nanite Programming" + description = "Nanite programs that perform military-grade functions." + prereq_ids = list("nanite_harmonic", "syndicate_basic") + design_ids = list("explosive_nanites","pyro_nanites","meltdown_nanites","viral_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) + export_price = 12500 + +/datum/techweb_node/nanite_hazard + id = "nanite_hazard" + display_name = "Hazard Nanite Programs" + description = "Extremely advanced Nanite programs with the potential of being extremely dangerous." + prereq_ids = list("nanite_harmonic", "alientech") + design_ids = list("spreading_nanites","mindcontrol_nanites","mitosis_nanites") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + export_price = 15000 + +////////////////////////Alien technology//////////////////////// +/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech + id = "alientech" + display_name = "Alien Technology" + description = "Things used by the greys." + prereq_ids = list("biotech","engineering") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 20000 + hidden = TRUE + design_ids = list("alienalloy") + +/datum/techweb_node/alientech/New() + . = ..() + boost_item_paths = typesof(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, + /obj/item/retractor/alien, /obj/item/circular_saw/alien, /obj/item/cautery/alien, + /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, + /obj/item/crowbar/abductor, /obj/item/multitool/abductor, + /obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor, + /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, + /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor) + +/datum/techweb_node/alien_bio + id = "alien_bio" + display_name = "Alien Biological Tools" + description = "Advanced biological tools." + prereq_ids = list("alientech", "advance_surgerytools") + design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery", "ayyplantgenes") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 10000 + +/datum/techweb_node/alien_engi + id = "alien_engi" + display_name = "Alien Engineering" + description = "Alien engineering tools." + prereq_ids = list("alientech", "exp_tools") + design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) + export_price = 10000 + +/datum/techweb_node/syndicate_basic + id = "syndicate_basic" + display_name = "Illegal Technology" + description = "Dangerous research used to create dangerous objects." + prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") + design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow", "donksofttoyvendor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) + export_price = 5000 + hidden = TRUE + +/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. + . = ..() + boost_item_paths = list() + for(var/path in GLOB.uplink_items) + var/datum/uplink_item/UI = new path + if(!UI.item || !UI.illegal_tech) + continue + boost_item_paths |= UI.item //allows deconning to unlock. + +/datum/techweb_node/advanced_illegal_ballistics + id = "advanced_illegal_ballistics" + display_name = "Advanced Non-Standard Ballistics" + description = "Ballistic ammunition for non-standard firearms. Usually the ones you don't have nor want to be involved with." + design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","pistolm9mm","m45","bolt_clip") + prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns from traitors, space, or anything in between. + export_price = 7000 + +//Helpers for debugging/balancing the techweb in its entirety! +/proc/total_techweb_exports() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + . = 0 + for(var/i in processing) + var/datum/techweb_node/TN = i + . += TN.export_price + +/proc/total_techweb_points() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + var/datum/techweb/TW = new + TW.research_points = list() + for(var/i in processing) + var/datum/techweb_node/TN = i + TW.add_point_list(TN.research_costs) + return TW.research_points + +/proc/total_techweb_points_printout() + var/list/datum/techweb_node/processing = list() + for(var/i in subtypesof(/datum/techweb_node)) + processing += new i + var/datum/techweb/TW = new + TW.research_points = list() + for(var/i in processing) + var/datum/techweb_node/TN = i + TW.add_point_list(TN.research_costs) + return TW.printout_points() diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 73eb12fd6a1326358e18f20b7823538eb974b544..71fceba8b4df1735833a78dad91efa252f0c487d 100644 GIT binary patch literal 51443 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 literal 49032 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 diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index cc0b5d198f..c0b7d426f3 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,21 +1,21 @@ -require=function(){function t(e,n,a){function r(o,s){if(!n[o]){if(!e[o]){var p="function"==typeof require&&require;if(!s&&p)return p(o,!0);if(i)return i(o,!0);var u=Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[o]={exports:{}};e[o][0].call(c.exports,function(t){var n=e[o][1][t];return r(n||t)},c,c.exports,t,e,n,a)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o=0;--a){var r=this.tryEntries[a],i=r.completion;if("root"===r.tryLoc)return e("end");if(r.tryLoc<=this.prev){var o=b.call(r,"catchLoc"),s=b.call(r,"finallyLoc");if(o&&s){if(this.prev=0;--n){var a=this.tryEntries[n];if(a.tryLoc<=this.prev&&b.call(a,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),d(n),O}},"catch":function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var a=n.completion;if("throw"===a.type){var r=a.arg;d(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:h(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=g),O}}}("object"==typeof t?t:"object"==typeof window?window:"object"==typeof self?self:this)}).call(this,void 0!==t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],3:[function(t,e,n){t(129),e.exports=t(24).RegExp.escape},{129:129,24:24}],4:[function(t,e,n){e.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},{}],5:[function(t,e,n){var a=t(19);e.exports=function(t,e){if("number"!=typeof t&&"Number"!=a(t))throw TypeError(e);return+t}},{19:19}],6:[function(t,e,n){var a=t(127)("unscopables"),r=Array.prototype;void 0==r[a]&&t(43)(r,a,{}),e.exports=function(t){r[a][t]=!0}},{127:127,43:43}],7:[function(t,e,n){e.exports=function(t,e,n,a){if(!(t instanceof e)||void 0!==a&&a in t)throw TypeError(n+": incorrect invocation!");return t}},{}],8:[function(t,e,n){var a=t(52);e.exports=function(t){if(!a(t))throw TypeError(t+" is not an object!");return t}},{52:52}],9:[function(t,e,n){"use strict";var a=t(117),r=t(112),i=t(116);e.exports=[].copyWithin||function(t,e){var n=a(this),o=i(n.length),s=r(t,o),p=r(e,o),u=arguments.length>2?arguments[2]:void 0,c=Math.min((void 0===u?o:r(u,o))-p,o-s),l=1;for(s>p&&p+c>s&&(l=-1,p+=c-1,s+=c-1);c-- >0;)p in n?n[s]=n[p]:delete n[s],s+=l,p+=l;return n}},{112:112,116:116,117:117}],10:[function(t,e,n){"use strict";var a=t(117),r=t(112),i=t(116);e.exports=function(t){for(var e=a(this),n=i(e.length),o=arguments.length,s=r(o>1?arguments[1]:void 0,n),p=o>2?arguments[2]:void 0,u=void 0===p?n:r(p,n);u>s;)e[s++]=t;return e}},{112:112,116:116,117:117}],11:[function(t,e,n){var a=t(40);e.exports=function(t,e){var n=[];return a(t,!1,n.push,n,e),n}},{40:40}],12:[function(t,e,n){var a=t(115),r=t(116),i=t(112);e.exports=function(t){return function(e,n,o){var s,p=a(e),u=r(p.length),c=i(o,u);if(t&&n!=n){for(;u>c;)if(s=p[c++],s!=s)return!0}else for(;u>c;c++)if((t||c in p)&&p[c]===n)return t||c||0;return!t&&-1}}},{112:112,115:115,116:116}],13:[function(t,e,n){var a=t(26),r=t(48),i=t(117),o=t(116),s=t(16);e.exports=function(t,e){var n=1==t,p=2==t,u=3==t,c=4==t,l=6==t,d=5==t||l,f=e||s;return function(e,s,h){for(var m,g,v=i(e),b=r(v),y=a(s,h,3),_=o(b.length),x=0,w=n?f(e,_):p?f(e,0):void 0;_>x;x++)if((d||x in b)&&(m=b[x],g=y(m,x,v),t))if(n)w[x]=g;else if(g)switch(t){case 3:return!0;case 5:return m;case 6:return x;case 2:w.push(m)}else if(c)return!1;return l?-1:u||c?c:w}}},{116:116,117:117,16:16,26:26,48:48}],14:[function(t,e,n){var a=t(4),r=t(117),i=t(48),o=t(116);e.exports=function(t,e,n,s,p){a(e);var u=r(t),c=i(u),l=o(u.length),d=p?l-1:0,f=p?-1:1;if(2>n)for(;;){if(d in c){s=c[d],d+=f;break}if(d+=f,p?0>d:d>=l)throw TypeError("Reduce of empty array with no initial value")}for(;p?d>=0:l>d;d+=f)d in c&&(s=e(s,c[d],d,u));return s}},{116:116,117:117,4:4,48:48}],15:[function(t,e,n){var a=t(52),r=t(50),i=t(127)("species");e.exports=function(t){var e;return r(t)&&(e=t.constructor,"function"!=typeof e||e!==Array&&!r(e.prototype)||(e=void 0),a(e)&&(e=e[i],null===e&&(e=void 0))),void 0===e?Array:e}},{127:127,50:50,52:52}],16:[function(t,e,n){var a=t(15);e.exports=function(t,e){return new(a(t))(e)}},{15:15}],17:[function(t,e,n){"use strict";var a=t(4),r=t(52),i=t(47),o=[].slice,s={},p=function(t,e,n){if(!(e in s)){for(var a=[],r=0;e>r;r++)a[r]="a["+r+"]";s[e]=Function("F,a","return new F("+a.join(",")+")")}return s[e](t,n)};e.exports=Function.bind||function(t){var e=a(this),n=o.call(arguments,1),s=function(){var a=n.concat(o.call(arguments));return this instanceof s?p(e,a.length,a):i(e,a,t)};return r(e.prototype)&&(s.prototype=e.prototype),s}},{4:4,47:47,52:52}],18:[function(t,e,n){var a=t(19),r=t(127)("toStringTag"),i="Arguments"==a(function(){return arguments}()),o=function(t,e){try{return t[e]}catch(n){}};e.exports=function(t){var e,n,s;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=o(e=Object(t),r))?n:i?a(e):"Object"==(s=a(e))&&"function"==typeof e.callee?"Arguments":s}},{127:127,19:19}],19:[function(t,e,n){var a={}.toString;e.exports=function(t){return a.call(t).slice(8,-1)}},{}],20:[function(t,e,n){"use strict";var a=t(72).f,r=t(71),i=t(91),o=t(26),s=t(7),p=t(40),u=t(56),c=t(58),l=t(98),d=t(30),f=t(66).fastKey,h=t(124),m=d?"_s":"size",g=function(t,e){var n,a=f(e);if("F"!==a)return t._i[a];for(n=t._f;n;n=n.n)if(n.k==e)return n};e.exports={getConstructor:function(t,e,n,u){var c=t(function(t,a){s(t,c,e,"_i"),t._t=e,t._i=r(null),t._f=void 0,t._l=void 0,t[m]=0,void 0!=a&&p(a,n,t[u],t)});return i(c.prototype,{clear:function(){for(var t=h(this,e),n=t._i,a=t._f;a;a=a.n)a.r=!0,a.p&&(a.p=a.p.n=void 0),delete n[a.i];t._f=t._l=void 0,t[m]=0},"delete":function(t){var n=h(this,e),a=g(n,t);if(a){var r=a.n,i=a.p;delete n._i[a.i],a.r=!0,i&&(i.n=r),r&&(r.p=i),n._f==a&&(n._f=r),n._l==a&&(n._l=i),n[m]--}return!!a},forEach:function(t){h(this,e);for(var n,a=o(t,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(a(n.v,n.k,this);n&&n.r;)n=n.p},has:function(t){return!!g(h(this,e),t)}}),d&&a(c.prototype,"size",{get:function(){return h(this,e)[m]}}),c},def:function(t,e,n){var a,r,i=g(t,e);return i?i.v=n:(t._l=i={i:r=f(e,!0),k:e,v:n,p:a=t._l,n:void 0,r:!1},t._f||(t._f=i),a&&(a.n=i),t[m]++,"F"!==r&&(t._i[r]=i)),t},getEntry:g,setStrong:function(t,e,n){u(t,e,function(t,n){this._t=h(t,e),this._k=n,this._l=void 0},function(){for(var t=this,e=t._k,n=t._l;n&&n.r;)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?"keys"==e?c(0,n.k):"values"==e?c(0,n.v):c(0,[n.k,n.v]):(t._t=void 0,c(1))},n?"entries":"values",!n,!0),l(e)}}},{124:124,26:26,30:30,40:40,56:56,58:58,66:66,7:7,71:71,72:72,91:91,98:98}],21:[function(t,e,n){var a=t(18),r=t(11);e.exports=function(t){return function(){if(a(this)!=t)throw TypeError(t+"#toJSON isn't generic");return r(this)}}},{11:11,18:18}],22:[function(t,e,n){"use strict";var a=t(91),r=t(66).getWeak,i=t(8),o=t(52),s=t(7),p=t(40),u=t(13),c=t(42),l=t(124),d=u(5),f=u(6),h=0,m=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},v=function(t,e){return d(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=v(this,t);return e?e[1]:void 0},has:function(t){return!!v(this,t)},set:function(t,e){var n=v(this,t);n?n[1]=e:this.a.push([t,e])},"delete":function(t){var e=f(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},e.exports={getConstructor:function(t,e,n,i){var u=t(function(t,a){s(t,u,e,"_i"),t._t=e,t._i=h++,t._l=void 0,void 0!=a&&p(a,n,t[i],t)});return a(u.prototype,{"delete":function(t){if(!o(t))return!1;var n=r(t);return n===!0?m(l(this,e))["delete"](t):n&&c(n,this._i)&&delete n[this._i]},has:function(t){if(!o(t))return!1;var n=r(t);return n===!0?m(l(this,e)).has(t):n&&c(n,this._i)}}),u},def:function(t,e,n){var a=r(i(e),!0);return a===!0?m(t).set(e,n):a[t._i]=n,t},ufstore:m}},{124:124,13:13,40:40,42:42,52:52,66:66,7:7,8:8,91:91}],23:[function(t,e,n){"use strict";var a=t(41),r=t(34),i=t(92),o=t(91),s=t(66),p=t(40),u=t(7),c=t(52),l=t(36),d=t(57),f=t(99),h=t(46);e.exports=function(t,e,n,m,g,v){var b=a[t],y=b,_=g?"set":"add",x=y&&y.prototype,w={},k=function(t){var e=x[t];i(x,t,"delete"==t?function(t){return v&&!c(t)?!1:e.call(this,0===t?0:t)}:"has"==t?function(t){return v&&!c(t)?!1:e.call(this,0===t?0:t)}:"get"==t?function(t){return v&&!c(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof y&&(v||x.forEach&&!l(function(){(new y).entries().next()}))){var S=new y,E=S[_](v?{}:-0,1)!=S,C=l(function(){S.has(1)}),P=d(function(t){new y(t)}),A=!v&&l(function(){for(var t=new y,e=5;e--;)t[_](e,e);return!t.has(-0)});P||(y=e(function(e,n){u(e,y,t);var a=h(new b,e,y);return void 0!=n&&p(n,g,a[_],a),a}),y.prototype=x,x.constructor=y),(C||A)&&(k("delete"),k("has"),g&&k("get")),(A||E)&&k(_),v&&x.clear&&delete x.clear}else y=m.getConstructor(e,t,g,_),o(y.prototype,n),s.NEED=!0;return f(y,t),w[t]=y,r(r.G+r.W+r.F*(y!=b),w),v||m.setStrong(y,t,g),y}},{34:34,36:36,40:40,41:41,46:46,52:52,57:57,66:66,7:7,91:91,92:92,99:99}],24:[function(t,e,n){var a=e.exports={version:"2.5.6"};"number"==typeof __e&&(__e=a)},{}],25:[function(t,e,n){"use strict";var a=t(72),r=t(90);e.exports=function(t,e,n){e in t?a.f(t,e,r(0,n)):t[e]=n}},{72:72,90:90}],26:[function(t,e,n){var a=t(4);e.exports=function(t,e,n){if(a(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,a){return t.call(e,n,a)};case 3:return function(n,a,r){return t.call(e,n,a,r)}}return function(){return t.apply(e,arguments)}}},{4:4}],27:[function(t,e,n){"use strict";var a=t(36),r=Date.prototype.getTime,i=Date.prototype.toISOString,o=function(t){return t>9?t:"0"+t};e.exports=a(function(){return"0385-07-25T07:06:39.999Z"!=i.call(new Date(-5e13-1))})||!a(function(){i.call(new Date(NaN))})?function(){if(!isFinite(r.call(this)))throw RangeError("Invalid time value");var t=this,e=t.getUTCFullYear(),n=t.getUTCMilliseconds(),a=0>e?"-":e>9999?"+":"";return a+("00000"+Math.abs(e)).slice(a?-6:-4)+"-"+o(t.getUTCMonth()+1)+"-"+o(t.getUTCDate())+"T"+o(t.getUTCHours())+":"+o(t.getUTCMinutes())+":"+o(t.getUTCSeconds())+"."+(n>99?n:"0"+o(n))+"Z"}:i},{36:36}],28:[function(t,e,n){"use strict";var a=t(8),r=t(118),i="number";e.exports=function(t){if("string"!==t&&t!==i&&"default"!==t)throw TypeError("Incorrect hint");return r(a(this),t!=i)}},{118:118,8:8}],29:[function(t,e,n){e.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],30:[function(t,e,n){e.exports=!t(36)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{36:36}],31:[function(t,e,n){var a=t(52),r=t(41).document,i=a(r)&&a(r.createElement);e.exports=function(t){return i?r.createElement(t):{}}},{41:41,52:52}],32:[function(t,e,n){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},{}],33:[function(t,e,n){var a=t(81),r=t(78),i=t(82);e.exports=function(t){var e=a(t),n=r.f;if(n)for(var o,s=n(t),p=i.f,u=0;s.length>u;)p.call(t,o=s[u++])&&e.push(o);return e}},{78:78,81:81,82:82}],34:[function(t,e,n){var a=t(41),r=t(24),i=t(43),o=t(92),s=t(26),p="prototype",u=function(t,e,n){var c,l,d,f,h=t&u.F,m=t&u.G,g=t&u.S,v=t&u.P,b=t&u.B,y=m?a:g?a[e]||(a[e]={}):(a[e]||{})[p],_=m?r:r[e]||(r[e]={}),x=_[p]||(_[p]={});m&&(n=e);for(c in n)l=!h&&y&&void 0!==y[c],d=(l?y:n)[c],f=b&&l?s(d,a):v&&"function"==typeof d?s(Function.call,d):d,y&&o(y,c,d,t&u.U),_[c]!=d&&i(_,c,f),v&&x[c]!=d&&(x[c]=d)};a.core=r,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},{24:24,26:26,41:41,43:43,92:92}],35:[function(t,e,n){var a=t(127)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[a]=!1,!"/./"[t](e)}catch(r){}}return!0}},{127:127}],36:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],37:[function(t,e,n){"use strict";var a=t(43),r=t(92),i=t(36),o=t(29),s=t(127);e.exports=function(t,e,n){var p=s(t),u=n(o,p,""[t]),c=u[0],l=u[1];i(function(){var e={};return e[p]=function(){return 7},7!=""[t](e)})&&(r(String.prototype,t,c),a(RegExp.prototype,p,2==e?function(t,e){return l.call(t,this,e)}:function(t){return l.call(t,this)}))}},{127:127,29:29,36:36,43:43,92:92}],38:[function(t,e,n){"use strict";var a=t(8);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{8:8}],39:[function(t,e,n){"use strict";function a(t,e,n,u,c,l,d,f){for(var h,m,g=c,v=0,b=d?s(d,f,3):!1;u>v;){if(v in n){if(h=b?b(n[v],v,e):n[v],m=!1,i(h)&&(m=h[p],m=void 0!==m?!!m:r(h)),m&&l>0)g=a(t,e,h,o(h.length),g,l-1)-1;else{if(g>=9007199254740991)throw TypeError();t[g]=h}g++}v++}return g}var r=t(50),i=t(52),o=t(116),s=t(26),p=t(127)("isConcatSpreadable");e.exports=a},{116:116,127:127,26:26,50:50,52:52}],40:[function(t,e,n){var a=t(26),r=t(54),i=t(49),o=t(8),s=t(116),p=t(128),u={},c={},n=e.exports=function(t,e,n,l,d){var f,h,m,g,v=d?function(){return t}:p(t),b=a(n,l,e?2:1),y=0;if("function"!=typeof v)throw TypeError(t+" is not iterable!");if(i(v)){for(f=s(t.length);f>y;y++)if(g=e?b(o(h=t[y])[0],h[1]):b(t[y]),g===u||g===c)return g}else for(m=v.call(t);!(h=m.next()).done;)if(g=r(m,b,h.value,e),g===u||g===c)return g};n.BREAK=u,n.RETURN=c},{116:116,128:128,26:26,49:49,54:54,8:8}],41:[function(t,e,n){var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},{}],42:[function(t,e,n){var a={}.hasOwnProperty;e.exports=function(t,e){return a.call(t,e)}},{}],43:[function(t,e,n){var a=t(72),r=t(90);e.exports=t(30)?function(t,e,n){return a.f(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},{30:30,72:72,90:90}],44:[function(t,e,n){var a=t(41).document;e.exports=a&&a.documentElement},{41:41}],45:[function(t,e,n){e.exports=!t(30)&&!t(36)(function(){return 7!=Object.defineProperty(t(31)("div"),"a",{get:function(){return 7}}).a})},{30:30,31:31,36:36}],46:[function(t,e,n){var a=t(52),r=t(97).set;e.exports=function(t,e,n){var i,o=e.constructor;return o!==n&&"function"==typeof o&&(i=o.prototype)!==n.prototype&&a(i)&&r&&r(t,i),t}},{52:52,97:97}],47:[function(t,e,n){e.exports=function(t,e,n){var a=void 0===n;switch(e.length){case 0:return a?t():t.call(n);case 1:return a?t(e[0]):t.call(n,e[0]);case 2:return a?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return a?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return a?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},{}],48:[function(t,e,n){var a=t(19);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==a(t)?t.split(""):Object(t)}},{19:19}],49:[function(t,e,n){var a=t(59),r=t(127)("iterator"),i=Array.prototype;e.exports=function(t){return void 0!==t&&(a.Array===t||i[r]===t)}},{127:127,59:59}],50:[function(t,e,n){var a=t(19);e.exports=Array.isArray||function(t){return"Array"==a(t)}},{19:19}],51:[function(t,e,n){var a=t(52),r=Math.floor;e.exports=function(t){return!a(t)&&isFinite(t)&&r(t)===t}},{52:52}],52:[function(t,e,n){e.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],53:[function(t,e,n){var a=t(52),r=t(19),i=t(127)("match");e.exports=function(t){var e;return a(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==r(t))}},{127:127,19:19,52:52}],54:[function(t,e,n){var a=t(8);e.exports=function(t,e,n,r){try{return r?e(a(n)[0],n[1]):e(n)}catch(i){var o=t["return"];throw void 0!==o&&a(o.call(t)),i}}},{8:8}],55:[function(t,e,n){"use strict";var a=t(71),r=t(90),i=t(99),o={};t(43)(o,t(127)("iterator"),function(){return this}),e.exports=function(t,e,n){t.prototype=a(o,{next:r(1,n)}),i(t,e+" Iterator")}},{127:127,43:43,71:71,90:90,99:99}],56:[function(t,e,n){"use strict";var a=t(60),r=t(34),i=t(92),o=t(43),s=t(59),p=t(55),u=t(99),c=t(79),l=t(127)("iterator"),d=!([].keys&&"next"in[].keys()),f="@@iterator",h="keys",m="values",g=function(){return this};e.exports=function(t,e,n,v,b,y,_){p(n,e,v);var x,w,k,S=function(t){if(!d&&t in A)return A[t];switch(t){case h:return function(){return new n(this,t)};case m:return function(){return new n(this,t)}}return function(){return new n(this,t)}},E=e+" Iterator",C=b==m,P=!1,A=t.prototype,O=A[l]||A[f]||b&&A[b],T=O||S(b),R=b?C?S("entries"):T:void 0,M="Array"==e?A.entries||O:O;if(M&&(k=c(M.call(new t)),k!==Object.prototype&&k.next&&(u(k,E,!0),a||"function"==typeof k[l]||o(k,l,g))),C&&O&&O.name!==m&&(P=!0,T=function(){return O.call(this)}),a&&!_||!d&&!P&&A[l]||o(A,l,T),s[e]=T,s[E]=g,b)if(x={values:C?T:S(m),keys:y?T:S(h),entries:R},_)for(w in x)w in A||i(A,w,x[w]);else r(r.P+r.F*(d||P),e,x);return x}},{127:127,34:34,43:43,55:55,59:59,60:60,79:79,92:92,99:99}],57:[function(t,e,n){var a=t(127)("iterator"),r=!1;try{var i=[7][a]();i["return"]=function(){r=!0},Array.from(i,function(){throw 2})}catch(o){}e.exports=function(t,e){if(!e&&!r)return!1;var n=!1;try{var i=[7],o=i[a]();o.next=function(){return{done:n=!0}},i[a]=function(){return o},t(i)}catch(s){}return n}},{127:127}],58:[function(t,e,n){e.exports=function(t,e){return{value:e,done:!!t}}},{}],59:[function(t,e,n){e.exports={}},{}],60:[function(t,e,n){e.exports=!1},{}],61:[function(t,e,n){var a=Math.expm1;e.exports=!a||a(10)>22025.465794806718||a(10)<22025.465794806718||-2e-17!=a(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:Math.exp(t)-1}:a},{}],62:[function(t,e,n){var a=t(65),r=Math.pow,i=r(2,-52),o=r(2,-23),s=r(2,127)*(2-o),p=r(2,-126),u=function(t){return t+1/i-1/i};e.exports=Math.fround||function(t){var e,n,r=Math.abs(t),c=a(t);return p>r?c*u(r/p/o)*p*o:(e=(1+o/i)*r,n=e-(e-r),n>s||n!=n?c*(1/0):c*n)}},{65:65}],63:[function(t,e,n){e.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:Math.log(1+t)}},{}],64:[function(t,e,n){e.exports=Math.scale||function(t,e,n,a,r){return 0===arguments.length||t!=t||e!=e||n!=n||a!=a||r!=r?NaN:t===1/0||t===-(1/0)?t:(t-e)*(r-a)/(n-e)+a}},{}],65:[function(t,e,n){e.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1}},{}],66:[function(t,e,n){var a=t(122)("meta"),r=t(52),i=t(42),o=t(72).f,s=0,p=Object.isExtensible||function(){return!0},u=!t(36)(function(){return p(Object.preventExtensions({}))}),c=function(t){o(t,a,{value:{i:"O"+ ++s,w:{}}})},l=function(t,e){if(!r(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!i(t,a)){if(!p(t))return"F";if(!e)return"E";c(t)}return t[a].i},d=function(t,e){if(!i(t,a)){if(!p(t))return!0;if(!e)return!1;c(t)}return t[a].w},f=function(t){return u&&h.NEED&&p(t)&&!i(t,a)&&c(t),t},h=e.exports={KEY:a,NEED:!1,fastKey:l,getWeak:d,onFreeze:f}},{122:122,36:36,42:42,52:52,72:72}],67:[function(t,e,n){var a=t(159),r=t(34),i=t(101)("metadata"),o=i.store||(i.store=new(t(265))),s=function(t,e,n){var r=o.get(t);if(!r){if(!n)return;o.set(t,r=new a)}var i=r.get(e);if(!i){if(!n)return;r.set(e,i=new a)}return i},p=function(t,e,n){var a=s(e,n,!1);return void 0===a?!1:a.has(t)},u=function(t,e,n){var a=s(e,n,!1);return void 0===a?void 0:a.get(t)},c=function(t,e,n,a){s(n,a,!0).set(t,e)},l=function(t,e){var n=s(t,e,!1),a=[];return n&&n.forEach(function(t,e){a.push(e)}),a},d=function(t){return void 0===t||"symbol"==typeof t?t:t+""},f=function(t){r(r.S,"Reflect",t)};e.exports={store:o,map:s,has:p,get:u,set:c,keys:l,key:d,exp:f}},{101:101,159:159,265:265,34:34}],68:[function(t,e,n){var a=t(41),r=t(111).set,i=a.MutationObserver||a.WebKitMutationObserver,o=a.process,s=a.Promise,p="process"==t(19)(o);e.exports=function(){var t,e,n,u=function(){var a,r;for(p&&(a=o.domain)&&a.exit();t;){r=t.fn,t=t.next;try{r()}catch(i){throw t?n():e=void 0,i}}e=void 0,a&&a.enter()};if(p)n=function(){o.nextTick(u)};else if(!i||a.navigator&&a.navigator.standalone)if(s&&s.resolve){var c=s.resolve(void 0);n=function(){c.then(u)}}else n=function(){r.call(a,u)};else{var l=!0,d=document.createTextNode("");new i(u).observe(d,{characterData:!0}),n=function(){d.data=l=!l}}return function(a){var r={fn:a,next:void 0};e&&(e.next=r),t||(t=r,n()),e=r}}},{111:111,19:19,41:41}],69:[function(t,e,n){"use strict";function a(t){var e,n;this.promise=new t(function(t,a){if(void 0!==e||void 0!==n)throw TypeError("Bad Promise constructor");e=t,n=a}),this.resolve=r(e),this.reject=r(n)}var r=t(4);e.exports.f=function(t){return new a(t)}},{4:4}],70:[function(t,e,n){"use strict";var a=t(81),r=t(78),i=t(82),o=t(117),s=t(48),p=Object.assign;e.exports=!p||t(36)(function(){var t={},e={},n=Symbol(),a="abcdefghijklmnopqrst";return t[n]=7,a.split("").forEach(function(t){e[t]=t}),7!=p({},t)[n]||Object.keys(p({},e)).join("")!=a})?function(t,e){for(var n=o(t),p=arguments.length,u=1,c=r.f,l=i.f;p>u;)for(var d,f=s(arguments[u++]),h=c?a(f).concat(c(f)):a(f),m=h.length,g=0;m>g;)l.call(f,d=h[g++])&&(n[d]=f[d]);return n}:p},{117:117,36:36,48:48,78:78,81:81,82:82}],71:[function(t,e,n){var a=t(8),r=t(73),i=t(32),o=t(100)("IE_PROTO"),s=function(){},p="prototype",u=function(){var e,n=t(31)("iframe"),a=i.length,r="<",o=">";for(n.style.display="none",t(44).appendChild(n),n.src="javascript:",e=n.contentWindow.document,e.open(),e.write(r+"script"+o+"document.F=Object"+r+"/script"+o),e.close(),u=e.F;a--;)delete u[p][i[a]];return u()};e.exports=Object.create||function(t,e){var n;return null!==t?(s[p]=a(t),n=new s,s[p]=null,n[o]=t):n=u(),void 0===e?n:r(n,e)}},{100:100,31:31,32:32,44:44,73:73,8:8}],72:[function(t,e,n){var a=t(8),r=t(45),i=t(118),o=Object.defineProperty;n.f=t(30)?Object.defineProperty:function(t,e,n){if(a(t),e=i(e,!0),a(n),r)try{return o(t,e,n)}catch(s){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},{118:118,30:30,45:45,8:8}],73:[function(t,e,n){var a=t(72),r=t(8),i=t(81);e.exports=t(30)?Object.defineProperties:function(t,e){r(t);for(var n,o=i(e),s=o.length,p=0;s>p;)a.f(t,n=o[p++],e[n]);return t}},{30:30,72:72,8:8,81:81}],74:[function(t,e,n){"use strict";e.exports=t(60)||!t(36)(function(){var e=Math.random();__defineSetter__.call(null,e,function(){}),delete t(41)[e]})},{36:36,41:41,60:60}],75:[function(t,e,n){var a=t(82),r=t(90),i=t(115),o=t(118),s=t(42),p=t(45),u=Object.getOwnPropertyDescriptor;n.f=t(30)?u:function(t,e){if(t=i(t),e=o(e,!0),p)try{return u(t,e)}catch(n){}return s(t,e)?r(!a.f.call(t,e),t[e]):void 0}},{115:115,118:118,30:30,42:42,45:45,82:82,90:90}],76:[function(t,e,n){var a=t(115),r=t(77).f,i={}.toString,o="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return r(t)}catch(e){return o.slice()}};e.exports.f=function(t){return o&&"[object Window]"==i.call(t)?s(t):r(a(t))}},{115:115,77:77}],77:[function(t,e,n){var a=t(80),r=t(32).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return a(t,r)}},{32:32,80:80}],78:[function(t,e,n){n.f=Object.getOwnPropertySymbols},{}],79:[function(t,e,n){var a=t(42),r=t(117),i=t(100)("IE_PROTO"),o=Object.prototype;e.exports=Object.getPrototypeOf||function(t){return t=r(t),a(t,i)?t[i]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?o:null}},{100:100,117:117,42:42}],80:[function(t,e,n){var a=t(42),r=t(115),i=t(12)(!1),o=t(100)("IE_PROTO");e.exports=function(t,e){var n,s=r(t),p=0,u=[];for(n in s)n!=o&&a(s,n)&&u.push(n);for(;e.length>p;)a(s,n=e[p++])&&(~i(u,n)||u.push(n));return u}},{100:100,115:115,12:12,42:42}],81:[function(t,e,n){var a=t(80),r=t(32);e.exports=Object.keys||function(t){return a(t,r)}},{32:32,80:80}],82:[function(t,e,n){n.f={}.propertyIsEnumerable},{}],83:[function(t,e,n){var a=t(34),r=t(24),i=t(36);e.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],o={};o[t]=e(n),a(a.S+a.F*i(function(){n(1)}),"Object",o)}},{24:24,34:34,36:36}],84:[function(t,e,n){var a=t(81),r=t(115),i=t(82).f;e.exports=function(t){return function(e){for(var n,o=r(e),s=a(o),p=s.length,u=0,c=[];p>u;)i.call(o,n=s[u++])&&c.push(t?[n,o[n]]:o[n]);return c}}},{115:115,81:81,82:82}],85:[function(t,e,n){var a=t(77),r=t(78),i=t(8),o=t(41).Reflect;e.exports=o&&o.ownKeys||function(t){var e=a.f(i(t)),n=r.f;return n?e.concat(n(t)):e}},{41:41,77:77,78:78,8:8}],86:[function(t,e,n){var a=t(41).parseFloat,r=t(109).trim;e.exports=1/a(t(110)+"-0")!==-(1/0)?function(t){var e=r(t+"",3),n=a(e);return 0===n&&"-"==e.charAt(0)?-0:n}:a},{109:109,110:110,41:41}],87:[function(t,e,n){var a=t(41).parseInt,r=t(109).trim,i=t(110),o=/^[-+]?0[xX]/;e.exports=8!==a(i+"08")||22!==a(i+"0x16")?function(t,e){var n=r(t+"",3);return a(n,e>>>0||(o.test(n)?16:10))}:a},{109:109,110:110,41:41}],88:[function(t,e,n){e.exports=function(t){try{return{e:!1,v:t()}}catch(e){return{e:!0,v:e}}}},{}],89:[function(t,e,n){var a=t(8),r=t(52),i=t(69);e.exports=function(t,e){if(a(t),r(e)&&e.constructor===t)return e;var n=i.f(t),o=n.resolve;return o(e),n.promise}},{52:52,69:69,8:8}],90:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],91:[function(t,e,n){var a=t(92);e.exports=function(t,e,n){for(var r in e)a(t,r,e[r],n);return t}},{92:92}],92:[function(t,e,n){var a=t(41),r=t(43),i=t(42),o=t(122)("src"),s="toString",p=Function[s],u=(""+p).split(s);t(24).inspectSource=function(t){return p.call(t)},(e.exports=function(t,e,n,s){var p="function"==typeof n;p&&(i(n,"name")||r(n,"name",e)),t[e]!==n&&(p&&(i(n,o)||r(n,o,t[e]?""+t[e]:u.join(e+""))),t===a?t[e]=n:s?t[e]?t[e]=n:r(t,e,n):(delete t[e],r(t,e,n)))})(Function.prototype,s,function(){ -return"function"==typeof this&&this[o]||p.call(this)})},{122:122,24:24,41:41,42:42,43:43}],93:[function(t,e,n){e.exports=function(t,e){var n=e===Object(e)?function(t){return e[t]}:e;return function(e){return(e+"").replace(t,n)}}},{}],94:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}},{}],95:[function(t,e,n){"use strict";var a=t(34),r=t(4),i=t(26),o=t(40);e.exports=function(t){a(a.S,t,{from:function(t){var e,n,a,s,p=arguments[1];return r(this),e=void 0!==p,e&&r(p),void 0==t?new this:(n=[],e?(a=0,s=i(p,arguments[2],2),o(t,!1,function(t){n.push(s(t,a++))})):o(t,!1,n.push,n),new this(n))}})}},{26:26,34:34,4:4,40:40}],96:[function(t,e,n){"use strict";var a=t(34);e.exports=function(t){a(a.S,t,{of:function(){for(var t=arguments.length,e=Array(t);t--;)e[t]=arguments[t];return new this(e)}})}},{34:34}],97:[function(t,e,n){var a=t(52),r=t(8),i=function(t,e){if(r(t),!a(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,a){try{a=t(26)(Function.call,t(75).f(Object.prototype,"__proto__").set,2),a(e,[]),n=!(e instanceof Array)}catch(r){n=!0}return function(t,e){return i(t,e),n?t.__proto__=e:a(t,e),t}}({},!1):void 0),check:i}},{26:26,52:52,75:75,8:8}],98:[function(t,e,n){"use strict";var a=t(41),r=t(72),i=t(30),o=t(127)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.f(e,o,{configurable:!0,get:function(){return this}})}},{127:127,30:30,41:41,72:72}],99:[function(t,e,n){var a=t(72).f,r=t(42),i=t(127)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{127:127,42:42,72:72}],100:[function(t,e,n){var a=t(101)("keys"),r=t(122);e.exports=function(t){return a[t]||(a[t]=r(t))}},{101:101,122:122}],101:[function(t,e,n){var a=t(24),r=t(41),i="__core-js_shared__",o=r[i]||(r[i]={});(e.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:a.version,mode:t(60)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},{24:24,41:41,60:60}],102:[function(t,e,n){var a=t(8),r=t(4),i=t(127)("species");e.exports=function(t,e){var n,o=a(t).constructor;return void 0===o||void 0==(n=a(o)[i])?e:r(n)}},{127:127,4:4,8:8}],103:[function(t,e,n){"use strict";var a=t(36);e.exports=function(t,e){return!!t&&a(function(){e?t.call(null,function(){},1):t.call(null)})}},{36:36}],104:[function(t,e,n){var a=t(114),r=t(29);e.exports=function(t){return function(e,n){var i,o,s=r(e)+"",p=a(n),u=s.length;return 0>p||p>=u?t?"":void 0:(i=s.charCodeAt(p),55296>i||i>56319||p+1===u||(o=s.charCodeAt(p+1))<56320||o>57343?t?s.charAt(p):i:t?s.slice(p,p+2):(i-55296<<10)+(o-56320)+65536)}}},{114:114,29:29}],105:[function(t,e,n){var a=t(53),r=t(29);e.exports=function(t,e,n){if(a(e))throw TypeError("String#"+n+" doesn't accept regex!");return r(t)+""}},{29:29,53:53}],106:[function(t,e,n){var a=t(34),r=t(36),i=t(29),o=/"/g,s=function(t,e,n,a){var r=i(t)+"",s="<"+e;return""!==n&&(s+=" "+n+'="'+(a+"").replace(o,""")+'"'),s+">"+r+""};e.exports=function(t,e){var n={};n[t]=e(s),a(a.P+a.F*r(function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}),"String",n)}},{29:29,34:34,36:36}],107:[function(t,e,n){var a=t(116),r=t(108),i=t(29);e.exports=function(t,e,n,o){var s=i(t)+"",p=s.length,u=void 0===n?" ":n+"",c=a(e);if(p>=c||""==u)return s;var l=c-p,d=r.call(u,Math.ceil(l/u.length));return d.length>l&&(d=d.slice(0,l)),o?d+s:s+d}},{108:108,116:116,29:29}],108:[function(t,e,n){"use strict";var a=t(114),r=t(29);e.exports=function(t){var e=r(this)+"",n="",i=a(t);if(0>i||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},{114:114,29:29}],109:[function(t,e,n){var a=t(34),r=t(29),i=t(36),o=t(110),s="["+o+"]",p="​…",u=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(t,e,n){var r={},s=i(function(){return!!o[t]()||p[t]()!=p}),u=r[t]=s?e(d):o[t];n&&(r[n]=u),a(a.P+a.F*s,"String",r)},d=l.trim=function(t,e){return t=r(t)+"",1&e&&(t=t.replace(u,"")),2&e&&(t=t.replace(c,"")),t};e.exports=l},{110:110,29:29,34:34,36:36}],110:[function(t,e,n){e.exports=" \n\x0B\f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029\ufeff"},{}],111:[function(t,e,n){var a,r,i,o=t(26),s=t(47),p=t(44),u=t(31),c=t(41),l=c.process,d=c.setImmediate,f=c.clearImmediate,h=c.MessageChannel,m=c.Dispatch,g=0,v={},b="onreadystatechange",y=function(){var t=+this;if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},_=function(t){y.call(t.data)};d&&f||(d=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return v[++g]=function(){s("function"==typeof t?t:Function(t),e)},a(g),g},f=function(t){delete v[t]},"process"==t(19)(l)?a=function(t){l.nextTick(o(y,t,1))}:m&&m.now?a=function(t){m.now(o(y,t,1))}:h?(r=new h,i=r.port2,r.port1.onmessage=_,a=o(i.postMessage,i,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(a=function(t){c.postMessage(t+"","*")},c.addEventListener("message",_,!1)):a=b in u("script")?function(t){p.appendChild(u("script"))[b]=function(){p.removeChild(this),y.call(t)}}:function(t){setTimeout(o(y,t,1),0)}),e.exports={set:d,clear:f}},{19:19,26:26,31:31,41:41,44:44,47:47}],112:[function(t,e,n){var a=t(114),r=Math.max,i=Math.min;e.exports=function(t,e){return t=a(t),0>t?r(t+e,0):i(t,e)}},{114:114}],113:[function(t,e,n){var a=t(114),r=t(116);e.exports=function(t){if(void 0===t)return 0;var e=a(t),n=r(e);if(e!==n)throw RangeError("Wrong length!");return n}},{114:114,116:116}],114:[function(t,e,n){var a=Math.ceil,r=Math.floor;e.exports=function(t){return isNaN(t=+t)?0:(t>0?r:a)(t)}},{}],115:[function(t,e,n){var a=t(48),r=t(29);e.exports=function(t){return a(r(t))}},{29:29,48:48}],116:[function(t,e,n){var a=t(114),r=Math.min;e.exports=function(t){return t>0?r(a(t),9007199254740991):0}},{114:114}],117:[function(t,e,n){var a=t(29);e.exports=function(t){return Object(a(t))}},{29:29}],118:[function(t,e,n){var a=t(52);e.exports=function(t,e){if(!a(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!a(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},{52:52}],119:[function(t,e,n){"use strict";if(t(30)){var a=t(60),r=t(41),i=t(36),o=t(34),s=t(121),p=t(120),u=t(26),c=t(7),l=t(90),d=t(43),f=t(91),h=t(114),m=t(116),g=t(113),v=t(112),b=t(118),y=t(42),_=t(18),x=t(52),w=t(117),k=t(49),S=t(71),E=t(79),C=t(77).f,P=t(128),A=t(122),O=t(127),T=t(13),R=t(12),M=t(102),L=t(140),j=t(59),D=t(57),N=t(98),F=t(10),I=t(9),B=t(72),U=t(75),V=B.f,q=U.f,G=r.RangeError,z=r.TypeError,W=r.Uint8Array,H="ArrayBuffer",K="Shared"+H,Q="BYTES_PER_ELEMENT",Y="prototype",$=Array[Y],J=p.ArrayBuffer,X=p.DataView,Z=T(0),tt=T(2),et=T(3),nt=T(4),at=T(5),rt=T(6),it=R(!0),ot=R(!1),st=L.values,pt=L.keys,ut=L.entries,ct=$.lastIndexOf,lt=$.reduce,dt=$.reduceRight,ft=$.join,ht=$.sort,mt=$.slice,gt=$.toString,vt=$.toLocaleString,bt=O("iterator"),yt=O("toStringTag"),_t=A("typed_constructor"),xt=A("def_constructor"),wt=s.CONSTR,kt=s.TYPED,St=s.VIEW,Et="Wrong length!",Ct=T(1,function(t,e){return Rt(M(t,t[xt]),e)}),Pt=i(function(){return 1===new W(new Uint16Array([1]).buffer)[0]}),At=!!W&&!!W[Y].set&&i(function(){new W(1).set({})}),Ot=function(t,e){var n=h(t);if(0>n||n%e)throw G("Wrong offset!");return n},Tt=function(t){if(x(t)&&kt in t)return t;throw z(t+" is not a typed array!")},Rt=function(t,e){if(!(x(t)&&_t in t))throw z("It is not a typed array constructor!");return new t(e)},Mt=function(t,e){return Lt(M(t,t[xt]),e)},Lt=function(t,e){for(var n=0,a=e.length,r=Rt(t,a);a>n;)r[n]=e[n++];return r},jt=function(t,e,n){V(t,e,{get:function(){return this._d[n]}})},Dt=function(t){var e,n,a,r,i,o,s=w(t),p=arguments.length,c=p>1?arguments[1]:void 0,l=void 0!==c,d=P(s);if(void 0!=d&&!k(d)){for(o=d.call(s),a=[],e=0;!(i=o.next()).done;e++)a.push(i.value);s=a}for(l&&p>2&&(c=u(c,arguments[2],2)),e=0,n=m(s.length),r=Rt(this,n);n>e;e++)r[e]=l?c(s[e],e):s[e];return r},Nt=function(){for(var t=0,e=arguments.length,n=Rt(this,e);e>t;)n[t]=arguments[t++];return n},Ft=!!W&&i(function(){vt.call(new W(1))}),It=function(){return vt.apply(Ft?mt.call(Tt(this)):Tt(this),arguments)},Bt={copyWithin:function(t,e){return I.call(Tt(this),t,e,arguments.length>2?arguments[2]:void 0)},every:function(t){return nt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return F.apply(Tt(this),arguments)},filter:function(t){return Mt(this,tt(Tt(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return at(Tt(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return rt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){Z(Tt(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return ot(Tt(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return it(Tt(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return ft.apply(Tt(this),arguments)},lastIndexOf:function(t){return ct.apply(Tt(this),arguments)},map:function(t){return Ct(Tt(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return lt.apply(Tt(this),arguments)},reduceRight:function(t){return dt.apply(Tt(this),arguments)},reverse:function(){for(var t,e=this,n=Tt(e).length,a=Math.floor(n/2),r=0;a>r;)t=e[r],e[r++]=e[--n],e[n]=t;return e},some:function(t){return et(Tt(this),t,arguments.length>1?arguments[1]:void 0)},sort:function(t){return ht.call(Tt(this),t)},subarray:function(t,e){var n=Tt(this),a=n.length,r=v(t,a);return new(M(n,n[xt]))(n.buffer,n.byteOffset+r*n.BYTES_PER_ELEMENT,m((void 0===e?a:v(e,a))-r))}},Ut=function(t,e){return Mt(this,mt.call(Tt(this),t,e))},Vt=function(t){Tt(this);var e=Ot(arguments[1],1),n=this.length,a=w(t),r=m(a.length),i=0;if(r+e>n)throw G(Et);for(;r>i;)this[e+i]=a[i++]},qt={entries:function(){return ut.call(Tt(this))},keys:function(){return pt.call(Tt(this))},values:function(){return st.call(Tt(this))}},Gt=function(t,e){return x(t)&&t[kt]&&"symbol"!=typeof e&&e in t&&+e+""==e+""},zt=function(t,e){return Gt(t,e=b(e,!0))?l(2,t[e]):q(t,e)},Wt=function(t,e,n){return!(Gt(t,e=b(e,!0))&&x(n)&&y(n,"value"))||y(n,"get")||y(n,"set")||n.configurable||y(n,"writable")&&!n.writable||y(n,"enumerable")&&!n.enumerable?V(t,e,n):(t[e]=n.value,t)};wt||(U.f=zt,B.f=Wt),o(o.S+o.F*!wt,"Object",{getOwnPropertyDescriptor:zt,defineProperty:Wt}),i(function(){gt.call({})})&&(gt=vt=function(){return ft.call(this)});var Ht=f({},Bt);f(Ht,qt),d(Ht,bt,qt.values),f(Ht,{slice:Ut,set:Vt,constructor:function(){},toString:gt,toLocaleString:It}),jt(Ht,"buffer","b"),jt(Ht,"byteOffset","o"),jt(Ht,"byteLength","l"),jt(Ht,"length","e"),V(Ht,yt,{get:function(){return this[kt]}}),e.exports=function(t,e,n,p){p=!!p;var u=t+(p?"Clamped":"")+"Array",l="get"+t,f="set"+t,h=r[u],v=h||{},b=h&&E(h),y=!h||!s.ABV,w={},k=h&&h[Y],P=function(t,n){var a=t._d;return a.v[l](n*e+a.o,Pt)},A=function(t,n,a){var r=t._d;p&&(a=(a=Math.round(a))<0?0:a>255?255:255&a),r.v[f](n*e+r.o,a,Pt)},O=function(t,e){V(t,e,{get:function(){return P(this,e)},set:function(t){return A(this,e,t)},enumerable:!0})};y?(h=n(function(t,n,a,r){c(t,h,u,"_d");var i,o,s,p,l=0,f=0;if(x(n)){if(!(n instanceof J||(p=_(n))==H||p==K))return kt in n?Lt(h,n):Dt.call(h,n);i=n,f=Ot(a,e);var v=n.byteLength;if(void 0===r){if(v%e)throw G(Et);if(o=v-f,0>o)throw G(Et)}else if(o=m(r)*e,o+f>v)throw G(Et);s=o/e}else s=g(n),o=s*e,i=new J(o);for(d(t,"_d",{b:i,o:f,l:o,e:s,v:new X(i)});s>l;)O(t,l++)}),k=h[Y]=S(Ht),d(k,"constructor",h)):i(function(){h(1)})&&i(function(){new h(-1)})&&D(function(t){new h,new h(null),new h(1.5),new h(t)},!0)||(h=n(function(t,n,a,r){c(t,h,u);var i;return x(n)?n instanceof J||(i=_(n))==H||i==K?void 0!==r?new v(n,Ot(a,e),r):void 0!==a?new v(n,Ot(a,e)):new v(n):kt in n?Lt(h,n):Dt.call(h,n):new v(g(n))}),Z(b!==Function.prototype?C(v).concat(C(b)):C(v),function(t){t in h||d(h,t,v[t])}),h[Y]=k,a||(k.constructor=h));var T=k[bt],R=!!T&&("values"==T.name||void 0==T.name),M=qt.values;d(h,_t,!0),d(k,kt,u),d(k,St,!0),d(k,xt,h),(p?new h(1)[yt]==u:yt in k)||V(k,yt,{get:function(){return u}}),w[u]=h,o(o.G+o.W+o.F*(h!=v),w),o(o.S,u,{BYTES_PER_ELEMENT:e}),o(o.S+o.F*i(function(){v.of.call(h,1)}),u,{from:Dt,of:Nt}),Q in k||d(k,Q,e),o(o.P,u,Bt),N(u),o(o.P+o.F*At,u,{set:Vt}),o(o.P+o.F*!R,u,qt),a||k.toString==gt||(k.toString=gt),o(o.P+o.F*i(function(){new h(1).slice()}),u,{slice:Ut}),o(o.P+o.F*(i(function(){return[1,2].toLocaleString()!=new h([1,2]).toLocaleString()})||!i(function(){k.toLocaleString.call([1,2])})),u,{toLocaleString:It}),j[u]=R?T:M,a||R||d(k,bt,M)}}else e.exports=function(){}},{10:10,102:102,112:112,113:113,114:114,116:116,117:117,118:118,12:12,120:120,121:121,122:122,127:127,128:128,13:13,140:140,18:18,26:26,30:30,34:34,36:36,41:41,42:42,43:43,49:49,52:52,57:57,59:59,60:60,7:7,71:71,72:72,75:75,77:77,79:79,9:9,90:90,91:91,98:98}],120:[function(t,e,n){"use strict";function a(t,e,n){var a,r,i,o=Array(n),s=8*n-e-1,p=(1<>1,c=23===e?V(2,-24)-V(2,-77):0,l=0,d=0>t||0===t&&0>1/t?1:0;for(t=U(t),t!=t||t===I?(r=t!=t?1:0,a=p):(a=q(G(t)/z),t*(i=V(2,-a))<1&&(a--,i*=2),t+=a+u>=1?c/i:c*V(2,1-u),t*i>=2&&(a++,i/=2),a+u>=p?(r=0,a=p):a+u>=1?(r=(t*i-1)*V(2,e),a+=u):(r=t*V(2,u-1)*V(2,e),a=0));e>=8;o[l++]=255&r,r/=256,e-=8);for(a=a<0;o[l++]=255&a,a/=256,s-=8);return o[--l]|=128*d,o}function r(t,e,n){var a,r=8*n-e-1,i=(1<>1,s=r-7,p=n-1,u=t[p--],c=127&u;for(u>>=7;s>0;c=256*c+t[p],p--,s-=8);for(a=c&(1<<-s)-1,c>>=-s,s+=e;s>0;a=256*a+t[p],p--,s-=8);if(0===c)c=1-o;else{if(c===i)return a?NaN:u?-I:I;a+=V(2,e),c-=o}return(u?-1:1)*a*V(2,c-e)}function i(t){return t[3]<<24|t[2]<<16|t[1]<<8|t[0]}function o(t){return[255&t]}function s(t){return[255&t,t>>8&255]}function p(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]}function u(t){return a(t,52,8)}function c(t){return a(t,23,4)}function l(t,e,n){C(t[R],e,{get:function(){return this[n]}})}function d(t,e,n,a){var r=+n,i=S(r);if(i+e>t[Y])throw F(L);var o=t[Q]._b,s=i+t[$],p=o.slice(s,s+e);return a?p:p.reverse()}function f(t,e,n,a,r,i){var o=+n,s=S(o);if(s+e>t[Y])throw F(L);for(var p=t[Q]._b,u=s+t[$],c=a(+r),l=0;e>l;l++)p[u+l]=c[i?l:e-l-1]}var h=t(41),m=t(30),g=t(60),v=t(121),b=t(43),y=t(91),_=t(36),x=t(7),w=t(114),k=t(116),S=t(113),E=t(77).f,C=t(72).f,P=t(10),A=t(99),O="ArrayBuffer",T="DataView",R="prototype",M="Wrong length!",L="Wrong index!",j=h[O],D=h[T],N=h.Math,F=h.RangeError,I=h.Infinity,B=j,U=N.abs,V=N.pow,q=N.floor,G=N.log,z=N.LN2,W="buffer",H="byteLength",K="byteOffset",Q=m?"_b":W,Y=m?"_l":H,$=m?"_o":K;if(v.ABV){if(!_(function(){j(1)})||!_(function(){new j(-1)})||_(function(){return new j,new j(1.5),new j(NaN),j.name!=O})){j=function(t){return x(this,j),new B(S(t))};for(var J,X=j[R]=B[R],Z=E(B),tt=0;Z.length>tt;)(J=Z[tt++])in j||b(j,J,B[J]);g||(X.constructor=j)}var et=new D(new j(2)),nt=D[R].setInt8;et.setInt8(0,2147483648),et.setInt8(1,2147483649),(et.getInt8(0)||!et.getInt8(1))&&y(D[R],{setInt8:function(t,e){nt.call(this,t,e<<24>>24)},setUint8:function(t,e){nt.call(this,t,e<<24>>24)}},!0)}else j=function(t){x(this,j,O);var e=S(t);this._b=P.call(Array(e),0),this[Y]=e},D=function(t,e,n){x(this,D,T),x(t,j,T);var a=t[Y],r=w(e);if(0>r||r>a)throw F("Wrong offset!");if(n=void 0===n?a-r:k(n),r+n>a)throw F(M);this[Q]=t,this[$]=r,this[Y]=n},m&&(l(j,H,"_l"),l(D,W,"_b"),l(D,H,"_l"),l(D,K,"_o")),y(D[R],{getInt8:function(t){return d(this,1,t)[0]<<24>>24},getUint8:function(t){return d(this,1,t)[0]},getInt16:function(t){var e=d(this,2,t,arguments[1]);return(e[1]<<8|e[0])<<16>>16},getUint16:function(t){var e=d(this,2,t,arguments[1]);return e[1]<<8|e[0]},getInt32:function(t){return i(d(this,4,t,arguments[1]))},getUint32:function(t){return i(d(this,4,t,arguments[1]))>>>0},getFloat32:function(t){return r(d(this,4,t,arguments[1]),23,4)},getFloat64:function(t){return r(d(this,8,t,arguments[1]),52,8)},setInt8:function(t,e){f(this,1,t,o,e)},setUint8:function(t,e){f(this,1,t,o,e)},setInt16:function(t,e){f(this,2,t,s,e,arguments[2])},setUint16:function(t,e){f(this,2,t,s,e,arguments[2])},setInt32:function(t,e){f(this,4,t,p,e,arguments[2])},setUint32:function(t,e){f(this,4,t,p,e,arguments[2])},setFloat32:function(t,e){f(this,4,t,c,e,arguments[2])},setFloat64:function(t,e){f(this,8,t,u,e,arguments[2])}});A(j,O),A(D,T),b(D[R],v.VIEW,!0),n[O]=j,n[T]=D},{10:10,113:113,114:114,116:116,121:121,30:30,36:36,41:41,43:43,60:60,7:7,72:72,77:77,91:91,99:99}],121:[function(t,e,n){for(var a,r=t(41),i=t(43),o=t(122),s=o("typed_array"),p=o("view"),u=!(!r.ArrayBuffer||!r.DataView),c=u,l=0,d=9,f="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");d>l;)(a=r[f[l++]])?(i(a.prototype,s,!0),i(a.prototype,p,!0)):c=!1;e.exports={ABV:u,CONSTR:c,TYPED:s,VIEW:p}},{122:122,41:41,43:43}],122:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++a+r).toString(36))}},{}],123:[function(t,e,n){var a=t(41),r=a.navigator;e.exports=r&&r.userAgent||""},{41:41}],124:[function(t,e,n){var a=t(52);e.exports=function(t,e){if(!a(t)||t._t!==e)throw TypeError("Incompatible receiver, "+e+" required!");return t}},{52:52}],125:[function(t,e,n){var a=t(41),r=t(24),i=t(60),o=t(126),s=t(72).f;e.exports=function(t){var e=r.Symbol||(r.Symbol=i?{}:a.Symbol||{});"_"==t.charAt(0)||t in e||s(e,t,{value:o.f(t)})}},{126:126,24:24,41:41,60:60,72:72}],126:[function(t,e,n){n.f=t(127)},{127:127}],127:[function(t,e,n){var a=t(101)("wks"),r=t(122),i=t(41).Symbol,o="function"==typeof i,s=e.exports=function(t){return a[t]||(a[t]=o&&i[t]||(o?i:r)("Symbol."+t))};s.store=a},{101:101,122:122,41:41}],128:[function(t,e,n){var a=t(18),r=t(127)("iterator"),i=t(59);e.exports=t(24).getIteratorMethod=function(t){return void 0!=t?t[r]||t["@@iterator"]||i[a(t)]:void 0}},{127:127,18:18,24:24,59:59}],129:[function(t,e,n){var a=t(34),r=t(93)(/[\\^$*+?.()|[\]{}]/g,"\\$&");a(a.S,"RegExp",{escape:function(t){return r(t)}})},{34:34,93:93}],130:[function(t,e,n){var a=t(34);a(a.P,"Array",{copyWithin:t(9)}),t(6)("copyWithin")},{34:34,6:6,9:9}],131:[function(t,e,n){"use strict";var a=t(34),r=t(13)(4);a(a.P+a.F*!t(103)([].every,!0),"Array",{every:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],132:[function(t,e,n){var a=t(34);a(a.P,"Array",{fill:t(10)}),t(6)("fill")},{10:10,34:34,6:6}],133:[function(t,e,n){"use strict";var a=t(34),r=t(13)(2);a(a.P+a.F*!t(103)([].filter,!0),"Array",{filter:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],134:[function(t,e,n){"use strict";var a=t(34),r=t(13)(6),i="findIndex",o=!0;i in[]&&Array(1)[i](function(){o=!1}),a(a.P+a.F*o,"Array",{findIndex:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)(i)},{13:13,34:34,6:6}],135:[function(t,e,n){"use strict";var a=t(34),r=t(13)(5),i="find",o=!0;i in[]&&Array(1)[i](function(){o=!1}),a(a.P+a.F*o,"Array",{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)(i)},{13:13,34:34,6:6}],136:[function(t,e,n){"use strict";var a=t(34),r=t(13)(0),i=t(103)([].forEach,!0);a(a.P+a.F*!i,"Array",{forEach:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],137:[function(t,e,n){"use strict";var a=t(26),r=t(34),i=t(117),o=t(54),s=t(49),p=t(116),u=t(25),c=t(128);r(r.S+r.F*!t(57)(function(t){Array.from(t)}),"Array",{from:function(t){var e,n,r,l,d=i(t),f="function"==typeof this?this:Array,h=arguments.length,m=h>1?arguments[1]:void 0,g=void 0!==m,v=0,b=c(d);if(g&&(m=a(m,h>2?arguments[2]:void 0,2)),void 0==b||f==Array&&s(b))for(e=p(d.length),n=new f(e);e>v;v++)u(n,v,g?m(d[v],v):d[v]);else for(l=b.call(d),n=new f;!(r=l.next()).done;v++)u(n,v,g?o(l,m,[r.value,v],!0):r.value);return n.length=v,n}})},{116:116,117:117,128:128,25:25,26:26,34:34,49:49,54:54,57:57}],138:[function(t,e,n){"use strict";var a=t(34),r=t(12)(!1),i=[].indexOf,o=!!i&&1/[1].indexOf(1,-0)<0;a(a.P+a.F*(o||!t(103)(i)),"Array",{indexOf:function(t){return o?i.apply(this,arguments)||0:r(this,t,arguments[1])}})},{103:103,12:12,34:34}],139:[function(t,e,n){var a=t(34);a(a.S,"Array",{isArray:t(50)})},{34:34,50:50}],140:[function(t,e,n){"use strict";var a=t(6),r=t(58),i=t(59),o=t(115);e.exports=t(56)(Array,"Array",function(t,e){this._t=o(t),this._i=0,this._k=e},function(){var t=this._t,e=this._k,n=this._i++;return!t||n>=t.length?(this._t=void 0,r(1)):"keys"==e?r(0,n):"values"==e?r(0,t[n]):r(0,[n,t[n]])},"values"),i.Arguments=i.Array,a("keys"),a("values"),a("entries")},{115:115,56:56,58:58,59:59,6:6}],141:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=[].join;a(a.P+a.F*(t(48)!=Object||!t(103)(i)),"Array",{join:function(t){return i.call(r(this),void 0===t?",":t)}})},{103:103,115:115,34:34,48:48}],142:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=t(114),o=t(116),s=[].lastIndexOf,p=!!s&&1/[1].lastIndexOf(1,-0)<0;a(a.P+a.F*(p||!t(103)(s)),"Array",{lastIndexOf:function(t){if(p)return s.apply(this,arguments)||0;var e=r(this),n=o(e.length),a=n-1;for(arguments.length>1&&(a=Math.min(a,i(arguments[1]))),0>a&&(a=n+a);a>=0;a--)if(a in e&&e[a]===t)return a||0;return-1}})},{103:103,114:114,115:115,116:116,34:34}],143:[function(t,e,n){"use strict";var a=t(34),r=t(13)(1);a(a.P+a.F*!t(103)([].map,!0),"Array",{map:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],144:[function(t,e,n){"use strict";var a=t(34),r=t(25);a(a.S+a.F*t(36)(function(){function t(){}return!(Array.of.call(t)instanceof t)}),"Array",{of:function(){for(var t=0,e=arguments.length,n=new("function"==typeof this?this:Array)(e);e>t;)r(n,t,arguments[t++]);return n.length=e,n}})},{25:25,34:34,36:36}],145:[function(t,e,n){"use strict";var a=t(34),r=t(14);a(a.P+a.F*!t(103)([].reduceRight,!0),"Array",{reduceRight:function(t){return r(this,t,arguments.length,arguments[1],!0)}})},{103:103,14:14,34:34}],146:[function(t,e,n){"use strict";var a=t(34),r=t(14);a(a.P+a.F*!t(103)([].reduce,!0),"Array",{reduce:function(t){return r(this,t,arguments.length,arguments[1],!1)}})},{103:103,14:14,34:34}],147:[function(t,e,n){"use strict";var a=t(34),r=t(44),i=t(19),o=t(112),s=t(116),p=[].slice;a(a.P+a.F*t(36)(function(){r&&p.call(r)}),"Array",{slice:function(t,e){var n=s(this.length),a=i(this);if(e=void 0===e?n:e,"Array"==a)return p.call(this,t,e);for(var r=o(t,n),u=o(e,n),c=s(u-r),l=Array(c),d=0;c>d;d++)l[d]="String"==a?this.charAt(r+d):this[r+d];return l}})},{112:112,116:116,19:19,34:34,36:36,44:44}],148:[function(t,e,n){"use strict";var a=t(34),r=t(13)(3);a(a.P+a.F*!t(103)([].some,!0),"Array",{some:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],149:[function(t,e,n){"use strict";var a=t(34),r=t(4),i=t(117),o=t(36),s=[].sort,p=[1,2,3];a(a.P+a.F*(o(function(){p.sort(void 0)})||!o(function(){p.sort(null)})||!t(103)(s)),"Array",{sort:function(t){return void 0===t?s.call(i(this)):s.call(i(this),r(t))}})},{103:103,117:117,34:34,36:36,4:4}],150:[function(t,e,n){t(98)("Array")},{98:98}],151:[function(t,e,n){var a=t(34);a(a.S,"Date",{now:function(){return(new Date).getTime()}})},{34:34}],152:[function(t,e,n){var a=t(34),r=t(27);a(a.P+a.F*(Date.prototype.toISOString!==r),"Date",{toISOString:r})},{27:27,34:34}],153:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118);a(a.P+a.F*t(36)(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(t){var e=r(this),n=i(e);return"number"!=typeof n||isFinite(n)?e.toISOString():null}})},{117:117,118:118,34:34,36:36}],154:[function(t,e,n){var a=t(127)("toPrimitive"),r=Date.prototype;a in r||t(43)(r,a,t(28))},{127:127,28:28,43:43}],155:[function(t,e,n){var a=Date.prototype,r="Invalid Date",i="toString",o=a[i],s=a.getTime;new Date(NaN)+""!=r&&t(92)(a,i,function(){var t=s.call(this);return t===t?o.call(this):r})},{92:92}],156:[function(t,e,n){var a=t(34);a(a.P,"Function",{bind:t(17)})},{17:17,34:34}],157:[function(t,e,n){"use strict";var a=t(52),r=t(79),i=t(127)("hasInstance"),o=Function.prototype;i in o||t(72).f(o,i,{value:function(t){if("function"!=typeof this||!a(t))return!1;if(!a(this.prototype))return t instanceof this;for(;t=r(t);)if(this.prototype===t)return!0;return!1}})},{127:127,52:52,72:72,79:79}],158:[function(t,e,n){var a=t(72).f,r=Function.prototype,i=/^\s*function ([^ (]*)/,o="name";o in r||t(30)&&a(r,o,{configurable:!0,get:function(){try{return(""+this).match(i)[1]}catch(t){return""}}})},{30:30,72:72}],159:[function(t,e,n){"use strict";var a=t(20),r=t(124),i="Map";e.exports=t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var e=a.getEntry(r(this,i),t);return e&&e.v},set:function(t,e){return a.def(r(this,i),0===t?0:t,e)}},a,!0)},{124:124,20:20,23:23}],160:[function(t,e,n){var a=t(34),r=t(63),i=Math.sqrt,o=Math.acosh;a(a.S+a.F*!(o&&710==Math.floor(o(Number.MAX_VALUE))&&o(1/0)==1/0),"Math",{acosh:function(t){return(t=+t)<1?NaN:t>94906265.62425156?Math.log(t)+Math.LN2:r(t-1+i(t-1)*i(t+1))}})},{34:34,63:63}],161:[function(t,e,n){function a(t){return isFinite(t=+t)&&0!=t?0>t?-a(-t):Math.log(t+Math.sqrt(t*t+1)):t}var r=t(34),i=Math.asinh;r(r.S+r.F*!(i&&1/i(0)>0),"Math",{asinh:a})},{34:34}],162:[function(t,e,n){var a=t(34),r=Math.atanh;a(a.S+a.F*!(r&&1/r(-0)<0),"Math",{atanh:function(t){return 0==(t=+t)?t:Math.log((1+t)/(1-t))/2}})},{34:34}],163:[function(t,e,n){var a=t(34),r=t(65);a(a.S,"Math",{cbrt:function(t){return r(t=+t)*Math.pow(Math.abs(t),1/3)}})},{34:34,65:65}],164:[function(t,e,n){var a=t(34);a(a.S,"Math",{clz32:function(t){return(t>>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},{34:34}],165:[function(t,e,n){var a=t(34),r=Math.exp;a(a.S,"Math",{cosh:function(t){return(r(t=+t)+r(-t))/2}})},{34:34}],166:[function(t,e,n){var a=t(34),r=t(61);a(a.S+a.F*(r!=Math.expm1),"Math",{expm1:r})},{34:34,61:61}],167:[function(t,e,n){var a=t(34);a(a.S,"Math",{fround:t(62)})},{34:34,62:62}],168:[function(t,e,n){var a=t(34),r=Math.abs;a(a.S,"Math",{hypot:function(t,e){for(var n,a,i=0,o=0,s=arguments.length,p=0;s>o;)n=r(arguments[o++]),n>p?(a=p/n,i=i*a*a+1,p=n):n>0?(a=n/p,i+=a*a):i+=n;return p===1/0?1/0:p*Math.sqrt(i)}})},{34:34}],169:[function(t,e,n){var a=t(34),r=Math.imul;a(a.S+a.F*t(36)(function(){return-5!=r(4294967295,5)||2!=r.length}),"Math",{imul:function(t,e){var n=65535,a=+t,r=+e,i=n&a,o=n&r;return 0|i*o+((n&a>>>16)*o+i*(n&r>>>16)<<16>>>0)}})},{34:34,36:36}],170:[function(t,e,n){var a=t(34);a(a.S,"Math",{log10:function(t){return Math.log(t)*Math.LOG10E}})},{34:34}],171:[function(t,e,n){var a=t(34);a(a.S,"Math",{log1p:t(63)})},{34:34,63:63}],172:[function(t,e,n){var a=t(34);a(a.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},{34:34}],173:[function(t,e,n){var a=t(34);a(a.S,"Math",{sign:t(65)})},{34:34,65:65}],174:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S+a.F*t(36)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(r(t)-r(-t))/2:(i(t-1)-i(-t-1))*(Math.E/2)}})},{34:34,36:36,61:61}],175:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S,"Math",{tanh:function(t){var e=r(t=+t),n=r(-t);return e==1/0?1:n==1/0?-1:(e-n)/(i(t)+i(-t))}})},{34:34,61:61}],176:[function(t,e,n){var a=t(34);a(a.S,"Math",{trunc:function(t){return(t>0?Math.floor:Math.ceil)(t)}})},{34:34}],177:[function(t,e,n){"use strict";var a=t(41),r=t(42),i=t(19),o=t(46),s=t(118),p=t(36),u=t(77).f,c=t(75).f,l=t(72).f,d=t(109).trim,f="Number",h=a[f],m=h,g=h.prototype,v=i(t(71)(g))==f,b="trim"in String.prototype,y=function(t){var e=s(t,!1);if("string"==typeof e&&e.length>2){e=b?e.trim():d(e,3);var n,a,r,i=e.charCodeAt(0);if(43===i||45===i){if(n=e.charCodeAt(2),88===n||120===n)return NaN}else if(48===i){switch(e.charCodeAt(1)){case 66:case 98:a=2,r=49;break;case 79:case 111:a=8,r=55;break;default:return+e}for(var o,p=e.slice(2),u=0,c=p.length;c>u;u++)if(o=p.charCodeAt(u),48>o||o>r)return NaN;return parseInt(p,a)}}return+e};if(!h(" 0o1")||!h("0b1")||h("+0x1")){h=function(t){var e=arguments.length<1?0:t,n=this;return n instanceof h&&(v?p(function(){g.valueOf.call(n)}):i(n)!=f)?o(new m(y(e)),n,h):y(e)};for(var _,x=t(30)?u(m):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),w=0;x.length>w;w++)r(m,_=x[w])&&!r(h,_)&&l(h,_,c(m,_));h.prototype=g,g.constructor=h,t(92)(a,f,h)}},{109:109,118:118,19:19,30:30,36:36,41:41,42:42,46:46,71:71,72:72,75:75,77:77,92:92}],178:[function(t,e,n){var a=t(34);a(a.S,"Number",{EPSILON:Math.pow(2,-52)})},{34:34}],179:[function(t,e,n){var a=t(34),r=t(41).isFinite;a(a.S,"Number",{isFinite:function(t){return"number"==typeof t&&r(t)}})},{34:34,41:41}],180:[function(t,e,n){var a=t(34);a(a.S,"Number",{isInteger:t(51)})},{34:34,51:51}],181:[function(t,e,n){var a=t(34);a(a.S,"Number",{isNaN:function(t){return t!=t}})},{34:34}],182:[function(t,e,n){var a=t(34),r=t(51),i=Math.abs;a(a.S,"Number",{isSafeInteger:function(t){return r(t)&&i(t)<=9007199254740991}})},{34:34,51:51}],183:[function(t,e,n){var a=t(34);a(a.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},{34:34}],184:[function(t,e,n){var a=t(34);a(a.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},{34:34}],185:[function(t,e,n){var a=t(34),r=t(86);a(a.S+a.F*(Number.parseFloat!=r),"Number",{parseFloat:r})},{34:34,86:86}],186:[function(t,e,n){var a=t(34),r=t(87);a(a.S+a.F*(Number.parseInt!=r),"Number",{parseInt:r})},{34:34,87:87}],187:[function(t,e,n){"use strict";var a=t(34),r=t(114),i=t(5),o=t(108),s=1..toFixed,p=Math.floor,u=[0,0,0,0,0,0],c="Number.toFixed: incorrect invocation!",l="0",d=function(t,e){for(var n=-1,a=e;++n<6;)a+=t*u[n],u[n]=a%1e7,a=p(a/1e7)},f=function(t){for(var e=6,n=0;--e>=0;)n+=u[e],u[e]=p(n/t),n=n%t*1e7},h=function(){for(var t=6,e="";--t>=0;)if(""!==e||0===t||0!==u[t]){var n=u[t]+"";e=""===e?n:e+o.call(l,7-n.length)+n}return e},m=function(t,e,n){return 0===e?n:e%2===1?m(t,e-1,n*t):m(t*t,e/2,n)},g=function(t){for(var e=0,n=t;n>=4096;)e+=12,n/=4096;for(;n>=2;)e+=1,n/=2;return e};a(a.P+a.F*(!!s&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0))||!t(36)(function(){s.call({})})),"Number",{toFixed:function(t){var e,n,a,s,p=i(this,c),u=r(t),v="",b=l;if(0>u||u>20)throw RangeError(c);if(p!=p)return"NaN";if(-1e21>=p||p>=1e21)return p+"";if(0>p&&(v="-",p=-p),p>1e-21)if(e=g(p*m(2,69,1))-69,n=0>e?p*m(2,-e,1):p/m(2,e,1),n*=4503599627370496,e=52-e,e>0){for(d(0,n),a=u;a>=7;)d(1e7,0),a-=7;for(d(m(10,a,1),0),a=e-1;a>=23;)f(1<<23),a-=23;f(1<0?(s=b.length,b=v+(u>=s?"0."+o.call(l,u-s)+b:b.slice(0,s-u)+"."+b.slice(s-u))):b=v+b,b}})},{108:108,114:114,34:34,36:36,5:5}],188:[function(t,e,n){"use strict";var a=t(34),r=t(36),i=t(5),o=1..toPrecision;a(a.P+a.F*(r(function(){return"1"!==o.call(1,void 0)})||!r(function(){o.call({})})),"Number",{toPrecision:function(t){var e=i(this,"Number#toPrecision: incorrect invocation!");return void 0===t?o.call(e):o.call(e,t)}})},{34:34,36:36,5:5}],189:[function(t,e,n){var a=t(34);a(a.S+a.F,"Object",{assign:t(70)})},{34:34,70:70}],190:[function(t,e,n){var a=t(34);a(a.S,"Object",{create:t(71)})},{34:34,71:71}],191:[function(t,e,n){var a=t(34);a(a.S+a.F*!t(30),"Object",{defineProperties:t(73)})},{30:30,34:34,73:73}],192:[function(t,e,n){var a=t(34);a(a.S+a.F*!t(30),"Object",{defineProperty:t(72).f})},{30:30,34:34,72:72}],193:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("freeze",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],194:[function(t,e,n){var a=t(115),r=t(75).f;t(83)("getOwnPropertyDescriptor",function(){return function(t,e){return r(a(t),e)}})},{115:115,75:75,83:83}],195:[function(t,e,n){t(83)("getOwnPropertyNames",function(){return t(76).f})},{76:76,83:83}],196:[function(t,e,n){var a=t(117),r=t(79);t(83)("getPrototypeOf",function(){return function(t){return r(a(t))}})},{117:117,79:79,83:83}],197:[function(t,e,n){var a=t(52);t(83)("isExtensible",function(t){return function(e){return a(e)?t?t(e):!0:!1}}); -},{52:52,83:83}],198:[function(t,e,n){var a=t(52);t(83)("isFrozen",function(t){return function(e){return a(e)?t?t(e):!1:!0}})},{52:52,83:83}],199:[function(t,e,n){var a=t(52);t(83)("isSealed",function(t){return function(e){return a(e)?t?t(e):!1:!0}})},{52:52,83:83}],200:[function(t,e,n){var a=t(34);a(a.S,"Object",{is:t(94)})},{34:34,94:94}],201:[function(t,e,n){var a=t(117),r=t(81);t(83)("keys",function(){return function(t){return r(a(t))}})},{117:117,81:81,83:83}],202:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("preventExtensions",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],203:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("seal",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],204:[function(t,e,n){var a=t(34);a(a.S,"Object",{setPrototypeOf:t(97).set})},{34:34,97:97}],205:[function(t,e,n){"use strict";var a=t(18),r={};r[t(127)("toStringTag")]="z",r+""!="[object z]"&&t(92)(Object.prototype,"toString",function(){return"[object "+a(this)+"]"},!0)},{127:127,18:18,92:92}],206:[function(t,e,n){var a=t(34),r=t(86);a(a.G+a.F*(parseFloat!=r),{parseFloat:r})},{34:34,86:86}],207:[function(t,e,n){var a=t(34),r=t(87);a(a.G+a.F*(parseInt!=r),{parseInt:r})},{34:34,87:87}],208:[function(t,e,n){"use strict";var a,r,i,o,s=t(60),p=t(41),u=t(26),c=t(18),l=t(34),d=t(52),f=t(4),h=t(7),m=t(40),g=t(102),v=t(111).set,b=t(68)(),y=t(69),_=t(88),x=t(123),w=t(89),k="Promise",S=p.TypeError,E=p.process,C=E&&E.versions,P=C&&C.v8||"",A=p[k],O="process"==c(E),T=function(){},R=r=y.f,M=!!function(){try{var e=A.resolve(1),n=(e.constructor={})[t(127)("species")]=function(t){t(T,T)};return(O||"function"==typeof PromiseRejectionEvent)&&e.then(T)instanceof n&&0!==P.indexOf("6.6")&&-1===x.indexOf("Chrome/66")}catch(a){}}(),L=function(t){var e;return d(t)&&"function"==typeof(e=t.then)?e:!1},j=function(t,e){if(!t._n){t._n=!0;var n=t._c;b(function(){for(var a=t._v,r=1==t._s,i=0,o=function(e){var n,i,o,s=r?e.ok:e.fail,p=e.resolve,u=e.reject,c=e.domain;try{s?(r||(2==t._h&&F(t),t._h=1),s===!0?n=a:(c&&c.enter(),n=s(a),c&&(c.exit(),o=!0)),n===e.promise?u(S("Promise-chain cycle")):(i=L(n))?i.call(n,p,u):p(n)):u(a)}catch(l){c&&!o&&c.exit(),u(l)}};n.length>i;)o(n[i++]);t._c=[],t._n=!1,e&&!t._h&&D(t)})}},D=function(t){v.call(p,function(){var e,n,a,r=t._v,i=N(t);if(i&&(e=_(function(){O?E.emit("unhandledRejection",r,t):(n=p.onunhandledrejection)?n({promise:t,reason:r}):(a=p.console)&&a.error&&a.error("Unhandled promise rejection",r)}),t._h=O||N(t)?2:1),t._a=void 0,i&&e.e)throw e.v})},N=function(t){return 1!==t._h&&0===(t._a||t._c).length},F=function(t){v.call(p,function(){var e;O?E.emit("rejectionHandled",t):(e=p.onrejectionhandled)&&e({promise:t,reason:t._v})})},I=function(t){var e=this;e._d||(e._d=!0,e=e._w||e,e._v=t,e._s=2,e._a||(e._a=e._c.slice()),j(e,!0))},B=function(t){var e,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===t)throw S("Promise can't be resolved itself");(e=L(t))?b(function(){var a={_w:n,_d:!1};try{e.call(t,u(B,a,1),u(I,a,1))}catch(r){I.call(a,r)}}):(n._v=t,n._s=1,j(n,!1))}catch(a){I.call({_w:n,_d:!1},a)}}};M||(A=function(t){h(this,A,k,"_h"),f(t),a.call(this);try{t(u(B,this,1),u(I,this,1))}catch(e){I.call(this,e)}},a=function(t){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1},a.prototype=t(91)(A.prototype,{then:function(t,e){var n=R(g(this,A));return n.ok="function"==typeof t?t:!0,n.fail="function"==typeof e&&e,n.domain=O?E.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&j(this,!1),n.promise},"catch":function(t){return this.then(void 0,t)}}),i=function(){var t=new a;this.promise=t,this.resolve=u(B,t,1),this.reject=u(I,t,1)},y.f=R=function(t){return t===A||t===o?new i(t):r(t)}),l(l.G+l.W+l.F*!M,{Promise:A}),t(99)(A,k),t(98)(k),o=t(24)[k],l(l.S+l.F*!M,k,{reject:function(t){var e=R(this),n=e.reject;return n(t),e.promise}}),l(l.S+l.F*(s||!M),k,{resolve:function(t){return w(s&&this===o?A:this,t)}}),l(l.S+l.F*!(M&&t(57)(function(t){A.all(t)["catch"](T)})),k,{all:function(t){var e=this,n=R(e),a=n.resolve,r=n.reject,i=_(function(){var n=[],i=0,o=1;m(t,!1,function(t){var s=i++,p=!1;n.push(void 0),o++,e.resolve(t).then(function(t){p||(p=!0,n[s]=t,--o||a(n))},r)}),--o||a(n)});return i.e&&r(i.v),n.promise},race:function(t){var e=this,n=R(e),a=n.reject,r=_(function(){m(t,!1,function(t){e.resolve(t).then(n.resolve,a)})});return r.e&&a(r.v),n.promise}})},{102:102,111:111,123:123,127:127,18:18,24:24,26:26,34:34,4:4,40:40,41:41,52:52,57:57,60:60,68:68,69:69,7:7,88:88,89:89,91:91,98:98,99:99}],209:[function(t,e,n){var a=t(34),r=t(4),i=t(8),o=(t(41).Reflect||{}).apply,s=Function.apply;a(a.S+a.F*!t(36)(function(){o(function(){})}),"Reflect",{apply:function(t,e,n){var a=r(t),p=i(n);return o?o(a,e,p):s.call(a,e,p)}})},{34:34,36:36,4:4,41:41,8:8}],210:[function(t,e,n){var a=t(34),r=t(71),i=t(4),o=t(8),s=t(52),p=t(36),u=t(17),c=(t(41).Reflect||{}).construct,l=p(function(){function t(){}return!(c(function(){},[],t)instanceof t)}),d=!p(function(){c(function(){})});a(a.S+a.F*(l||d),"Reflect",{construct:function(t,e){i(t),o(e);var n=arguments.length<3?t:i(arguments[2]);if(d&&!l)return c(t,e,n);if(t==n){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var a=[null];return a.push.apply(a,e),new(u.apply(t,a))}var p=n.prototype,f=r(s(p)?p:Object.prototype),h=Function.apply.call(t,f,e);return s(h)?h:f}})},{17:17,34:34,36:36,4:4,41:41,52:52,71:71,8:8}],211:[function(t,e,n){var a=t(72),r=t(34),i=t(8),o=t(118);r(r.S+r.F*t(36)(function(){Reflect.defineProperty(a.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(t,e,n){i(t),e=o(e,!0),i(n);try{return a.f(t,e,n),!0}catch(r){return!1}}})},{118:118,34:34,36:36,72:72,8:8}],212:[function(t,e,n){var a=t(34),r=t(75).f,i=t(8);a(a.S,"Reflect",{deleteProperty:function(t,e){var n=r(i(t),e);return n&&!n.configurable?!1:delete t[e]}})},{34:34,75:75,8:8}],213:[function(t,e,n){"use strict";var a=t(34),r=t(8),i=function(t){this._t=r(t),this._i=0;var e,n=this._k=[];for(e in t)n.push(e)};t(55)(i,"Object",function(){var t,e=this,n=e._k;do if(e._i>=n.length)return{value:void 0,done:!0};while(!((t=n[e._i++])in e._t));return{value:t,done:!1}}),a(a.S,"Reflect",{enumerate:function(t){return new i(t)}})},{34:34,55:55,8:8}],214:[function(t,e,n){var a=t(75),r=t(34),i=t(8);r(r.S,"Reflect",{getOwnPropertyDescriptor:function(t,e){return a.f(i(t),e)}})},{34:34,75:75,8:8}],215:[function(t,e,n){var a=t(34),r=t(79),i=t(8);a(a.S,"Reflect",{getPrototypeOf:function(t){return r(i(t))}})},{34:34,79:79,8:8}],216:[function(t,e,n){function a(t,e){var n,s,c=arguments.length<3?t:arguments[2];return u(t)===c?t[e]:(n=r.f(t,e))?o(n,"value")?n.value:void 0!==n.get?n.get.call(c):void 0:p(s=i(t))?a(s,e,c):void 0}var r=t(75),i=t(79),o=t(42),s=t(34),p=t(52),u=t(8);s(s.S,"Reflect",{get:a})},{34:34,42:42,52:52,75:75,79:79,8:8}],217:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{has:function(t,e){return e in t}})},{34:34}],218:[function(t,e,n){var a=t(34),r=t(8),i=Object.isExtensible;a(a.S,"Reflect",{isExtensible:function(t){return r(t),i?i(t):!0}})},{34:34,8:8}],219:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{ownKeys:t(85)})},{34:34,85:85}],220:[function(t,e,n){var a=t(34),r=t(8),i=Object.preventExtensions;a(a.S,"Reflect",{preventExtensions:function(t){r(t);try{return i&&i(t),!0}catch(e){return!1}}})},{34:34,8:8}],221:[function(t,e,n){var a=t(34),r=t(97);r&&a(a.S,"Reflect",{setPrototypeOf:function(t,e){r.check(t,e);try{return r.set(t,e),!0}catch(n){return!1}}})},{34:34,97:97}],222:[function(t,e,n){function a(t,e,n){var p,d,f=arguments.length<4?t:arguments[3],h=i.f(c(t),e);if(!h){if(l(d=o(t)))return a(d,e,n,f);h=u(0)}if(s(h,"value")){if(h.writable===!1||!l(f))return!1;if(p=i.f(f,e)){if(p.get||p.set||p.writable===!1)return!1;p.value=n,r.f(f,e,p)}else r.f(f,e,u(0,n));return!0}return void 0===h.set?!1:(h.set.call(f,n),!0)}var r=t(72),i=t(75),o=t(79),s=t(42),p=t(34),u=t(90),c=t(8),l=t(52);p(p.S,"Reflect",{set:a})},{34:34,42:42,52:52,72:72,75:75,79:79,8:8,90:90}],223:[function(t,e,n){var a=t(41),r=t(46),i=t(72).f,o=t(77).f,s=t(53),p=t(38),u=a.RegExp,c=u,l=u.prototype,d=/a/g,f=/a/g,h=new u(d)!==d;if(t(30)&&(!h||t(36)(function(){return f[t(127)("match")]=!1,u(d)!=d||u(f)==f||"/a/i"!=u(d,"i")}))){u=function(t,e){var n=this instanceof u,a=s(t),i=void 0===e;return!n&&a&&t.constructor===u&&i?t:r(h?new c(a&&!i?t.source:t,e):c((a=t instanceof u)?t.source:t,a&&i?p.call(t):e),n?this:l,u)};for(var m=(function(t){t in u||i(u,t,{configurable:!0,get:function(){return c[t]},set:function(e){c[t]=e}})}),g=o(c),v=0;g.length>v;)m(g[v++]);l.constructor=u,u.prototype=l,t(92)(a,"RegExp",u)}t(98)("RegExp")},{127:127,30:30,36:36,38:38,41:41,46:46,53:53,72:72,77:77,92:92,98:98}],224:[function(t,e,n){t(30)&&"g"!=/./g.flags&&t(72).f(RegExp.prototype,"flags",{configurable:!0,get:t(38)})},{30:30,38:38,72:72}],225:[function(t,e,n){t(37)("match",1,function(t,e,n){return[function(n){"use strict";var a=t(this),r=void 0==n?void 0:n[e];return void 0!==r?r.call(n,a):RegExp(n)[e](a+"")},n]})},{37:37}],226:[function(t,e,n){t(37)("replace",2,function(t,e,n){return[function(a,r){"use strict";var i=t(this),o=void 0==a?void 0:a[e];return void 0!==o?o.call(a,i,r):n.call(i+"",a,r)},n]})},{37:37}],227:[function(t,e,n){t(37)("search",1,function(t,e,n){return[function(n){"use strict";var a=t(this),r=void 0==n?void 0:n[e];return void 0!==r?r.call(n,a):RegExp(n)[e](a+"")},n]})},{37:37}],228:[function(t,e,n){t(37)("split",2,function(e,n,a){"use strict";var r=t(53),i=a,o=[].push,s="split",p="length",u="lastIndex";if("c"=="abbc"[s](/(b)*/)[1]||4!="test"[s](/(?:)/,-1)[p]||2!="ab"[s](/(?:ab)*/)[p]||4!="."[s](/(.?)(.?)/)[p]||"."[s](/()()/)[p]>1||""[s](/.?/)[p]){var c=void 0===/()??/.exec("")[1];a=function(t,e){var n=this+"";if(void 0===t&&0===e)return[];if(!r(t))return i.call(n,t,e);var a,s,l,d,f,h=[],m=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),g=0,v=void 0===e?4294967295:e>>>0,b=RegExp(t.source,m+"g");for(c||(a=RegExp("^"+b.source+"$(?!\\s)",m));(s=b.exec(n))&&(l=s.index+s[0][p],!(l>g&&(h.push(n.slice(g,s.index)),!c&&s[p]>1&&s[0].replace(a,function(){for(f=1;f1&&s.index=v)));)b[u]===s.index&&b[u]++;return g===n[p]?(d||!b.test(""))&&h.push(""):h.push(n.slice(g)),h[p]>v?h.slice(0,v):h}}else"0"[s](void 0,0)[p]&&(a=function(t,e){return void 0===t&&0===e?[]:i.call(this,t,e)});return[function(t,r){var i=e(this),o=void 0==t?void 0:t[n];return void 0!==o?o.call(t,i,r):a.call(i+"",t,r)},a]})},{37:37,53:53}],229:[function(t,e,n){"use strict";t(224);var a=t(8),r=t(38),i=t(30),o="toString",s=/./[o],p=function(e){t(92)(RegExp.prototype,o,e,!0)};t(36)(function(){return"/a/b"!=s.call({source:"a",flags:"b"})})?p(function(){var t=a(this);return"/".concat(t.source,"/","flags"in t?t.flags:!i&&t instanceof RegExp?r.call(t):void 0)}):s.name!=o&&p(function(){return s.call(this)})},{224:224,30:30,36:36,38:38,8:8,92:92}],230:[function(t,e,n){"use strict";var a=t(20),r=t(124),i="Set";e.exports=t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return a.def(r(this,i),t=0===t?0:t,t)}},a)},{124:124,20:20,23:23}],231:[function(t,e,n){"use strict";t(106)("anchor",function(t){return function(e){return t(this,"a","name",e)}})},{106:106}],232:[function(t,e,n){"use strict";t(106)("big",function(t){return function(){return t(this,"big","","")}})},{106:106}],233:[function(t,e,n){"use strict";t(106)("blink",function(t){return function(){return t(this,"blink","","")}})},{106:106}],234:[function(t,e,n){"use strict";t(106)("bold",function(t){return function(){return t(this,"b","","")}})},{106:106}],235:[function(t,e,n){"use strict";var a=t(34),r=t(104)(!1);a(a.P,"String",{codePointAt:function(t){return r(this,t)}})},{104:104,34:34}],236:[function(t,e,n){"use strict";var a=t(34),r=t(116),i=t(105),o="endsWith",s=""[o];a(a.P+a.F*t(35)(o),"String",{endsWith:function(t){var e=i(this,t,o),n=arguments.length>1?arguments[1]:void 0,a=r(e.length),p=void 0===n?a:Math.min(r(n),a),u=t+"";return s?s.call(e,u,p):e.slice(p-u.length,p)===u}})},{105:105,116:116,34:34,35:35}],237:[function(t,e,n){"use strict";t(106)("fixed",function(t){return function(){return t(this,"tt","","")}})},{106:106}],238:[function(t,e,n){"use strict";t(106)("fontcolor",function(t){return function(e){return t(this,"font","color",e)}})},{106:106}],239:[function(t,e,n){"use strict";t(106)("fontsize",function(t){return function(e){return t(this,"font","size",e)}})},{106:106}],240:[function(t,e,n){var a=t(34),r=t(112),i=String.fromCharCode,o=String.fromCodePoint;a(a.S+a.F*(!!o&&1!=o.length),"String",{fromCodePoint:function(t){for(var e,n=[],a=arguments.length,o=0;a>o;){if(e=+arguments[o++],r(e,1114111)!==e)throw RangeError(e+" is not a valid code point");n.push(65536>e?i(e):i(((e-=65536)>>10)+55296,e%1024+56320))}return n.join("")}})},{112:112,34:34}],241:[function(t,e,n){"use strict";var a=t(34),r=t(105),i="includes";a(a.P+a.F*t(35)(i),"String",{includes:function(t){return!!~r(this,t,i).indexOf(t,arguments.length>1?arguments[1]:void 0)}})},{105:105,34:34,35:35}],242:[function(t,e,n){"use strict";t(106)("italics",function(t){return function(){return t(this,"i","","")}})},{106:106}],243:[function(t,e,n){"use strict";var a=t(104)(!0);t(56)(String,"String",function(t){this._t=t+"",this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=a(e,n),this._i+=t.length,{value:t,done:!1})})},{104:104,56:56}],244:[function(t,e,n){"use strict";t(106)("link",function(t){return function(e){return t(this,"a","href",e)}})},{106:106}],245:[function(t,e,n){var a=t(34),r=t(115),i=t(116);a(a.S,"String",{raw:function(t){for(var e=r(t.raw),n=i(e.length),a=arguments.length,o=[],s=0;n>s;)o.push(e[s++]+""),a>s&&o.push(arguments[s]+"");return o.join("")}})},{115:115,116:116,34:34}],246:[function(t,e,n){var a=t(34);a(a.P,"String",{repeat:t(108)})},{108:108,34:34}],247:[function(t,e,n){"use strict";t(106)("small",function(t){return function(){return t(this,"small","","")}})},{106:106}],248:[function(t,e,n){"use strict";var a=t(34),r=t(116),i=t(105),o="startsWith",s=""[o];a(a.P+a.F*t(35)(o),"String",{startsWith:function(t){var e=i(this,t,o),n=r(Math.min(arguments.length>1?arguments[1]:void 0,e.length)),a=t+"";return s?s.call(e,a,n):e.slice(n,n+a.length)===a}})},{105:105,116:116,34:34,35:35}],249:[function(t,e,n){"use strict";t(106)("strike",function(t){return function(){return t(this,"strike","","")}})},{106:106}],250:[function(t,e,n){"use strict";t(106)("sub",function(t){return function(){return t(this,"sub","","")}})},{106:106}],251:[function(t,e,n){"use strict";t(106)("sup",function(t){return function(){return t(this,"sup","","")}})},{106:106}],252:[function(t,e,n){"use strict";t(109)("trim",function(t){return function(){return t(this,3)}})},{109:109}],253:[function(t,e,n){"use strict";var a=t(41),r=t(42),i=t(30),o=t(34),s=t(92),p=t(66).KEY,u=t(36),c=t(101),l=t(99),d=t(122),f=t(127),h=t(126),m=t(125),g=t(33),v=t(50),b=t(8),y=t(52),_=t(115),x=t(118),w=t(90),k=t(71),S=t(76),E=t(75),C=t(72),P=t(81),A=E.f,O=C.f,T=S.f,R=a.Symbol,M=a.JSON,L=M&&M.stringify,j="prototype",D=f("_hidden"),N=f("toPrimitive"),F={}.propertyIsEnumerable,I=c("symbol-registry"),B=c("symbols"),U=c("op-symbols"),V=Object[j],q="function"==typeof R,G=a.QObject,z=!G||!G[j]||!G[j].findChild,W=i&&u(function(){return 7!=k(O({},"a",{get:function(){return O(this,"a",{value:7}).a}})).a})?function(t,e,n){var a=A(V,e);a&&delete V[e],O(t,e,n),a&&t!==V&&O(V,e,a)}:O,H=function(t){var e=B[t]=k(R[j]);return e._k=t,e},K=q&&"symbol"==typeof R.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof R},Q=function(t,e,n){return t===V&&Q(U,e,n),b(t),e=x(e,!0),b(n),r(B,e)?(n.enumerable?(r(t,D)&&t[D][e]&&(t[D][e]=!1),n=k(n,{enumerable:w(0,!1)})):(r(t,D)||O(t,D,w(1,{})),t[D][e]=!0),W(t,e,n)):O(t,e,n)},Y=function(t,e){b(t);for(var n,a=g(e=_(e)),r=0,i=a.length;i>r;)Q(t,n=a[r++],e[n]);return t},$=function(t,e){return void 0===e?k(t):Y(k(t),e)},J=function(t){var e=F.call(this,t=x(t,!0));return this===V&&r(B,t)&&!r(U,t)?!1:e||!r(this,t)||!r(B,t)||r(this,D)&&this[D][t]?e:!0},X=function(t,e){if(t=_(t),e=x(e,!0),t!==V||!r(B,e)||r(U,e)){var n=A(t,e);return!n||!r(B,e)||r(t,D)&&t[D][e]||(n.enumerable=!0),n}},Z=function(t){for(var e,n=T(_(t)),a=[],i=0;n.length>i;)r(B,e=n[i++])||e==D||e==p||a.push(e);return a},tt=function(t){for(var e,n=t===V,a=T(n?U:_(t)),i=[],o=0;a.length>o;)r(B,e=a[o++])&&(n?r(V,e):!0)&&i.push(B[e]);return i};q||(R=function(){if(this instanceof R)throw TypeError("Symbol is not a constructor!");var t=d(arguments.length>0?arguments[0]:void 0),e=function(n){this===V&&e.call(U,n),r(this,D)&&r(this[D],t)&&(this[D][t]=!1),W(this,t,w(1,n))};return i&&z&&W(V,t,{configurable:!0,set:e}),H(t)},s(R[j],"toString",function(){return this._k}),E.f=X,C.f=Q,t(77).f=S.f=Z,t(82).f=J,t(78).f=tt,i&&!t(60)&&s(V,"propertyIsEnumerable",J,!0),h.f=function(t){return H(f(t))}),o(o.G+o.W+o.F*!q,{Symbol:R});for(var et="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),nt=0;et.length>nt;)f(et[nt++]);for(var at=P(f.store),rt=0;at.length>rt;)m(at[rt++]);o(o.S+o.F*!q,"Symbol",{"for":function(t){return r(I,t+="")?I[t]:I[t]=R(t)},keyFor:function(t){if(!K(t))throw TypeError(t+" is not a symbol!");for(var e in I)if(I[e]===t)return e},useSetter:function(){z=!0},useSimple:function(){z=!1}}),o(o.S+o.F*!q,"Object",{create:$,defineProperty:Q,defineProperties:Y,getOwnPropertyDescriptor:X,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),M&&o(o.S+o.F*(!q||u(function(){var t=R();return"[null]"!=L([t])||"{}"!=L({a:t})||"{}"!=L(Object(t))})),"JSON",{stringify:function(t){for(var e,n,a=[t],r=1;arguments.length>r;)a.push(arguments[r++]);return n=e=a[1],!y(e)&&void 0===t||K(t)?void 0:(v(e)||(e=function(t,e){return"function"==typeof n&&(e=n.call(this,t,e)),K(e)?void 0:e}),a[1]=e,L.apply(M,a))}}),R[j][N]||t(43)(R[j],N,R[j].valueOf),l(R,"Symbol"),l(Math,"Math",!0),l(a.JSON,"JSON",!0)},{101:101,115:115,118:118,122:122,125:125,126:126,127:127,30:30,33:33,34:34,36:36,41:41,42:42,43:43,50:50,52:52,60:60,66:66,71:71,72:72,75:75,76:76,77:77,78:78,8:8,81:81,82:82,90:90,92:92,99:99}],254:[function(t,e,n){"use strict";var a=t(34),r=t(121),i=t(120),o=t(8),s=t(112),p=t(116),u=t(52),c=t(41).ArrayBuffer,l=t(102),d=i.ArrayBuffer,f=i.DataView,h=r.ABV&&c.isView,m=d.prototype.slice,g=r.VIEW,v="ArrayBuffer";a(a.G+a.W+a.F*(c!==d),{ArrayBuffer:d}),a(a.S+a.F*!r.CONSTR,v,{isView:function(t){return h&&h(t)||u(t)&&g in t}}),a(a.P+a.U+a.F*t(36)(function(){return!new d(2).slice(1,void 0).byteLength}),v,{slice:function(t,e){if(void 0!==m&&void 0===e)return m.call(o(this),t);for(var n=o(this).byteLength,a=s(t,n),r=s(void 0===e?n:e,n),i=new(l(this,d))(p(r-a)),u=new f(this),c=new f(i),h=0;r>a;)c.setUint8(h++,u.getUint8(a++));return i}}),t(98)(v)},{102:102,112:112,116:116,120:120,121:121,34:34,36:36,41:41,52:52,8:8,98:98}],255:[function(t,e,n){var a=t(34);a(a.G+a.W+a.F*!t(121).ABV,{DataView:t(120).DataView})},{120:120,121:121,34:34}],256:[function(t,e,n){t(119)("Float32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],257:[function(t,e,n){t(119)("Float64",8,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],258:[function(t,e,n){t(119)("Int16",2,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],259:[function(t,e,n){t(119)("Int32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],260:[function(t,e,n){t(119)("Int8",1,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],261:[function(t,e,n){t(119)("Uint16",2,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],262:[function(t,e,n){t(119)("Uint32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],263:[function(t,e,n){t(119)("Uint8",1,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],264:[function(t,e,n){t(119)("Uint8",1,function(t){return function(e,n,a){return t(this,e,n,a)}},!0)},{119:119}],265:[function(t,e,n){"use strict";var a,r=t(13)(0),i=t(92),o=t(66),s=t(70),p=t(22),u=t(52),c=t(36),l=t(124),d="WeakMap",f=o.getWeak,h=Object.isExtensible,m=p.ufstore,g={},v=function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},b={get:function(t){if(u(t)){var e=f(t);return e===!0?m(l(this,d)).get(t):e?e[this._i]:void 0}},set:function(t,e){return p.def(l(this,d),t,e)}},y=e.exports=t(23)(d,v,b,p,!0,!0);c(function(){return 7!=(new y).set((Object.freeze||Object)(g),7).get(g)})&&(a=p.getConstructor(v,d),s(a.prototype,b),o.NEED=!0,r(["delete","has","get","set"],function(t){var e=y.prototype,n=e[t];i(e,t,function(e,r){if(u(e)&&!h(e)){this._f||(this._f=new a);var i=this._f[t](e,r);return"set"==t?this:i}return n.call(this,e,r)})}))},{124:124,13:13,22:22,23:23,36:36,52:52,66:66,70:70,92:92}],266:[function(t,e,n){"use strict";var a=t(22),r=t(124),i="WeakSet";t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return a.def(r(this,i),t,!0)}},a,!1,!0)},{124:124,22:22,23:23}],267:[function(t,e,n){"use strict";var a=t(34),r=t(39),i=t(117),o=t(116),s=t(4),p=t(16);a(a.P,"Array",{flatMap:function(t){var e,n,a=i(this);return s(t),e=o(a.length),n=p(a,0),r(n,a,a,e,0,1,t,arguments[1]),n}}),t(6)("flatMap")},{116:116,117:117,16:16,34:34,39:39,4:4,6:6}],268:[function(t,e,n){"use strict";var a=t(34),r=t(39),i=t(117),o=t(116),s=t(114),p=t(16);a(a.P,"Array",{flatten:function(){var t=arguments[0],e=i(this),n=o(e.length),a=p(e,0);return r(a,e,e,n,0,void 0===t?1:s(t)),a}}),t(6)("flatten")},{114:114,116:116,117:117,16:16,34:34,39:39,6:6}],269:[function(t,e,n){"use strict";var a=t(34),r=t(12)(!0);a(a.P,"Array",{includes:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)("includes")},{12:12,34:34,6:6}],270:[function(t,e,n){var a=t(34),r=t(68)(),i=t(41).process,o="process"==t(19)(i);a(a.G,{asap:function(t){var e=o&&i.domain;r(e?e.bind(t):t)}})},{19:19,34:34,41:41,68:68}],271:[function(t,e,n){var a=t(34),r=t(19);a(a.S,"Error",{isError:function(t){return"Error"===r(t)}})},{19:19,34:34}],272:[function(t,e,n){var a=t(34);a(a.G,{global:t(41)})},{34:34,41:41}],273:[function(t,e,n){t(95)("Map")},{95:95}],274:[function(t,e,n){t(96)("Map")},{96:96}],275:[function(t,e,n){var a=t(34);a(a.P+a.R,"Map",{toJSON:t(21)("Map")})},{21:21,34:34}],276:[function(t,e,n){var a=t(34);a(a.S,"Math",{clamp:function(t,e,n){return Math.min(n,Math.max(e,t))}})},{34:34}],277:[function(t,e,n){var a=t(34);a(a.S,"Math",{DEG_PER_RAD:Math.PI/180})},{34:34}],278:[function(t,e,n){var a=t(34),r=180/Math.PI;a(a.S,"Math",{degrees:function(t){return t*r}})},{34:34}],279:[function(t,e,n){var a=t(34),r=t(64),i=t(62);a(a.S,"Math",{fscale:function(t,e,n,a,o){return i(r(t,e,n,a,o))}})},{34:34,62:62,64:64}],280:[function(t,e,n){var a=t(34);a(a.S,"Math",{iaddh:function(t,e,n,a){var r=t>>>0,i=e>>>0,o=n>>>0;return i+(a>>>0)+((r&o|(r|o)&~(r+o>>>0))>>>31)|0}})},{34:34}],281:[function(t,e,n){var a=t(34);a(a.S,"Math",{imulh:function(t,e){var n=65535,a=+t,r=+e,i=a&n,o=r&n,s=a>>16,p=r>>16,u=(s*o>>>0)+(i*o>>>16);return s*p+(u>>16)+((i*p>>>0)+(u&n)>>16)}})},{34:34}],282:[function(t,e,n){var a=t(34);a(a.S,"Math",{isubh:function(t,e,n,a){var r=t>>>0,i=e>>>0,o=n>>>0;return i-(a>>>0)-((~r&o|~(r^o)&r-o>>>0)>>>31)|0}})},{34:34}],283:[function(t,e,n){var a=t(34);a(a.S,"Math",{RAD_PER_DEG:180/Math.PI})},{34:34}],284:[function(t,e,n){var a=t(34),r=Math.PI/180;a(a.S,"Math",{radians:function(t){return t*r}})},{34:34}],285:[function(t,e,n){var a=t(34);a(a.S,"Math",{scale:t(64)})},{34:34,64:64}],286:[function(t,e,n){var a=t(34);a(a.S,"Math",{signbit:function(t){return(t=+t)!=t?t:0==t?1/t==1/0:t>0}})},{34:34}],287:[function(t,e,n){var a=t(34);a(a.S,"Math",{umulh:function(t,e){var n=65535,a=+t,r=+e,i=a&n,o=r&n,s=a>>>16,p=r>>>16,u=(s*o>>>0)+(i*o>>>16);return s*p+(u>>>16)+((i*p>>>0)+(u&n)>>>16)}})},{34:34}],288:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineGetter__:function(t,e){o.f(r(this),t,{get:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],289:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineSetter__:function(t,e){o.f(r(this),t,{set:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],290:[function(t,e,n){var a=t(34),r=t(84)(!0);a(a.S,"Object",{entries:function(t){return r(t)}})},{34:34,84:84}],291:[function(t,e,n){var a=t(34),r=t(85),i=t(115),o=t(75),s=t(25);a(a.S,"Object",{getOwnPropertyDescriptors:function(t){for(var e,n,a=i(t),p=o.f,u=r(a),c={},l=0;u.length>l;)n=p(a,e=u[l++]),void 0!==n&&s(c,e,n);return c}})},{115:115,25:25,34:34,75:75,85:85}],292:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupGetter__:function(t){var e,n=r(this),a=i(t,!0);do if(e=s(n,a))return e.get;while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],293:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupSetter__:function(t){var e,n=r(this),a=i(t,!0);do if(e=s(n,a))return e.set;while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],294:[function(t,e,n){var a=t(34),r=t(84)(!1);a(a.S,"Object",{values:function(t){return r(t)}})},{34:34,84:84}],295:[function(t,e,n){"use strict";var a=t(34),r=t(41),i=t(24),o=t(68)(),s=t(127)("observable"),p=t(4),u=t(8),c=t(7),l=t(91),d=t(43),f=t(40),h=f.RETURN,m=function(t){return null==t?void 0:p(t)},g=function(t){var e=t._c;e&&(t._c=void 0,e())},v=function(t){return void 0===t._o},b=function(t){v(t)||(t._o=void 0,g(t))},y=function(t,e){u(t),this._c=void 0,this._o=t,t=new _(this);try{var n=e(t),a=n;null!=n&&("function"==typeof n.unsubscribe?n=function(){a.unsubscribe()}:p(n),this._c=n)}catch(r){return void t.error(r)}v(this)&&g(this)};y.prototype=l({},{unsubscribe:function(){b(this)}});var _=function(t){this._s=t};_.prototype=l({},{next:function(t){var e=this._s;if(!v(e)){var n=e._o;try{var a=m(n.next);if(a)return a.call(n,t)}catch(r){try{b(e)}finally{throw r}}}},error:function(t){var e=this._s;if(v(e))throw t;var n=e._o;e._o=void 0;try{var a=m(n.error);if(!a)throw t;t=a.call(n,t)}catch(r){try{g(e)}finally{throw r}}return g(e),t},complete:function(t){var e=this._s;if(!v(e)){var n=e._o;e._o=void 0;try{var a=m(n.complete);t=a?a.call(n,t):void 0}catch(r){try{g(e)}finally{throw r}}return g(e),t}}});var x=function(t){c(this,x,"Observable","_f")._f=p(t)};l(x.prototype,{subscribe:function(t){return new y(t,this._f)},forEach:function(t){var e=this;return new(i.Promise||r.Promise)(function(n,a){p(t);var r=e.subscribe({next:function(e){try{return t(e)}catch(n){a(n),r.unsubscribe()}},error:a,complete:n})})}}),l(x,{from:function(t){var e="function"==typeof this?this:x,n=m(u(t)[s]);if(n){var a=u(n.call(t));return a.constructor===e?a:new e(function(t){return a.subscribe(t)})}return new e(function(e){var n=!1;return o(function(){if(!n){try{if(f(t,!1,function(t){return e.next(t),n?h:void 0})===h)return}catch(a){if(n)throw a;return void e.error(a)}e.complete()}}),function(){n=!0}})},of:function(){for(var t=0,e=arguments.length,n=Array(e);e>t;)n[t]=arguments[t++];return new("function"==typeof this?this:x)(function(t){var e=!1;return o(function(){if(!e){for(var a=0;a1?arguments[1]:void 0,!1)}})},{107:107,123:123,34:34}],313:[function(t,e,n){"use strict";var a=t(34),r=t(107),i=t(123);a(a.P+a.F*/Version\/10\.\d+(\.\d+)? Safari\//.test(i),"String",{padStart:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0,!0)}})},{107:107,123:123,34:34}],314:[function(t,e,n){"use strict";t(109)("trimLeft",function(t){return function(){return t(this,1)}},"trimStart")},{109:109}],315:[function(t,e,n){"use strict";t(109)("trimRight",function(t){return function(){return t(this,2)}},"trimEnd")},{109:109}],316:[function(t,e,n){t(125)("asyncIterator")},{125:125}],317:[function(t,e,n){t(125)("observable")},{125:125}],318:[function(t,e,n){var a=t(34);a(a.S,"System",{global:t(41) -})},{34:34,41:41}],319:[function(t,e,n){t(95)("WeakMap")},{95:95}],320:[function(t,e,n){t(96)("WeakMap")},{96:96}],321:[function(t,e,n){t(95)("WeakSet")},{95:95}],322:[function(t,e,n){t(96)("WeakSet")},{96:96}],323:[function(t,e,n){for(var a=t(140),r=t(81),i=t(92),o=t(41),s=t(43),p=t(59),u=t(127),c=u("iterator"),l=u("toStringTag"),d=p.Array,f={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=r(f),m=0;m2,r=a?o.call(arguments,2):!1;return t(a?function(){("function"==typeof e?e:Function(e)).apply(this,r)}:e,n)}};r(r.G+r.B+r.F*s,{setTimeout:p(a.setTimeout),setInterval:p(a.setInterval)})},{123:123,34:34,41:41}],326:[function(t,e,n){t(253),t(190),t(192),t(191),t(194),t(196),t(201),t(195),t(193),t(203),t(202),t(198),t(199),t(197),t(189),t(200),t(204),t(205),t(156),t(158),t(157),t(207),t(206),t(177),t(187),t(188),t(178),t(179),t(180),t(181),t(182),t(183),t(184),t(185),t(186),t(160),t(161),t(162),t(163),t(164),t(165),t(166),t(167),t(168),t(169),t(170),t(171),t(172),t(173),t(174),t(175),t(176),t(240),t(245),t(252),t(243),t(235),t(236),t(241),t(246),t(248),t(231),t(232),t(233),t(234),t(237),t(238),t(239),t(242),t(244),t(247),t(249),t(250),t(251),t(151),t(153),t(152),t(155),t(154),t(139),t(137),t(144),t(141),t(147),t(149),t(136),t(143),t(133),t(148),t(131),t(146),t(145),t(138),t(142),t(130),t(132),t(135),t(134),t(150),t(140),t(223),t(229),t(224),t(225),t(226),t(227),t(228),t(208),t(159),t(230),t(265),t(266),t(254),t(255),t(260),t(263),t(264),t(258),t(261),t(259),t(262),t(256),t(257),t(209),t(210),t(211),t(212),t(213),t(216),t(214),t(215),t(217),t(218),t(219),t(220),t(222),t(221),t(269),t(267),t(268),t(310),t(313),t(312),t(314),t(315),t(311),t(316),t(317),t(291),t(294),t(290),t(288),t(289),t(292),t(293),t(275),t(309),t(274),t(308),t(320),t(322),t(273),t(307),t(319),t(321),t(272),t(318),t(271),t(276),t(277),t(278),t(279),t(280),t(282),t(281),t(283),t(284),t(285),t(287),t(286),t(296),t(297),t(298),t(299),t(301),t(300),t(303),t(302),t(304),t(305),t(306),t(270),t(295),t(325),t(324),t(323),e.exports=t(24)},{130:130,131:131,132:132,133:133,134:134,135:135,136:136,137:137,138:138,139:139,140:140,141:141,142:142,143:143,144:144,145:145,146:146,147:147,148:148,149:149,150:150,151:151,152:152,153:153,154:154,155:155,156:156,157:157,158:158,159:159,160:160,161:161,162:162,163:163,164:164,165:165,166:166,167:167,168:168,169:169,170:170,171:171,172:172,173:173,174:174,175:175,176:176,177:177,178:178,179:179,180:180,181:181,182:182,183:183,184:184,185:185,186:186,187:187,188:188,189:189,190:190,191:191,192:192,193:193,194:194,195:195,196:196,197:197,198:198,199:199,200:200,201:201,202:202,203:203,204:204,205:205,206:206,207:207,208:208,209:209,210:210,211:211,212:212,213:213,214:214,215:215,216:216,217:217,218:218,219:219,220:220,221:221,222:222,223:223,224:224,225:225,226:226,227:227,228:228,229:229,230:230,231:231,232:232,233:233,234:234,235:235,236:236,237:237,238:238,239:239,24:24,240:240,241:241,242:242,243:243,244:244,245:245,246:246,247:247,248:248,249:249,250:250,251:251,252:252,253:253,254:254,255:255,256:256,257:257,258:258,259:259,260:260,261:261,262:262,263:263,264:264,265:265,266:266,267:267,268:268,269:269,270:270,271:271,272:272,273:273,274:274,275:275,276:276,277:277,278:278,279:279,280:280,281:281,282:282,283:283,284:284,285:285,286:286,287:287,288:288,289:289,290:290,291:291,292:292,293:293,294:294,295:295,296:296,297:297,298:298,299:299,300:300,301:301,302:302,303:303,304:304,305:305,306:306,307:307,308:308,309:309,310:310,311:311,312:312,313:313,314:314,315:315,316:316,317:317,318:318,319:319,320:320,321:321,322:322,323:323,324:324,325:325}],327:[function(t,e,n){!function(t){"use strict";function e(){return c.createDocumentFragment()}function n(t){return c.createElement(t)}function a(t){if(1===t.length)return r(t[0]);for(var n=e(),a=B.call(t),i=0;i-1}}([].indexOf||function(t){for(U=this.length;U--&&this[U]!==t;);return U}),item:function(t){return this[t]||null},remove:function(){for(var t,e=0;e=p?e(i):document.fonts.load(u(i,i.family),s).then(function(e){1<=e.length?t(i):setTimeout(d,25)},function(){e(i)})};d()}else n(function(){function n(){var e;(e=-1!=g&&-1!=v||-1!=g&&-1!=b||-1!=v&&-1!=b)&&((e=g!=v&&g!=b&&v!=b)||(null===l&&(e=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent),l=!!e&&(536>parseInt(e[1],10)||536===parseInt(e[1],10)&&11>=parseInt(e[2],10))),e=l&&(g==y&&v==y&&b==y||g==_&&v==_&&b==_||g==x&&v==x&&b==x)),e=!e),e&&(null!==w.parentNode&&w.parentNode.removeChild(w),clearTimeout(k),t(i))}function d(){if((new Date).getTime()-c>=p)null!==w.parentNode&&w.parentNode.removeChild(w),e(i);else{var t=document.hidden;(!0===t||void 0===t)&&(g=f.a.offsetWidth,v=h.a.offsetWidth,b=m.a.offsetWidth,n()),k=setTimeout(d,50)}}var f=new a(s),h=new a(s),m=new a(s),g=-1,v=-1,b=-1,y=-1,_=-1,x=-1,w=document.createElement("div"),k=0;w.dir="ltr",r(f,u(i,"sans-serif")),r(h,u(i,"serif")),r(m,u(i,"monospace")),w.appendChild(f.a),w.appendChild(h.a),w.appendChild(m.a),document.body.appendChild(w),y=f.a.offsetWidth,_=h.a.offsetWidth,x=m.a.offsetWidth,d(),o(f,function(t){g=t,n()}),r(f,u(i,'"'+i.family+'",sans-serif')),o(h,function(t){v=t,n()}),r(h,u(i,'"'+i.family+'",serif')),o(m,function(t){b=t,n()}),r(m,u(i,'"'+i.family+'",monospace'))})})},window.FontFaceObserver=s,window.FontFaceObserver.prototype.check=s.prototype.a,void 0!==e&&(e.exports=window.FontFaceObserver)}()},{}],330:[function(t,e,n){!function(t,n){function a(t,e){var n=t.createElement("p"),a=t.getElementsByTagName("head")[0]||t.documentElement;return n.innerHTML="x",a.insertBefore(n.lastChild,a.firstChild)}function r(){var t=_.elements;return"string"==typeof t?t.split(" "):t}function i(t,e){var n=_.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof t&&(t=t.join(" ")),_.elements=n+" "+t,c(e)}function o(t){var e=y[t[v]];return e||(e={},b++,t[v]=b,y[b]=e),e}function s(t,e,a){if(e||(e=n),d)return e.createElement(t);a||(a=o(e));var r;return r=a.cache[t]?a.cache[t].cloneNode():g.test(t)?(a.cache[t]=a.createElem(t)).cloneNode():a.createElem(t),!r.canHaveChildren||m.test(t)||r.tagUrn?r:a.frag.appendChild(r)}function p(t,e){if(t||(t=n),d)return t.createDocumentFragment();e=e||o(t);for(var a=e.frag.cloneNode(),i=0,s=r(),p=s.length;p>i;i++)a.createElement(s[i]);return a}function u(t,e){e.cache||(e.cache={},e.createElem=t.createElement,e.createFrag=t.createDocumentFragment,e.frag=e.createFrag()),t.createElement=function(n){return _.shivMethods?s(n,t,e):e.createElem(n)},t.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+r().join().replace(/[\w\-:]+/g,function(t){return e.createElem(t),e.frag.createElement(t),'c("'+t+'")'})+");return n}")(_,e.frag)}function c(t){t||(t=n);var e=o(t);return!_.shivCSS||l||e.hasCSS||(e.hasCSS=!!a(t,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),d||u(t,e),t}var l,d,f="3.7.3-pre",h=t.html5||{},m=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,g=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",b=0,y={};!function(){try{var t=n.createElement("a");t.innerHTML="",l="hidden"in t,d=1==t.childNodes.length||function(){n.createElement("a");var t=n.createDocumentFragment();return void 0===t.cloneNode||void 0===t.createDocumentFragment||void 0===t.createElement}()}catch(e){l=!0,d=!0}}();var _={elements:h.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:f,shivCSS:h.shivCSS!==!1,supportsUnknownElements:d,shivMethods:h.shivMethods!==!1,type:"default",shivDocument:c,createElement:s,createDocumentFragment:p,addElements:i};t.html5=_,c(n),"object"==typeof e&&e.exports&&(e.exports=_)}("undefined"!=typeof window?window:this,document)},{}],331:[function(t,e,n){(function(t){(function(t){!function(t){function e(t,e,n,a){for(var i,o,s=n.slice(),p=r(e,t),u=0,c=s.length;c>u&&(i=s[u],"object"==typeof i?"function"==typeof i.handleEvent&&i.handleEvent(p):i.call(t,p),!p.stoppedImmediatePropagation);u++);return o=!p.stoppedPropagation,a&&o&&t.parentNode?t.parentNode.dispatchEvent(p):!p.defaultPrevented}function n(t,e){return{configurable:!0,get:t,set:e}}function a(t,e,a){var r=y(e||t,a);v(t,"textContent",n(function(){return r.get.call(this)},function(t){r.set.call(this,t)}))}function r(t,e){return t.currentTarget=e,t.eventPhase=t.target===t.currentTarget?2:3,t}function i(t,e){for(var n=t.length;n--&&t[n]!==e;);return n}function o(){if("BR"===this.tagName)return"\n";for(var t=this.firstChild,e=[];t;)8!==t.nodeType&&7!==t.nodeType&&e.push(t.textContent),t=t.nextSibling;return e.join("")}function s(t){var e=document.createEvent("Event");e.initEvent("input",!0,!0),(t.srcElement||t.fromElement||document).dispatchEvent(e)}function p(t){!f&&S.test(document.readyState)&&(f=!f,document.detachEvent(h,p),t=document.createEvent("Event"),t.initEvent(m,!0,!0),document.dispatchEvent(t))}function u(t){return function(){return P[t]||document.body&&document.body[t]||0}}function c(t){for(var e;e=this.lastChild;)this.removeChild(e);null!=t&&this.appendChild(document.createTextNode(t))}function l(e,n){return n||(n=t.event),n.target||(n.target=n.srcElement||n.fromElement||document),n.timeStamp||(n.timeStamp=(new Date).getTime()),n}if(!document.createEvent){var d=!0,f=!1,h="onreadystatechange",m="DOMContentLoaded",g="__IE8__"+Math.random(),v=Object.defineProperty||function(t,e,n){t[e]=n.value},b=Object.defineProperties||function(e,n){for(var a in n)if(_.call(n,a))try{v(e,a,n[a])}catch(r){t.console&&console.log(a+" failed on object:",e,r.message)}},y=Object.getOwnPropertyDescriptor,_=Object.prototype.hasOwnProperty,x=t.Element.prototype,w=t.Text.prototype,k=/^[a-z]+$/,S=/loaded|complete/,E={},C=document.createElement("div"),P=document.documentElement,A=P.removeAttribute,O=P.setAttribute,T=function(t){return{enumerable:!0,writable:!0,configurable:!0,value:t}};a(t.HTMLCommentElement.prototype,x,"nodeValue"),a(t.HTMLScriptElement.prototype,null,"text"),a(w,null,"nodeValue"),a(t.HTMLTitleElement.prototype,null,"text"),v(t.HTMLStyleElement.prototype,"textContent",function(t){return n(function(){return t.get.call(this.styleSheet)},function(e){t.set.call(this.styleSheet,e)})}(y(t.CSSStyleSheet.prototype,"cssText")));var R=/\b\s*alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/;v(t.CSSStyleDeclaration.prototype,"opacity",{get:function(){var t=this.filter.match(R);return t?""+t[1]/100:""},set:function(t){this.zoom=1;var e=!1;t=1>t?" alpha(opacity="+Math.round(100*t)+")":"",this.filter=this.filter.replace(R,function(){return e=!0,t}),!e&&t&&(this.filter+=t)}}),b(x,{textContent:{get:o,set:c},firstElementChild:{get:function(){for(var t=this.childNodes||[],e=0,n=t.length;n>e;e++)if(1==t[e].nodeType)return t[e]}},lastElementChild:{get:function(){for(var t=this.childNodes||[],e=t.length;e--;)if(1==t[e].nodeType)return t[e]}},oninput:{get:function(){return this._oninput||null},set:function(t){this._oninput&&(this.removeEventListener("input",this._oninput),this._oninput=t,t&&this.addEventListener("input",t))}},previousElementSibling:{get:function(){for(var t=this.previousSibling;t&&1!=t.nodeType;)t=t.previousSibling;return t}},nextElementSibling:{get:function(){for(var t=this.nextSibling;t&&1!=t.nodeType;)t=t.nextSibling;return t}},childElementCount:{get:function(){for(var t=0,e=this.childNodes||[],n=e.length;n--;t+=1==e[n].nodeType);return t}},addEventListener:T(function(t,n,a){if("function"==typeof n||"object"==typeof n){var r,o,p=this,u="on"+t,c=p[g]||v(p,g,{value:{}})[g],d=c[u]||(c[u]={}),f=d.h||(d.h=[]);if(!_.call(d,"w")){if(d.w=function(t){return t[g]||e(p,l(p,t),f,!1)},!_.call(E,u))if(k.test(t)){try{r=document.createEventObject(),r[g]=!0,9!=p.nodeType&&(null==p.parentNode&&C.appendChild(p),(o=p.getAttribute(u))&&A.call(p,u)),p.fireEvent(u,r),E[u]=!0}catch(h){for(E[u]=!1;C.hasChildNodes();)C.removeChild(C.firstChild)}null!=o&&O.call(p,u,o)}else E[u]=!1;(d.n=E[u])&&p.attachEvent(u,d.w)}i(f,n)<0&&f[a?"unshift":"push"](n),"input"===t&&p.attachEvent("onkeyup",s)}}),dispatchEvent:T(function(t){var n,a=this,r="on"+t.type,i=a[g],o=i&&i[r],s=!!o;return t.target||(t.target=a),s?o.n?a.fireEvent(r,t):e(a,t,o.h,!0):(n=a.parentNode)?n.dispatchEvent(t):!0,!t.defaultPrevented}),removeEventListener:T(function(t,e,n){if("function"==typeof e||"object"==typeof e){var a=this,r="on"+t,o=a[g],s=o&&o[r],p=s&&s.h,u=p?i(p,e):-1;u>-1&&p.splice(u,1)}})}),b(w,{addEventListener:T(x.addEventListener),dispatchEvent:T(x.dispatchEvent),removeEventListener:T(x.removeEventListener)}),b(t.XMLHttpRequest.prototype,{addEventListener:T(function(t,e,n){var a=this,r="on"+t,o=a[g]||v(a,g,{value:{}})[g],s=o[r]||(o[r]={}),p=s.h||(s.h=[]);i(p,e)<0&&(a[r]||(a[r]=function(){var e=document.createEvent("Event");e.initEvent(t,!0,!0),a.dispatchEvent(e)}),p[n?"unshift":"push"](e))}),dispatchEvent:T(function(t){var n=this,a="on"+t.type,r=n[g],i=r&&r[a],o=!!i;return o&&(i.n?n.fireEvent(a,t):e(n,t,i.h,!0))}),removeEventListener:T(x.removeEventListener)});var M=y(Event.prototype,"button").get;b(t.Event.prototype,{bubbles:T(!0),cancelable:T(!0),preventDefault:T(function(){this.cancelable&&(this.returnValue=!1)}),stopPropagation:T(function(){this.stoppedPropagation=!0,this.cancelBubble=!0}),stopImmediatePropagation:T(function(){this.stoppedImmediatePropagation=!0,this.stopPropagation()}),initEvent:T(function(t,e,n){this.type=t,this.bubbles=!!e,this.cancelable=!!n,this.bubbles||this.stopPropagation()}),pageX:{get:function(){return this._pageX||(this._pageX=this.clientX+t.scrollX-(P.clientLeft||0))}},pageY:{get:function(){return this._pageY||(this._pageY=this.clientY+t.scrollY-(P.clientTop||0))}},which:{get:function(){return this.keyCode?this.keyCode:isNaN(this.button)?void 0:this.button+1}},charCode:{get:function(){return this.keyCode&&"keypress"==this.type?this.keyCode:0}},buttons:{get:function(){return M.call(this)}},button:{get:function(){var t=this.buttons;return 1&t?0:2&t?2:4&t?1:void 0}},defaultPrevented:{get:function(){var t,e=this.returnValue;return!(e===t||e)}},relatedTarget:{get:function(){var t=this.type;return"mouseover"===t?this.fromElement:"mouseout"===t?this.toElement:null}}}),b(t.HTMLDocument.prototype,{defaultView:{get:function(){return this.parentWindow}},textContent:{get:function(){return 11===this.nodeType?o.call(this):null},set:function(t){11===this.nodeType&&c.call(this,t)}},addEventListener:T(function(e,n,a){var r=this;x.addEventListener.call(r,e,n,a),d&&e===m&&!S.test(r.readyState)&&(d=!1,r.attachEvent(h,p),t==top&&!function i(t){try{r.documentElement.doScroll("left"),p()}catch(e){setTimeout(i,50)}}())}),dispatchEvent:T(x.dispatchEvent),removeEventListener:T(x.removeEventListener),createEvent:T(function(t){var e;if("Event"!==t)throw Error("unsupported "+t);return e=document.createEventObject(),e.timeStamp=(new Date).getTime(),e})}),b(t.Window.prototype,{getComputedStyle:T(function(){function t(t){this._=t}function e(){}var n=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,a=/^(top|right|bottom|left)$/,r=/\-([a-z])/g,i=function(t,e){return e.toUpperCase()};return t.prototype.getPropertyValue=function(t){var e,o,s,p=this._,u=p.style,c=p.currentStyle,l=p.runtimeStyle;return"opacity"==t?u.opacity||"1":(t=("float"===t?"style-float":t).replace(r,i),e=c?c[t]:u[t],n.test(e)&&!a.test(t)&&(o=u.left,s=l&&l.left,s&&(l.left=c.left),u.left="fontSize"===t?"1em":e,e=u.pixelLeft+"px",u.left=o,s&&(l.left=s)),null==e?e:e+""||"auto")},e.prototype.getPropertyValue=function(){return null},function(n,a){return a?new e(n):new t(n)}}()),addEventListener:T(function(n,a,r){var o,s=t,p="on"+n;s[p]||(s[p]=function(t){return e(s,l(s,t),o,!1)&&void 0}),o=s[p][g]||(s[p][g]=[]),i(o,a)<0&&o[r?"unshift":"push"](a)}),dispatchEvent:T(function(e){var n=t["on"+e.type];return n?n.call(t,e)!==!1&&!e.defaultPrevented:!0}),removeEventListener:T(function(e,n,a){var r="on"+e,o=(t[r]||Object)[g],s=o?i(o,n):-1;s>-1&&o.splice(s,1)}),pageXOffset:{get:u("scrollLeft")},pageYOffset:{get:u("scrollTop")},scrollX:{get:u("scrollLeft")},scrollY:{get:u("scrollTop")},innerWidth:{get:u("clientWidth")},innerHeight:{get:u("clientHeight")}}),t.HTMLElement=t.Element,function(t,e,n){for(n=0;na;a++)e.appendChild(n[a].cloneNode(!0));return e},n.cloneRange=function(){var t=new e;return t._start=this._start,t._end=this._end,t},n.deleteContents=function(){for(var e=this._start.parentNode,n=t(this._start,this._end),a=0,r=n.length;r>a;a++)e.removeChild(n[a])},n.extractContents=function(){for(var e=this._start.ownerDocument.createDocumentFragment(),n=t(this._start,this._end),a=0,r=n.length;r>a;a++)e.appendChild(n[a]);return e},n.setEndAfter=function(t){this._end=t},n.setEndBefore=function(t){this._end=t.previousSibling},n.setStartAfter=function(t){this._start=t.nextSibling},n.setStartBefore=function(t){this._start=t}}}()}}(this.window||t)}).call(this,void 0!==t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],332:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e=s)return(0,p["default"])({points:n});for(var l=1;s-1>=l;l++)i.push((0,u.times)(a,(0,u.minus)(n[l],n[l-1])));for(var d=[(0,u.plus)(n[0],c(i[0],i[1]))],l=1;s-2>=l;l++)d.push((0,u.minus)(n[l],(0,u.average)([i[l],i[l-1]])));d.push((0,u.minus)(n[s-1],c(i[s-2],i[s-3])));var f=d[0],h=d[1],m=n[0],g=n[1],v=(e=(0,o["default"])()).moveto.apply(e,r(m)).curveto(f[0],f[1],h[0],h[1],g[0],g[1]);return{path:(0,u.range)(2,s).reduce(function(t,e){var a=d[e],r=n[e];return t.smoothcurveto(a[0],a[1],r[0],r[1])},v),centroid:(0,u.average)(n)}},e.exports=n["default"]},{335:335,336:336,337:337}],333:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=t(334),o=a(i),s=t(335),p=1e-5,u=function(t,e){var n=t.map(e),a=n.sort(function(t,e){var n=r(t,2),a=n[0],i=(n[1],r(e,2)),o=i[0];i[1];return a-o}),i=a.length,o=a[0][0],u=a[i-1][0],c=(0,s.minBy)(a,function(t){return t[1]}),l=(0,s.maxBy)(a,function(t){return t[1]});return o==u&&(u+=p),c==l&&(l+=p),{points:a,xmin:o,xmax:u,ymin:c,ymax:l}};n["default"]=function(t){var e=t.data,n=t.xaccessor,a=t.yaccessor,i=t.width,p=t.height,c=t.closed,l=t.min,d=t.max;n||(n=function(t){var e=r(t,2),n=e[0];e[1];return n}),a||(a=function(t){var e=r(t,2),n=(e[0],e[1]);return n});var f=function(t){return[n(t),a(t)]},h=e.map(function(t){return u(t,f)}),m=(0,s.minBy)(h,function(t){return t.xmin}),g=(0,s.maxBy)(h,function(t){return t.xmax}),v=null==l?(0,s.minBy)(h,function(t){return t.ymin}):l,b=null==d?(0,s.maxBy)(h,function(t){return t.ymax}):d;c&&(v=Math.min(v,0),b=Math.max(b,0));var y=c?0:v,_=(0,o["default"])([m,g],[0,i]),x=(0,o["default"])([v,b],[p,0]),w=function(t){var e=r(t,2),n=e[0],a=e[1];return[_(n),x(a)]};return{arranged:h,scale:w,xscale:_,yscale:x,base:y}},e.exports=n["default"]},{334:334,335:335}],334:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function i(t,e){var n=a(t,2),r=n[0],o=n[1],s=a(e,2),p=s[0],u=s[1],c=function(t){return p+(u-p)*(t-r)/(o-r)};return c.inverse=function(){return i([p,u],[r,o])},c};n["default"]=r,e.exports=n["default"]},{}],335:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function(t){return t.reduce(function(t,e){return t+e},0)},i=function(t){return t.reduce(function(t,e){return Math.min(t,e)})},o=function(t){return t.reduce(function(t,e){return Math.max(t,e)})},s=function(t,e){return t.reduce(function(t,n){return t+e(n)},0)},p=function(t,e){return t.reduce(function(t,n){return Math.min(t,e(n))},1/0)},u=function(t,e){return t.reduce(function(t,n){return Math.max(t,e(n))},-(1/0))},c=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return[r+s,i+p]},l=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return[r-s,i-p]},d=function(t,e){var n=a(e,2),r=n[0],i=n[1];return[t*r,t*i]},f=function(t){var e=a(t,2),n=e[0],r=e[1];return Math.sqrt(n*n+r*r)},h=function(t){return t.reduce(c,[0,0])},m=function(t){return d(1/t.length,t.reduce(c))},g=function(t,e){return d(t,[Math.sin(e),-Math.cos(e)])},v=function(t,e){var n=t||{};for(var a in n){var r=n[a];e[a]=r(e.index,e.item,e.group)}return e},b=function(t,e,n){for(var a=[],r=t;e>r;r++)a.push(r);return n&&a.push(e),a},y=function(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=Object.keys(t)[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){var p=o.value,u=t[p];n.push(e(p,u))}}catch(c){r=!0,i=c}finally{ -try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n},_=function(t){return y(t,function(t,e){return[t,e]})},x=function(t){return t};n.sum=r,n.min=i,n.max=o,n.sumBy=s,n.minBy=p,n.maxBy=u,n.plus=c,n.minus=l,n.times=d,n.id=x,n.length=f,n.sumVectors=h,n.average=m,n.onCircle=g,n.enhance=v,n.range=b,n.mapObject=y,n.pairs=_,n["default"]={sum:r,min:i,max:o,sumBy:s,minBy:p,maxBy:u,plus:c,minus:l,times:d,id:x,length:f,sumVectors:h,average:m,onCircle:g,enhance:v,range:b,mapObject:y,pairs:_}},{}],336:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function i(t){var e=t||[],n=function(t,e){var n=t.slice(0,t.length);return n.push(e),n},r=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return r===s&&i===p},o=function(t,e){for(var n=t.length;"0"===t.charAt(n-1);)n-=1;return"."===t.charAt(n-1)&&(n-=1),t.substr(0,n)},s=function(t,e){var n=t.toFixed(e);return o(n)},p=function(t){var e=t.command,n=t.params,a=n.map(function(t){return s(t,6)});return e+" "+a.join(" ")},u=function(t,e){var n=t.command,r=t.params,i=a(e,2),o=i[0],s=i[1];switch(n){case"M":return[r[0],r[1]];case"L":return[r[0],r[1]];case"H":return[r[0],s];case"V":return[o,r[0]];case"Z":return null;case"C":return[r[4],r[5]];case"S":return[r[2],r[3]];case"Q":return[r[2],r[3]];case"T":return[r[0],r[1]];case"A":return[r[5],r[6]]}},c=function(t,e){return function(n){var a="object"==typeof n?t.map(function(t){return n[t]}):arguments;return e.apply(null,a)}},l=function(t){return i(n(e,t))};return{moveto:c(["x","y"],function(t,e){return l({command:"M",params:[t,e]})}),lineto:c(["x","y"],function(t,e){return l({command:"L",params:[t,e]})}),hlineto:c(["x"],function(t){return l({command:"H",params:[t]})}),vlineto:c(["y"],function(t){return l({command:"V",params:[t]})}),closepath:function(){return l({command:"Z",params:[]})},curveto:c(["x1","y1","x2","y2","x","y"],function(t,e,n,a,r,i){return l({command:"C",params:[t,e,n,a,r,i]})}),smoothcurveto:c(["x2","y2","x","y"],function(t,e,n,a){return l({command:"S",params:[t,e,n,a]})}),qcurveto:c(["x1","y1","x","y"],function(t,e,n,a){return l({command:"Q",params:[t,e,n,a]})}),smoothqcurveto:c(["x","y"],function(t,e){return l({command:"T",params:[t,e]})}),arc:c(["rx","ry","xrot","largeArcFlag","sweepFlag","x","y"],function(t,e,n,a,r,i,o){return l({command:"A",params:[t,e,n,a,r,i,o]})}),print:function(){return e.map(p).join(" ")},points:function(){var t=[],n=[0,0],a=!0,r=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){var p=o.value,c=u(p,n);n=c,c&&t.push(c)}}catch(l){r=!0,i=l}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return t},instructions:function(){return e.slice(0,e.length)},connect:function(t){var e=this.points(),n=e[e.length-1],a=t.points()[0],o=t.instructions().slice(1);return r(n,a)||o.unshift({command:"L",params:a}),i(this.instructions().concat(o))}}};n["default"]=function(){return r()},e.exports=n["default"]},{}],337:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];for(var r,i;i=n.shift();)for(r in i)Mo.call(i,r)&&(t[r]=i[r]);return t}function r(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];return n.forEach(function(e){for(var n in e)!e.hasOwnProperty(n)||n in t||(t[n]=e[n])}),t}function i(t){return"[object Array]"===Lo.call(t)}function o(t){return jo.test(Lo.call(t))}function s(t,e){return null===t&&null===e?!0:"object"==typeof t||"object"==typeof e?!1:t===e}function p(t){return!isNaN(parseFloat(t))&&isFinite(t)}function u(t){return t&&"[object Object]"===Lo.call(t)}function c(t,e){return t.replace(/%s/g,function(){return e.shift()})}function l(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];throw t=c(t,n),Error(t)}function d(){Mg.DEBUG&&Oo.apply(null,arguments)}function f(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];t=c(t,n),To(t,n)}function h(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];t=c(t,n),Do[t]||(Do[t]=!0,To(t,n))}function m(){Mg.DEBUG&&f.apply(null,arguments)}function g(){Mg.DEBUG&&h.apply(null,arguments)}function v(t,e,n){var a=b(t,e,n);return a?a[t][n]:null}function b(t,e,n){for(;e;){if(n in e[t])return e;if(e.isolated)return null;e=e.parent}}function y(t){return function(){return t}}function _(t){var e,n,a,r,i,o;for(e=t.split("."),(n=zo[e.length])||(n=x(e.length)),i=[],a=function(t,n){return t?"*":e[n]},r=n.length;r--;)o=n[r].map(a).join("."),i.hasOwnProperty(o)||(i.push(o),i[o]=!0);return i}function x(t){var e,n,a,r,i,o,s,p,u="";if(!zo[t]){for(a=[];u.length=i;i+=1){for(n=i.toString(2);n.lengtho;o++)p.push(r(n[o]));a[i]=p}zo[t]=a}return zo[t]}function w(t,e,n,a){var r=t[e];if(!r||!r.equalsOrStartsWith(a)&&r.equalsOrStartsWith(n))return t[e]=r?r.replace(n,a):a,!0}function k(t){var e=t.slice(2);return"i"===t[1]&&p(e)?+e:e}function S(t){return null==t?t:(Ko.hasOwnProperty(t)||(Ko[t]=new Qo(t)),Ko[t])}function E(t,e){function n(e,n){var a,r,o;return n.isRoot?o=[].concat(Object.keys(t.viewmodel.data),Object.keys(t.viewmodel.mappings),Object.keys(t.viewmodel.computations)):(a=t.viewmodel.wrapped[n.str],r=a?a.get():t.viewmodel.get(n),o=r?Object.keys(r):null),o&&o.forEach(function(t){"_ractive"===t&&i(r)||e.push(n.join(t))}),e}var a,r,o;for(a=e.str.split("."),o=[$o];r=a.shift();)"*"===r?o=o.reduce(n,[]):o[0]===$o?o[0]=S(r):o=o.map(C(r));return o}function C(t){return function(e){return e.join(t)}}function P(t){return t?t.replace(Wo,".$1"):""}function A(t,e,n){if("string"!=typeof e||!p(n))throw Error("Bad arguments");var a=void 0,r=void 0;if(/\*/.test(e))return r={},E(t,S(P(e))).forEach(function(e){var a=t.viewmodel.get(e);if(!p(a))throw Error(Xo);r[e.str]=a+n}),t.set(r);if(a=t.get(e),!p(a))throw Error(Xo);return t.set(e,+a+n)}function O(t,e){return Jo(this,t,void 0===e?1:+e)}function T(t){this.event=t,this.method="on"+t,this.deprecate=as[t]}function R(t,e){var n=t.indexOf(e);-1===n&&t.push(e)}function M(t,e){for(var n=0,a=t.length;a>n;n++)if(t[n]==e)return!0;return!1}function L(t,e){var n;if(!i(t)||!i(e))return!1;if(t.length!==e.length)return!1;for(n=t.length;n--;)if(t[n]!==e[n])return!1;return!0}function j(t){return"string"==typeof t?[t]:void 0===t?[]:t}function D(t){return t[t.length-1]}function N(t,e){var n=t.indexOf(e);-1!==n&&t.splice(n,1)}function F(t){for(var e=[],n=t.length;n--;)e[n]=t[n];return e}function I(t){setTimeout(t,0)}function B(t,e){return function(){for(var n;n=t.shift();)n(e)}}function U(t,e,n,a){var r;if(e===t)throw new TypeError("A promise's fulfillment handler cannot return the same promise");if(e instanceof rs)e.then(n,a);else if(!e||"object"!=typeof e&&"function"!=typeof e)n(e);else{try{r=e.then}catch(i){return void a(i)}if("function"==typeof r){var o,s,p;s=function(e){o||(o=!0,U(t,e,n,a))},p=function(t){o||(o=!0,a(t))};try{r.call(e,s,p)}catch(i){if(!o)return a(i),void(o=!0)}}else n(e)}}function V(t,e,n){var a;return e=P(e),"~/"===e.substr(0,2)?(a=S(e.substring(2)),z(t,a.firstKey,n)):"."===e[0]?(a=q(cs(n),e),a&&z(t,a.firstKey,n)):a=G(t,S(e),n),a}function q(t,e){var n;if(void 0!=t&&"string"!=typeof t&&(t=t.str),"."===e)return S(t);if(n=t?t.split("."):[],"../"===e.substr(0,3)){for(;"../"===e.substr(0,3);){if(!n.length)throw Error('Could not resolve reference - too many "../" prefixes');n.pop(),e=e.substring(3)}return n.push(e),S(n.join("."))}return S(t?t+e.replace(/^\.\//,"."):e.replace(/^\.\/?/,""))}function G(t,e,n,a){var r,i,o,s,p;if(e.isRoot)return e;for(i=e.firstKey;n;)if(r=n.context,n=n.parent,r&&(s=!0,o=t.viewmodel.get(r),o&&("object"==typeof o||"function"==typeof o)&&i in o))return r.join(e.str);return W(t.viewmodel,i)?e:t.parent&&!t.isolated&&(s=!0,n=t.component.parentFragment,i=S(i),p=G(t.parent,i,n,!0))?(t.viewmodel.map(i,{origin:t.parent.viewmodel,keypath:p}),e):a||s?void 0:(t.viewmodel.set(e,void 0),e)}function z(t,e){var n;!t.parent||t.isolated||W(t.viewmodel,e)||(e=S(e),(n=G(t.parent,e,t.component.parentFragment,!0))&&t.viewmodel.map(e,{origin:t.parent.viewmodel,keypath:n}))}function W(t,e){return""===e||e in t.data||e in t.computations||e in t.mappings}function H(t){t.teardown()}function K(t){t.unbind()}function Q(t){t.unrender()}function Y(t){t.cancel()}function $(t){t.detach()}function J(t){t.detachNodes()}function X(t){!t.ready||t.outros.length||t.outroChildren||(t.outrosComplete||(t.parent?t.parent.decrementOutros(t):t.detachNodes(),t.outrosComplete=!0),t.intros.length||t.totalChildren||("function"==typeof t.callback&&t.callback(),t.parent&&t.parent.decrementTotal()))}function Z(){for(var t,e,n;fs.ractives.length;)e=fs.ractives.pop(),n=e.viewmodel.applyChanges(),n&&vs.fire(e,n);for(tt(),t=0;t=0;i--)r=t._subs[e[i]],r&&(s=vt(t,r,n,a)&&s);if(Gs.dequeue(t),t.parent&&s){if(o&&t.component){var p=t.component.name+"."+e[e.length-1];e=S(p).wildcardMatches(),n&&(n.component=t)}gt(t.parent,e,n,a)}}function vt(t,e,n,a){var r=null,i=!1;n&&!n._noArg&&(a=[n].concat(a)),e=e.slice();for(var o=0,s=e.length;s>o;o+=1)e[o].apply(t,a)===!1&&(i=!0);return n&&!n._noArg&&i&&(r=n.original)&&(r.preventDefault&&r.preventDefault(),r.stopPropagation&&r.stopPropagation()),!i}function bt(t){var e={args:Array.prototype.slice.call(arguments,1)};zs(this,t,e)}function yt(t){var e;return t=S(P(t)),e=this.viewmodel.get(t,Ks),void 0===e&&this.parent&&!this.isolated&&ls(this,t.str,this.component.parentFragment)&&(e=this.viewmodel.get(t)),e}function _t(e,n){if(!this.fragment.rendered)throw Error("The API has changed - you must call `ractive.render(target[, anchor])` to render your Ractive instance. Once rendered you can use `ractive.insert()`.");if(e=t(e),n=t(n)||null,!e)throw Error("You must specify a valid target to insert into");e.insertBefore(this.detach(),n),this.el=e,(e.__ractive_instances__||(e.__ractive_instances__=[])).push(this),this.detached=null,xt(this)}function xt(t){Ys.fire(t),t.findAllComponents("*").forEach(function(t){xt(t.instance)})}function wt(t,e,n){var a,r;return t=S(P(t)),a=this.viewmodel.get(t),i(a)&&i(e)?(r=bs.start(this,!0),this.viewmodel.merge(t,a,e,n),bs.end(),r):this.set(t,e,n&&n.complete)}function kt(t,e){var n,a;return n=E(t,e),a={},n.forEach(function(e){a[e.str]=t.get(e.str)}),a}function St(t,e,n,a){var r,i,o;e=S(P(e)),a=a||cp,e.isPattern?(r=new pp(t,e,n,a),t.viewmodel.patternObservers.push(r),i=!0):r=new Zs(t,e,n,a),r.init(a.init),t.viewmodel.register(e,r,i?"patternObservers":"observers"),r.ready=!0;var s={cancel:function(){var n;o||(i?(n=t.viewmodel.patternObservers.indexOf(r),t.viewmodel.patternObservers.splice(n,1),t.viewmodel.unregister(e,r,"patternObservers")):t.viewmodel.unregister(e,r,"observers"),o=!0)}};return t._observers.push(s),s}function Et(t,e,n){var a,r,i,o;if(u(t)){n=e,r=t,a=[];for(t in r)r.hasOwnProperty(t)&&(e=r[t],a.push(this.observe(t,e,n)));return{cancel:function(){for(;a.length;)a.pop().cancel()}}}if("function"==typeof t)return n=e,e=t,t="",up(this,t,e,n);if(i=t.split(" "),1===i.length)return up(this,t,e,n);for(a=[],o=i.length;o--;)t=i[o],t&&a.push(up(this,t,e,n));return{cancel:function(){for(;a.length;)a.pop().cancel()}}}function Ct(t,e,n){var a=this.observe(t,function(){e.apply(this,arguments),a.cancel()},{init:!1,defer:n&&n.defer});return a}function Pt(t,e){var n,a=this;if(t)n=t.split(" ").map(fp).filter(hp),n.forEach(function(t){var n,r;(n=a._subs[t])&&(e?(r=n.indexOf(e),-1!==r&&n.splice(r,1)):a._subs[t]=[])});else for(t in this._subs)delete this._subs[t];return this}function At(t,e){var n,a,r,i=this;if("object"==typeof t){n=[];for(a in t)t.hasOwnProperty(a)&&n.push(this.on(a,t[a]));return{cancel:function(){for(var t;t=n.pop();)t.cancel()}}}return r=t.split(" ").map(fp).filter(hp),r.forEach(function(t){(i._subs[t]||(i._subs[t]=[])).push(e)}),{cancel:function(){return i.off(t,e)}}}function Ot(t,e){var n=this.on(t,function(){e.apply(this,arguments),n.cancel()});return n}function Tt(t,e,n){var a,r,i,o,s,p,u=[];if(a=Rt(t,e,n),!a)return null;for(r=t.length,s=a.length-2-a[1],i=Math.min(r,a[0]),o=i+a[1],p=0;i>p;p+=1)u.push(p);for(;o>p;p+=1)u.push(-1);for(;r>p;p+=1)u.push(p+s);return 0!==s?u.touchedFrom=a[0]:u.touchedFrom=t.length,u}function Rt(t,e,n){switch(e){case"splice":for(void 0!==n[0]&&n[0]<0&&(n[0]=t.length+Math.max(n[0],-t.length));n.length<2;)n.push(0);return n[1]=Math.min(n[1],t.length-n[0]),n;case"sort":case"reverse":return null;case"pop":return t.length?[t.length-1,1]:[0,0];case"push":return[t.length,0].concat(n);case"shift":return[0,t.length?1:0];case"unshift":return[0,0].concat(n)}}function Mt(e,n){var a,r,i,o=this;if(i=this.transitionsEnabled,this.noIntro&&(this.transitionsEnabled=!1),a=bs.start(this,!0),bs.scheduleTask(function(){return Rp.fire(o)},!0),this.fragment.rendered)throw Error("You cannot call ractive.render() on an already rendered instance! Call ractive.unrender() first");if(e=t(e)||this.el,n=t(n)||this.anchor,this.el=e,this.anchor=n,!this.append&&e){var s=e.__ractive_instances__;s&&s.length&&Lt(s),e.innerHTML=""}return this.cssId&&Op.apply(),e&&((r=e.__ractive_instances__)?r.push(this):e.__ractive_instances__=[this],n?e.insertBefore(this.fragment.render(),n):e.appendChild(this.fragment.render())),bs.end(),this.transitionsEnabled=i,a.then(function(){return Mp.fire(o)})}function Lt(t){t.splice(0,t.length).forEach(H)}function jt(t,e){for(var n=t.slice(),a=e.length;a--;)~n.indexOf(e[a])||n.push(e[a]);return n}function Dt(t,e){var n,a,r;return a='[data-ractive-css~="{'+e+'}"]',r=function(t){var e,n,r,i,o,s,p,u=[];for(e=[];n=Ip.exec(t);)e.push({str:n[0],base:n[1],modifiers:n[2]});for(i=e.map(Ft),p=e.length;p--;)s=i.slice(),r=e[p],s[p]=r.base+a+r.modifiers||"",o=i.slice(),o[p]=a+" "+o[p],u.push(s.join(" "),o.join(" "));return u.join(", ")},n=Up.test(t)?t.replace(Up,a):t.replace(Fp,"").replace(Np,function(t,e){var n,a;return Bp.test(e)?t:(n=e.split(",").map(Nt),a=n.map(r).join(", ")+" ",t.replace(e,a))})}function Nt(t){return t.trim?t.trim():t.replace(/^\s+/,"").replace(/\s+$/,"")}function Ft(t){return t.str}function It(t){t&&t.constructor!==Object&&("function"==typeof t||("object"!=typeof t?l("data option must be an object or a function, `"+t+"` is not valid"):m("If supplied, options.data should be a plain JavaScript object - using a non-POJO as the root object may work, but is discouraged")))}function Bt(t,e){It(e);var n="function"==typeof t,a="function"==typeof e;return e||n||(e={}),n||a?function(){var r=a?Ut(e,this):e,i=n?Ut(t,this):t;return Vt(r,i)}:Vt(e,t)}function Ut(t,e){var n=t.call(e);if(n)return"object"!=typeof n&&l("Data function must return an object"),n.constructor!==Object&&g("Data function returned something other than a plain JavaScript object. This might work, but is strongly discouraged"),n}function Vt(t,e){if(t&&e){for(var n in e)n in t||(t[n]=e[n]);return t}return t||e}function qt(t){var e=So(Qp);return e.parse=function(e,n){return Gt(e,n||t)},e}function Gt(t,e){if(!Hp)throw Error("Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser");return Hp(t,e||this.options)}function zt(t,e){var n;if(!Xi){if(e&&e.noThrow)return;throw Error("Cannot retrieve template #"+t+" as Ractive is not running in a browser.")}if(Wt(t)&&(t=t.substring(1)),!(n=document.getElementById(t))){if(e&&e.noThrow)return;throw Error("Could not find template element with id #"+t)}if("SCRIPT"!==n.tagName.toUpperCase()){if(e&&e.noThrow)return;throw Error("Template element with id #"+t+", must be a " - - var/title_attributes = "class='uiTitle'" - if (title_image) - title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" - - return {" - - - - - [head_content] - - -
- [title ? "
[title]
" : ""] -
- "} -//" This is here because else the rest of the file looks like a string in notepad++. -/datum/browser/proc/get_footer() - return {" -
-
- -"} - -/datum/browser/proc/get_content() - return {" - [get_header()] - [content] - [get_footer()] - "} - -/datum/browser/proc/open(use_onclose = 1) - if(isnull(window_id)) //null check because this can potentially nuke goonchat - WARNING("Browser [title] tried to open with a null ID") - to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!") - return - var/window_size = "" - if (width && height) - window_size = "size=[width]x[height];" - if (stylesheets.len) - send_asset_list(user, stylesheets, verify=FALSE) - if (scripts.len) - send_asset_list(user, scripts, verify=FALSE) - user << browse(get_content(), "window=[window_id];[window_size][window_options]") - if (use_onclose) - setup_onclose() - -/datum/browser/proc/setup_onclose() - set waitfor = 0 //winexists sleeps, so we don't need to. - for (var/i in 1 to 10) - if (user && winexists(user, window_id)) - onclose(user, window_id, ref) - break - -/datum/browser/proc/close() - if(!isnull(window_id))//null check because this can potentially nuke goonchat - user << browse(null, "window=[window_id]") - else - WARNING("Browser [title] tried to close with a null ID") - -/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000) - if (!User) - return - - var/output = {"
[Message]

-
- [Button1]"} - - if (Button2) - output += {"[Button2]"} - - if (Button3) - output += {"[Button3]"} - - output += {"
"} - - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout) - set_content(output) - -/datum/browser/modal/alert/Topic(href,href_list) - if (href_list["close"] || !user || !user.client) - opentime = 0 - return - if (href_list["button"]) - var/button = text2num(href_list["button"]) - if (button <= 3 && button >= 1) - selectedbutton = button - opentime = 0 - close() - -//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) -/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) - if (!User) - User = usr - switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)) - if (1) - return Button1 - if (2) - return Button2 - if (3) - return Button3 - -//Same shit, but it returns the button number, could at some point support unlimited button amounts. -/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) - if (!istype(User)) - if (istype(User, /client/)) - var/client/C = User - User = C.mob - else - return - var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout) - A.open() - A.wait() - if (A.selectedbutton) - return A.selectedbutton - -/datum/browser/modal - var/opentime = 0 - var/timeout - var/selectedbutton = 0 - var/stealfocus - -/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, StealFocus = 1, Timeout = 6000) - ..() - stealfocus = StealFocus - if (!StealFocus) - window_options += "focus=false;" - timeout = Timeout - - -/datum/browser/modal/close() - .=..() - opentime = 0 - -/datum/browser/modal/open(use_onclose = 1) - set waitfor = 0 - opentime = world.time - - if (stealfocus) - . = ..(use_onclose = 1) - else - var/focusedwindow = winget(user, null, "focus") - . = ..(use_onclose = 1) - - //waits for the window to show up client side before attempting to un-focus it - //winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping - for (var/i in 1 to 10) - if (user && winexists(user, window_id)) - if (focusedwindow) - winset(user, focusedwindow, "focus=true") - else - winset(user, "mapwindow", "focus=true") - break - if (timeout) - addtimer(CALLBACK(src, .proc/close), timeout) - -/datum/browser/modal/proc/wait() - while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) - stoplag(1) - -/datum/browser/modal/listpicker - var/valueslist = list() - -/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor) - if (!User) - return - - var/output = {"
    "} - if (inputtype == "checkbox" || inputtype == "radio") - for (var/i in values) - var/div_slider = slidecolor - if(!i["allowed_edit"]) - div_slider = "locked" - output += {"
  • - -
  • "} - else - for (var/i in values) - output += {"
  • -
  • "} - output += {"
- "} - - if (Button2) - output += {""} - - if (Button3) - output += {""} - - output += {"
"} - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) - set_content(output) - -/datum/browser/modal/listpicker/Topic(href,href_list) - if (href_list["close"] || !user || !user.client) - opentime = 0 - return - if (href_list["button"]) - var/button = text2num(href_list["button"]) - if (button <= 3 && button >= 1) - selectedbutton = button - for (var/item in href_list) - switch(item) - if ("close", "button", "src") - continue - else - valueslist[item] = href_list[item] - opentime = 0 - close() - -/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor) - if (!istype(User)) - if (istype(User, /client/)) - var/client/C = User - User = C.mob - else - return - var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor) - A.open() - A.wait() - if (A.selectedbutton) - return list("button" = A.selectedbutton, "values" = A.valueslist) - -/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null) - if (!User || !(bitfield in GLOB.bitfields)) - return - var/list/pickerlist = list() - for (var/i in GLOB.bitfields[bitfield]) - var/can_edit = 1 - if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i])) - can_edit = 0 - if (current_value & GLOB.bitfields[bitfield][i]) - pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) - else - pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) - var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor) - if (islist(result)) - if (result["button"] == 2) // If the user pressed the cancel button - return - . = 0 - for (var/flag in result["values"]) - . |= GLOB.bitfields[bitfield][flag] - else - return - -/datum/browser/modal/preflikepicker - var/settings = list() - var/icon/preview_icon = null - var/datum/callback/preview_update - -/datum/browser/modal/preflikepicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/settings,inputtype="checkbox", width = 600, height, slidecolor) - if (!User) - return - src.settings = settings - - ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) - set_content(ShowChoices(User)) - -/datum/browser/modal/preflikepicker/proc/ShowChoices(mob/user) - if (settings["preview_callback"]) - var/datum/callback/callback = settings["preview_callback"] - preview_icon = callback.Invoke(settings) - if (preview_icon) - user << browse_rsc(preview_icon, "previewicon.png") - var/dat = "" - - for (var/name in settings["mainsettings"]) - var/setting = settings["mainsettings"][name] - if (setting["type"] == "datum") - if (setting["subtypesonly"]) - dat += "[setting["desc"]]: [setting["value"]]
" - else - dat += "[setting["desc"]]: [setting["value"]]
" - else - dat += "[setting["desc"]]: [setting["value"]]
" - - if (preview_icon) - dat += "" - - dat += "
" - - dat += "" - - dat += "" - - dat += "
Ok " - - dat += "
" - - return dat - -/datum/browser/modal/preflikepicker/Topic(href,href_list) - if (href_list["close"] || !user || !user.client) - opentime = 0 - return - if (href_list["task"] == "input") - var/setting = href_list["setting"] - switch (href_list["type"]) - if ("datum") - var/oldval = settings["mainsettings"][setting]["value"] - if (href_list["subtypesonly"]) - settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(subtypesof(text2path(href_list["path"])))) - else - settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(typesof(text2path(href_list["path"])))) - if (isnull(settings["mainsettings"][setting]["value"])) - settings["mainsettings"][setting]["value"] = oldval - if ("string") - settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) - if ("number") - settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num - if ("color") - settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color - if ("boolean") - settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("Yes","No") - if ("ckey") - settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("none") + GLOB.directory - if (settings["mainsettings"][setting]["callback"]) - var/datum/callback/callback = settings["mainsettings"][setting]["callback"] - settings = callback.Invoke(settings) - if (href_list["button"]) - var/button = text2num(href_list["button"]) - if (button <= 3 && button >= 1) - selectedbutton = button - if (selectedbutton != 1) - set_content(ShowChoices(user)) - open() - return - for (var/item in href_list) - switch(item) - if ("close", "button", "src") - continue - opentime = 0 - close() - -/proc/presentpreflikepicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor) - if (!istype(User)) - if (istype(User, /client/)) - var/client/C = User - User = C.mob - else - return - var/datum/browser/modal/preflikepicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, settings, width, height, slidecolor) - A.open() - A.wait() - if (A.selectedbutton) - return list("button" = A.selectedbutton, "settings" = A.settings) - -// This will allow you to show an icon in the browse window -// This is added to mob so that it can be used without a reference to the browser object -// There is probably a better place for this... -/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1) - - -// Registers the on-close verb for a browse window (client/verb/.windowclose) -// this will be called when the close-button of a window is pressed. -// -// This is usually only needed for devices that regularly update the browse window, -// e.g. canisters, timers, etc. -// -// windowid should be the specified window name -// e.g. code is : user << browse(text, "window=fred") -// then use : onclose(user, "fred") -// -// Optionally, specify the "ref" parameter as the controlled atom (usually src) -// to pass a "close=1" parameter to the atom's Topic() proc for special handling. -// Otherwise, the user mob's machine var will be reset directly. -// -/proc/onclose(mob/user, windowid, atom/ref=null) - if(!user.client) - return - var/param = "null" - if(ref) - param = "[REF(ref)]" - - winset(user, windowid, "on-close=\".windowclose [param]\"") - - - -// the on-close client verb -// called when a browser popup window is closed after registering with proc/onclose() -// if a valid atom reference is supplied, call the atom's Topic() with "close=1" -// otherwise, just reset the client mob's machine var. -// -/client/verb/windowclose(atomref as text) - set hidden = 1 // hide this verb from the user's panel - set name = ".windowclose" // no autocomplete on cmd line - - if(atomref!="null") // if passed a real atomref - var/hsrc = locate(atomref) // find the reffed atom - var/href = "close=1" - if(hsrc) - usr = src.mob - src.Topic(href, params2list(href), hsrc) // this will direct to the atom's - return // Topic() proc via client.Topic() - - // no atomref specified (or not found) - // so just reset the user mob's machine var - if(src && src.mob) - src.mob.unset_machine() +/datum/browser + var/mob/user + var/title + var/window_id // window_id is used as the window name for browse and onclose + var/width = 0 + var/height = 0 + var/atom/ref = null + var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id + var/stylesheets[0] + var/scripts[0] + var/title_image + var/head_elements + var/body_elements + var/head_content = "" + var/content = "" + + +/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) + + user = nuser + window_id = nwindow_id + if (ntitle) + title = format_text(ntitle) + if (nwidth) + width = nwidth + if (nheight) + height = nheight + if (nref) + ref = nref + add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs + +/datum/browser/proc/add_head_content(nhead_content) + head_content = nhead_content + +/datum/browser/proc/set_window_options(nwindow_options) + window_options = nwindow_options + +/datum/browser/proc/set_title_image(ntitle_image) + //title_image = ntitle_image + +/datum/browser/proc/add_stylesheet(name, file) + stylesheets["[ckey(name)].css"] = file + register_asset("[ckey(name)].css", file) + +/datum/browser/proc/add_script(name, file) + scripts["[ckey(name)].js"] = file + register_asset("[ckey(name)].js", file) + +/datum/browser/proc/set_content(ncontent) + content = ncontent + +/datum/browser/proc/add_content(ncontent) + content += ncontent + +/datum/browser/proc/get_header() + var/file + for (file in stylesheets) + head_content += "" + + for (file in scripts) + head_content += "" + + var/title_attributes = "class='uiTitle'" + if (title_image) + title_attributes = "class='uiTitle icon' style='background-image: url([title_image]);'" + + return {" + + + + + [head_content] + + +
+ [title ? "
[title]
" : ""] +
+ "} +//" This is here because else the rest of the file looks like a string in notepad++. +/datum/browser/proc/get_footer() + return {" +
+
+ +"} + +/datum/browser/proc/get_content() + return {" + [get_header()] + [content] + [get_footer()] + "} + +/datum/browser/proc/open(use_onclose = 1) + if(isnull(window_id)) //null check because this can potentially nuke goonchat + WARNING("Browser [title] tried to open with a null ID") + to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!") + return + var/window_size = "" + if (width && height) + window_size = "size=[width]x[height];" + if (stylesheets.len) + send_asset_list(user, stylesheets, verify=FALSE) + if (scripts.len) + send_asset_list(user, scripts, verify=FALSE) + user << browse(get_content(), "window=[window_id];[window_size][window_options]") + if (use_onclose) + setup_onclose() + +/datum/browser/proc/setup_onclose() + set waitfor = 0 //winexists sleeps, so we don't need to. + for (var/i in 1 to 10) + if (user && winexists(user, window_id)) + onclose(user, window_id, ref) + break + +/datum/browser/proc/close() + if(!isnull(window_id))//null check because this can potentially nuke goonchat + user << browse(null, "window=[window_id]") + else + WARNING("Browser [title] tried to close with a null ID") + +/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000) + if (!User) + return + + var/output = {"
[Message]

+
+ [Button1]"} + + if (Button2) + output += {"[Button2]"} + + if (Button3) + output += {"[Button3]"} + + output += {"
"} + + ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout) + set_content(output) + +/datum/browser/modal/alert/Topic(href,href_list) + if (href_list["close"] || !user || !user.client) + opentime = 0 + return + if (href_list["button"]) + var/button = text2num(href_list["button"]) + if (button <= 3 && button >= 1) + selectedbutton = button + opentime = 0 + close() + +//designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) +/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) + if (!User) + User = usr + switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)) + if (1) + return Button1 + if (2) + return Button2 + if (3) + return Button3 + +//Same shit, but it returns the button number, could at some point support unlimited button amounts. +/proc/askuser(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) + if (!istype(User)) + if (istype(User, /client/)) + var/client/C = User + User = C.mob + else + return + var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout) + A.open() + A.wait() + if (A.selectedbutton) + return A.selectedbutton + +/datum/browser/modal + var/opentime = 0 + var/timeout + var/selectedbutton = 0 + var/stealfocus + +/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, StealFocus = 1, Timeout = 6000) + ..() + stealfocus = StealFocus + if (!StealFocus) + window_options += "focus=false;" + timeout = Timeout + + +/datum/browser/modal/close() + .=..() + opentime = 0 + +/datum/browser/modal/open(use_onclose = 1) + set waitfor = 0 + opentime = world.time + + if (stealfocus) + . = ..(use_onclose = 1) + else + var/focusedwindow = winget(user, null, "focus") + . = ..(use_onclose = 1) + + //waits for the window to show up client side before attempting to un-focus it + //winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping + for (var/i in 1 to 10) + if (user && winexists(user, window_id)) + if (focusedwindow) + winset(user, focusedwindow, "focus=true") + else + winset(user, "mapwindow", "focus=true") + break + if (timeout) + addtimer(CALLBACK(src, .proc/close), timeout) + +/datum/browser/modal/proc/wait() + while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time)) + stoplag(1) + +/datum/browser/modal/listpicker + var/valueslist = list() + +/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor) + if (!User) + return + + var/output = {"
    "} + if (inputtype == "checkbox" || inputtype == "radio") + for (var/i in values) + var/div_slider = slidecolor + if(!i["allowed_edit"]) + div_slider = "locked" + output += {"
  • + +
  • "} + else + for (var/i in values) + output += {"
  • +
  • "} + output += {"
+ "} + + if (Button2) + output += {""} + + if (Button3) + output += {""} + + output += {"
"} + ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) + set_content(output) + +/datum/browser/modal/listpicker/Topic(href,href_list) + if (href_list["close"] || !user || !user.client) + opentime = 0 + return + if (href_list["button"]) + var/button = text2num(href_list["button"]) + if (button <= 3 && button >= 1) + selectedbutton = button + for (var/item in href_list) + switch(item) + if ("close", "button", "src") + continue + else + valueslist[item] = href_list[item] + opentime = 0 + close() + +/proc/presentpicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor) + if (!istype(User)) + if (istype(User, /client/)) + var/client/C = User + User = C.mob + else + return + var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor) + A.open() + A.wait() + if (A.selectedbutton) + return list("button" = A.selectedbutton, "values" = A.valueslist) + +/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null) + if (!User || !(bitfield in GLOB.bitfields)) + return + var/list/pickerlist = list() + for (var/i in GLOB.bitfields[bitfield]) + var/can_edit = 1 + if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i])) + can_edit = 0 + if (current_value & GLOB.bitfields[bitfield][i]) + pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) + else + pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit)) + var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor) + if (islist(result)) + if (result["button"] == 2) // If the user pressed the cancel button + return + . = 0 + for (var/flag in result["values"]) + . |= GLOB.bitfields[bitfield][flag] + else + return + +/datum/browser/modal/preflikepicker + var/settings = list() + var/icon/preview_icon = null + var/datum/callback/preview_update + +/datum/browser/modal/preflikepicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/settings,inputtype="checkbox", width = 600, height, slidecolor) + if (!User) + return + src.settings = settings + + ..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout) + set_content(ShowChoices(User)) + +/datum/browser/modal/preflikepicker/proc/ShowChoices(mob/user) + if (settings["preview_callback"]) + var/datum/callback/callback = settings["preview_callback"] + preview_icon = callback.Invoke(settings) + if (preview_icon) + user << browse_rsc(preview_icon, "previewicon.png") + var/dat = "" + + for (var/name in settings["mainsettings"]) + var/setting = settings["mainsettings"][name] + if (setting["type"] == "datum") + if (setting["subtypesonly"]) + dat += "[setting["desc"]]: [setting["value"]]
" + else + dat += "[setting["desc"]]: [setting["value"]]
" + else + dat += "[setting["desc"]]: [setting["value"]]
" + + if (preview_icon) + dat += "" + + dat += "
" + + dat += "" + + dat += "" + + dat += "
Ok " + + dat += "
" + + return dat + +/datum/browser/modal/preflikepicker/Topic(href,href_list) + if (href_list["close"] || !user || !user.client) + opentime = 0 + return + if (href_list["task"] == "input") + var/setting = href_list["setting"] + switch (href_list["type"]) + if ("datum") + var/oldval = settings["mainsettings"][setting]["value"] + if (href_list["subtypesonly"]) + settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(subtypesof(text2path(href_list["path"])))) + else + settings["mainsettings"][setting]["value"] = pick_closest_path(null, make_types_fancy(typesof(text2path(href_list["path"])))) + if (isnull(settings["mainsettings"][setting]["value"])) + settings["mainsettings"][setting]["value"] = oldval + if ("string") + settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) + if ("number") + settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num + if ("color") + settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color + if ("boolean") + settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("Yes","No") + if ("ckey") + settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("none") + GLOB.directory + if (settings["mainsettings"][setting]["callback"]) + var/datum/callback/callback = settings["mainsettings"][setting]["callback"] + settings = callback.Invoke(settings) + if (href_list["button"]) + var/button = text2num(href_list["button"]) + if (button <= 3 && button >= 1) + selectedbutton = button + if (selectedbutton != 1) + set_content(ShowChoices(user)) + open() + return + for (var/item in href_list) + switch(item) + if ("close", "button", "src") + continue + opentime = 0 + close() + +/proc/presentpreflikepicker(var/mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/settings, width, height, slidecolor) + if (!istype(User)) + if (istype(User, /client/)) + var/client/C = User + User = C.mob + else + return + var/datum/browser/modal/preflikepicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, settings, width, height, slidecolor) + A.open() + A.wait() + if (A.selectedbutton) + return list("button" = A.selectedbutton, "settings" = A.settings) + +// This will allow you to show an icon in the browse window +// This is added to mob so that it can be used without a reference to the browser object +// There is probably a better place for this... +/mob/proc/browse_rsc_icon(icon, icon_state, dir = -1) + + +// Registers the on-close verb for a browse window (client/verb/.windowclose) +// this will be called when the close-button of a window is pressed. +// +// This is usually only needed for devices that regularly update the browse window, +// e.g. canisters, timers, etc. +// +// windowid should be the specified window name +// e.g. code is : user << browse(text, "window=fred") +// then use : onclose(user, "fred") +// +// Optionally, specify the "ref" parameter as the controlled atom (usually src) +// to pass a "close=1" parameter to the atom's Topic() proc for special handling. +// Otherwise, the user mob's machine var will be reset directly. +// +/proc/onclose(mob/user, windowid, atom/ref=null) + if(!user.client) + return + var/param = "null" + if(ref) + param = "[REF(ref)]" + + winset(user, windowid, "on-close=\".windowclose [param]\"") + + + +// the on-close client verb +// called when a browser popup window is closed after registering with proc/onclose() +// if a valid atom reference is supplied, call the atom's Topic() with "close=1" +// otherwise, just reset the client mob's machine var. +// +/client/verb/windowclose(atomref as text) + set hidden = 1 // hide this verb from the user's panel + set name = ".windowclose" // no autocomplete on cmd line + + if(atomref!="null") // if passed a real atomref + var/hsrc = locate(atomref) // find the reffed atom + var/href = "close=1" + if(hsrc) + usr = src.mob + src.Topic(href, params2list(href), hsrc) // this will direct to the atom's + return // Topic() proc via client.Topic() + + // no atomref specified (or not found) + // so just reset the user mob's machine var + if(src && src.mob) + src.mob.unset_machine() diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 72b9681f91..0baf7d7d1b 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -1,314 +1,314 @@ -/datum/component - var/dupe_mode = COMPONENT_DUPE_HIGHLANDER - var/dupe_type - 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 - var/can_transfer = FALSE - -/datum/component/New(datum/P, ...) - parent = P - var/list/arguments = args.Copy(2) - if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) - qdel(src, TRUE, TRUE) - CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") - - _JoinParent(P) - -/datum/component/proc/_JoinParent() - var/datum/P = parent - //lazy init the parent's dc list - var/list/dc = P.datum_components - if(!dc) - P.datum_components = dc = list() - - //set up the typecache - var/our_type = type - for(var/I in _GetInverseTypeList(our_type)) - var/test = dc[I] - if(test) //already another component of this type here - var/list/components_of_type - if(!length(test)) - components_of_type = list(test) - dc[I] = components_of_type - else - components_of_type = test - if(I == our_type) //exact match, take priority - var/inserted = FALSE - for(var/J in 1 to components_of_type.len) - var/datum/component/C = components_of_type[J] - if(C.type != our_type) //but not over other exact matches - components_of_type.Insert(J, I) - inserted = TRUE - break - if(!inserted) - components_of_type += src - else //indirect match, back of the line with ya - components_of_type += src - else //only component of this type, no list - dc[I] = src - - 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() - SEND_SIGNAL(src, COMSIG_COMPONENT_REGISTER_PARENT) //CITADEL EDIT - -/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 ..() - -/datum/component/proc/_RemoveFromParent() - var/datum/P = parent - var/list/dc = P.datum_components - for(var/I in _GetInverseTypeList()) - var/list/components_of_type = dc[I] - if(length(components_of_type)) // - var/list/subtracted = components_of_type - src - if(subtracted.len == 1) //only 1 guy left - dc[I] = subtracted[1] //make him special - else - dc[I] = subtracted - else //just us - dc -= I - if(!dc.len) - P.datum_components = null - - UnregisterFromParent() - -/datum/component/proc/UnregisterFromParent() - SEND_SIGNAL(src, COMSIG_COMPONENT_UNREGISTER_PARENT) //CITADEL EDIT - -/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE) - if(QDELETED(src) || QDELETED(target)) - return - - var/list/procs = signal_procs - if(!procs) - signal_procs = procs = list() - if(!procs[target]) - procs[target] = list() - var/list/lookup = target.comp_lookup - if(!lookup) - target.comp_lookup = lookup = list() - - 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] = proctype - - if(!lookup[sig_type]) // Nothing has registered here yet - lookup[sig_type] = src - else if(lookup[sig_type] == src) // We already registered here - continue - else if(!length(lookup[sig_type])) // One other thing registered here - lookup[sig_type] = list(lookup[sig_type]=TRUE) - lookup[sig_type][src] = TRUE - else // Many other things have registered here - lookup[sig_type][src] = TRUE - - signal_enabled = TRUE - -/datum/proc/UnregisterSignal(datum/target, sig_type_or_types) - var/list/lookup = target.comp_lookup - if(!signal_procs || !signal_procs[target] || !lookup) - return - if(!islist(sig_type_or_types)) - sig_type_or_types = list(sig_type_or_types) - for(var/sig in sig_type_or_types) - switch(length(lookup[sig])) - if(2) - lookup[sig] = (lookup[sig]-src)[1] - if(1) - stack_trace("[target] ([target.type]) somehow has single length list inside comp_lookup") - if(src in lookup[sig]) - lookup -= sig - if(!length(lookup)) - target.comp_lookup = null - break - if(0) - lookup -= sig - if(!length(lookup)) - target.comp_lookup = null - break - else - lookup[sig] -= src - - signal_procs[target] -= sig_type_or_types - if(!signal_procs[target].len) - signal_procs -= target - -/datum/component/proc/InheritComponent(datum/component/C, i_am_original) - return - -/datum/component/proc/PreTransfer() - return - -/datum/component/proc/PostTransfer() - return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it - -/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) - current_type = type2parent(current_type) - . += current_type - -/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/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/proctype = C.signal_procs[src][sigtype] - . |= CallAsync(C, proctype, arguments) - -// The type arg is casted so initial works, you shouldn't be passing a real instance into this -/datum/proc/GetComponent(datum/component/c_type) - RETURN_TYPE(c_type) - if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED) - 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 - . = dc[c_type] - if(length(.)) - return .[1] - -/datum/proc/GetExactComponent(c_type) - var/list/dc = datum_components - if(!dc) - return null - var/datum/component/C = dc[c_type] - if(C) - if(length(C)) - C = C[1] - if(C.type == c_type) - return C - return null - -/datum/proc/GetComponents(c_type) - var/list/dc = datum_components - if(!dc) - return null - . = dc[c_type] - if(!length(.)) - return list(.) - -/datum/proc/AddComponent(new_type, ...) - var/datum/component/nt = new_type - var/dm = initial(nt.dupe_mode) - var/dt = initial(nt.dupe_type) - - var/datum/component/old_comp - var/datum/component/new_comp - - if(ispath(nt)) - if(nt == /datum/component) - CRASH("[nt] attempted instantiation!") - else - new_comp = nt - nt = new_comp.type - - args[1] = src - - if(dm != COMPONENT_DUPE_ALLOWED) - if(!dt) - old_comp = GetExactComponent(nt) - else - old_comp = GetComponent(dt) - if(old_comp) - switch(dm) - if(COMPONENT_DUPE_UNIQUE) - if(!new_comp) - new_comp = new nt(arglist(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)) - 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) - else - old_comp.InheritComponent(new_comp, TRUE) - 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 - else if(!new_comp) - new_comp = new nt(arglist(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 - -/datum/proc/LoadComponent(component_type, ...) - . = GetComponent(component_type) - if(!.) - return AddComponent(arglist(args)) - -/datum/component/proc/RemoveComponent() - if(!parent) - return - var/datum/old_parent = parent - PreTransfer() - _RemoveFromParent() - parent = null - SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) - -/datum/proc/TakeComponent(datum/component/target) - if(!target || target.parent == src) - return - if(target.parent) - target.RemoveComponent() - target.parent = src - var/result = target.PostTransfer() - switch(result) - if(COMPONENT_INCOMPATIBLE) - var/c_type = target.type - qdel(target) - CRASH("Incompatible [c_type] transfer attempt to a [type]!") - - if(target == AddComponent(target)) - target._JoinParent() - -/datum/proc/TransferComponents(datum/target) - var/list/dc = datum_components - if(!dc) - return - var/comps = dc[/datum/component] - if(islist(comps)) - for(var/datum/component/I in comps) - if(I.can_transfer) - target.TakeComponent(I) - else - var/datum/component/C = comps - if(C.can_transfer) - target.TakeComponent(comps) - -/datum/component/ui_host() - return parent +/datum/component + var/dupe_mode = COMPONENT_DUPE_HIGHLANDER + var/dupe_type + 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 + var/can_transfer = FALSE + +/datum/component/New(datum/P, ...) + parent = P + var/list/arguments = args.Copy(2) + if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) + qdel(src, TRUE, TRUE) + CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") + + _JoinParent(P) + +/datum/component/proc/_JoinParent() + var/datum/P = parent + //lazy init the parent's dc list + var/list/dc = P.datum_components + if(!dc) + P.datum_components = dc = list() + + //set up the typecache + var/our_type = type + for(var/I in _GetInverseTypeList(our_type)) + var/test = dc[I] + if(test) //already another component of this type here + var/list/components_of_type + if(!length(test)) + components_of_type = list(test) + dc[I] = components_of_type + else + components_of_type = test + if(I == our_type) //exact match, take priority + var/inserted = FALSE + for(var/J in 1 to components_of_type.len) + var/datum/component/C = components_of_type[J] + if(C.type != our_type) //but not over other exact matches + components_of_type.Insert(J, I) + inserted = TRUE + break + if(!inserted) + components_of_type += src + else //indirect match, back of the line with ya + components_of_type += src + else //only component of this type, no list + dc[I] = src + + 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() + SEND_SIGNAL(src, COMSIG_COMPONENT_REGISTER_PARENT) //CITADEL EDIT + +/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 ..() + +/datum/component/proc/_RemoveFromParent() + var/datum/P = parent + var/list/dc = P.datum_components + for(var/I in _GetInverseTypeList()) + var/list/components_of_type = dc[I] + if(length(components_of_type)) // + var/list/subtracted = components_of_type - src + if(subtracted.len == 1) //only 1 guy left + dc[I] = subtracted[1] //make him special + else + dc[I] = subtracted + else //just us + dc -= I + if(!dc.len) + P.datum_components = null + + UnregisterFromParent() + +/datum/component/proc/UnregisterFromParent() + SEND_SIGNAL(src, COMSIG_COMPONENT_UNREGISTER_PARENT) //CITADEL EDIT + +/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE) + if(QDELETED(src) || QDELETED(target)) + return + + var/list/procs = signal_procs + if(!procs) + signal_procs = procs = list() + if(!procs[target]) + procs[target] = list() + var/list/lookup = target.comp_lookup + if(!lookup) + target.comp_lookup = lookup = list() + + 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] = proctype + + if(!lookup[sig_type]) // Nothing has registered here yet + lookup[sig_type] = src + else if(lookup[sig_type] == src) // We already registered here + continue + else if(!length(lookup[sig_type])) // One other thing registered here + lookup[sig_type] = list(lookup[sig_type]=TRUE) + lookup[sig_type][src] = TRUE + else // Many other things have registered here + lookup[sig_type][src] = TRUE + + signal_enabled = TRUE + +/datum/proc/UnregisterSignal(datum/target, sig_type_or_types) + var/list/lookup = target.comp_lookup + if(!signal_procs || !signal_procs[target] || !lookup) + return + if(!islist(sig_type_or_types)) + sig_type_or_types = list(sig_type_or_types) + for(var/sig in sig_type_or_types) + switch(length(lookup[sig])) + if(2) + lookup[sig] = (lookup[sig]-src)[1] + if(1) + stack_trace("[target] ([target.type]) somehow has single length list inside comp_lookup") + if(src in lookup[sig]) + lookup -= sig + if(!length(lookup)) + target.comp_lookup = null + break + if(0) + lookup -= sig + if(!length(lookup)) + target.comp_lookup = null + break + else + lookup[sig] -= src + + signal_procs[target] -= sig_type_or_types + if(!signal_procs[target].len) + signal_procs -= target + +/datum/component/proc/InheritComponent(datum/component/C, i_am_original) + return + +/datum/component/proc/PreTransfer() + return + +/datum/component/proc/PostTransfer() + return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it + +/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) + current_type = type2parent(current_type) + . += current_type + +/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/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/proctype = C.signal_procs[src][sigtype] + . |= CallAsync(C, proctype, arguments) + +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/datum/proc/GetComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED) + 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 + . = dc[c_type] + if(length(.)) + return .[1] + +/datum/proc/GetExactComponent(c_type) + var/list/dc = datum_components + if(!dc) + return null + var/datum/component/C = dc[c_type] + if(C) + if(length(C)) + C = C[1] + if(C.type == c_type) + return C + return null + +/datum/proc/GetComponents(c_type) + var/list/dc = datum_components + if(!dc) + return null + . = dc[c_type] + if(!length(.)) + return list(.) + +/datum/proc/AddComponent(new_type, ...) + var/datum/component/nt = new_type + var/dm = initial(nt.dupe_mode) + var/dt = initial(nt.dupe_type) + + var/datum/component/old_comp + var/datum/component/new_comp + + if(ispath(nt)) + if(nt == /datum/component) + CRASH("[nt] attempted instantiation!") + else + new_comp = nt + nt = new_comp.type + + args[1] = src + + if(dm != COMPONENT_DUPE_ALLOWED) + if(!dt) + old_comp = GetExactComponent(nt) + else + old_comp = GetComponent(dt) + if(old_comp) + switch(dm) + if(COMPONENT_DUPE_UNIQUE) + if(!new_comp) + new_comp = new nt(arglist(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)) + 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) + else + old_comp.InheritComponent(new_comp, TRUE) + 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 + else if(!new_comp) + new_comp = new nt(arglist(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 + +/datum/proc/LoadComponent(component_type, ...) + . = GetComponent(component_type) + if(!.) + return AddComponent(arglist(args)) + +/datum/component/proc/RemoveComponent() + if(!parent) + return + var/datum/old_parent = parent + PreTransfer() + _RemoveFromParent() + parent = null + SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) + +/datum/proc/TakeComponent(datum/component/target) + if(!target || target.parent == src) + return + if(target.parent) + target.RemoveComponent() + target.parent = src + var/result = target.PostTransfer() + switch(result) + if(COMPONENT_INCOMPATIBLE) + var/c_type = target.type + qdel(target) + CRASH("Incompatible [c_type] transfer attempt to a [type]!") + + if(target == AddComponent(target)) + target._JoinParent() + +/datum/proc/TransferComponents(datum/target) + var/list/dc = datum_components + if(!dc) + return + var/comps = dc[/datum/component] + if(islist(comps)) + for(var/datum/component/I in comps) + if(I.can_transfer) + target.TakeComponent(I) + else + var/datum/component/C = comps + if(C.can_transfer) + target.TakeComponent(comps) + +/datum/component/ui_host() + return parent diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm index 08f3c1d643..da2ff1b177 100644 --- a/code/datums/components/jousting.dm +++ b/code/datums/components/jousting.dm @@ -1,74 +1,74 @@ -/datum/component/jousting - var/current_direction = NONE - var/max_tile_charge = 5 - var/min_tile_charge = 2 //tiles before this code gets into effect. - var/current_tile_charge = 0 - var/movement_reset_tolerance = 2 //deciseconds - var/unmounted_damage_boost_per_tile = 0 - var/unmounted_knockdown_chance_per_tile = 0 - var/unmounted_knockdown_time = 0 - var/mounted_damage_boost_per_tile = 2 - var/mounted_knockdown_chance_per_tile = 20 - var/mounted_knockdown_time = 20 - var/requires_mob_riding = TRUE //whether this only works if the attacker is riding a mob, rather than anything they can buckle to. - var/requires_mount = TRUE //kinda defeats the point of jousting if you're not mounted but whatever. - var/mob/current_holder - var/current_timerid - -/datum/component/jousting/Initialize() - if(!isitem(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) - RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) - RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/on_attack) - -/datum/component/jousting/proc/on_equip(datum/source, mob/user, slot) - RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/mob_move, TRUE) - current_holder = user - -/datum/component/jousting/proc/on_drop(datum/source, mob/user) - UnregisterSignal(user, COMSIG_MOVABLE_MOVED) - current_holder = null - current_direction = NONE - current_tile_charge = 0 - -/datum/component/jousting/proc/on_attack(datum/source, mob/living/target, mob/user) - if(user != current_holder) - return - var/current = current_tile_charge - var/obj/item/I = parent - var/target_buckled = target.buckled ? TRUE : FALSE //we don't need the reference of what they're buckled to, just whether they are. - if((requires_mount && ((requires_mob_riding && !ismob(user.buckled)) || (!user.buckled))) || !current_direction || (current_tile_charge < min_tile_charge)) - return - var/turf/target_turf = get_step(user, current_direction) - if(target in range(1, target_turf)) - var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current - var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time) - var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current - var/sharp = I.get_sharpness() - var/msg - if(damage) - msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]" - target.apply_damage(damage, BRUTE, user.zone_selected, 0) - if(prob(knockdown_chance)) - msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]" - if(target_buckled) - target.buckled.unbuckle_mob(target) - target.Knockdown(knockdown_time) - if(length(msg)) - user.visible_message("[msg]!") - -/datum/component/jousting/proc/mob_move(datum/source, newloc, dir) - if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled)))) - return - if(dir != current_direction) - current_tile_charge = 0 - current_direction = dir - if(current_tile_charge < max_tile_charge) - current_tile_charge++ - if(current_timerid) - deltimer(current_timerid) - current_timerid = addtimer(CALLBACK(src, .proc/reset_charge), movement_reset_tolerance, TIMER_STOPPABLE) - -/datum/component/jousting/proc/reset_charge() - current_tile_charge = 0 +/datum/component/jousting + var/current_direction = NONE + var/max_tile_charge = 5 + var/min_tile_charge = 2 //tiles before this code gets into effect. + var/current_tile_charge = 0 + var/movement_reset_tolerance = 2 //deciseconds + var/unmounted_damage_boost_per_tile = 0 + var/unmounted_knockdown_chance_per_tile = 0 + var/unmounted_knockdown_time = 0 + var/mounted_damage_boost_per_tile = 2 + var/mounted_knockdown_chance_per_tile = 20 + var/mounted_knockdown_time = 20 + var/requires_mob_riding = TRUE //whether this only works if the attacker is riding a mob, rather than anything they can buckle to. + var/requires_mount = TRUE //kinda defeats the point of jousting if you're not mounted but whatever. + var/mob/current_holder + var/current_timerid + +/datum/component/jousting/Initialize() + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/on_attack) + +/datum/component/jousting/proc/on_equip(datum/source, mob/user, slot) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/mob_move, TRUE) + current_holder = user + +/datum/component/jousting/proc/on_drop(datum/source, mob/user) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + current_holder = null + current_direction = NONE + current_tile_charge = 0 + +/datum/component/jousting/proc/on_attack(datum/source, mob/living/target, mob/user) + if(user != current_holder) + return + var/current = current_tile_charge + var/obj/item/I = parent + var/target_buckled = target.buckled ? TRUE : FALSE //we don't need the reference of what they're buckled to, just whether they are. + if((requires_mount && ((requires_mob_riding && !ismob(user.buckled)) || (!user.buckled))) || !current_direction || (current_tile_charge < min_tile_charge)) + return + var/turf/target_turf = get_step(user, current_direction) + if(target in range(1, target_turf)) + var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current + var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time) + var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current + var/sharp = I.get_sharpness() + var/msg + if(damage) + msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]" + target.apply_damage(damage, BRUTE, user.zone_selected, 0) + if(prob(knockdown_chance)) + msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]" + if(target_buckled) + target.buckled.unbuckle_mob(target) + target.Knockdown(knockdown_time) + if(length(msg)) + user.visible_message("[msg]!") + +/datum/component/jousting/proc/mob_move(datum/source, newloc, dir) + if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled)))) + return + if(dir != current_direction) + current_tile_charge = 0 + current_direction = dir + if(current_tile_charge < max_tile_charge) + current_tile_charge++ + if(current_timerid) + deltimer(current_timerid) + current_timerid = addtimer(CALLBACK(src, .proc/reset_charge), movement_reset_tolerance, TIMER_STOPPABLE) + +/datum/component/jousting/proc/reset_charge() + current_tile_charge = 0 diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm index bbdbb7dc66..045611ab9d 100644 --- a/code/datums/components/lockon_aiming.dm +++ b/code/datums/components/lockon_aiming.dm @@ -1,239 +1,239 @@ -#define LOCKON_AIMING_MAX_CURSOR_RADIUS 7 -#define LOCKON_IGNORE_RESULT "ignore_my_result" -#define LOCKON_RANGING_BREAK_CHECK if(current_ranging_id != this_id){return LOCKON_IGNORE_RESULT} - -/datum/component/lockon_aiming - dupe_mode = COMPONENT_DUPE_ALLOWED - var/lock_icon = 'icons/mob/cameramob.dmi' - var/lock_icon_state = "marker" - var/mutable_appearance/lock_appearance - var/list/image/lock_images - var/list/target_typecache - var/list/immune_weakrefs //list(weakref = TRUE) - var/mob_stat_check = TRUE //if a potential target is a mob make sure it's conscious! - var/lock_amount = 1 - var/lock_cursor_range = 5 - var/list/locked_weakrefs - var/update_disabled = FALSE - var/current_ranging_id = 0 - var/list/last_location - var/datum/callback/on_lock - var/datum/callback/can_target_callback - -/datum/component/lockon_aiming/Initialize(range, list/typecache, amount, list/immune, datum/callback/when_locked, icon, icon_state, datum/callback/target_callback) - if(!ismob(parent)) - return COMPONENT_INCOMPATIBLE - if(target_callback) - can_target_callback = target_callback - else - can_target_callback = CALLBACK(src, .proc/can_target) - if(range) - lock_cursor_range = range - if(typecache) - target_typecache = typecache - if(amount) - lock_amount = amount - immune_weakrefs = list(WEAKREF(parent) = TRUE) //Manually take this out if you want.. - if(immune) - for(var/i in immune) - if(isweakref(i)) - immune_weakrefs[i] = TRUE - else if(isatom(i)) - immune_weakrefs[WEAKREF(i)] = TRUE - if(when_locked) - on_lock = when_locked - if(icon) - lock_icon = icon - if(icon_state) - lock_icon_state = icon_state - generate_lock_visuals() - var/mob/M = parent - LAZYOR(M.mousemove_intercept_objects, src) - START_PROCESSING(SSfastprocess, src) - -/datum/component/lockon_aiming/Destroy() - var/mob/M = parent - clear_visuals() - LAZYREMOVE(M.mousemove_intercept_objects, src) - STOP_PROCESSING(SSfastprocess, src) - return ..() - -/datum/component/lockon_aiming/proc/show_visuals() - LAZYINITLIST(lock_images) - var/mob/M = parent - if(!M.client) - return - for(var/i in locked_weakrefs) - var/datum/weakref/R = i - var/atom/A = R.resolve() - if(!A) - continue //It'll be cleared by processing. - var/image/I = new - I.appearance = lock_appearance - I.loc = A - M.client.images |= I - lock_images |= I - -/datum/component/lockon_aiming/proc/clear_visuals() - var/mob/M = parent - if(!M.client) - return - if(!lock_images) - return - for(var/i in lock_images) - M.client.images -= i - qdel(i) - lock_images.Cut() - -/datum/component/lockon_aiming/proc/refresh_visuals() - clear_visuals() - show_visuals() - -/datum/component/lockon_aiming/proc/generate_lock_visuals() - lock_appearance = mutable_appearance(icon = lock_icon, icon_state = lock_icon_state, layer = FLOAT_LAYER) - -/datum/component/lockon_aiming/proc/unlock_all(refresh_vis = TRUE) - LAZYCLEARLIST(locked_weakrefs) - if(refresh_vis) - refresh_visuals() - -/datum/component/lockon_aiming/proc/unlock(atom/A, refresh_vis = TRUE) - if(!A.weak_reference) - return - LAZYREMOVE(locked_weakrefs, A.weak_reference) - if(refresh_vis) - refresh_visuals() - -/datum/component/lockon_aiming/proc/lock(atom/A, refresh_vis = TRUE) - LAZYOR(locked_weakrefs, WEAKREF(A)) - if(refresh_vis) - refresh_visuals() - -/datum/component/lockon_aiming/proc/add_immune_atom(atom/A) - var/datum/weakref/R = WEAKREF(A) - if(immune_weakrefs && (immune_weakrefs[R])) - return - LAZYSET(immune_weakrefs, R, TRUE) - -/datum/component/lockon_aiming/proc/remove_immune_atom(atom/A) - if(!A.weak_reference || !immune_weakrefs) //if A doesn't have a weakref how did it get on the immunity list? - return - LAZYREMOVE(immune_weakrefs, A.weak_reference) - -/datum/component/lockon_aiming/onMouseMove(object,location,control,params) - var/mob/M = parent - if(!istype(M) || !M.client) - return - var/datum/position/P = mouse_absolute_datum_map_position_from_client(M.client) - if(!P) - return - var/turf/T = P.return_turf() - LAZYINITLIST(last_location) - if(length(last_location) == 3 && last_location[1] == T.x && last_location[2] == T.y && last_location[3] == T.z) - return //Same turf, don't bother. - if(last_location) - last_location.Cut() - else - last_location = list() - last_location.len = 3 - last_location[1] = T.x - last_location[2] = T.y - last_location[3] = T.z - autolock() - -/datum/component/lockon_aiming/process() - if(update_disabled) - return - if(!last_location) - return - var/changed = FALSE - for(var/i in locked_weakrefs) - var/datum/weakref/R = i - if(istype(R)) - var/atom/thing = R.resolve() - if(!istype(thing) || (get_dist(thing, locate(last_location[1], last_location[2], last_location[3])) > lock_cursor_range)) - unlock(R) - changed = TRUE - else - unlock(R) - changed = TRUE - if(changed) - autolock() - -/datum/component/lockon_aiming/proc/autolock() - var/mob/M = parent - if(!M.client) - return FALSE - var/datum/position/current = mouse_absolute_datum_map_position_from_client(M.client) - var/turf/target = current.return_turf() - var/list/atom/targets = get_nearest(target, target_typecache, lock_amount, lock_cursor_range) - if(targets == LOCKON_IGNORE_RESULT) - return - unlock_all(FALSE) - for(var/i in targets) - if(immune_weakrefs[WEAKREF(i)]) - continue - lock(i, FALSE) - refresh_visuals() - on_lock.Invoke(locked_weakrefs) - -/datum/component/lockon_aiming/proc/can_target(atom/A) - var/mob/M = A - return is_type_in_typecache(A, target_typecache) && !(ismob(A) && mob_stat_check && M.stat != CONSCIOUS) && !immune_weakrefs[WEAKREF(A)] - -/datum/component/lockon_aiming/proc/get_nearest(turf/T, list/typecache, amount, range) - current_ranging_id++ - var/this_id = current_ranging_id - var/list/L = list() - var/turf/center = get_turf(T) - if(amount < 1 || range < 0 || !istype(center) || !islist(typecache)) - return - if(range == 0) - return typecache_filter_list(T.contents + T, typecache) - var/x = 0 - var/y = 0 - var/cd = 0 - while(cd <= range) - x = center.x - cd + 1 - y = center.y + cd - LOCKON_RANGING_BREAK_CHECK - for(x in x to center.x + cd) - T = locate(x, y, center.z) - if(T) - L |= special_list_filter(T.contents, can_target_callback) - if(L.len >= amount) - L.Cut(amount+1) - return L - LOCKON_RANGING_BREAK_CHECK - y = center.y + cd - 1 - x = center.x + cd - for(y in center.y - cd to y) - T = locate(x, y, center.z) - if(T) - L |= special_list_filter(T.contents, can_target_callback) - if(L.len >= amount) - L.Cut(amount+1) - return L - LOCKON_RANGING_BREAK_CHECK - y = center.y - cd - x = center.x + cd - 1 - for(x in center.x - cd to x) - T = locate(x, y, center.z) - if(T) - L |= special_list_filter(T.contents, can_target_callback) - if(L.len >= amount) - L.Cut(amount+1) - return L - LOCKON_RANGING_BREAK_CHECK - y = center.y - cd + 1 - x = center.x - cd - for(y in y to center.y + cd) - T = locate(x, y, center.z) - if(T) - L |= special_list_filter(T.contents, can_target_callback) - if(L.len >= amount) - L.Cut(amount+1) - return L - LOCKON_RANGING_BREAK_CHECK - cd++ - CHECK_TICK +#define LOCKON_AIMING_MAX_CURSOR_RADIUS 7 +#define LOCKON_IGNORE_RESULT "ignore_my_result" +#define LOCKON_RANGING_BREAK_CHECK if(current_ranging_id != this_id){return LOCKON_IGNORE_RESULT} + +/datum/component/lockon_aiming + dupe_mode = COMPONENT_DUPE_ALLOWED + var/lock_icon = 'icons/mob/cameramob.dmi' + var/lock_icon_state = "marker" + var/mutable_appearance/lock_appearance + var/list/image/lock_images + var/list/target_typecache + var/list/immune_weakrefs //list(weakref = TRUE) + var/mob_stat_check = TRUE //if a potential target is a mob make sure it's conscious! + var/lock_amount = 1 + var/lock_cursor_range = 5 + var/list/locked_weakrefs + var/update_disabled = FALSE + var/current_ranging_id = 0 + var/list/last_location + var/datum/callback/on_lock + var/datum/callback/can_target_callback + +/datum/component/lockon_aiming/Initialize(range, list/typecache, amount, list/immune, datum/callback/when_locked, icon, icon_state, datum/callback/target_callback) + if(!ismob(parent)) + return COMPONENT_INCOMPATIBLE + if(target_callback) + can_target_callback = target_callback + else + can_target_callback = CALLBACK(src, .proc/can_target) + if(range) + lock_cursor_range = range + if(typecache) + target_typecache = typecache + if(amount) + lock_amount = amount + immune_weakrefs = list(WEAKREF(parent) = TRUE) //Manually take this out if you want.. + if(immune) + for(var/i in immune) + if(isweakref(i)) + immune_weakrefs[i] = TRUE + else if(isatom(i)) + immune_weakrefs[WEAKREF(i)] = TRUE + if(when_locked) + on_lock = when_locked + if(icon) + lock_icon = icon + if(icon_state) + lock_icon_state = icon_state + generate_lock_visuals() + var/mob/M = parent + LAZYOR(M.mousemove_intercept_objects, src) + START_PROCESSING(SSfastprocess, src) + +/datum/component/lockon_aiming/Destroy() + var/mob/M = parent + clear_visuals() + LAZYREMOVE(M.mousemove_intercept_objects, src) + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/datum/component/lockon_aiming/proc/show_visuals() + LAZYINITLIST(lock_images) + var/mob/M = parent + if(!M.client) + return + for(var/i in locked_weakrefs) + var/datum/weakref/R = i + var/atom/A = R.resolve() + if(!A) + continue //It'll be cleared by processing. + var/image/I = new + I.appearance = lock_appearance + I.loc = A + M.client.images |= I + lock_images |= I + +/datum/component/lockon_aiming/proc/clear_visuals() + var/mob/M = parent + if(!M.client) + return + if(!lock_images) + return + for(var/i in lock_images) + M.client.images -= i + qdel(i) + lock_images.Cut() + +/datum/component/lockon_aiming/proc/refresh_visuals() + clear_visuals() + show_visuals() + +/datum/component/lockon_aiming/proc/generate_lock_visuals() + lock_appearance = mutable_appearance(icon = lock_icon, icon_state = lock_icon_state, layer = FLOAT_LAYER) + +/datum/component/lockon_aiming/proc/unlock_all(refresh_vis = TRUE) + LAZYCLEARLIST(locked_weakrefs) + if(refresh_vis) + refresh_visuals() + +/datum/component/lockon_aiming/proc/unlock(atom/A, refresh_vis = TRUE) + if(!A.weak_reference) + return + LAZYREMOVE(locked_weakrefs, A.weak_reference) + if(refresh_vis) + refresh_visuals() + +/datum/component/lockon_aiming/proc/lock(atom/A, refresh_vis = TRUE) + LAZYOR(locked_weakrefs, WEAKREF(A)) + if(refresh_vis) + refresh_visuals() + +/datum/component/lockon_aiming/proc/add_immune_atom(atom/A) + var/datum/weakref/R = WEAKREF(A) + if(immune_weakrefs && (immune_weakrefs[R])) + return + LAZYSET(immune_weakrefs, R, TRUE) + +/datum/component/lockon_aiming/proc/remove_immune_atom(atom/A) + if(!A.weak_reference || !immune_weakrefs) //if A doesn't have a weakref how did it get on the immunity list? + return + LAZYREMOVE(immune_weakrefs, A.weak_reference) + +/datum/component/lockon_aiming/onMouseMove(object,location,control,params) + var/mob/M = parent + if(!istype(M) || !M.client) + return + var/datum/position/P = mouse_absolute_datum_map_position_from_client(M.client) + if(!P) + return + var/turf/T = P.return_turf() + LAZYINITLIST(last_location) + if(length(last_location) == 3 && last_location[1] == T.x && last_location[2] == T.y && last_location[3] == T.z) + return //Same turf, don't bother. + if(last_location) + last_location.Cut() + else + last_location = list() + last_location.len = 3 + last_location[1] = T.x + last_location[2] = T.y + last_location[3] = T.z + autolock() + +/datum/component/lockon_aiming/process() + if(update_disabled) + return + if(!last_location) + return + var/changed = FALSE + for(var/i in locked_weakrefs) + var/datum/weakref/R = i + if(istype(R)) + var/atom/thing = R.resolve() + if(!istype(thing) || (get_dist(thing, locate(last_location[1], last_location[2], last_location[3])) > lock_cursor_range)) + unlock(R) + changed = TRUE + else + unlock(R) + changed = TRUE + if(changed) + autolock() + +/datum/component/lockon_aiming/proc/autolock() + var/mob/M = parent + if(!M.client) + return FALSE + var/datum/position/current = mouse_absolute_datum_map_position_from_client(M.client) + var/turf/target = current.return_turf() + var/list/atom/targets = get_nearest(target, target_typecache, lock_amount, lock_cursor_range) + if(targets == LOCKON_IGNORE_RESULT) + return + unlock_all(FALSE) + for(var/i in targets) + if(immune_weakrefs[WEAKREF(i)]) + continue + lock(i, FALSE) + refresh_visuals() + on_lock.Invoke(locked_weakrefs) + +/datum/component/lockon_aiming/proc/can_target(atom/A) + var/mob/M = A + return is_type_in_typecache(A, target_typecache) && !(ismob(A) && mob_stat_check && M.stat != CONSCIOUS) && !immune_weakrefs[WEAKREF(A)] + +/datum/component/lockon_aiming/proc/get_nearest(turf/T, list/typecache, amount, range) + current_ranging_id++ + var/this_id = current_ranging_id + var/list/L = list() + var/turf/center = get_turf(T) + if(amount < 1 || range < 0 || !istype(center) || !islist(typecache)) + return + if(range == 0) + return typecache_filter_list(T.contents + T, typecache) + var/x = 0 + var/y = 0 + var/cd = 0 + while(cd <= range) + x = center.x - cd + 1 + y = center.y + cd + LOCKON_RANGING_BREAK_CHECK + for(x in x to center.x + cd) + T = locate(x, y, center.z) + if(T) + L |= special_list_filter(T.contents, can_target_callback) + if(L.len >= amount) + L.Cut(amount+1) + return L + LOCKON_RANGING_BREAK_CHECK + y = center.y + cd - 1 + x = center.x + cd + for(y in center.y - cd to y) + T = locate(x, y, center.z) + if(T) + L |= special_list_filter(T.contents, can_target_callback) + if(L.len >= amount) + L.Cut(amount+1) + return L + LOCKON_RANGING_BREAK_CHECK + y = center.y - cd + x = center.x + cd - 1 + for(x in center.x - cd to x) + T = locate(x, y, center.z) + if(T) + L |= special_list_filter(T.contents, can_target_callback) + if(L.len >= amount) + L.Cut(amount+1) + return L + LOCKON_RANGING_BREAK_CHECK + y = center.y - cd + 1 + x = center.x - cd + for(y in y to center.y + cd) + T = locate(x, y, center.z) + if(T) + L |= special_list_filter(T.contents, can_target_callback) + if(L.len >= amount) + L.Cut(amount+1) + return L + LOCKON_RANGING_BREAK_CHECK + cd++ + CHECK_TICK diff --git a/code/datums/components/ntnet_interface.dm b/code/datums/components/ntnet_interface.dm index 7c364a61ab..6159c7c2c4 100644 --- a/code/datums/components/ntnet_interface.dm +++ b/code/datums/components/ntnet_interface.dm @@ -1,68 +1,68 @@ -//Thing meant for allowing datums and objects to access a NTnet network datum. -/datum/proc/ntnet_receive(datum/netdata/data) - return - -/datum/proc/ntnet_receive_broadcast(datum/netdata/data) - return - -/datum/proc/ntnet_send(datum/netdata/data, netid) - var/datum/component/ntnet_interface/NIC = GetComponent(/datum/component/ntnet_interface) - if(!NIC) - return FALSE - return NIC.__network_send(data, netid) - -/datum/component/ntnet_interface - var/hardware_id //text. this is the true ID. do not change this. stuff like ID forgery can be done manually. - var/network_name = "" //text - var/list/networks_connected_by_id = list() //id = datum/ntnet - var/differentiate_broadcast = TRUE //If false, broadcasts go to ntnet_receive. NOT RECOMMENDED. - -/datum/component/ntnet_interface/Initialize(force_name = "NTNet Device", autoconnect_station_network = TRUE) //Don't force ID unless you know what you're doing! - hardware_id = "[SSnetworks.get_next_HID()]" - network_name = force_name - if(!SSnetworks.register_interface(src)) - . = COMPONENT_INCOMPATIBLE - CRASH("Unable to register NTNet interface. Interface deleted.") - if(autoconnect_station_network) - register_connection(SSnetworks.station_network) - -/datum/component/ntnet_interface/Destroy() - unregister_all_connections() - SSnetworks.unregister_interface(src) - return ..() - -/datum/component/ntnet_interface/proc/__network_receive(datum/netdata/data) //Do not directly proccall! - SEND_SIGNAL(parent, COMSIG_COMPONENT_NTNET_RECEIVE, data) - if(differentiate_broadcast && data.broadcast) - parent.ntnet_receive_broadcast(data) - else - parent.ntnet_receive(data) - -/datum/component/ntnet_interface/proc/__network_send(datum/netdata/data, netid) //Do not directly proccall! - // Process data before sending it - data.pre_send(src) - - if(netid) - if(networks_connected_by_id[netid]) - var/datum/ntnet/net = networks_connected_by_id[netid] - return net.process_data_transmit(src, data) - return FALSE - for(var/i in networks_connected_by_id) - var/datum/ntnet/net = networks_connected_by_id[i] - net.process_data_transmit(src, data) - return TRUE - -/datum/component/ntnet_interface/proc/register_connection(datum/ntnet/net) - if(net.interface_connect(src)) - networks_connected_by_id[net.network_id] = net - return TRUE - -/datum/component/ntnet_interface/proc/unregister_all_connections() - for(var/i in networks_connected_by_id) - unregister_connection(networks_connected_by_id[i]) - return TRUE - -/datum/component/ntnet_interface/proc/unregister_connection(datum/ntnet/net) - net.interface_disconnect(src) - networks_connected_by_id -= net.network_id - return TRUE +//Thing meant for allowing datums and objects to access a NTnet network datum. +/datum/proc/ntnet_receive(datum/netdata/data) + return + +/datum/proc/ntnet_receive_broadcast(datum/netdata/data) + return + +/datum/proc/ntnet_send(datum/netdata/data, netid) + var/datum/component/ntnet_interface/NIC = GetComponent(/datum/component/ntnet_interface) + if(!NIC) + return FALSE + return NIC.__network_send(data, netid) + +/datum/component/ntnet_interface + var/hardware_id //text. this is the true ID. do not change this. stuff like ID forgery can be done manually. + var/network_name = "" //text + var/list/networks_connected_by_id = list() //id = datum/ntnet + var/differentiate_broadcast = TRUE //If false, broadcasts go to ntnet_receive. NOT RECOMMENDED. + +/datum/component/ntnet_interface/Initialize(force_name = "NTNet Device", autoconnect_station_network = TRUE) //Don't force ID unless you know what you're doing! + hardware_id = "[SSnetworks.get_next_HID()]" + network_name = force_name + if(!SSnetworks.register_interface(src)) + . = COMPONENT_INCOMPATIBLE + CRASH("Unable to register NTNet interface. Interface deleted.") + if(autoconnect_station_network) + register_connection(SSnetworks.station_network) + +/datum/component/ntnet_interface/Destroy() + unregister_all_connections() + SSnetworks.unregister_interface(src) + return ..() + +/datum/component/ntnet_interface/proc/__network_receive(datum/netdata/data) //Do not directly proccall! + SEND_SIGNAL(parent, COMSIG_COMPONENT_NTNET_RECEIVE, data) + if(differentiate_broadcast && data.broadcast) + parent.ntnet_receive_broadcast(data) + else + parent.ntnet_receive(data) + +/datum/component/ntnet_interface/proc/__network_send(datum/netdata/data, netid) //Do not directly proccall! + // Process data before sending it + data.pre_send(src) + + if(netid) + if(networks_connected_by_id[netid]) + var/datum/ntnet/net = networks_connected_by_id[netid] + return net.process_data_transmit(src, data) + return FALSE + for(var/i in networks_connected_by_id) + var/datum/ntnet/net = networks_connected_by_id[i] + net.process_data_transmit(src, data) + return TRUE + +/datum/component/ntnet_interface/proc/register_connection(datum/ntnet/net) + if(net.interface_connect(src)) + networks_connected_by_id[net.network_id] = net + return TRUE + +/datum/component/ntnet_interface/proc/unregister_all_connections() + for(var/i in networks_connected_by_id) + unregister_connection(networks_connected_by_id[i]) + return TRUE + +/datum/component/ntnet_interface/proc/unregister_connection(datum/ntnet/net) + net.interface_disconnect(src) + networks_connected_by_id -= net.network_id + return TRUE diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index c05b07a693..0775a725b9 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -1,359 +1,359 @@ -/datum/component/riding - var/last_vehicle_move = 0 //used for move delays - var/last_move_diagonal = FALSE - var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower - var/keytype - - var/slowed = FALSE - var/slowvalue = 1 - - var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one. - var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change. - var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py) - var/list/allowed_turf_typecache - var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence. - var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more. - var/override_allow_spacemove = FALSE - var/drive_verb = "drive" - var/ride_check_rider_incapacitated = FALSE - var/ride_check_rider_restrained = FALSE - var/ride_check_ridden_incapacitated = FALSE - var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob - -/datum/component/riding/Initialize() - if(!ismovableatom(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle) - RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle) - RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/vehicle_moved) - -/datum/component/riding/proc/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) - restore_position(M) - unequip_buckle_inhands(M) - -/datum/component/riding/proc/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) - handle_vehicle_offsets() - -/datum/component/riding/proc/handle_vehicle_layer() - var/atom/movable/AM = parent - var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER) - . = defaults["[AM.dir]"] - if(directional_vehicle_layers["[AM.dir]"]) - . = directional_vehicle_layers["[AM.dir]"] - if(isnull(.)) //you can set it to null to not change it. - . = AM.layer - AM.layer = . - -/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer) - directional_vehicle_layers["[dir]"] = layer - -/datum/component/riding/proc/vehicle_moved(datum/source) - var/atom/movable/AM = parent - for(var/i in AM.buckled_mobs) - ride_check(i) - handle_vehicle_offsets() - handle_vehicle_layer() - -/datum/component/riding/proc/ride_check(mob/living/M) - var/atom/movable/AM = parent - var/mob/AMM = AM - if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE))) - AM.visible_message("[M] falls off of [AM]!") - AM.unbuckle_mob(M) - return TRUE - -/datum/component/riding/proc/force_dismount(mob/living/M) - var/atom/movable/AM = parent - AM.unbuckle_mob(M) - -/datum/component/riding/proc/handle_vehicle_offsets() - var/atom/movable/AM = parent - var/AM_dir = "[AM.dir]" - var/passindex = 0 - if(AM.has_buckled_mobs()) - for(var/m in AM.buckled_mobs) - passindex++ - var/mob/living/buckled_mob = m - var/list/offsets = get_offsets(passindex) - var/rider_dir = get_rider_dir(passindex) - buckled_mob.setDir(rider_dir) - dir_loop: - for(var/offsetdir in offsets) - if(offsetdir == AM_dir) - var/list/diroffsets = offsets[offsetdir] - buckled_mob.pixel_x = diroffsets[1] - if(diroffsets.len >= 2) - buckled_mob.pixel_y = diroffsets[2] - if(diroffsets.len == 3) - buckled_mob.layer = diroffsets[3] - break dir_loop - var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) - var/px = default_vehicle_pixel_offsets[AM_dir] - var/py = default_vehicle_pixel_offsets[AM_dir] - if(directional_vehicle_offsets[AM_dir]) - if(isnull(directional_vehicle_offsets[AM_dir])) - px = AM.pixel_x - py = AM.pixel_y - else - px = directional_vehicle_offsets[AM_dir][1] - py = directional_vehicle_offsets[AM_dir][2] - AM.pixel_x = px - AM.pixel_y = py - -/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y) - directional_vehicle_offsets["[dir]"] = list(x, y) - -//Override this to set your vehicle's various pixel offsets -/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer) - . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) - if(riding_offsets["[pass_index]"]) - . = riding_offsets["[pass_index]"] - else if(riding_offsets["[RIDING_OFFSET_ALL]"]) - . = riding_offsets["[RIDING_OFFSET_ALL]"] - -/datum/component/riding/proc/set_riding_offsets(index, list/offsets) - if(!islist(offsets)) - return FALSE - riding_offsets["[index]"] = offsets - -//Override this to set the passengers/riders dir based on which passenger they are. -//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc. -/datum/component/riding/proc/get_rider_dir(pass_index) - var/atom/movable/AM = parent - return AM.dir - -//KEYS -/datum/component/riding/proc/keycheck(mob/user) - return !keytype || user.is_holding_item_of_type(keytype) - -//BUCKLE HOOKS -/datum/component/riding/proc/restore_position(mob/living/buckled_mob) - if(buckled_mob) - buckled_mob.pixel_x = 0 - buckled_mob.pixel_y = 0 - if(buckled_mob.client) - buckled_mob.client.change_view(CONFIG_GET(string/default_view)) - -//MOVEMENT -/datum/component/riding/proc/turf_check(turf/next, turf/current) - if(allowed_turf_typecache && !allowed_turf_typecache[next.type]) - return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type]) - else if(forbid_turf_typecache && forbid_turf_typecache[next.type]) - return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type]) - return TRUE - -/datum/component/riding/proc/handle_ride(mob/user, direction) - var/atom/movable/AM = parent - if(user.incapacitated()) - Unbuckle(user) - return - - if(world.time < last_vehicle_move + ((last_move_diagonal? 2 : 1) * vehicle_move_delay)) - return - last_vehicle_move = world.time - - if(keycheck(user)) - var/turf/next = get_step(AM, direction) - var/turf/current = get_turf(AM) - if(!istype(next) || !istype(current)) - return //not happening. - if(!turf_check(next, current)) - to_chat(user, "Your \the [AM] can not go onto [next]!") - return - if(!Process_Spacemove(direction) || !isturf(AM.loc)) - return - step(AM, direction) - - if((direction & (direction - 1)) && (AM.loc == next)) //moved diagonally - last_move_diagonal = TRUE - else - last_move_diagonal = FALSE - - handle_vehicle_layer() - handle_vehicle_offsets() - else - to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].") - -/datum/component/riding/proc/Unbuckle(atom/movable/M) - addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE) - -/datum/component/riding/proc/Process_Spacemove(direction) - var/atom/movable/AM = parent - return override_allow_spacemove || AM.has_gravity() - -/datum/component/riding/proc/account_limbs(mob/living/M) - if(M.get_num_legs() < 2 && !slowed) - vehicle_move_delay = vehicle_move_delay + slowvalue - slowed = TRUE - else if(slowed) - vehicle_move_delay = vehicle_move_delay - slowvalue - slowed = FALSE - -///////Yes, I said humans. No, this won't end well...////////// -/datum/component/riding/human - -/datum/component/riding/human/Initialize() - . = ..() - RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee) - -/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) - var/mob/living/carbon/human/H = parent - H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING) - . = ..() - -/datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) - . = ..() - var/mob/living/carbon/human/H = parent - H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN) - -/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target) - var/mob/living/carbon/human/H = parent - if(H.a_intent == INTENT_DISARM && (target in H.buckled_mobs)) - force_dismount(target) - -/datum/component/riding/human/handle_vehicle_layer() - var/atom/movable/AM = parent - if(AM.buckled_mobs && AM.buckled_mobs.len) - for(var/mob/M in AM.buckled_mobs) //ensure proper layering of piggyback and carry, sometimes weird offsets get applied - M.layer = MOB_LAYER - if(!AM.buckle_lying) - if(AM.dir == SOUTH) - AM.layer = ABOVE_MOB_LAYER - else - AM.layer = OBJ_LAYER - else - if(AM.dir == NORTH) - AM.layer = OBJ_LAYER - else - AM.layer = ABOVE_MOB_LAYER - else - AM.layer = MOB_LAYER - -/datum/component/riding/human/get_offsets(pass_index) - var/mob/living/carbon/human/H = parent - if(H.buckle_lying) - return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6)) - else - return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4)) - - -/datum/component/riding/human/force_dismount(mob/living/user) - var/atom/movable/AM = parent - AM.unbuckle_mob(user) - user.Knockdown(60) - user.visible_message("[AM] pushes [user] off of [AM.p_them()]!") - -/datum/component/riding/cyborg - -/datum/component/riding/cyborg/ride_check(mob/user) - var/atom/movable/AM = parent - if(user.incapacitated()) - var/kick = TRUE - if(iscyborg(AM)) - var/mob/living/silicon/robot/R = AM - if(R.module && R.module.ride_allow_incapacitated) - kick = FALSE - if(kick) - to_chat(user, "You fall off of [AM]!") - Unbuckle(user) - return - if(iscarbon(user)) - var/mob/living/carbon/carbonuser = user - if(!carbonuser.get_num_arms()) - Unbuckle(user) - to_chat(user, "You can't grab onto [AM] with no hands!") - return - -/datum/component/riding/cyborg/handle_vehicle_layer() - var/atom/movable/AM = parent - if(AM.buckled_mobs && AM.buckled_mobs.len) - if(AM.dir == SOUTH) - AM.layer = ABOVE_MOB_LAYER - else - AM.layer = OBJ_LAYER - else - AM.layer = MOB_LAYER - -/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer) - return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3)) - -/datum/component/riding/cyborg/handle_vehicle_offsets() - var/atom/movable/AM = parent - if(AM.has_buckled_mobs()) - for(var/mob/living/M in AM.buckled_mobs) - M.setDir(AM.dir) - if(iscyborg(AM)) - var/mob/living/silicon/robot/R = AM - if(istype(R.module)) - M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)] - M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)] - else - ..() - -/datum/component/riding/cyborg/force_dismount(mob/living/M) - var/atom/movable/AM = parent - AM.unbuckle_mob(M) - var/turf/target = get_edge_target_turf(AM, AM.dir) - var/turf/targetm = get_step(get_turf(AM), AM.dir) - M.Move(targetm) - M.visible_message("[M] is thrown clear of [AM]!") - M.throw_at(target, 14, 5, AM) - M.Knockdown(60) - -/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override) - var/list/equipped - var/mob/living/L = riding_target_override ? riding_target_override : user - for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--) - var/obj/item/riding_offhand/inhand = new - inhand.rider = L - inhand.parent = parent - if(!user.put_in_hands(inhand, TRUE)) - qdel(inhand) // it isn't going to be added to offhands anyway - break - LAZYADD(equipped, inhand) - var/amount_equipped = LAZYLEN(equipped) - if(amount_equipped) - LAZYADD(offhands[L], equipped) - if(amount_equipped >= amount_required) - return TRUE - unequip_buckle_inhands(L) - return FALSE - -/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user) - for(var/a in offhands[user]) - LAZYREMOVE(offhands[user], a) - if(a) //edge cases null entries - var/obj/item/riding_offhand/O = a - if(O.parent != parent) - CRASH("RIDING OFFHAND ON WRONG MOB") - else if(!O.selfdeleting) - qdel(O) - return TRUE - -/obj/item/riding_offhand - name = "offhand" - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "offhand" - w_class = WEIGHT_CLASS_HUGE - item_flags = ABSTRACT | DROPDEL | NOBLUDGEON - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - var/mob/living/carbon/rider - var/mob/living/parent - var/selfdeleting = FALSE - -/obj/item/riding_offhand/dropped() - selfdeleting = TRUE - . = ..() - -/obj/item/riding_offhand/equipped() - if(loc != rider && loc != parent) - selfdeleting = TRUE - qdel(src) - . = ..() - -/obj/item/riding_offhand/Destroy() - var/atom/movable/AM = parent - if(selfdeleting) - if(rider in AM.buckled_mobs) - AM.unbuckle_mob(rider) - . = ..() +/datum/component/riding + var/last_vehicle_move = 0 //used for move delays + var/last_move_diagonal = FALSE + var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower + var/keytype + + var/slowed = FALSE + var/slowvalue = 1 + + var/list/riding_offsets = list() //position_of_user = list(dir = list(px, py)), or RIDING_OFFSET_ALL for a generic one. + var/list/directional_vehicle_layers = list() //["[DIRECTION]"] = layer. Don't set it for a direction for default, set a direction to null for no change. + var/list/directional_vehicle_offsets = list() //same as above but instead of layer you have a list(px, py) + var/list/allowed_turf_typecache + var/list/forbid_turf_typecache //allow typecache for only certain turfs, forbid to allow all but those. allow only certain turfs will take precedence. + var/allow_one_away_from_valid_turf = TRUE //allow moving one tile away from a valid turf but not more. + var/override_allow_spacemove = FALSE + var/drive_verb = "drive" + var/ride_check_rider_incapacitated = FALSE + var/ride_check_rider_restrained = FALSE + var/ride_check_ridden_incapacitated = FALSE + var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob + +/datum/component/riding/Initialize() + if(!ismovableatom(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/vehicle_mob_buckle) + RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/vehicle_moved) + +/datum/component/riding/proc/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) + restore_position(M) + unequip_buckle_inhands(M) + +/datum/component/riding/proc/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) + handle_vehicle_offsets() + +/datum/component/riding/proc/handle_vehicle_layer() + var/atom/movable/AM = parent + var/static/list/defaults = list(TEXT_NORTH = OBJ_LAYER, TEXT_SOUTH = ABOVE_MOB_LAYER, TEXT_EAST = ABOVE_MOB_LAYER, TEXT_WEST = ABOVE_MOB_LAYER) + . = defaults["[AM.dir]"] + if(directional_vehicle_layers["[AM.dir]"]) + . = directional_vehicle_layers["[AM.dir]"] + if(isnull(.)) //you can set it to null to not change it. + . = AM.layer + AM.layer = . + +/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer) + directional_vehicle_layers["[dir]"] = layer + +/datum/component/riding/proc/vehicle_moved(datum/source) + var/atom/movable/AM = parent + for(var/i in AM.buckled_mobs) + ride_check(i) + handle_vehicle_offsets() + handle_vehicle_layer() + +/datum/component/riding/proc/ride_check(mob/living/M) + var/atom/movable/AM = parent + var/mob/AMM = AM + if((ride_check_rider_restrained && M.restrained(TRUE)) || (ride_check_rider_incapacitated && M.incapacitated(FALSE, TRUE)) || (ride_check_ridden_incapacitated && istype(AMM) && AMM.incapacitated(FALSE, TRUE))) + AM.visible_message("[M] falls off of [AM]!") + AM.unbuckle_mob(M) + return TRUE + +/datum/component/riding/proc/force_dismount(mob/living/M) + var/atom/movable/AM = parent + AM.unbuckle_mob(M) + +/datum/component/riding/proc/handle_vehicle_offsets() + var/atom/movable/AM = parent + var/AM_dir = "[AM.dir]" + var/passindex = 0 + if(AM.has_buckled_mobs()) + for(var/m in AM.buckled_mobs) + passindex++ + var/mob/living/buckled_mob = m + var/list/offsets = get_offsets(passindex) + var/rider_dir = get_rider_dir(passindex) + buckled_mob.setDir(rider_dir) + dir_loop: + for(var/offsetdir in offsets) + if(offsetdir == AM_dir) + var/list/diroffsets = offsets[offsetdir] + buckled_mob.pixel_x = diroffsets[1] + if(diroffsets.len >= 2) + buckled_mob.pixel_y = diroffsets[2] + if(diroffsets.len == 3) + buckled_mob.layer = diroffsets[3] + break dir_loop + var/list/static/default_vehicle_pixel_offsets = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) + var/px = default_vehicle_pixel_offsets[AM_dir] + var/py = default_vehicle_pixel_offsets[AM_dir] + if(directional_vehicle_offsets[AM_dir]) + if(isnull(directional_vehicle_offsets[AM_dir])) + px = AM.pixel_x + py = AM.pixel_y + else + px = directional_vehicle_offsets[AM_dir][1] + py = directional_vehicle_offsets[AM_dir][2] + AM.pixel_x = px + AM.pixel_y = py + +/datum/component/riding/proc/set_vehicle_dir_offsets(dir, x, y) + directional_vehicle_offsets["[dir]"] = list(x, y) + +//Override this to set your vehicle's various pixel offsets +/datum/component/riding/proc/get_offsets(pass_index) // list(dir = x, y, layer) + . = list(TEXT_NORTH = list(0, 0), TEXT_SOUTH = list(0, 0), TEXT_EAST = list(0, 0), TEXT_WEST = list(0, 0)) + if(riding_offsets["[pass_index]"]) + . = riding_offsets["[pass_index]"] + else if(riding_offsets["[RIDING_OFFSET_ALL]"]) + . = riding_offsets["[RIDING_OFFSET_ALL]"] + +/datum/component/riding/proc/set_riding_offsets(index, list/offsets) + if(!islist(offsets)) + return FALSE + riding_offsets["[index]"] = offsets + +//Override this to set the passengers/riders dir based on which passenger they are. +//ie: rider facing the vehicle's dir, but passenger 2 facing backwards, etc. +/datum/component/riding/proc/get_rider_dir(pass_index) + var/atom/movable/AM = parent + return AM.dir + +//KEYS +/datum/component/riding/proc/keycheck(mob/user) + return !keytype || user.is_holding_item_of_type(keytype) + +//BUCKLE HOOKS +/datum/component/riding/proc/restore_position(mob/living/buckled_mob) + if(buckled_mob) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + if(buckled_mob.client) + buckled_mob.client.change_view(CONFIG_GET(string/default_view)) + +//MOVEMENT +/datum/component/riding/proc/turf_check(turf/next, turf/current) + if(allowed_turf_typecache && !allowed_turf_typecache[next.type]) + return (allow_one_away_from_valid_turf && allowed_turf_typecache[current.type]) + else if(forbid_turf_typecache && forbid_turf_typecache[next.type]) + return (allow_one_away_from_valid_turf && !forbid_turf_typecache[current.type]) + return TRUE + +/datum/component/riding/proc/handle_ride(mob/user, direction) + var/atom/movable/AM = parent + if(user.incapacitated()) + Unbuckle(user) + return + + if(world.time < last_vehicle_move + ((last_move_diagonal? 2 : 1) * vehicle_move_delay)) + return + last_vehicle_move = world.time + + if(keycheck(user)) + var/turf/next = get_step(AM, direction) + var/turf/current = get_turf(AM) + if(!istype(next) || !istype(current)) + return //not happening. + if(!turf_check(next, current)) + to_chat(user, "Your \the [AM] can not go onto [next]!") + return + if(!Process_Spacemove(direction) || !isturf(AM.loc)) + return + step(AM, direction) + + if((direction & (direction - 1)) && (AM.loc == next)) //moved diagonally + last_move_diagonal = TRUE + else + last_move_diagonal = FALSE + + handle_vehicle_layer() + handle_vehicle_offsets() + else + to_chat(user, "You'll need the keys in one of your hands to [drive_verb] [AM].") + +/datum/component/riding/proc/Unbuckle(atom/movable/M) + addtimer(CALLBACK(parent, /atom/movable/.proc/unbuckle_mob, M), 0, TIMER_UNIQUE) + +/datum/component/riding/proc/Process_Spacemove(direction) + var/atom/movable/AM = parent + return override_allow_spacemove || AM.has_gravity() + +/datum/component/riding/proc/account_limbs(mob/living/M) + if(M.get_num_legs() < 2 && !slowed) + vehicle_move_delay = vehicle_move_delay + slowvalue + slowed = TRUE + else if(slowed) + vehicle_move_delay = vehicle_move_delay - slowvalue + slowed = FALSE + +///////Yes, I said humans. No, this won't end well...////////// +/datum/component/riding/human + +/datum/component/riding/human/Initialize() + . = ..() + RegisterSignal(parent, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/on_host_unarmed_melee) + +/datum/component/riding/human/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE) + var/mob/living/carbon/human/H = parent + H.remove_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING) + . = ..() + +/datum/component/riding/human/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE) + . = ..() + var/mob/living/carbon/human/H = parent + H.add_movespeed_modifier(MOVESPEED_ID_HUMAN_CARRYING, multiplicative_slowdown = HUMAN_CARRY_SLOWDOWN) + +/datum/component/riding/human/proc/on_host_unarmed_melee(atom/target) + var/mob/living/carbon/human/H = parent + if(H.a_intent == INTENT_DISARM && (target in H.buckled_mobs)) + force_dismount(target) + +/datum/component/riding/human/handle_vehicle_layer() + var/atom/movable/AM = parent + if(AM.buckled_mobs && AM.buckled_mobs.len) + for(var/mob/M in AM.buckled_mobs) //ensure proper layering of piggyback and carry, sometimes weird offsets get applied + M.layer = MOB_LAYER + if(!AM.buckle_lying) + if(AM.dir == SOUTH) + AM.layer = ABOVE_MOB_LAYER + else + AM.layer = OBJ_LAYER + else + if(AM.dir == NORTH) + AM.layer = OBJ_LAYER + else + AM.layer = ABOVE_MOB_LAYER + else + AM.layer = MOB_LAYER + +/datum/component/riding/human/get_offsets(pass_index) + var/mob/living/carbon/human/H = parent + if(H.buckle_lying) + return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6)) + else + return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4)) + + +/datum/component/riding/human/force_dismount(mob/living/user) + var/atom/movable/AM = parent + AM.unbuckle_mob(user) + user.Knockdown(60) + user.visible_message("[AM] pushes [user] off of [AM.p_them()]!") + +/datum/component/riding/cyborg + +/datum/component/riding/cyborg/ride_check(mob/user) + var/atom/movable/AM = parent + if(user.incapacitated()) + var/kick = TRUE + if(iscyborg(AM)) + var/mob/living/silicon/robot/R = AM + if(R.module && R.module.ride_allow_incapacitated) + kick = FALSE + if(kick) + to_chat(user, "You fall off of [AM]!") + Unbuckle(user) + return + if(iscarbon(user)) + var/mob/living/carbon/carbonuser = user + if(!carbonuser.get_num_arms()) + Unbuckle(user) + to_chat(user, "You can't grab onto [AM] with no hands!") + return + +/datum/component/riding/cyborg/handle_vehicle_layer() + var/atom/movable/AM = parent + if(AM.buckled_mobs && AM.buckled_mobs.len) + if(AM.dir == SOUTH) + AM.layer = ABOVE_MOB_LAYER + else + AM.layer = OBJ_LAYER + else + AM.layer = MOB_LAYER + +/datum/component/riding/cyborg/get_offsets(pass_index) // list(dir = x, y, layer) + return list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(-6, 3), TEXT_WEST = list( 6, 3)) + +/datum/component/riding/cyborg/handle_vehicle_offsets() + var/atom/movable/AM = parent + if(AM.has_buckled_mobs()) + for(var/mob/living/M in AM.buckled_mobs) + M.setDir(AM.dir) + if(iscyborg(AM)) + var/mob/living/silicon/robot/R = AM + if(istype(R.module)) + M.pixel_x = R.module.ride_offset_x[dir2text(AM.dir)] + M.pixel_y = R.module.ride_offset_y[dir2text(AM.dir)] + else + ..() + +/datum/component/riding/cyborg/force_dismount(mob/living/M) + var/atom/movable/AM = parent + AM.unbuckle_mob(M) + var/turf/target = get_edge_target_turf(AM, AM.dir) + var/turf/targetm = get_step(get_turf(AM), AM.dir) + M.Move(targetm) + M.visible_message("[M] is thrown clear of [AM]!") + M.throw_at(target, 14, 5, AM) + M.Knockdown(60) + +/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override) + var/list/equipped + var/mob/living/L = riding_target_override ? riding_target_override : user + for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--) + var/obj/item/riding_offhand/inhand = new + inhand.rider = L + inhand.parent = parent + if(!user.put_in_hands(inhand, TRUE)) + qdel(inhand) // it isn't going to be added to offhands anyway + break + LAZYADD(equipped, inhand) + var/amount_equipped = LAZYLEN(equipped) + if(amount_equipped) + LAZYADD(offhands[L], equipped) + if(amount_equipped >= amount_required) + return TRUE + unequip_buckle_inhands(L) + return FALSE + +/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user) + for(var/a in offhands[user]) + LAZYREMOVE(offhands[user], a) + if(a) //edge cases null entries + var/obj/item/riding_offhand/O = a + if(O.parent != parent) + CRASH("RIDING OFFHAND ON WRONG MOB") + else if(!O.selfdeleting) + qdel(O) + return TRUE + +/obj/item/riding_offhand + name = "offhand" + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + item_flags = ABSTRACT | DROPDEL | NOBLUDGEON + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/mob/living/carbon/rider + var/mob/living/parent + var/selfdeleting = FALSE + +/obj/item/riding_offhand/dropped() + selfdeleting = TRUE + . = ..() + +/obj/item/riding_offhand/equipped() + if(loc != rider && loc != parent) + selfdeleting = TRUE + qdel(src) + . = ..() + +/obj/item/riding_offhand/Destroy() + var/atom/movable/AM = parent + if(selfdeleting) + if(rider in AM.buckled_mobs) + AM.unbuckle_mob(rider) + . = ..() diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index a32a9cab43..6682c3901d 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -1,15 +1,15 @@ -/datum/component/slippery - var/intensity - var/lube_flags - var/datum/callback/callback - -/datum/component/slippery/Initialize(_intensity, _lube_flags = NONE, datum/callback/_callback) - intensity = max(_intensity, 0) - lube_flags = _lube_flags - callback = _callback - RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip) - -/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM) - var/mob/victim = AM - if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags) && callback) - callback.Invoke(victim) +/datum/component/slippery + var/intensity + var/lube_flags + var/datum/callback/callback + +/datum/component/slippery/Initialize(_intensity, _lube_flags = NONE, datum/callback/_callback) + intensity = max(_intensity, 0) + lube_flags = _lube_flags + callback = _callback + RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip) + +/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM) + var/mob/victim = AM + if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags) && callback) + callback.Invoke(victim) diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index accc8cadaf..4c8f1b4c97 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -1,208 +1,208 @@ - -// External storage-related logic: -// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages -// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement - -/datum/component/storage/concrete - can_transfer = TRUE - var/drop_all_on_deconstruct = TRUE - var/drop_all_on_destroy = FALSE - var/drop_all_on_break = FALSE - var/unlock_on_break = FALSE - var/transfer_contents_on_component_transfer = FALSE - var/list/datum/component/storage/slaves = list() - - var/list/_contents_limbo // Where objects go to live mid transfer - var/list/_user_limbo // The last users before the component started moving - -/datum/component/storage/concrete/Initialize() - . = ..() - RegisterSignal(parent, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del) - RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct) - RegisterSignal(parent, COMSIG_OBJ_BREAK, .proc/on_break) - -/datum/component/storage/concrete/Destroy() - var/atom/real_location = real_location() - for(var/atom/_A in real_location) - _A.mouse_opacity = initial(_A.mouse_opacity) - if(drop_all_on_destroy) - do_quick_empty() - for(var/i in slaves) - var/datum/component/storage/slave = i - slave.change_master(null) - QDEL_LIST(_contents_limbo) - _user_limbo = null - return ..() - -/datum/component/storage/concrete/master() - return src - -/datum/component/storage/concrete/real_location() - return parent - -/datum/component/storage/concrete/PreTransfer() - if(is_using) - _user_limbo = is_using.Copy() - close_all() - if(transfer_contents_on_component_transfer) - _contents_limbo = list() - for(var/atom/movable/AM in parent) - _contents_limbo += AM - AM.moveToNullspace() - -/datum/component/storage/concrete/PostTransfer() - if(!isatom(parent)) - return COMPONENT_INCOMPATIBLE - if(transfer_contents_on_component_transfer) - for(var/i in _contents_limbo) - var/atom/movable/AM = i - AM.forceMove(parent) - _contents_limbo = null - if(_user_limbo) - for(var/i in _user_limbo) - show_to(i) - _user_limbo = null - -/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE) - . = TRUE - var/atom/real_location = real_location() - if(I.loc != real_location && real_location) - I.forceMove(real_location) - refresh_mob_views() - -/datum/component/storage/concrete/refresh_mob_views() - . = ..() - for(var/i in slaves) - var/datum/component/storage/slave = i - slave.refresh_mob_views() - -/datum/component/storage/concrete/emp_act(datum/source, severity) - if(emp_shielded) - return - var/atom/real_location = real_location() - for(var/i in real_location) - var/atom/A = i - A.emp_act(severity) - -/datum/component/storage/concrete/proc/on_slave_link(datum/component/storage/S) - if(S == src) - return FALSE - slaves += S - return TRUE - -/datum/component/storage/concrete/proc/on_slave_unlink(datum/component/storage/S) - slaves -= S - return FALSE - -/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A) - var/atom/real_location = parent - if(A in real_location) - usr = null - remove_from_storage(A, null) - -/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled) - if(drop_all_on_deconstruct) - do_quick_empty() - -/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag) - if(drop_all_on_break) - do_quick_empty() - if(unlock_on_break) - set_locked(source, FALSE) - -/datum/component/storage/concrete/can_see_contents() - . = ..() - for(var/i in slaves) - var/datum/component/storage/slave = i - . |= slave.can_see_contents() - -//Resets screen loc and other vars of something being removed from storage. -/datum/component/storage/concrete/_removal_reset(atom/movable/thing) - thing.layer = initial(thing.layer) - thing.plane = initial(thing.plane) - thing.mouse_opacity = initial(thing.mouse_opacity) - if(thing.maptext) - thing.maptext = "" - -/datum/component/storage/concrete/remove_from_storage(atom/movable/AM, atom/new_location) - //Cache this as it should be reusable down the bottom, will not apply if anyone adds a sleep to dropped - //or moving objects, things that should never happen - var/atom/parent = src.parent - var/list/seeing_mobs = can_see_contents() - for(var/mob/M in seeing_mobs) - M.client.screen -= AM - if(ismob(parent.loc) && isitem(AM)) - var/obj/item/I = AM - var/mob/M = parent.loc - I.dropped(M) - if(new_location) - //Reset the items values - _removal_reset(AM) - AM.forceMove(new_location) - //We don't want to call this if the item is being destroyed - AM.on_exit_storage(src) - else - //Being destroyed, just move to nullspace now (so it's not in contents for the icon update) - AM.moveToNullspace() - refresh_mob_views() - if(isobj(parent)) - var/obj/O = parent - O.update_icon() - return TRUE - -/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M) - return TRUE - -/datum/component/storage/concrete/proc/handle_item_insertion_from_slave(datum/component/storage/slave, obj/item/I, prevent_warning = FALSE, M) - . = handle_item_insertion(I, prevent_warning, M, slave) - if(. && !prevent_warning) - slave.mob_item_insertion_feedback(usr, M, I) - -/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum - var/datum/component/storage/concrete/master = master() - var/atom/parent = src.parent - var/moved = FALSE - if(!istype(I)) - return FALSE - if(M) - if(!M.temporarilyRemoveItemFromInventory(I)) - return FALSE - else - moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever. - if(I.pulledby) - I.pulledby.stop_pulling() - if(silent) - prevent_warning = TRUE - if(!_insert_physical_item(I)) - if(moved) - if(M) - if(!M.put_in_active_hand(I)) - I.forceMove(parent.drop_location()) - else - I.forceMove(parent.drop_location()) - return FALSE - I.on_enter_storage(master) - refresh_mob_views() - I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt - if(M) - if(M.client && M.active_storage != src) - M.client.screen -= I - if(M.observers && M.observers.len) - for(var/i in M.observers) - var/mob/dead/observe = i - if(observe.client && observe.active_storage != src) - observe.client.screen -= I - if(!remote) - parent.add_fingerprint(M) - if(!prevent_warning) - mob_item_insertion_feedback(usr, M, I) - update_icon() - return TRUE - -/datum/component/storage/concrete/update_icon() - if(isobj(parent)) - var/obj/O = parent - O.update_icon() - for(var/i in slaves) - var/datum/component/storage/slave = i - slave.update_icon() + +// External storage-related logic: +// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages +// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement + +/datum/component/storage/concrete + can_transfer = TRUE + var/drop_all_on_deconstruct = TRUE + var/drop_all_on_destroy = FALSE + var/drop_all_on_break = FALSE + var/unlock_on_break = FALSE + var/transfer_contents_on_component_transfer = FALSE + var/list/datum/component/storage/slaves = list() + + var/list/_contents_limbo // Where objects go to live mid transfer + var/list/_user_limbo // The last users before the component started moving + +/datum/component/storage/concrete/Initialize() + . = ..() + RegisterSignal(parent, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del) + RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct) + RegisterSignal(parent, COMSIG_OBJ_BREAK, .proc/on_break) + +/datum/component/storage/concrete/Destroy() + var/atom/real_location = real_location() + for(var/atom/_A in real_location) + _A.mouse_opacity = initial(_A.mouse_opacity) + if(drop_all_on_destroy) + do_quick_empty() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.change_master(null) + QDEL_LIST(_contents_limbo) + _user_limbo = null + return ..() + +/datum/component/storage/concrete/master() + return src + +/datum/component/storage/concrete/real_location() + return parent + +/datum/component/storage/concrete/PreTransfer() + if(is_using) + _user_limbo = is_using.Copy() + close_all() + if(transfer_contents_on_component_transfer) + _contents_limbo = list() + for(var/atom/movable/AM in parent) + _contents_limbo += AM + AM.moveToNullspace() + +/datum/component/storage/concrete/PostTransfer() + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if(transfer_contents_on_component_transfer) + for(var/i in _contents_limbo) + var/atom/movable/AM = i + AM.forceMove(parent) + _contents_limbo = null + if(_user_limbo) + for(var/i in _user_limbo) + show_to(i) + _user_limbo = null + +/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE) + . = TRUE + var/atom/real_location = real_location() + if(I.loc != real_location && real_location) + I.forceMove(real_location) + refresh_mob_views() + +/datum/component/storage/concrete/refresh_mob_views() + . = ..() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.refresh_mob_views() + +/datum/component/storage/concrete/emp_act(datum/source, severity) + if(emp_shielded) + return + var/atom/real_location = real_location() + for(var/i in real_location) + var/atom/A = i + A.emp_act(severity) + +/datum/component/storage/concrete/proc/on_slave_link(datum/component/storage/S) + if(S == src) + return FALSE + slaves += S + return TRUE + +/datum/component/storage/concrete/proc/on_slave_unlink(datum/component/storage/S) + slaves -= S + return FALSE + +/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A) + var/atom/real_location = parent + if(A in real_location) + usr = null + remove_from_storage(A, null) + +/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled) + if(drop_all_on_deconstruct) + do_quick_empty() + +/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag) + if(drop_all_on_break) + do_quick_empty() + if(unlock_on_break) + set_locked(source, FALSE) + +/datum/component/storage/concrete/can_see_contents() + . = ..() + for(var/i in slaves) + var/datum/component/storage/slave = i + . |= slave.can_see_contents() + +//Resets screen loc and other vars of something being removed from storage. +/datum/component/storage/concrete/_removal_reset(atom/movable/thing) + thing.layer = initial(thing.layer) + thing.plane = initial(thing.plane) + thing.mouse_opacity = initial(thing.mouse_opacity) + if(thing.maptext) + thing.maptext = "" + +/datum/component/storage/concrete/remove_from_storage(atom/movable/AM, atom/new_location) + //Cache this as it should be reusable down the bottom, will not apply if anyone adds a sleep to dropped + //or moving objects, things that should never happen + var/atom/parent = src.parent + var/list/seeing_mobs = can_see_contents() + for(var/mob/M in seeing_mobs) + M.client.screen -= AM + if(ismob(parent.loc) && isitem(AM)) + var/obj/item/I = AM + var/mob/M = parent.loc + I.dropped(M) + if(new_location) + //Reset the items values + _removal_reset(AM) + AM.forceMove(new_location) + //We don't want to call this if the item is being destroyed + AM.on_exit_storage(src) + else + //Being destroyed, just move to nullspace now (so it's not in contents for the icon update) + AM.moveToNullspace() + refresh_mob_views() + if(isobj(parent)) + var/obj/O = parent + O.update_icon() + return TRUE + +/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M) + return TRUE + +/datum/component/storage/concrete/proc/handle_item_insertion_from_slave(datum/component/storage/slave, obj/item/I, prevent_warning = FALSE, M) + . = handle_item_insertion(I, prevent_warning, M, slave) + if(. && !prevent_warning) + slave.mob_item_insertion_feedback(usr, M, I) + +/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum + var/datum/component/storage/concrete/master = master() + var/atom/parent = src.parent + var/moved = FALSE + if(!istype(I)) + return FALSE + if(M) + if(!M.temporarilyRemoveItemFromInventory(I)) + return FALSE + else + moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever. + if(I.pulledby) + I.pulledby.stop_pulling() + if(silent) + prevent_warning = TRUE + if(!_insert_physical_item(I)) + if(moved) + if(M) + if(!M.put_in_active_hand(I)) + I.forceMove(parent.drop_location()) + else + I.forceMove(parent.drop_location()) + return FALSE + I.on_enter_storage(master) + refresh_mob_views() + I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt + if(M) + if(M.client && M.active_storage != src) + M.client.screen -= I + if(M.observers && M.observers.len) + for(var/i in M.observers) + var/mob/dead/observe = i + if(observe.client && observe.active_storage != src) + observe.client.screen -= I + if(!remote) + parent.add_fingerprint(M) + if(!prevent_warning) + mob_item_insertion_feedback(usr, M, I) + update_icon() + return TRUE + +/datum/component/storage/concrete/update_icon() + if(isobj(parent)) + var/obj/O = parent + O.update_icon() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.update_icon() diff --git a/code/datums/components/storage/concrete/bag_of_holding.dm b/code/datums/components/storage/concrete/bag_of_holding.dm index bf97ec6516..8b9ecf5a4e 100644 --- a/code/datums/components/storage/concrete/bag_of_holding.dm +++ b/code/datums/components/storage/concrete/bag_of_holding.dm @@ -1,36 +1,36 @@ -/datum/component/storage/concrete/bluespace/bag_of_holding/handle_item_insertion(obj/item/W, prevent_warning = FALSE, mob/living/user) - var/atom/A = parent - if(A == W) //don't put yourself into yourself. - return - var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(W.GetAllContents(), typecacheof(/obj/item/storage/backpack/holding)) - matching -= A - if(istype(W, /obj/item/storage/backpack/holding) || matching.len) - var/safety = alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [A.name]?", "Abort", "Proceed") - if(safety != "Proceed" || QDELETED(A) || QDELETED(W) || QDELETED(user) || !user.canUseTopic(A, BE_CLOSE, iscarbon(user))) - return - var/turf/loccheck = get_turf(A) - if(is_reebe(loccheck.z)) - user.visible_message("An unseen force knocks [user] to the ground!", "\"I think not!\"") - user.Knockdown(60) - return - if(istype(loccheck.loc, /area/fabric_of_reality)) - to_chat(user, "You can't do that here!") - to_chat(user, "The Bluespace interfaces of the two devices catastrophically malfunction!") - qdel(W) - playsound(loccheck,'sound/effects/supermatter.ogg', 200, 1) - user.gib(TRUE, TRUE, TRUE) - for(var/turf/T in range(6,loccheck)) - if(istype(T, /turf/open/space/transit)) - continue - for(var/mob/living/M in T) - if(M.movement_type & FLYING) - M.visible_message("The bluespace collapse crushes the air towards it, pulling [M] towards the ground...") - M.Knockdown(5, TRUE, TRUE) //Overrides stun absorbs. - T.TerraformTurf(/turf/open/chasm/magic, /turf/open/chasm/magic) - for (var/obj/structure/ladder/unbreakable/binary/ladder in GLOB.ladders) - ladder.ActivateAlmonds() - message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].") - log_game("[key_name(user)] detonated a bag of holding at [loc_name(loccheck)].") - qdel(A) - return - . = ..() +/datum/component/storage/concrete/bluespace/bag_of_holding/handle_item_insertion(obj/item/W, prevent_warning = FALSE, mob/living/user) + var/atom/A = parent + if(A == W) //don't put yourself into yourself. + return + var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(W.GetAllContents(), typecacheof(/obj/item/storage/backpack/holding)) + matching -= A + if(istype(W, /obj/item/storage/backpack/holding) || matching.len) + var/safety = alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [A.name]?", "Abort", "Proceed") + if(safety != "Proceed" || QDELETED(A) || QDELETED(W) || QDELETED(user) || !user.canUseTopic(A, BE_CLOSE, iscarbon(user))) + return + var/turf/loccheck = get_turf(A) + if(is_reebe(loccheck.z)) + user.visible_message("An unseen force knocks [user] to the ground!", "\"I think not!\"") + user.Knockdown(60) + return + if(istype(loccheck.loc, /area/fabric_of_reality)) + to_chat(user, "You can't do that here!") + to_chat(user, "The Bluespace interfaces of the two devices catastrophically malfunction!") + qdel(W) + playsound(loccheck,'sound/effects/supermatter.ogg', 200, 1) + user.gib(TRUE, TRUE, TRUE) + for(var/turf/T in range(6,loccheck)) + if(istype(T, /turf/open/space/transit)) + continue + for(var/mob/living/M in T) + if(M.movement_type & FLYING) + M.visible_message("The bluespace collapse crushes the air towards it, pulling [M] towards the ground...") + M.Knockdown(5, TRUE, TRUE) //Overrides stun absorbs. + T.TerraformTurf(/turf/open/chasm/magic, /turf/open/chasm/magic) + for (var/obj/structure/ladder/unbreakable/binary/ladder in GLOB.ladders) + ladder.ActivateAlmonds() + message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].") + log_game("[key_name(user)] detonated a bag of holding at [loc_name(loccheck)].") + qdel(A) + return + . = ..() diff --git a/code/datums/components/storage/concrete/implant.dm b/code/datums/components/storage/concrete/implant.dm index 0348d340ae..5ee4c13c24 100644 --- a/code/datums/components/storage/concrete/implant.dm +++ b/code/datums/components/storage/concrete/implant.dm @@ -1,18 +1,18 @@ -/datum/component/storage/concrete/implant - max_w_class = WEIGHT_CLASS_NORMAL - max_combined_w_class = 6 - max_items = 2 - drop_all_on_destroy = TRUE - drop_all_on_deconstruct = TRUE - silent = TRUE - allow_big_nesting = TRUE - -/datum/component/storage/concrete/implant/Initialize() - . = ..() - cant_hold = typecacheof(list(/obj/item/disk/nuclear)) - -/datum/component/storage/concrete/implant/InheritComponent(datum/component/storage/concrete/implant/I, original) - if(!istype(I)) - return ..() - max_combined_w_class += I.max_combined_w_class - max_items += I.max_items +/datum/component/storage/concrete/implant + max_w_class = WEIGHT_CLASS_NORMAL + max_combined_w_class = 6 + max_items = 2 + drop_all_on_destroy = TRUE + drop_all_on_deconstruct = TRUE + silent = TRUE + allow_big_nesting = TRUE + +/datum/component/storage/concrete/implant/Initialize() + . = ..() + cant_hold = typecacheof(list(/obj/item/disk/nuclear)) + +/datum/component/storage/concrete/implant/InheritComponent(datum/component/storage/concrete/implant/I, original) + if(!istype(I)) + return ..() + max_combined_w_class += I.max_combined_w_class + max_items += I.max_items diff --git a/code/datums/components/storage/concrete/rped.dm b/code/datums/components/storage/concrete/rped.dm index e1cc4ff6ae..2f95466238 100644 --- a/code/datums/components/storage/concrete/rped.dm +++ b/code/datums/components/storage/concrete/rped.dm @@ -1,36 +1,36 @@ -/datum/component/storage/concrete/rped - collection_mode = COLLECT_EVERYTHING - allow_quick_gather = TRUE - allow_quick_empty = TRUE - click_gather = TRUE - max_w_class = WEIGHT_CLASS_NORMAL - max_combined_w_class = 100 - max_items = 100 - display_numerical_stacking = TRUE - -/datum/component/storage/concrete/rped/can_be_inserted(obj/item/I, stop_messages, mob/M) - . = ..() - if(!I.get_part_rating()) - if (!stop_messages) - to_chat(M, "[parent] only accepts machine parts!") - return FALSE - -/datum/component/storage/concrete/bluespace/rped - collection_mode = COLLECT_EVERYTHING - allow_quick_gather = TRUE - allow_quick_empty = TRUE - click_gather = TRUE - max_w_class = WEIGHT_CLASS_BULKY // can fit vending refills - max_combined_w_class = 800 - max_items = 350 - display_numerical_stacking = TRUE - -/datum/component/storage/concrete/bluespace/rped/can_be_inserted(obj/item/I, stop_messages, mob/M) - . = ..() - if(!I.get_part_rating()) - if (!stop_messages) - to_chat(M, "[parent] only accepts machine parts!") - return FALSE - -/datum/component/storage/concrete/cyborg/rped - max_items = 150 +/datum/component/storage/concrete/rped + collection_mode = COLLECT_EVERYTHING + allow_quick_gather = TRUE + allow_quick_empty = TRUE + click_gather = TRUE + max_w_class = WEIGHT_CLASS_NORMAL + max_combined_w_class = 100 + max_items = 100 + display_numerical_stacking = TRUE + +/datum/component/storage/concrete/rped/can_be_inserted(obj/item/I, stop_messages, mob/M) + . = ..() + if(!I.get_part_rating()) + if (!stop_messages) + to_chat(M, "[parent] only accepts machine parts!") + return FALSE + +/datum/component/storage/concrete/bluespace/rped + collection_mode = COLLECT_EVERYTHING + allow_quick_gather = TRUE + allow_quick_empty = TRUE + click_gather = TRUE + max_w_class = WEIGHT_CLASS_BULKY // can fit vending refills + max_combined_w_class = 800 + max_items = 350 + display_numerical_stacking = TRUE + +/datum/component/storage/concrete/bluespace/rped/can_be_inserted(obj/item/I, stop_messages, mob/M) + . = ..() + if(!I.get_part_rating()) + if (!stop_messages) + to_chat(M, "[parent] only accepts machine parts!") + return FALSE + +/datum/component/storage/concrete/cyborg/rped + max_items = 150 diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index 76a9b2e6aa..55e5c03c2b 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -1,800 +1,800 @@ -#define COLLECT_ONE 0 -#define COLLECT_EVERYTHING 1 -#define COLLECT_SAME 2 - -#define DROP_NOTHING 0 -#define DROP_AT_PARENT 1 -#define DROP_AT_LOCATION 2 - -// External storage-related logic: -// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages -// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement - -/datum/component/storage - dupe_mode = COMPONENT_DUPE_UNIQUE - var/datum/component/storage/concrete/master //If not null, all actions act on master and this is just an access point. - - var/list/can_hold //if this is set, only things in this typecache will fit. - var/list/cant_hold //if this is set, anything in this typecache will not be able to fit. - - var/list/mob/is_using //lazy list of mobs looking at the contents of this storage. - - var/locked = FALSE //when locked nothing can see inside or use it. - - var/max_w_class = WEIGHT_CLASS_SMALL //max size of objects that will fit. - var/max_combined_w_class = 14 //max combined sizes of objects that will fit. - var/max_items = 7 //max number of objects that will fit. - - var/emp_shielded = FALSE - - var/silent = FALSE //whether this makes a message when things are put in. - var/click_gather = FALSE //whether this can be clicked on items to pick it up rather than the other way around. - var/rustle_sound = TRUE //play rustle sound on interact. - var/allow_quick_empty = FALSE //allow empty verb which allows dumping on the floor of everything inside quickly. - var/allow_quick_gather = FALSE //allow toggle mob verb which toggles collecting all items from a tile. - - var/collection_mode = COLLECT_EVERYTHING - - var/insert_preposition = "in" //you put things "in" a bag, but "on" a tray. - - var/display_numerical_stacking = FALSE //stack things of the same type and show as a single object with a number. - - var/obj/screen/storage/boxes //storage display object - var/obj/screen/close/closer //close button object - - var/allow_big_nesting = FALSE //allow storage objects of the same or greater size. - - var/attack_hand_interact = TRUE //interact on attack hand. - var/quickdraw = FALSE //altclick interact - - var/datum/action/item_action/storage_gather_mode/modeswitch_action - - //Screen variables: Do not mess with these vars unless you know what you're doing. They're not defines so storage that isn't in the same location can be supported in the future. - var/screen_max_columns = 7 //These two determine maximum screen sizes. - var/screen_max_rows = INFINITY - var/screen_pixel_x = 16 //These two are pixel values for screen loc of boxes and closer - var/screen_pixel_y = 16 - var/screen_start_x = 4 //These two are where the storage starts being rendered, screen_loc wise. - var/screen_start_y = 2 - //End - - var/limited_random_access = FALSE //Quick if statement in accessible_items to determine if we care at all about what people can access at once. - var/limited_random_access_stack_position = 0 //If >0, can only access top items - var/limited_random_access_stack_bottom_up = FALSE //If TRUE, above becomes bottom items - -/datum/component/storage/Initialize(datum/component/storage/concrete/master) - if(!isatom(parent)) - return COMPONENT_INCOMPATIBLE - if(master) - change_master(master) - boxes = new(null, src) - closer = new(null, src) - orient2hud() - - RegisterSignal(parent, COMSIG_CONTAINS_STORAGE, .proc/on_check) - RegisterSignal(parent, COMSIG_IS_STORAGE_LOCKED, .proc/check_locked) - RegisterSignal(parent, COMSIG_TRY_STORAGE_SHOW, .proc/signal_show_attempt) - RegisterSignal(parent, COMSIG_TRY_STORAGE_INSERT, .proc/signal_insertion_attempt) - RegisterSignal(parent, COMSIG_TRY_STORAGE_CAN_INSERT, .proc/signal_can_insert) - RegisterSignal(parent, COMSIG_TRY_STORAGE_TAKE_TYPE, .proc/signal_take_type) - RegisterSignal(parent, COMSIG_TRY_STORAGE_FILL_TYPE, .proc/signal_fill_type) - RegisterSignal(parent, COMSIG_TRY_STORAGE_SET_LOCKSTATE, .proc/set_locked) - RegisterSignal(parent, COMSIG_TRY_STORAGE_TAKE, .proc/signal_take_obj) - RegisterSignal(parent, COMSIG_TRY_STORAGE_QUICK_EMPTY, .proc/signal_quick_empty) - RegisterSignal(parent, COMSIG_TRY_STORAGE_HIDE_FROM, .proc/signal_hide_attempt) - RegisterSignal(parent, COMSIG_TRY_STORAGE_HIDE_ALL, .proc/close_all) - RegisterSignal(parent, COMSIG_TRY_STORAGE_RETURN_INVENTORY, .proc/signal_return_inv) - - RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/attackby) - - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_PAW, .proc/on_attack_hand) - RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/emp_act) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, .proc/show_to_ghost) - RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/refresh_mob_views) - RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/_remove_and_refresh) - RegisterSignal(parent, COMSIG_ATOM_CANREACH, .proc/canreach_react) - - RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, .proc/preattack_intercept) - RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/attack_self) - RegisterSignal(parent, COMSIG_ITEM_PICKUP, .proc/signal_on_pickup) - - RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all) - RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/check_views) - - RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click) - RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto) - RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, .proc/mousedrop_receive) - - update_actions() - -/datum/component/storage/Destroy() - close_all() - QDEL_NULL(boxes) - QDEL_NULL(closer) - LAZYCLEARLIST(is_using) - return ..() - -/datum/component/storage/PreTransfer() - update_actions() - -/datum/component/storage/proc/update_actions() - QDEL_NULL(modeswitch_action) - if(!isitem(parent) || !allow_quick_gather) - return - var/obj/item/I = parent - modeswitch_action = new(I) - RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, .proc/action_trigger) - if(I.obj_flags & IN_INVENTORY) - var/mob/M = I.loc - if(!istype(M)) - return - modeswitch_action.Grant(M) - -/datum/component/storage/proc/change_master(datum/component/storage/concrete/new_master) - if(new_master == src || (!isnull(new_master) && !istype(new_master))) - return FALSE - if(master) - master.on_slave_unlink(src) - master = new_master - if(master) - master.on_slave_link(src) - return TRUE - -/datum/component/storage/proc/master() - if(master == src) - return //infinite loops yo. - return master - -/datum/component/storage/proc/real_location() - var/datum/component/storage/concrete/master = master() - return master? master.real_location() : null - -//What players can access -//this proc can probably eat a refactor at some point. -/datum/component/storage/proc/accessible_items(random_access = TRUE) - var/list/contents = contents() - if(contents) - if(limited_random_access && random_access) - if(limited_random_access_stack_position && (length(contents) > limited_random_access_stack_position)) - if(limited_random_access_stack_bottom_up) - contents.Cut(1, limited_random_access_stack_position + 1) - else - contents.Cut(1, length(contents) - limited_random_access_stack_position + 1) - return contents - -/datum/component/storage/proc/canreach_react(datum/source, list/next) - var/datum/component/storage/concrete/master = master() - if(!master) - return - . = COMPONENT_BLOCK_REACH - next += master.parent - for(var/i in master.slaves) - var/datum/component/storage/slave = i - next += slave.parent - -/datum/component/storage/proc/attack_self(datum/source, mob/M) - if(check_locked(source, M, TRUE)) - return FALSE - if((M.get_active_held_item() == parent) && allow_quick_empty) - quick_empty(M) - -/datum/component/storage/proc/preattack_intercept(datum/source, obj/O, mob/M, params) - if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE)) - return FALSE - . = COMPONENT_NO_ATTACK - if(check_locked(source, M, TRUE)) - return FALSE - var/atom/A = parent - var/obj/item/I = O - if(collection_mode == COLLECT_ONE) - if(can_be_inserted(I, null, M)) - handle_item_insertion(I, null, M) - A.do_squish() - return - if(!isturf(I.loc)) - return - var/list/things = I.loc.contents.Copy() - if(collection_mode == COLLECT_SAME) - things = typecache_filter_list(things, typecacheof(I.type)) - var/len = length(things) - if(!len) - to_chat(M, "You failed to pick up anything with [parent].") - return - var/datum/progressbar/progress = new(M, len, I.loc) - var/list/rejections = list() - while(do_after(M, 10, TRUE, parent, FALSE, CALLBACK(src, .proc/handle_mass_pickup, things, I.loc, rejections, progress))) - stoplag(1) - qdel(progress) - to_chat(M, "You put everything you could [insert_preposition] [parent].") - A.do_squish(1.4, 0.4) - -/datum/component/storage/proc/handle_mass_item_insertion(list/things, datum/component/storage/src_object, mob/user, datum/progressbar/progress) - var/atom/source_real_location = src_object.real_location() - for(var/obj/item/I in things) - things -= I - if(I.loc != source_real_location) - continue - if(user.active_storage != src_object) - if(I.on_found(user)) - break - if(can_be_inserted(I,FALSE,user)) - handle_item_insertion(I, TRUE, user) - if (TICK_CHECK) - progress.update(progress.goal - things.len) - return TRUE - - progress.update(progress.goal - things.len) - return FALSE - -/datum/component/storage/proc/handle_mass_pickup(list/things, atom/thing_loc, list/rejections, datum/progressbar/progress) - var/atom/real_location = real_location() - for(var/obj/item/I in things) - things -= I - if(I.loc != thing_loc) - continue - if(I.type in rejections) // To limit bag spamming: any given type only complains once - continue - if(!can_be_inserted(I, stop_messages = TRUE)) // Note can_be_inserted still makes noise when the answer is no - if(real_location.contents.len >= max_items) - break - rejections += I.type // therefore full bags are still a little spammy - continue - - handle_item_insertion(I, TRUE) //The TRUE stops the "You put the [parent] into [S]" insertion message from being displayed. - - if (TICK_CHECK) - progress.update(progress.goal - things.len) - return TRUE - - progress.update(progress.goal - things.len) - return FALSE - -/datum/component/storage/proc/quick_empty(mob/M) - var/atom/A = parent - if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated()) - return - if(check_locked(null, M, TRUE)) - return FALSE - A.add_fingerprint(M) - to_chat(M, "You start dumping out [parent].") - var/turf/T = get_turf(A) - var/list/things = contents() - var/datum/progressbar/progress = new(M, length(things), T) - while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress))) - stoplag(1) - qdel(progress) - A.do_squish(0.8, 1.2) - -/datum/component/storage/proc/mass_remove_from_storage(atom/target, list/things, datum/progressbar/progress, trigger_on_found = TRUE) - var/atom/real_location = real_location() - for(var/obj/item/I in things) - things -= I - if(I.loc != real_location) - continue - remove_from_storage(I, target) - if(trigger_on_found && I.on_found()) - return FALSE - if(TICK_CHECK) - progress.update(progress.goal - length(things)) - return TRUE - progress.update(progress.goal - length(things)) - return FALSE - -/datum/component/storage/proc/do_quick_empty(atom/_target) - if(!_target) - _target = get_turf(parent) - if(usr) - hide_from(usr) - var/list/contents = contents() - var/atom/real_location = real_location() - for(var/obj/item/I in contents) - if(I.loc != real_location) - continue - remove_from_storage(I, _target) - return TRUE - -/datum/component/storage/proc/set_locked(datum/source, new_state) - locked = new_state - if(check_locked()) - close_all() - -/datum/component/storage/proc/_process_numerical_display() - . = list() - for(var/obj/item/I in accessible_items()) - if(QDELETED(I)) - continue - if(!.[I.type]) - .[I.type] = new /datum/numbered_display(I, 1) - else - var/datum/numbered_display/ND = .[I.type] - ND.number++ - . = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE) - -//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing. -/datum/component/storage/proc/orient2hud(mob/user, maxcolumns) - var/list/accessible_contents = accessible_items() - var/adjusted_contents = length(accessible_contents) - - //Numbered contents display - var/list/datum/numbered_display/numbered_contents - if(display_numerical_stacking) - numbered_contents = _process_numerical_display() - adjusted_contents = numbered_contents.len - - var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns) - var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows) - standard_orient_objs(rows, columns, numbered_contents) - -//This proc draws out the inventory and places the items on it. It uses the standard position. -/datum/component/storage/proc/standard_orient_objs(rows, cols, list/obj/item/numerical_display_contents) - boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+cols-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" - var/cx = screen_start_x - var/cy = screen_start_y - if(islist(numerical_display_contents)) - for(var/type in numerical_display_contents) - var/datum/numbered_display/ND = numerical_display_contents[type] - ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE - ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" - ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" - ND.sample_object.layer = ABOVE_HUD_LAYER - ND.sample_object.plane = ABOVE_HUD_PLANE - cx++ - if(cx - screen_start_x >= cols) - cx = screen_start_x - cy++ - if(cy - screen_start_y >= rows) - break - else - for(var/obj/O in accessible_items()) - if(QDELETED(O)) - continue - O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" - O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" - O.maptext = "" - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - cx++ - if(cx - screen_start_x >= cols) - cx = screen_start_x - cy++ - if(cy - screen_start_y >= rows) - break - closer.screen_loc = "[screen_start_x + cols]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]" - -/datum/component/storage/proc/show_to(mob/M) - if(!M.client) - return FALSE - var/list/cview = getviewsize(M.client.view) - var/maxallowedscreensize = cview[1]-8 - if(M.active_storage != src && (M.stat == CONSCIOUS)) - for(var/obj/item/I in accessible_items()) - if(I.on_found(M)) - return FALSE - if(M.active_storage) - M.active_storage.hide_from(M) - orient2hud(M, (isliving(M) ? maxallowedscreensize : 7)) - M.client.screen |= boxes - M.client.screen |= closer - M.client.screen |= accessible_items() - M.active_storage = src - LAZYOR(is_using, M) - return TRUE - -/datum/component/storage/proc/hide_from(mob/M) - if(!M.client) - return TRUE - var/atom/real_location = real_location() - M.client.screen -= boxes - M.client.screen -= closer - M.client.screen -= real_location.contents - if(M.active_storage == src) - M.active_storage = null - LAZYREMOVE(is_using, M) - return TRUE - -/datum/component/storage/proc/close(mob/M) - hide_from(M) - -/datum/component/storage/proc/close_all() - . = FALSE - for(var/mob/M in can_see_contents()) - close(M) - . = TRUE //returns TRUE if any mobs actually got a close(M) call - -/datum/component/storage/proc/check_views() - for(var/mob/M in can_see_contents()) - if(!isobserver(M) && !M.CanReach(src, view_only = TRUE)) - close(M) - -/datum/component/storage/proc/emp_act(datum/source, severity) - if(emp_shielded) - return - var/datum/component/storage/concrete/master = master() - master.emp_act(source, severity) - -//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. -//The numbers are calculated from the bottom-left The bottom-left slot being 1,1. -/datum/component/storage/proc/orient_objs(tx, ty, mx, my) - var/atom/real_location = real_location() - var/cx = tx - var/cy = ty - boxes.screen_loc = "[tx]:,[ty] to [mx],[my]" - for(var/obj/O in real_location) - if(QDELETED(O)) - continue - O.screen_loc = "[cx],[cy]" - O.layer = ABOVE_HUD_LAYER - O.plane = ABOVE_HUD_PLANE - cx++ - if(cx > mx) - cx = tx - cy-- - closer.screen_loc = "[mx+1],[my]" - -//Resets something that is being removed from storage. -/datum/component/storage/proc/_removal_reset(atom/movable/thing) - if(!istype(thing)) - return FALSE - var/datum/component/storage/concrete/master = master() - if(!istype(master)) - return FALSE - return master._removal_reset(thing) - -/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) - _removal_reset(thing) - refresh_mob_views() - -//Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted -/datum/component/storage/proc/remove_from_storage(atom/movable/AM, atom/new_location) - if(!istype(AM)) - return FALSE - var/datum/component/storage/concrete/master = master() - if(!istype(master)) - return FALSE - return master.remove_from_storage(AM, new_location) - -/datum/component/storage/proc/refresh_mob_views() - var/list/seeing = can_see_contents() - for(var/i in seeing) - show_to(i) - return TRUE - -/datum/component/storage/proc/can_see_contents() - var/list/cansee = list() - for(var/mob/M in is_using) - if(M.active_storage == src && M.client) - cansee |= M - else - LAZYREMOVE(is_using, M) - return cansee - -//Tries to dump content -/datum/component/storage/proc/dump_content_at(atom/dest_object, mob/M) - var/atom/A = parent - var/atom/dump_destination = dest_object.get_dumping_location() - if(A.Adjacent(M) && dump_destination && M.Adjacent(dump_destination)) - if(check_locked(null, M, TRUE)) - return FALSE - if(dump_destination.storage_contents_dump_act(src, M)) - playsound(A, "rustle", 50, 1, -5) - A.do_squish(0.8, 1.2) - return TRUE - return FALSE - -//This proc is called when you want to place an item into the storage item. -/datum/component/storage/proc/attackby(datum/source, obj/item/I, mob/M, params) - if(istype(I, /obj/item/hand_labeler)) - var/obj/item/hand_labeler/labeler = I - if(labeler.mode) - return FALSE - . = TRUE //no afterattack - if(iscyborg(M)) - return - if(!can_be_inserted(I, FALSE, M)) - var/atom/real_location = real_location() - if(real_location.contents.len >= max_items) //don't use items on the backpack if they don't fit - return TRUE - return FALSE - handle_item_insertion(I, FALSE, M) - var/atom/A = parent - A.do_squish() - -/datum/component/storage/proc/return_inv(recursive) - var/list/ret = list() - ret |= contents() - if(recursive) - for(var/i in ret.Copy()) - var/atom/A = i - SEND_SIGNAL(A, COMSIG_TRY_STORAGE_RETURN_INVENTORY, ret, TRUE) - return ret - -/datum/component/storage/proc/contents() //ONLY USE IF YOU NEED TO COPY CONTENTS OF REAL LOCATION, COPYING IS NOT AS FAST AS DIRECT ACCESS! - var/atom/real_location = real_location() - return real_location.contents.Copy() - -//Abuses the fact that lists are just references, or something like that. -/datum/component/storage/proc/signal_return_inv(datum/source, list/interface, recursive = TRUE) - if(!islist(interface)) - return FALSE - interface |= return_inv(recursive) - return TRUE - -/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M) - set waitfor = FALSE - . = COMPONENT_NO_MOUSEDROP - var/atom/A = parent - if(ismob(M)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked - A.add_fingerprint(M) - if(!over_object) - return FALSE - if(ismecha(M.loc)) // stops inventory actions in a mech - return FALSE - // this must come before the screen objects only block, dunno why it wasn't before - if(over_object == M) - user_show_to_mob(M) - if(!M.incapacitated()) - if(!istype(over_object, /obj/screen)) - dump_content_at(over_object, M) - return - if(A.loc != M) - return - playsound(A, "rustle", 50, 1, -5) - A.do_jiggle() - if(istype(over_object, /obj/screen/inventory/hand)) - var/obj/screen/inventory/hand/H = over_object - M.putItemFromInventoryInHandIfPossible(A, H.held_index) - return - A.add_fingerprint(M) - -/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE) - var/atom/A = parent - if(!istype(M)) - return FALSE - A.add_fingerprint(M) - if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE))) - return FALSE - show_to(M) - -/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) - if(isitem(O)) - var/obj/item/I = O - if(iscarbon(M) || isdrone(M)) - var/mob/living/L = M - if(!L.incapacitated() && I == L.get_active_held_item()) - if(!SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE) && can_be_inserted(I, FALSE)) //If it has storage it should be trying to dump, not insert. - handle_item_insertion(I, FALSE, L) - var/atom/A = parent - A.do_squish() - -//This proc return 1 if the item can be picked up and 0 if it can't. -//Set the stop_messages to stop it from printing messages -/datum/component/storage/proc/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M) - if(!istype(I) || (I.item_flags & ABSTRACT)) - return FALSE //Not an item - if(I == parent) - return FALSE //no paradoxes for you - var/atom/real_location = real_location() - var/atom/host = parent - if(real_location == I.loc) - return FALSE //Means the item is already in the storage item - if(check_locked(null, M, !stop_messages)) - if(M && !stop_messages) - host.add_fingerprint(M) - return FALSE - if(real_location.contents.len >= max_items) - if(!stop_messages) - to_chat(M, "[host] is full, make some space!") - return FALSE //Storage item is full - if(length(can_hold)) - if(!is_type_in_typecache(I, can_hold)) - if(!stop_messages) - to_chat(M, "[host] cannot hold [I]!") - return FALSE - if(is_type_in_typecache(I, cant_hold)) //Check for specific items which this container can't hold. - if(!stop_messages) - to_chat(M, "[host] cannot hold [I]!") - return FALSE - if(I.w_class > max_w_class) - if(!stop_messages) - to_chat(M, "[I] is too big for [host]!") - return FALSE - var/sum_w_class = I.w_class - for(var/obj/item/_I in real_location) - sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. - if(sum_w_class > max_combined_w_class) - if(!stop_messages) - to_chat(M, "[I] won't fit in [host], make some space!") - return FALSE - if(isitem(host)) - var/obj/item/IP = host - var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage) - if((I.w_class >= IP.w_class) && STR_I && !allow_big_nesting) - if(!stop_messages) - to_chat(M, "[IP] cannot hold [I] as it's a storage item of the same size!") - return FALSE //To prevent the stacking of same sized storage items. - if(HAS_TRAIT(I, TRAIT_NODROP)) //SHOULD be handled in unEquip, but better safe than sorry. - to_chat(M, "\the [I] is stuck to your hand, you can't put it in \the [host]!") - return FALSE - var/datum/component/storage/concrete/master = master() - if(!istype(master)) - return FALSE - return master.slave_can_insert_object(src, I, stop_messages, M) - -/datum/component/storage/proc/_insert_physical_item(obj/item/I, override = FALSE) - return FALSE - -//This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() -//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, -//such as when picking up all the items on a tile with one click. -/datum/component/storage/proc/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) - var/atom/parent = src.parent - var/datum/component/storage/concrete/master = master() - if(!istype(master)) - return FALSE - if(silent) - prevent_warning = TRUE - if(M) - parent.add_fingerprint(M) - . = master.handle_item_insertion_from_slave(src, I, prevent_warning, M) - -/datum/component/storage/proc/mob_item_insertion_feedback(mob/user, mob/M, obj/item/I, override = FALSE) - if(silent && !override) - return - if(rustle_sound) - playsound(parent, "rustle", 50, 1, -5) - for(var/mob/viewing in viewers(user, null)) - if(M == viewing) - to_chat(usr, "You put [I] [insert_preposition]to [parent].") - else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is... - viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) - else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance... - viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) - -/datum/component/storage/proc/update_icon() - if(isobj(parent)) - var/obj/O = parent - O.update_icon() - -/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE) - if((!force && !can_be_inserted(I, TRUE, M)) || (I == parent)) - return FALSE - return handle_item_insertion(I, silent, M) - -/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE) - return can_be_inserted(I, silent, M) - -/datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) - return user_show_to_mob(M, TRUE) - -/datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE) - return user_show_to_mob(showto, force) - -/datum/component/storage/proc/on_check() - return TRUE - -/datum/component/storage/proc/check_locked(datum/source, mob/user, message = FALSE) - . = locked - if(message && . && user) - to_chat(user, "[parent] seems to be locked!") - -/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted) - if(!force) - if(check_adjacent) - if(!user || !user.CanReach(destination) || !user.CanReach(parent)) - return FALSE - var/list/taking = typecache_filter_list(contents(), typecacheof(type)) - if(taking.len > amount) - taking.len = amount - if(inserted) //duplicated code for performance, don't bother checking retval/checking for list every item. - for(var/i in taking) - if(remove_from_storage(i, destination)) - inserted |= i - else - for(var/i in taking) - remove_from_storage(i, destination) - return TRUE - -/datum/component/storage/proc/remaining_space_items() - var/atom/real_location = real_location() - return max(0, max_items - real_location.contents.len) - -/datum/component/storage/proc/signal_fill_type(datum/source, type, amount = 20, force = FALSE) - var/atom/real_location = real_location() - if(!force) - amount = min(remaining_space_items(), amount) - for(var/i in 1 to amount) - handle_item_insertion(new type(real_location), TRUE) - CHECK_TICK - return TRUE - -/datum/component/storage/proc/on_attack_hand(datum/source, mob/user) - var/atom/A = parent - if(!attack_hand_interact) - return - if(user.active_storage == src && A.loc == user) //if you're already looking inside the storage item - user.active_storage.close(user) - close(user) - . = COMPONENT_NO_ATTACK_HAND - return - - if(rustle_sound) - playsound(A, "rustle", 50, 1, -5) - - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.l_store == A && !H.get_active_held_item()) //Prevents opening if it's in a pocket. - . = COMPONENT_NO_ATTACK_HAND - H.put_in_hands(A) - H.l_store = null - return - if(H.r_store == A && !H.get_active_held_item()) - . = COMPONENT_NO_ATTACK_HAND - H.put_in_hands(A) - H.r_store = null - return - - if(A.loc == user) - . = COMPONENT_NO_ATTACK_HAND - if(!check_locked(source, user, TRUE)) - show_to(user) - A.do_jiggle() - -/datum/component/storage/proc/signal_on_pickup(datum/source, mob/user) - var/atom/A = parent - update_actions() - for(var/mob/M in range(1, A)) - if(M.active_storage == src) - close(M) - -/datum/component/storage/proc/signal_take_obj(datum/source, atom/movable/AM, new_loc, force = FALSE) - if(!(AM in real_location())) - return FALSE - return remove_from_storage(AM, new_loc) - -/datum/component/storage/proc/signal_quick_empty(datum/source, atom/loctarget) - return do_quick_empty(loctarget) - -/datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target) - return hide_from(target) - -/datum/component/storage/proc/on_alt_click(datum/source, mob/user) - if(!isliving(user) || !user.CanReach(parent)) - return - if(check_locked(source, user, TRUE)) - return TRUE - - var/atom/A = parent - if(!quickdraw) - A.add_fingerprint(user) - user_show_to_mob(user) - if(rustle_sound) - playsound(A, "rustle", 50, 1, -5) - return TRUE - - if(user.can_hold_items() && !user.incapacitated()) - var/obj/item/I = locate() in real_location() - if(!I) - return - A.add_fingerprint(user) - remove_from_storage(I, get_turf(user)) - if(!user.put_in_hands(I)) - user.visible_message("[user] fumbles with the [parent], letting [I] fall on the floor.", \ - "You fumble with [parent], letting [I] fall on the floor.") - return TRUE - user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") - return TRUE - -/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source) - gather_mode_switch(source.owner) - return COMPONENT_ACTION_BLOCK_TRIGGER - -/datum/component/storage/proc/gather_mode_switch(mob/user) - collection_mode = (collection_mode+1)%3 - switch(collection_mode) - if(COLLECT_SAME) - to_chat(user, "[parent] now picks up all items of a single type at once.") - if(COLLECT_EVERYTHING) - to_chat(user, "[parent] now picks up all items in a tile at once.") - if(COLLECT_ONE) - to_chat(user, "[parent] now picks up one item at a time.") +#define COLLECT_ONE 0 +#define COLLECT_EVERYTHING 1 +#define COLLECT_SAME 2 + +#define DROP_NOTHING 0 +#define DROP_AT_PARENT 1 +#define DROP_AT_LOCATION 2 + +// External storage-related logic: +// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages +// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement + +/datum/component/storage + dupe_mode = COMPONENT_DUPE_UNIQUE + var/datum/component/storage/concrete/master //If not null, all actions act on master and this is just an access point. + + var/list/can_hold //if this is set, only things in this typecache will fit. + var/list/cant_hold //if this is set, anything in this typecache will not be able to fit. + + var/list/mob/is_using //lazy list of mobs looking at the contents of this storage. + + var/locked = FALSE //when locked nothing can see inside or use it. + + var/max_w_class = WEIGHT_CLASS_SMALL //max size of objects that will fit. + var/max_combined_w_class = 14 //max combined sizes of objects that will fit. + var/max_items = 7 //max number of objects that will fit. + + var/emp_shielded = FALSE + + var/silent = FALSE //whether this makes a message when things are put in. + var/click_gather = FALSE //whether this can be clicked on items to pick it up rather than the other way around. + var/rustle_sound = TRUE //play rustle sound on interact. + var/allow_quick_empty = FALSE //allow empty verb which allows dumping on the floor of everything inside quickly. + var/allow_quick_gather = FALSE //allow toggle mob verb which toggles collecting all items from a tile. + + var/collection_mode = COLLECT_EVERYTHING + + var/insert_preposition = "in" //you put things "in" a bag, but "on" a tray. + + var/display_numerical_stacking = FALSE //stack things of the same type and show as a single object with a number. + + var/obj/screen/storage/boxes //storage display object + var/obj/screen/close/closer //close button object + + var/allow_big_nesting = FALSE //allow storage objects of the same or greater size. + + var/attack_hand_interact = TRUE //interact on attack hand. + var/quickdraw = FALSE //altclick interact + + var/datum/action/item_action/storage_gather_mode/modeswitch_action + + //Screen variables: Do not mess with these vars unless you know what you're doing. They're not defines so storage that isn't in the same location can be supported in the future. + var/screen_max_columns = 7 //These two determine maximum screen sizes. + var/screen_max_rows = INFINITY + var/screen_pixel_x = 16 //These two are pixel values for screen loc of boxes and closer + var/screen_pixel_y = 16 + var/screen_start_x = 4 //These two are where the storage starts being rendered, screen_loc wise. + var/screen_start_y = 2 + //End + + var/limited_random_access = FALSE //Quick if statement in accessible_items to determine if we care at all about what people can access at once. + var/limited_random_access_stack_position = 0 //If >0, can only access top items + var/limited_random_access_stack_bottom_up = FALSE //If TRUE, above becomes bottom items + +/datum/component/storage/Initialize(datum/component/storage/concrete/master) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if(master) + change_master(master) + boxes = new(null, src) + closer = new(null, src) + orient2hud() + + RegisterSignal(parent, COMSIG_CONTAINS_STORAGE, .proc/on_check) + RegisterSignal(parent, COMSIG_IS_STORAGE_LOCKED, .proc/check_locked) + RegisterSignal(parent, COMSIG_TRY_STORAGE_SHOW, .proc/signal_show_attempt) + RegisterSignal(parent, COMSIG_TRY_STORAGE_INSERT, .proc/signal_insertion_attempt) + RegisterSignal(parent, COMSIG_TRY_STORAGE_CAN_INSERT, .proc/signal_can_insert) + RegisterSignal(parent, COMSIG_TRY_STORAGE_TAKE_TYPE, .proc/signal_take_type) + RegisterSignal(parent, COMSIG_TRY_STORAGE_FILL_TYPE, .proc/signal_fill_type) + RegisterSignal(parent, COMSIG_TRY_STORAGE_SET_LOCKSTATE, .proc/set_locked) + RegisterSignal(parent, COMSIG_TRY_STORAGE_TAKE, .proc/signal_take_obj) + RegisterSignal(parent, COMSIG_TRY_STORAGE_QUICK_EMPTY, .proc/signal_quick_empty) + RegisterSignal(parent, COMSIG_TRY_STORAGE_HIDE_FROM, .proc/signal_hide_attempt) + RegisterSignal(parent, COMSIG_TRY_STORAGE_HIDE_ALL, .proc/close_all) + RegisterSignal(parent, COMSIG_TRY_STORAGE_RETURN_INVENTORY, .proc/signal_return_inv) + + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/attackby) + + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_PAW, .proc/on_attack_hand) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/emp_act) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, .proc/show_to_ghost) + RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/refresh_mob_views) + RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/_remove_and_refresh) + RegisterSignal(parent, COMSIG_ATOM_CANREACH, .proc/canreach_react) + + RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, .proc/preattack_intercept) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/attack_self) + RegisterSignal(parent, COMSIG_ITEM_PICKUP, .proc/signal_on_pickup) + + RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/check_views) + + RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click) + RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto) + RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, .proc/mousedrop_receive) + + update_actions() + +/datum/component/storage/Destroy() + close_all() + QDEL_NULL(boxes) + QDEL_NULL(closer) + LAZYCLEARLIST(is_using) + return ..() + +/datum/component/storage/PreTransfer() + update_actions() + +/datum/component/storage/proc/update_actions() + QDEL_NULL(modeswitch_action) + if(!isitem(parent) || !allow_quick_gather) + return + var/obj/item/I = parent + modeswitch_action = new(I) + RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, .proc/action_trigger) + if(I.obj_flags & IN_INVENTORY) + var/mob/M = I.loc + if(!istype(M)) + return + modeswitch_action.Grant(M) + +/datum/component/storage/proc/change_master(datum/component/storage/concrete/new_master) + if(new_master == src || (!isnull(new_master) && !istype(new_master))) + return FALSE + if(master) + master.on_slave_unlink(src) + master = new_master + if(master) + master.on_slave_link(src) + return TRUE + +/datum/component/storage/proc/master() + if(master == src) + return //infinite loops yo. + return master + +/datum/component/storage/proc/real_location() + var/datum/component/storage/concrete/master = master() + return master? master.real_location() : null + +//What players can access +//this proc can probably eat a refactor at some point. +/datum/component/storage/proc/accessible_items(random_access = TRUE) + var/list/contents = contents() + if(contents) + if(limited_random_access && random_access) + if(limited_random_access_stack_position && (length(contents) > limited_random_access_stack_position)) + if(limited_random_access_stack_bottom_up) + contents.Cut(1, limited_random_access_stack_position + 1) + else + contents.Cut(1, length(contents) - limited_random_access_stack_position + 1) + return contents + +/datum/component/storage/proc/canreach_react(datum/source, list/next) + var/datum/component/storage/concrete/master = master() + if(!master) + return + . = COMPONENT_BLOCK_REACH + next += master.parent + for(var/i in master.slaves) + var/datum/component/storage/slave = i + next += slave.parent + +/datum/component/storage/proc/attack_self(datum/source, mob/M) + if(check_locked(source, M, TRUE)) + return FALSE + if((M.get_active_held_item() == parent) && allow_quick_empty) + quick_empty(M) + +/datum/component/storage/proc/preattack_intercept(datum/source, obj/O, mob/M, params) + if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE)) + return FALSE + . = COMPONENT_NO_ATTACK + if(check_locked(source, M, TRUE)) + return FALSE + var/atom/A = parent + var/obj/item/I = O + if(collection_mode == COLLECT_ONE) + if(can_be_inserted(I, null, M)) + handle_item_insertion(I, null, M) + A.do_squish() + return + if(!isturf(I.loc)) + return + var/list/things = I.loc.contents.Copy() + if(collection_mode == COLLECT_SAME) + things = typecache_filter_list(things, typecacheof(I.type)) + var/len = length(things) + if(!len) + to_chat(M, "You failed to pick up anything with [parent].") + return + var/datum/progressbar/progress = new(M, len, I.loc) + var/list/rejections = list() + while(do_after(M, 10, TRUE, parent, FALSE, CALLBACK(src, .proc/handle_mass_pickup, things, I.loc, rejections, progress))) + stoplag(1) + qdel(progress) + to_chat(M, "You put everything you could [insert_preposition] [parent].") + A.do_squish(1.4, 0.4) + +/datum/component/storage/proc/handle_mass_item_insertion(list/things, datum/component/storage/src_object, mob/user, datum/progressbar/progress) + var/atom/source_real_location = src_object.real_location() + for(var/obj/item/I in things) + things -= I + if(I.loc != source_real_location) + continue + if(user.active_storage != src_object) + if(I.on_found(user)) + break + if(can_be_inserted(I,FALSE,user)) + handle_item_insertion(I, TRUE, user) + if (TICK_CHECK) + progress.update(progress.goal - things.len) + return TRUE + + progress.update(progress.goal - things.len) + return FALSE + +/datum/component/storage/proc/handle_mass_pickup(list/things, atom/thing_loc, list/rejections, datum/progressbar/progress) + var/atom/real_location = real_location() + for(var/obj/item/I in things) + things -= I + if(I.loc != thing_loc) + continue + if(I.type in rejections) // To limit bag spamming: any given type only complains once + continue + if(!can_be_inserted(I, stop_messages = TRUE)) // Note can_be_inserted still makes noise when the answer is no + if(real_location.contents.len >= max_items) + break + rejections += I.type // therefore full bags are still a little spammy + continue + + handle_item_insertion(I, TRUE) //The TRUE stops the "You put the [parent] into [S]" insertion message from being displayed. + + if (TICK_CHECK) + progress.update(progress.goal - things.len) + return TRUE + + progress.update(progress.goal - things.len) + return FALSE + +/datum/component/storage/proc/quick_empty(mob/M) + var/atom/A = parent + if(!M.canUseStorage() || !A.Adjacent(M) || M.incapacitated()) + return + if(check_locked(null, M, TRUE)) + return FALSE + A.add_fingerprint(M) + to_chat(M, "You start dumping out [parent].") + var/turf/T = get_turf(A) + var/list/things = contents() + var/datum/progressbar/progress = new(M, length(things), T) + while (do_after(M, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress))) + stoplag(1) + qdel(progress) + A.do_squish(0.8, 1.2) + +/datum/component/storage/proc/mass_remove_from_storage(atom/target, list/things, datum/progressbar/progress, trigger_on_found = TRUE) + var/atom/real_location = real_location() + for(var/obj/item/I in things) + things -= I + if(I.loc != real_location) + continue + remove_from_storage(I, target) + if(trigger_on_found && I.on_found()) + return FALSE + if(TICK_CHECK) + progress.update(progress.goal - length(things)) + return TRUE + progress.update(progress.goal - length(things)) + return FALSE + +/datum/component/storage/proc/do_quick_empty(atom/_target) + if(!_target) + _target = get_turf(parent) + if(usr) + hide_from(usr) + var/list/contents = contents() + var/atom/real_location = real_location() + for(var/obj/item/I in contents) + if(I.loc != real_location) + continue + remove_from_storage(I, _target) + return TRUE + +/datum/component/storage/proc/set_locked(datum/source, new_state) + locked = new_state + if(check_locked()) + close_all() + +/datum/component/storage/proc/_process_numerical_display() + . = list() + for(var/obj/item/I in accessible_items()) + if(QDELETED(I)) + continue + if(!.[I.type]) + .[I.type] = new /datum/numbered_display(I, 1) + else + var/datum/numbered_display/ND = .[I.type] + ND.number++ + . = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE) + +//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing. +/datum/component/storage/proc/orient2hud(mob/user, maxcolumns) + var/list/accessible_contents = accessible_items() + var/adjusted_contents = length(accessible_contents) + + //Numbered contents display + var/list/datum/numbered_display/numbered_contents + if(display_numerical_stacking) + numbered_contents = _process_numerical_display() + adjusted_contents = numbered_contents.len + + var/columns = CLAMP(max_items, 1, maxcolumns ? maxcolumns : screen_max_columns) + var/rows = CLAMP(CEILING(adjusted_contents / columns, 1), 1, screen_max_rows) + standard_orient_objs(rows, columns, numbered_contents) + +//This proc draws out the inventory and places the items on it. It uses the standard position. +/datum/component/storage/proc/standard_orient_objs(rows, cols, list/obj/item/numerical_display_contents) + boxes.screen_loc = "[screen_start_x]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y] to [screen_start_x+cols-1]:[screen_pixel_x],[screen_start_y+rows-1]:[screen_pixel_y]" + var/cx = screen_start_x + var/cy = screen_start_y + if(islist(numerical_display_contents)) + for(var/type in numerical_display_contents) + var/datum/numbered_display/ND = numerical_display_contents[type] + ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE + ND.sample_object.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" + ND.sample_object.maptext = "[(ND.number > 1)? "[ND.number]" : ""]" + ND.sample_object.layer = ABOVE_HUD_LAYER + ND.sample_object.plane = ABOVE_HUD_PLANE + cx++ + if(cx - screen_start_x >= cols) + cx = screen_start_x + cy++ + if(cy - screen_start_y >= rows) + break + else + for(var/obj/O in accessible_items()) + if(QDELETED(O)) + continue + O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip" + O.screen_loc = "[cx]:[screen_pixel_x],[cy]:[screen_pixel_y]" + O.maptext = "" + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + cx++ + if(cx - screen_start_x >= cols) + cx = screen_start_x + cy++ + if(cy - screen_start_y >= rows) + break + closer.screen_loc = "[screen_start_x + cols]:[screen_pixel_x],[screen_start_y]:[screen_pixel_y]" + +/datum/component/storage/proc/show_to(mob/M) + if(!M.client) + return FALSE + var/list/cview = getviewsize(M.client.view) + var/maxallowedscreensize = cview[1]-8 + if(M.active_storage != src && (M.stat == CONSCIOUS)) + for(var/obj/item/I in accessible_items()) + if(I.on_found(M)) + return FALSE + if(M.active_storage) + M.active_storage.hide_from(M) + orient2hud(M, (isliving(M) ? maxallowedscreensize : 7)) + M.client.screen |= boxes + M.client.screen |= closer + M.client.screen |= accessible_items() + M.active_storage = src + LAZYOR(is_using, M) + return TRUE + +/datum/component/storage/proc/hide_from(mob/M) + if(!M.client) + return TRUE + var/atom/real_location = real_location() + M.client.screen -= boxes + M.client.screen -= closer + M.client.screen -= real_location.contents + if(M.active_storage == src) + M.active_storage = null + LAZYREMOVE(is_using, M) + return TRUE + +/datum/component/storage/proc/close(mob/M) + hide_from(M) + +/datum/component/storage/proc/close_all() + . = FALSE + for(var/mob/M in can_see_contents()) + close(M) + . = TRUE //returns TRUE if any mobs actually got a close(M) call + +/datum/component/storage/proc/check_views() + for(var/mob/M in can_see_contents()) + if(!isobserver(M) && !M.CanReach(src, view_only = TRUE)) + close(M) + +/datum/component/storage/proc/emp_act(datum/source, severity) + if(emp_shielded) + return + var/datum/component/storage/concrete/master = master() + master.emp_act(source, severity) + +//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right. +//The numbers are calculated from the bottom-left The bottom-left slot being 1,1. +/datum/component/storage/proc/orient_objs(tx, ty, mx, my) + var/atom/real_location = real_location() + var/cx = tx + var/cy = ty + boxes.screen_loc = "[tx]:,[ty] to [mx],[my]" + for(var/obj/O in real_location) + if(QDELETED(O)) + continue + O.screen_loc = "[cx],[cy]" + O.layer = ABOVE_HUD_LAYER + O.plane = ABOVE_HUD_PLANE + cx++ + if(cx > mx) + cx = tx + cy-- + closer.screen_loc = "[mx+1],[my]" + +//Resets something that is being removed from storage. +/datum/component/storage/proc/_removal_reset(atom/movable/thing) + if(!istype(thing)) + return FALSE + var/datum/component/storage/concrete/master = master() + if(!istype(master)) + return FALSE + return master._removal_reset(thing) + +/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing) + _removal_reset(thing) + refresh_mob_views() + +//Call this proc to handle the removal of an item from the storage item. The item will be moved to the new_location target, if that is null it's being deleted +/datum/component/storage/proc/remove_from_storage(atom/movable/AM, atom/new_location) + if(!istype(AM)) + return FALSE + var/datum/component/storage/concrete/master = master() + if(!istype(master)) + return FALSE + return master.remove_from_storage(AM, new_location) + +/datum/component/storage/proc/refresh_mob_views() + var/list/seeing = can_see_contents() + for(var/i in seeing) + show_to(i) + return TRUE + +/datum/component/storage/proc/can_see_contents() + var/list/cansee = list() + for(var/mob/M in is_using) + if(M.active_storage == src && M.client) + cansee |= M + else + LAZYREMOVE(is_using, M) + return cansee + +//Tries to dump content +/datum/component/storage/proc/dump_content_at(atom/dest_object, mob/M) + var/atom/A = parent + var/atom/dump_destination = dest_object.get_dumping_location() + if(A.Adjacent(M) && dump_destination && M.Adjacent(dump_destination)) + if(check_locked(null, M, TRUE)) + return FALSE + if(dump_destination.storage_contents_dump_act(src, M)) + playsound(A, "rustle", 50, 1, -5) + A.do_squish(0.8, 1.2) + return TRUE + return FALSE + +//This proc is called when you want to place an item into the storage item. +/datum/component/storage/proc/attackby(datum/source, obj/item/I, mob/M, params) + if(istype(I, /obj/item/hand_labeler)) + var/obj/item/hand_labeler/labeler = I + if(labeler.mode) + return FALSE + . = TRUE //no afterattack + if(iscyborg(M)) + return + if(!can_be_inserted(I, FALSE, M)) + var/atom/real_location = real_location() + if(real_location.contents.len >= max_items) //don't use items on the backpack if they don't fit + return TRUE + return FALSE + handle_item_insertion(I, FALSE, M) + var/atom/A = parent + A.do_squish() + +/datum/component/storage/proc/return_inv(recursive) + var/list/ret = list() + ret |= contents() + if(recursive) + for(var/i in ret.Copy()) + var/atom/A = i + SEND_SIGNAL(A, COMSIG_TRY_STORAGE_RETURN_INVENTORY, ret, TRUE) + return ret + +/datum/component/storage/proc/contents() //ONLY USE IF YOU NEED TO COPY CONTENTS OF REAL LOCATION, COPYING IS NOT AS FAST AS DIRECT ACCESS! + var/atom/real_location = real_location() + return real_location.contents.Copy() + +//Abuses the fact that lists are just references, or something like that. +/datum/component/storage/proc/signal_return_inv(datum/source, list/interface, recursive = TRUE) + if(!islist(interface)) + return FALSE + interface |= return_inv(recursive) + return TRUE + +/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M) + set waitfor = FALSE + . = COMPONENT_NO_MOUSEDROP + var/atom/A = parent + if(ismob(M)) //all the check for item manipulation are in other places, you can safely open any storages as anything and its not buggy, i checked + A.add_fingerprint(M) + if(!over_object) + return FALSE + if(ismecha(M.loc)) // stops inventory actions in a mech + return FALSE + // this must come before the screen objects only block, dunno why it wasn't before + if(over_object == M) + user_show_to_mob(M) + if(!M.incapacitated()) + if(!istype(over_object, /obj/screen)) + dump_content_at(over_object, M) + return + if(A.loc != M) + return + playsound(A, "rustle", 50, 1, -5) + A.do_jiggle() + if(istype(over_object, /obj/screen/inventory/hand)) + var/obj/screen/inventory/hand/H = over_object + M.putItemFromInventoryInHandIfPossible(A, H.held_index) + return + A.add_fingerprint(M) + +/datum/component/storage/proc/user_show_to_mob(mob/M, force = FALSE) + var/atom/A = parent + if(!istype(M)) + return FALSE + A.add_fingerprint(M) + if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE))) + return FALSE + show_to(M) + +/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M) + if(isitem(O)) + var/obj/item/I = O + if(iscarbon(M) || isdrone(M)) + var/mob/living/L = M + if(!L.incapacitated() && I == L.get_active_held_item()) + if(!SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE) && can_be_inserted(I, FALSE)) //If it has storage it should be trying to dump, not insert. + handle_item_insertion(I, FALSE, L) + var/atom/A = parent + A.do_squish() + +//This proc return 1 if the item can be picked up and 0 if it can't. +//Set the stop_messages to stop it from printing messages +/datum/component/storage/proc/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M) + if(!istype(I) || (I.item_flags & ABSTRACT)) + return FALSE //Not an item + if(I == parent) + return FALSE //no paradoxes for you + var/atom/real_location = real_location() + var/atom/host = parent + if(real_location == I.loc) + return FALSE //Means the item is already in the storage item + if(check_locked(null, M, !stop_messages)) + if(M && !stop_messages) + host.add_fingerprint(M) + return FALSE + if(real_location.contents.len >= max_items) + if(!stop_messages) + to_chat(M, "[host] is full, make some space!") + return FALSE //Storage item is full + if(length(can_hold)) + if(!is_type_in_typecache(I, can_hold)) + if(!stop_messages) + to_chat(M, "[host] cannot hold [I]!") + return FALSE + if(is_type_in_typecache(I, cant_hold)) //Check for specific items which this container can't hold. + if(!stop_messages) + to_chat(M, "[host] cannot hold [I]!") + return FALSE + if(I.w_class > max_w_class) + if(!stop_messages) + to_chat(M, "[I] is too big for [host]!") + return FALSE + var/sum_w_class = I.w_class + for(var/obj/item/_I in real_location) + sum_w_class += _I.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it. + if(sum_w_class > max_combined_w_class) + if(!stop_messages) + to_chat(M, "[I] won't fit in [host], make some space!") + return FALSE + if(isitem(host)) + var/obj/item/IP = host + var/datum/component/storage/STR_I = I.GetComponent(/datum/component/storage) + if((I.w_class >= IP.w_class) && STR_I && !allow_big_nesting) + if(!stop_messages) + to_chat(M, "[IP] cannot hold [I] as it's a storage item of the same size!") + return FALSE //To prevent the stacking of same sized storage items. + if(HAS_TRAIT(I, TRAIT_NODROP)) //SHOULD be handled in unEquip, but better safe than sorry. + to_chat(M, "\the [I] is stuck to your hand, you can't put it in \the [host]!") + return FALSE + var/datum/component/storage/concrete/master = master() + if(!istype(master)) + return FALSE + return master.slave_can_insert_object(src, I, stop_messages, M) + +/datum/component/storage/proc/_insert_physical_item(obj/item/I, override = FALSE) + return FALSE + +//This proc handles items being inserted. It does not perform any checks of whether an item can or can't be inserted. That's done by can_be_inserted() +//The stop_warning parameter will stop the insertion message from being displayed. It is intended for cases where you are inserting multiple items at once, +//such as when picking up all the items on a tile with one click. +/datum/component/storage/proc/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) + var/atom/parent = src.parent + var/datum/component/storage/concrete/master = master() + if(!istype(master)) + return FALSE + if(silent) + prevent_warning = TRUE + if(M) + parent.add_fingerprint(M) + . = master.handle_item_insertion_from_slave(src, I, prevent_warning, M) + +/datum/component/storage/proc/mob_item_insertion_feedback(mob/user, mob/M, obj/item/I, override = FALSE) + if(silent && !override) + return + if(rustle_sound) + playsound(parent, "rustle", 50, 1, -5) + for(var/mob/viewing in viewers(user, null)) + if(M == viewing) + to_chat(usr, "You put [I] [insert_preposition]to [parent].") + else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is... + viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) + else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance... + viewing.show_message("[M] puts [I] [insert_preposition]to [parent].", MSG_VISUAL) + +/datum/component/storage/proc/update_icon() + if(isobj(parent)) + var/obj/O = parent + O.update_icon() + +/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE) + if((!force && !can_be_inserted(I, TRUE, M)) || (I == parent)) + return FALSE + return handle_item_insertion(I, silent, M) + +/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE) + return can_be_inserted(I, silent, M) + +/datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M) + return user_show_to_mob(M, TRUE) + +/datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE) + return user_show_to_mob(showto, force) + +/datum/component/storage/proc/on_check() + return TRUE + +/datum/component/storage/proc/check_locked(datum/source, mob/user, message = FALSE) + . = locked + if(message && . && user) + to_chat(user, "[parent] seems to be locked!") + +/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted) + if(!force) + if(check_adjacent) + if(!user || !user.CanReach(destination) || !user.CanReach(parent)) + return FALSE + var/list/taking = typecache_filter_list(contents(), typecacheof(type)) + if(taking.len > amount) + taking.len = amount + if(inserted) //duplicated code for performance, don't bother checking retval/checking for list every item. + for(var/i in taking) + if(remove_from_storage(i, destination)) + inserted |= i + else + for(var/i in taking) + remove_from_storage(i, destination) + return TRUE + +/datum/component/storage/proc/remaining_space_items() + var/atom/real_location = real_location() + return max(0, max_items - real_location.contents.len) + +/datum/component/storage/proc/signal_fill_type(datum/source, type, amount = 20, force = FALSE) + var/atom/real_location = real_location() + if(!force) + amount = min(remaining_space_items(), amount) + for(var/i in 1 to amount) + handle_item_insertion(new type(real_location), TRUE) + CHECK_TICK + return TRUE + +/datum/component/storage/proc/on_attack_hand(datum/source, mob/user) + var/atom/A = parent + if(!attack_hand_interact) + return + if(user.active_storage == src && A.loc == user) //if you're already looking inside the storage item + user.active_storage.close(user) + close(user) + . = COMPONENT_NO_ATTACK_HAND + return + + if(rustle_sound) + playsound(A, "rustle", 50, 1, -5) + + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.l_store == A && !H.get_active_held_item()) //Prevents opening if it's in a pocket. + . = COMPONENT_NO_ATTACK_HAND + H.put_in_hands(A) + H.l_store = null + return + if(H.r_store == A && !H.get_active_held_item()) + . = COMPONENT_NO_ATTACK_HAND + H.put_in_hands(A) + H.r_store = null + return + + if(A.loc == user) + . = COMPONENT_NO_ATTACK_HAND + if(!check_locked(source, user, TRUE)) + show_to(user) + A.do_jiggle() + +/datum/component/storage/proc/signal_on_pickup(datum/source, mob/user) + var/atom/A = parent + update_actions() + for(var/mob/M in range(1, A)) + if(M.active_storage == src) + close(M) + +/datum/component/storage/proc/signal_take_obj(datum/source, atom/movable/AM, new_loc, force = FALSE) + if(!(AM in real_location())) + return FALSE + return remove_from_storage(AM, new_loc) + +/datum/component/storage/proc/signal_quick_empty(datum/source, atom/loctarget) + return do_quick_empty(loctarget) + +/datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target) + return hide_from(target) + +/datum/component/storage/proc/on_alt_click(datum/source, mob/user) + if(!isliving(user) || !user.CanReach(parent)) + return + if(check_locked(source, user, TRUE)) + return TRUE + + var/atom/A = parent + if(!quickdraw) + A.add_fingerprint(user) + user_show_to_mob(user) + if(rustle_sound) + playsound(A, "rustle", 50, 1, -5) + return TRUE + + if(user.can_hold_items() && !user.incapacitated()) + var/obj/item/I = locate() in real_location() + if(!I) + return + A.add_fingerprint(user) + remove_from_storage(I, get_turf(user)) + if(!user.put_in_hands(I)) + user.visible_message("[user] fumbles with the [parent], letting [I] fall on the floor.", \ + "You fumble with [parent], letting [I] fall on the floor.") + return TRUE + user.visible_message("[user] draws [I] from [parent]!", "You draw [I] from [parent].") + return TRUE + +/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source) + gather_mode_switch(source.owner) + return COMPONENT_ACTION_BLOCK_TRIGGER + +/datum/component/storage/proc/gather_mode_switch(mob/user) + collection_mode = (collection_mode+1)%3 + switch(collection_mode) + if(COLLECT_SAME) + to_chat(user, "[parent] now picks up all items of a single type at once.") + if(COLLECT_EVERYTHING) + to_chat(user, "[parent] now picks up all items in a tile at once.") + if(COLLECT_ONE) + to_chat(user, "[parent] now picks up one item at a time.") diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index d6c5c0bf83..550ff95324 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -1,211 +1,211 @@ -/datum/component/wet_floor - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - can_transfer = TRUE - var/highest_strength = TURF_DRY - var/lube_flags = NONE //why do we have this? - var/list/time_left_list //In deciseconds. - var/static/mutable_appearance/permafrost_overlay = mutable_appearance('icons/effects/water.dmi', "ice_floor") - var/static/mutable_appearance/ice_overlay = mutable_appearance('icons/turf/overlays.dmi', "snowfloor") - var/static/mutable_appearance/water_overlay = mutable_appearance('icons/effects/water.dmi', "wet_floor_static") - var/static/mutable_appearance/generic_turf_overlay = mutable_appearance('icons/effects/water.dmi', "wet_static") - var/current_overlay - var/permanent = FALSE - var/last_process = 0 - -/datum/component/wet_floor/InheritComponent(datum/newcomp, orig, argslist) - if(!newcomp) //We are getting passed the arguments of a would-be new component, but not a new component - add_wet(arglist(argslist)) - else //We are being passed in a full blown component - var/datum/component/wet_floor/WF = newcomp //Lets make an assumption - if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us. - CRASH("Wet floor component tried to inherit another, but the other was able to garbage collect while being inherited! What a waste of time!") - return - for(var/i in WF.time_left_list) - add_wet(text2num(i), WF.time_left_list[i]) - -/datum/component/wet_floor/Initialize(strength, duration_minimum, duration_add, duration_maximum, _permanent = FALSE) - if(!isopenturf(parent)) - return COMPONENT_INCOMPATIBLE - add_wet(strength, duration_minimum, duration_add, duration_maximum) - permanent = _permanent - if(!permanent) - START_PROCESSING(SSwet_floors, src) - addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization. - last_process = world.time - -/datum/component/wet_floor/RegisterWithParent() - . = ..() - RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet) - RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry) - -/datum/component/wet_floor/UnregisterFromParent() - . = ..() - UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY)) - -/datum/component/wet_floor/Destroy() - STOP_PROCESSING(SSwet_floors, src) - var/turf/T = parent - qdel(T.GetComponent(/datum/component/slippery)) - if(istype(T)) //If this is false there is so many things wrong with it. - T.cut_overlay(current_overlay) - else - stack_trace("Warning: Wet floor component wasn't on a turf when being destroyed! This is really bad!") - return ..() - -/datum/component/wet_floor/proc/update_overlay() - var/intended - if(!istype(parent, /turf/open/floor)) - intended = generic_turf_overlay - else - switch(highest_strength) - if(TURF_WET_PERMAFROST) - intended = permafrost_overlay - if(TURF_WET_ICE) - intended = ice_overlay - else - intended = water_overlay - if(current_overlay != intended) - var/turf/T = parent - T.cut_overlay(current_overlay) - T.add_overlay(intended) - current_overlay = intended - -/datum/component/wet_floor/proc/AfterSlip(mob/living/L) - if(highest_strength == TURF_WET_LUBE) - L.confused = max(L.confused, 8) - -/datum/component/wet_floor/proc/update_flags() - var/intensity - lube_flags = NONE - switch(highest_strength) - if(TURF_WET_WATER) - intensity = 60 - lube_flags = NO_SLIP_WHEN_WALKING - if(TURF_WET_LUBE) - intensity = 80 - lube_flags = SLIDE | GALOSHES_DONT_HELP - if(TURF_WET_ICE) - intensity = 120 - lube_flags = SLIDE | GALOSHES_DONT_HELP - if(TURF_WET_PERMAFROST) - intensity = 120 - lube_flags = SLIDE_ICE | GALOSHES_DONT_HELP - if(TURF_WET_SUPERLUBE) - intensity = 120 - lube_flags = SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING - else - qdel(parent.GetComponent(/datum/component/slippery)) - return - - var/datum/component/slippery/S = parent.LoadComponent(/datum/component/slippery, NONE, CALLBACK(src, .proc/AfterSlip)) - S.intensity = intensity - S.lube_flags = lube_flags - -/datum/component/wet_floor/proc/dry(datum/source, strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY) - for(var/i in time_left_list) - if(text2num(i) <= strength) - time_left_list[i] = max(0, time_left_list[i] - duration_decrease) - if(immediate) - check() - -/datum/component/wet_floor/proc/max_time_left() - . = 0 - for(var/i in time_left_list) - . = max(., time_left_list[i]) - -/datum/component/wet_floor/process() - var/turf/open/T = parent - var/diff = world.time - last_process - var/decrease = 0 - var/t = T.GetTemperature() - switch(t) - if(-INFINITY to T0C) - add_wet(TURF_WET_ICE, max_time_left()) //Water freezes into ice! - if(T0C to T0C + 100) - decrease = ((T.air.temperature - T0C) / SSwet_floors.temperature_coeff) * (diff / SSwet_floors.time_ratio) - if(T0C + 100 to INFINITY) - decrease = INFINITY - decrease = max(0, decrease) - if((is_wet() & TURF_WET_ICE) && t > T0C) //Ice melts into water! - for(var/obj/O in T.contents) - if(O.obj_flags & FROZEN) - O.make_unfrozen() - add_wet(TURF_WET_WATER, max_time_left()) - dry(null, TURF_WET_ICE) - dry(null, ALL, FALSE, decrease) - check() - last_process = world.time - -/datum/component/wet_floor/proc/update_strength() - highest_strength = 0 //Not bitflag. - for(var/i in time_left_list) - highest_strength = max(highest_strength, text2num(i)) - -/datum/component/wet_floor/proc/is_wet() - . = 0 - for(var/i in time_left_list) - . |= text2num(i) - -/datum/component/wet_floor/PreTransfer() - var/turf/O = parent - O.cut_overlay(current_overlay) - //That turf is no longer slippery, we're out of here - //Slippery components don't transfer due to callbacks - qdel(O.GetComponent(/datum/component/slippery)) - -/datum/component/wet_floor/PostTransfer() - if(!isopenturf(parent)) - return COMPONENT_INCOMPATIBLE - var/turf/T = parent - T.add_overlay(current_overlay) - //Make sure to add/update any slippery component on the new turf (update_flags calls LoadComponent) - update_flags() - - //NB it's possible we get deleted after this, due to inherit - -/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE) - var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST, TURF_WET_SUPERLUBE) - if(duration_minimum <= 0 || !type) - return FALSE - if(type in allowed_types) - return _do_add_wet(type, duration_minimum, duration_add, duration_maximum) - else - . = NONE - for(var/i in allowed_types) - if(!(type & i)) - continue - . |= _do_add_wet(i, duration_minimum, duration_add, duration_maximum) - if(_permanent) - permanent = TRUE - STOP_PROCESSING(SSwet_floors, src) - -/datum/component/wet_floor/proc/_do_add_wet(type, duration_minimum, duration_add, duration_maximum) - var/time = 0 - if(LAZYACCESS(time_left_list, "[type]")) - time = CLAMP(LAZYACCESS(time_left_list, "[type]") + duration_add, duration_minimum, duration_maximum) - else - time = min(duration_minimum, duration_maximum) - LAZYSET(time_left_list, "[type]", time) - check(TRUE) - return TRUE - -/datum/component/wet_floor/proc/gc(on_init = FALSE) - if(!LAZYLEN(time_left_list)) - if(on_init) - var/turf/T = parent - stack_trace("Warning: Wet floor component gc'd right after initialization! What a waste of time and CPU! Type = [T? T.type : "ERROR - NO PARENT"], Location = [istype(T)? AREACOORD(T) : "ERROR - INVALID PARENT"].") - qdel(src) - return TRUE - return FALSE - -/datum/component/wet_floor/proc/check(force_update = FALSE) - var/changed = FALSE - for(var/i in time_left_list) - if(time_left_list[i] <= 0) - time_left_list -= i - changed = TRUE - if(changed || force_update) - update_strength() - update_overlay() - update_flags() - gc() +/datum/component/wet_floor + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + can_transfer = TRUE + var/highest_strength = TURF_DRY + var/lube_flags = NONE //why do we have this? + var/list/time_left_list //In deciseconds. + var/static/mutable_appearance/permafrost_overlay = mutable_appearance('icons/effects/water.dmi', "ice_floor") + var/static/mutable_appearance/ice_overlay = mutable_appearance('icons/turf/overlays.dmi', "snowfloor") + var/static/mutable_appearance/water_overlay = mutable_appearance('icons/effects/water.dmi', "wet_floor_static") + var/static/mutable_appearance/generic_turf_overlay = mutable_appearance('icons/effects/water.dmi', "wet_static") + var/current_overlay + var/permanent = FALSE + var/last_process = 0 + +/datum/component/wet_floor/InheritComponent(datum/newcomp, orig, argslist) + if(!newcomp) //We are getting passed the arguments of a would-be new component, but not a new component + add_wet(arglist(argslist)) + else //We are being passed in a full blown component + var/datum/component/wet_floor/WF = newcomp //Lets make an assumption + if(WF.gc()) //See if it's even valid, still. Also does LAZYLEN and stuff for us. + CRASH("Wet floor component tried to inherit another, but the other was able to garbage collect while being inherited! What a waste of time!") + return + for(var/i in WF.time_left_list) + add_wet(text2num(i), WF.time_left_list[i]) + +/datum/component/wet_floor/Initialize(strength, duration_minimum, duration_add, duration_maximum, _permanent = FALSE) + if(!isopenturf(parent)) + return COMPONENT_INCOMPATIBLE + add_wet(strength, duration_minimum, duration_add, duration_maximum) + permanent = _permanent + if(!permanent) + START_PROCESSING(SSwet_floors, src) + addtimer(CALLBACK(src, .proc/gc, TRUE), 1) //GC after initialization. + last_process = world.time + +/datum/component/wet_floor/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_TURF_IS_WET, .proc/is_wet) + RegisterSignal(parent, COMSIG_TURF_MAKE_DRY, .proc/dry) + +/datum/component/wet_floor/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list(COMSIG_TURF_IS_WET, COMSIG_TURF_MAKE_DRY)) + +/datum/component/wet_floor/Destroy() + STOP_PROCESSING(SSwet_floors, src) + var/turf/T = parent + qdel(T.GetComponent(/datum/component/slippery)) + if(istype(T)) //If this is false there is so many things wrong with it. + T.cut_overlay(current_overlay) + else + stack_trace("Warning: Wet floor component wasn't on a turf when being destroyed! This is really bad!") + return ..() + +/datum/component/wet_floor/proc/update_overlay() + var/intended + if(!istype(parent, /turf/open/floor)) + intended = generic_turf_overlay + else + switch(highest_strength) + if(TURF_WET_PERMAFROST) + intended = permafrost_overlay + if(TURF_WET_ICE) + intended = ice_overlay + else + intended = water_overlay + if(current_overlay != intended) + var/turf/T = parent + T.cut_overlay(current_overlay) + T.add_overlay(intended) + current_overlay = intended + +/datum/component/wet_floor/proc/AfterSlip(mob/living/L) + if(highest_strength == TURF_WET_LUBE) + L.confused = max(L.confused, 8) + +/datum/component/wet_floor/proc/update_flags() + var/intensity + lube_flags = NONE + switch(highest_strength) + if(TURF_WET_WATER) + intensity = 60 + lube_flags = NO_SLIP_WHEN_WALKING + if(TURF_WET_LUBE) + intensity = 80 + lube_flags = SLIDE | GALOSHES_DONT_HELP + if(TURF_WET_ICE) + intensity = 120 + lube_flags = SLIDE | GALOSHES_DONT_HELP + if(TURF_WET_PERMAFROST) + intensity = 120 + lube_flags = SLIDE_ICE | GALOSHES_DONT_HELP + if(TURF_WET_SUPERLUBE) + intensity = 120 + lube_flags = SLIDE | GALOSHES_DONT_HELP | SLIP_WHEN_CRAWLING + else + qdel(parent.GetComponent(/datum/component/slippery)) + return + + var/datum/component/slippery/S = parent.LoadComponent(/datum/component/slippery, NONE, CALLBACK(src, .proc/AfterSlip)) + S.intensity = intensity + S.lube_flags = lube_flags + +/datum/component/wet_floor/proc/dry(datum/source, strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY) + for(var/i in time_left_list) + if(text2num(i) <= strength) + time_left_list[i] = max(0, time_left_list[i] - duration_decrease) + if(immediate) + check() + +/datum/component/wet_floor/proc/max_time_left() + . = 0 + for(var/i in time_left_list) + . = max(., time_left_list[i]) + +/datum/component/wet_floor/process() + var/turf/open/T = parent + var/diff = world.time - last_process + var/decrease = 0 + var/t = T.GetTemperature() + switch(t) + if(-INFINITY to T0C) + add_wet(TURF_WET_ICE, max_time_left()) //Water freezes into ice! + if(T0C to T0C + 100) + decrease = ((T.air.temperature - T0C) / SSwet_floors.temperature_coeff) * (diff / SSwet_floors.time_ratio) + if(T0C + 100 to INFINITY) + decrease = INFINITY + decrease = max(0, decrease) + if((is_wet() & TURF_WET_ICE) && t > T0C) //Ice melts into water! + for(var/obj/O in T.contents) + if(O.obj_flags & FROZEN) + O.make_unfrozen() + add_wet(TURF_WET_WATER, max_time_left()) + dry(null, TURF_WET_ICE) + dry(null, ALL, FALSE, decrease) + check() + last_process = world.time + +/datum/component/wet_floor/proc/update_strength() + highest_strength = 0 //Not bitflag. + for(var/i in time_left_list) + highest_strength = max(highest_strength, text2num(i)) + +/datum/component/wet_floor/proc/is_wet() + . = 0 + for(var/i in time_left_list) + . |= text2num(i) + +/datum/component/wet_floor/PreTransfer() + var/turf/O = parent + O.cut_overlay(current_overlay) + //That turf is no longer slippery, we're out of here + //Slippery components don't transfer due to callbacks + qdel(O.GetComponent(/datum/component/slippery)) + +/datum/component/wet_floor/PostTransfer() + if(!isopenturf(parent)) + return COMPONENT_INCOMPATIBLE + var/turf/T = parent + T.add_overlay(current_overlay) + //Make sure to add/update any slippery component on the new turf (update_flags calls LoadComponent) + update_flags() + + //NB it's possible we get deleted after this, due to inherit + +/datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE) + var/static/list/allowed_types = list(TURF_WET_WATER, TURF_WET_LUBE, TURF_WET_ICE, TURF_WET_PERMAFROST, TURF_WET_SUPERLUBE) + if(duration_minimum <= 0 || !type) + return FALSE + if(type in allowed_types) + return _do_add_wet(type, duration_minimum, duration_add, duration_maximum) + else + . = NONE + for(var/i in allowed_types) + if(!(type & i)) + continue + . |= _do_add_wet(i, duration_minimum, duration_add, duration_maximum) + if(_permanent) + permanent = TRUE + STOP_PROCESSING(SSwet_floors, src) + +/datum/component/wet_floor/proc/_do_add_wet(type, duration_minimum, duration_add, duration_maximum) + var/time = 0 + if(LAZYACCESS(time_left_list, "[type]")) + time = CLAMP(LAZYACCESS(time_left_list, "[type]") + duration_add, duration_minimum, duration_maximum) + else + time = min(duration_minimum, duration_maximum) + LAZYSET(time_left_list, "[type]", time) + check(TRUE) + return TRUE + +/datum/component/wet_floor/proc/gc(on_init = FALSE) + if(!LAZYLEN(time_left_list)) + if(on_init) + var/turf/T = parent + stack_trace("Warning: Wet floor component gc'd right after initialization! What a waste of time and CPU! Type = [T? T.type : "ERROR - NO PARENT"], Location = [istype(T)? AREACOORD(T) : "ERROR - INVALID PARENT"].") + qdel(src) + return TRUE + return FALSE + +/datum/component/wet_floor/proc/check(force_update = FALSE) + var/changed = FALSE + for(var/i in time_left_list) + if(time_left_list[i] <= 0) + time_left_list -= i + changed = TRUE + if(changed || force_update) + update_strength() + update_overlay() + update_flags() + gc() diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index cf33fa3633..ebfba43852 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,296 +1,296 @@ - -/datum/datacore - var/medical[] = list() - var/medicalPrintCount = 0 - var/general[] = list() - var/security[] = list() - var/securityPrintCount = 0 - var/securityCrimeCounter = 0 - //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). - var/locked[] = list() - -/datum/data - var/name = "data" - -/datum/data/record - name = "record" - var/list/fields = list() - -/datum/data/record/Destroy() - if(src in GLOB.data_core.medical) - GLOB.data_core.medical -= src - if(src in GLOB.data_core.security) - GLOB.data_core.security -= src - if(src in GLOB.data_core.general) - GLOB.data_core.general -= src - if(src in GLOB.data_core.locked) - GLOB.data_core.locked -= src - . = ..() - -/datum/data/crime - name = "crime" - var/crimeName = "" - var/crimeDetails = "" - var/author = "" - var/time = "" - var/dataId = 0 - -/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "") - var/datum/data/crime/c = new /datum/data/crime - c.crimeName = cname - c.crimeDetails = cdetails - c.author = author - c.time = time - c.dataId = ++securityCrimeCounter - return c - -/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime) - for(var/datum/data/record/R in security) - if(R.fields["id"] == id) - var/list/crimes = R.fields["mi_crim"] - crimes |= crime - return - -/datum/datacore/proc/removeMinorCrime(id, cDataId) - for(var/datum/data/record/R in security) - if(R.fields["id"] == id) - var/list/crimes = R.fields["mi_crim"] - for(var/datum/data/crime/crime in crimes) - if(crime.dataId == text2num(cDataId)) - crimes -= crime - return - -/datum/datacore/proc/removeMajorCrime(id, cDataId) - for(var/datum/data/record/R in security) - if(R.fields["id"] == id) - var/list/crimes = R.fields["ma_crim"] - for(var/datum/data/crime/crime in crimes) - if(crime.dataId == text2num(cDataId)) - crimes -= crime - return - -/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime) - for(var/datum/data/record/R in security) - if(R.fields["id"] == id) - var/list/crimes = R.fields["ma_crim"] - crimes |= crime - return - -/datum/datacore/proc/manifest() - for(var/mob/dead/new_player/N in GLOB.player_list) - if(N.new_character) - log_manifest(N.ckey,N.new_character.mind,N.new_character) - if(ishuman(N.new_character)) - manifest_inject(N.new_character, N.client) - CHECK_TICK - -/datum/datacore/proc/manifest_modify(name, assignment) - var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general) - if(foundrecord) - foundrecord.fields["rank"] = assignment - -/datum/datacore/proc/get_manifest(monochrome, OOC) - var/list/heads = list() - var/list/sec = list() - var/list/eng = list() - var/list/med = list() - var/list/sci = list() - var/list/sup = list() - var/list/civ = list() - var/list/bot = list() - var/list/misc = list() - var/dat = {" - - - - "} - var/even = 0 - // sort mobs - for(var/datum/data/record/t in GLOB.data_core.general) - var/name = t.fields["name"] - var/rank = t.fields["rank"] - var/department = 0 - if(rank in GLOB.command_positions) - heads[name] = rank - department = 1 - if(rank in GLOB.security_positions) - sec[name] = rank - department = 1 - if(rank in GLOB.engineering_positions) - eng[name] = rank - department = 1 - if(rank in GLOB.medical_positions) - med[name] = rank - department = 1 - if(rank in GLOB.science_positions) - sci[name] = rank - department = 1 - if(rank in GLOB.supply_positions) - sup[name] = rank - department = 1 - if(rank in GLOB.civilian_positions) - civ[name] = rank - department = 1 - if(rank in GLOB.nonhuman_positions) - bot[name] = rank - department = 1 - if(!department && !(name in heads)) - misc[name] = rank - if(heads.len > 0) - dat += "" - for(var/name in heads) - dat += "" - even = !even - if(sec.len > 0) - dat += "" - for(var/name in sec) - dat += "" - even = !even - if(eng.len > 0) - dat += "" - for(var/name in eng) - dat += "" - even = !even - if(med.len > 0) - dat += "" - for(var/name in med) - dat += "" - even = !even - if(sci.len > 0) - dat += "" - for(var/name in sci) - dat += "" - even = !even - if(sup.len > 0) - dat += "" - for(var/name in sup) - dat += "" - even = !even - if(civ.len > 0) - dat += "" - for(var/name in civ) - dat += "" - even = !even - // in case somebody is insane and added them to the manifest, why not - if(bot.len > 0) - dat += "" - for(var/name in bot) - dat += "" - even = !even - // misc guys - if(misc.len > 0) - dat += "" - for(var/name in misc) - dat += "" - even = !even - - dat += "
NameRank
Heads
[name][heads[name]]
Security
[name][sec[name]]
Engineering
[name][eng[name]]
Medical
[name][med[name]]
Science
[name][sci[name]]
Supply
[name][sup[name]]
Civilian
[name][civ[name]]
Silicon
[name][bot[name]]
Miscellaneous
[name][misc[name]]
" - dat = replacetext(dat, "\n", "") - dat = replacetext(dat, "\t", "") - return dat - - -/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C) - set waitfor = FALSE - var/static/list/show_directions = list(SOUTH, WEST) - if(H.mind && (H.mind.assigned_role != H.mind.special_role)) - var/assignment - if(H.mind.assigned_role) - assignment = H.mind.assigned_role - else if(H.job) - assignment = H.job - else - assignment = "Unassigned" - - var/static/record_id_num = 1001 - var/id = num2hex(record_id_num++,6) - if(!C) - C = H.client - var/image = get_id_photo(H, C, show_directions) - var/datum/picture/pf = new - var/datum/picture/ps = new - pf.picture_name = "[H]" - ps.picture_name = "[H]" - pf.picture_desc = "This is [H]." - ps.picture_desc = "This is [H]." - pf.picture_image = icon(image, dir = SOUTH) - ps.picture_image = icon(image, dir = WEST) - var/obj/item/photo/photo_front = new(null, pf) - var/obj/item/photo/photo_side = new(null, ps) - - //These records should ~really~ be merged or something - //General Record - var/datum/data/record/G = new() - G.fields["id"] = id - G.fields["name"] = H.real_name - G.fields["rank"] = assignment - G.fields["age"] = H.age - G.fields["species"] = H.dna.species.name - G.fields["fingerprint"] = md5(H.dna.uni_identity) - G.fields["p_stat"] = "Active" - G.fields["m_stat"] = "Stable" - G.fields["sex"] = H.gender - G.fields["photo_front"] = photo_front - G.fields["photo_side"] = photo_side - general += G - - //Medical Record - var/datum/data/record/M = new() - M.fields["id"] = id - M.fields["name"] = H.real_name - M.fields["blood_type"] = H.dna.blood_type - M.fields["b_dna"] = H.dna.unique_enzymes - M.fields["mi_dis"] = "None" - M.fields["mi_dis_d"] = "No minor disabilities have been declared." - M.fields["ma_dis"] = "None" - M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - M.fields["alg"] = "None" - M.fields["alg_d"] = "No allergies have been detected in this patient." - M.fields["cdi"] = "None" - M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - M.fields["notes"] = H.get_trait_string(medical) - medical += M - - //Security Record - var/datum/data/record/S = new() - S.fields["id"] = id - S.fields["name"] = H.real_name - S.fields["criminal"] = "None" - S.fields["mi_crim"] = list() - S.fields["ma_crim"] = list() - S.fields["notes"] = "No notes." - security += S - - //Locked Record - var/datum/data/record/L = new() - L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others? - L.fields["name"] = H.real_name - L.fields["rank"] = H.mind.assigned_role - L.fields["age"] = H.age - L.fields["sex"] = H.gender - L.fields["blood_type"] = H.dna.blood_type - L.fields["b_dna"] = H.dna.unique_enzymes - L.fields["enzymes"] = H.dna.struc_enzymes - L.fields["identity"] = H.dna.uni_identity - L.fields["species"] = H.dna.species.type - L.fields["features"] = H.dna.features - L.fields["image"] = image - L.fields["mindref"] = H.mind - locked += L - return - -/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C, show_directions = list(SOUTH)) - var/datum/job/J = SSjob.GetJob(H.mind.assigned_role) - var/datum/preferences/P - if(!C) - C = H.client - if(C) - P = C.prefs - return get_flat_human_icon(null, J, P, DUMMY_HUMAN_SLOT_MANIFEST, show_directions) + +/datum/datacore + var/medical[] = list() + var/medicalPrintCount = 0 + var/general[] = list() + var/security[] = list() + var/securityPrintCount = 0 + var/securityCrimeCounter = 0 + //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). + var/locked[] = list() + +/datum/data + var/name = "data" + +/datum/data/record + name = "record" + var/list/fields = list() + +/datum/data/record/Destroy() + if(src in GLOB.data_core.medical) + GLOB.data_core.medical -= src + if(src in GLOB.data_core.security) + GLOB.data_core.security -= src + if(src in GLOB.data_core.general) + GLOB.data_core.general -= src + if(src in GLOB.data_core.locked) + GLOB.data_core.locked -= src + . = ..() + +/datum/data/crime + name = "crime" + var/crimeName = "" + var/crimeDetails = "" + var/author = "" + var/time = "" + var/dataId = 0 + +/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "") + var/datum/data/crime/c = new /datum/data/crime + c.crimeName = cname + c.crimeDetails = cdetails + c.author = author + c.time = time + c.dataId = ++securityCrimeCounter + return c + +/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime) + for(var/datum/data/record/R in security) + if(R.fields["id"] == id) + var/list/crimes = R.fields["mi_crim"] + crimes |= crime + return + +/datum/datacore/proc/removeMinorCrime(id, cDataId) + for(var/datum/data/record/R in security) + if(R.fields["id"] == id) + var/list/crimes = R.fields["mi_crim"] + for(var/datum/data/crime/crime in crimes) + if(crime.dataId == text2num(cDataId)) + crimes -= crime + return + +/datum/datacore/proc/removeMajorCrime(id, cDataId) + for(var/datum/data/record/R in security) + if(R.fields["id"] == id) + var/list/crimes = R.fields["ma_crim"] + for(var/datum/data/crime/crime in crimes) + if(crime.dataId == text2num(cDataId)) + crimes -= crime + return + +/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime) + for(var/datum/data/record/R in security) + if(R.fields["id"] == id) + var/list/crimes = R.fields["ma_crim"] + crimes |= crime + return + +/datum/datacore/proc/manifest() + for(var/mob/dead/new_player/N in GLOB.player_list) + if(N.new_character) + log_manifest(N.ckey,N.new_character.mind,N.new_character) + if(ishuman(N.new_character)) + manifest_inject(N.new_character, N.client) + CHECK_TICK + +/datum/datacore/proc/manifest_modify(name, assignment) + var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general) + if(foundrecord) + foundrecord.fields["rank"] = assignment + +/datum/datacore/proc/get_manifest(monochrome, OOC) + var/list/heads = list() + var/list/sec = list() + var/list/eng = list() + var/list/med = list() + var/list/sci = list() + var/list/sup = list() + var/list/civ = list() + var/list/bot = list() + var/list/misc = list() + var/dat = {" + + + + "} + var/even = 0 + // sort mobs + for(var/datum/data/record/t in GLOB.data_core.general) + var/name = t.fields["name"] + var/rank = t.fields["rank"] + var/department = 0 + if(rank in GLOB.command_positions) + heads[name] = rank + department = 1 + if(rank in GLOB.security_positions) + sec[name] = rank + department = 1 + if(rank in GLOB.engineering_positions) + eng[name] = rank + department = 1 + if(rank in GLOB.medical_positions) + med[name] = rank + department = 1 + if(rank in GLOB.science_positions) + sci[name] = rank + department = 1 + if(rank in GLOB.supply_positions) + sup[name] = rank + department = 1 + if(rank in GLOB.civilian_positions) + civ[name] = rank + department = 1 + if(rank in GLOB.nonhuman_positions) + bot[name] = rank + department = 1 + if(!department && !(name in heads)) + misc[name] = rank + if(heads.len > 0) + dat += "" + for(var/name in heads) + dat += "" + even = !even + if(sec.len > 0) + dat += "" + for(var/name in sec) + dat += "" + even = !even + if(eng.len > 0) + dat += "" + for(var/name in eng) + dat += "" + even = !even + if(med.len > 0) + dat += "" + for(var/name in med) + dat += "" + even = !even + if(sci.len > 0) + dat += "" + for(var/name in sci) + dat += "" + even = !even + if(sup.len > 0) + dat += "" + for(var/name in sup) + dat += "" + even = !even + if(civ.len > 0) + dat += "" + for(var/name in civ) + dat += "" + even = !even + // in case somebody is insane and added them to the manifest, why not + if(bot.len > 0) + dat += "" + for(var/name in bot) + dat += "" + even = !even + // misc guys + if(misc.len > 0) + dat += "" + for(var/name in misc) + dat += "" + even = !even + + dat += "
NameRank
Heads
[name][heads[name]]
Security
[name][sec[name]]
Engineering
[name][eng[name]]
Medical
[name][med[name]]
Science
[name][sci[name]]
Supply
[name][sup[name]]
Civilian
[name][civ[name]]
Silicon
[name][bot[name]]
Miscellaneous
[name][misc[name]]
" + dat = replacetext(dat, "\n", "") + dat = replacetext(dat, "\t", "") + return dat + + +/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C) + set waitfor = FALSE + var/static/list/show_directions = list(SOUTH, WEST) + if(H.mind && (H.mind.assigned_role != H.mind.special_role)) + var/assignment + if(H.mind.assigned_role) + assignment = H.mind.assigned_role + else if(H.job) + assignment = H.job + else + assignment = "Unassigned" + + var/static/record_id_num = 1001 + var/id = num2hex(record_id_num++,6) + if(!C) + C = H.client + var/image = get_id_photo(H, C, show_directions) + var/datum/picture/pf = new + var/datum/picture/ps = new + pf.picture_name = "[H]" + ps.picture_name = "[H]" + pf.picture_desc = "This is [H]." + ps.picture_desc = "This is [H]." + pf.picture_image = icon(image, dir = SOUTH) + ps.picture_image = icon(image, dir = WEST) + var/obj/item/photo/photo_front = new(null, pf) + var/obj/item/photo/photo_side = new(null, ps) + + //These records should ~really~ be merged or something + //General Record + var/datum/data/record/G = new() + G.fields["id"] = id + G.fields["name"] = H.real_name + G.fields["rank"] = assignment + G.fields["age"] = H.age + G.fields["species"] = H.dna.species.name + G.fields["fingerprint"] = md5(H.dna.uni_identity) + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + G.fields["sex"] = H.gender + G.fields["photo_front"] = photo_front + G.fields["photo_side"] = photo_side + general += G + + //Medical Record + var/datum/data/record/M = new() + M.fields["id"] = id + M.fields["name"] = H.real_name + M.fields["blood_type"] = H.dna.blood_type + M.fields["b_dna"] = H.dna.unique_enzymes + M.fields["mi_dis"] = "None" + M.fields["mi_dis_d"] = "No minor disabilities have been declared." + M.fields["ma_dis"] = "None" + M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + M.fields["alg"] = "None" + M.fields["alg_d"] = "No allergies have been detected in this patient." + M.fields["cdi"] = "None" + M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + M.fields["notes"] = H.get_trait_string(medical) + medical += M + + //Security Record + var/datum/data/record/S = new() + S.fields["id"] = id + S.fields["name"] = H.real_name + S.fields["criminal"] = "None" + S.fields["mi_crim"] = list() + S.fields["ma_crim"] = list() + S.fields["notes"] = "No notes." + security += S + + //Locked Record + var/datum/data/record/L = new() + L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others? + L.fields["name"] = H.real_name + L.fields["rank"] = H.mind.assigned_role + L.fields["age"] = H.age + L.fields["sex"] = H.gender + L.fields["blood_type"] = H.dna.blood_type + L.fields["b_dna"] = H.dna.unique_enzymes + L.fields["enzymes"] = H.dna.struc_enzymes + L.fields["identity"] = H.dna.uni_identity + L.fields["species"] = H.dna.species.type + L.fields["features"] = H.dna.features + L.fields["image"] = image + L.fields["mindref"] = H.mind + locked += L + return + +/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C, show_directions = list(SOUTH)) + var/datum/job/J = SSjob.GetJob(H.mind.assigned_role) + var/datum/preferences/P + if(!C) + C = H.client + if(C) + P = C.prefs + return get_flat_human_icon(null, J, P, DUMMY_HUMAN_SLOT_MANIFEST, show_directions) diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 8737cd8feb..34e4e7ac14 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -1,160 +1,160 @@ -/datum - var/gc_destroyed //Time when this object was destroyed. - var/list/active_timers //for SStimer - var/list/datum_components //for /datum/components - var/list/status_traits - var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register - var/list/list/datum/callback/signal_procs - var/signal_enabled = FALSE - var/datum_flags = NONE - var/datum/weakref/weak_reference - -#ifdef TESTING - var/running_find_references - var/last_find_references = 0 -#endif - -#ifdef DATUMVAR_DEBUGGING_MODE - var/list/cached_vars -#endif - -// Default implementation of clean-up code. -// This should be overridden to remove all references pointing to the object being destroyed. -// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE. -/datum/proc/Destroy(force=FALSE, ...) - tag = null - datum_flags &= ~DF_USE_TAG //In case something tries to REF us - weak_reference = null //ensure prompt GCing of weakref. - - var/list/timers = active_timers - active_timers = null - for(var/thing in timers) - var/datum/timedevent/timer = thing - if (timer.spent) - continue - qdel(timer) - - //BEGIN: ECS SHIT - signal_enabled = FALSE - - var/list/dc = datum_components - if(dc) - var/all_components = dc[/datum/component] - if(length(all_components)) - for(var/I in all_components) - var/datum/component/C = I - qdel(C, FALSE, TRUE) - else - var/datum/component/C = all_components - qdel(C, FALSE, TRUE) - dc.Cut() - - var/list/lookup = comp_lookup - if(lookup) - for(var/sig in lookup) - var/list/comps = lookup[sig] - if(length(comps)) - for(var/i in comps) - var/datum/component/comp = i - comp.UnregisterSignal(src, sig) - else - var/datum/component/comp = comps - comp.UnregisterSignal(src, sig) - comp_lookup = lookup = null - - for(var/target in signal_procs) - UnregisterSignal(target, signal_procs[target]) - //END: ECS SHIT - - return QDEL_HINT_QUEUE - -#ifdef DATUMVAR_DEBUGGING_MODE -/datum/proc/save_vars() - cached_vars = list() - for(var/i in vars) - if(i == "cached_vars") - continue - cached_vars[i] = vars[i] - -/datum/proc/check_changed_vars() - . = list() - for(var/i in vars) - if(i == "cached_vars") - continue - if(cached_vars[i] != vars[i]) - .[i] = list(cached_vars[i], vars[i]) - -/datum/proc/txt_changed_vars() - var/list/l = check_changed_vars() - var/t = "[src]([REF(src)]) changed vars:" - for(var/i in l) - t += "\"[i]\" \[[l[i][1]]\] --> \[[l[i][2]]\] " - t += "." - -/datum/proc/to_chat_check_changed_vars(target = world) - to_chat(target, txt_changed_vars()) -#endif - -//Return a LIST for serialize_datum to encode! Not the actual json! -/datum/proc/serialize_list(list/options) - CRASH("Attempted to serialize datum [src] of type [type] without serialize_list being implemented!") - -//Accepts a LIST from deserialize_datum. Should return src or another datum. -/datum/proc/deserialize_list(json, list/options) - CRASH("Attempted to deserialize datum [src] of type [type] without deserialize_list being implemented!") - -//Serializes into JSON. Does not encode type. -/datum/proc/serialize_json(list/options) - . = serialize_list(options) - if(!islist(.)) - . = null - else - . = json_encode(.) - -//Deserializes from JSON. Does not parse type. -/datum/proc/deserialize_json(list/input, list/options) - var/list/jsonlist = json_decode(input) - . = deserialize_list(jsonlist) - if(!istype(., /datum)) - . = null - -/proc/json_serialize_datum(datum/D, list/options) - if(!istype(D)) - return - var/list/jsonlist = D.serialize_list(options) - if(islist(jsonlist)) - jsonlist["DATUM_TYPE"] = D.type - return json_encode(jsonlist) - -/proc/json_deserialize_datum(list/jsonlist, list/options, target_type, strict_target_type = FALSE) - if(!islist(jsonlist)) - if(!istext(jsonlist)) - CRASH("Invalid JSON") - return - jsonlist = json_decode(jsonlist) - if(!islist(jsonlist)) - CRASH("Invalid JSON") - return - if(!jsonlist["DATUM_TYPE"]) - return - if(!ispath(jsonlist["DATUM_TYPE"])) - if(!istext(jsonlist["DATUM_TYPE"])) - return - jsonlist["DATUM_TYPE"] = text2path(jsonlist["DATUM_TYPE"]) - if(!ispath(jsonlist["DATUM_TYPE"])) - return - if(target_type) - if(!ispath(target_type)) - return - if(strict_target_type) - if(target_type != jsonlist["DATUM_TYPE"]) - return - else if(!ispath(jsonlist["DATUM_TYPE"], target_type)) - return - var/typeofdatum = jsonlist["DATUM_TYPE"] //BYOND won't directly read if this is just put in the line below, and will instead runtime because it thinks you're trying to make a new list? - var/datum/D = new typeofdatum - var/datum/returned = D.deserialize_list(jsonlist, options) - if(!istype(returned, /datum)) - qdel(D) - else - return returned +/datum + var/gc_destroyed //Time when this object was destroyed. + var/list/active_timers //for SStimer + var/list/datum_components //for /datum/components + var/list/status_traits + var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register + var/list/list/datum/callback/signal_procs + var/signal_enabled = FALSE + var/datum_flags = NONE + var/datum/weakref/weak_reference + +#ifdef TESTING + var/running_find_references + var/last_find_references = 0 +#endif + +#ifdef DATUMVAR_DEBUGGING_MODE + var/list/cached_vars +#endif + +// Default implementation of clean-up code. +// This should be overridden to remove all references pointing to the object being destroyed. +// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE. +/datum/proc/Destroy(force=FALSE, ...) + tag = null + datum_flags &= ~DF_USE_TAG //In case something tries to REF us + weak_reference = null //ensure prompt GCing of weakref. + + var/list/timers = active_timers + active_timers = null + for(var/thing in timers) + var/datum/timedevent/timer = thing + if (timer.spent) + continue + qdel(timer) + + //BEGIN: ECS SHIT + signal_enabled = FALSE + + var/list/dc = datum_components + if(dc) + var/all_components = dc[/datum/component] + if(length(all_components)) + for(var/I in all_components) + var/datum/component/C = I + qdel(C, FALSE, TRUE) + else + var/datum/component/C = all_components + qdel(C, FALSE, TRUE) + dc.Cut() + + var/list/lookup = comp_lookup + if(lookup) + for(var/sig in lookup) + var/list/comps = lookup[sig] + if(length(comps)) + for(var/i in comps) + var/datum/component/comp = i + comp.UnregisterSignal(src, sig) + else + var/datum/component/comp = comps + comp.UnregisterSignal(src, sig) + comp_lookup = lookup = null + + for(var/target in signal_procs) + UnregisterSignal(target, signal_procs[target]) + //END: ECS SHIT + + return QDEL_HINT_QUEUE + +#ifdef DATUMVAR_DEBUGGING_MODE +/datum/proc/save_vars() + cached_vars = list() + for(var/i in vars) + if(i == "cached_vars") + continue + cached_vars[i] = vars[i] + +/datum/proc/check_changed_vars() + . = list() + for(var/i in vars) + if(i == "cached_vars") + continue + if(cached_vars[i] != vars[i]) + .[i] = list(cached_vars[i], vars[i]) + +/datum/proc/txt_changed_vars() + var/list/l = check_changed_vars() + var/t = "[src]([REF(src)]) changed vars:" + for(var/i in l) + t += "\"[i]\" \[[l[i][1]]\] --> \[[l[i][2]]\] " + t += "." + +/datum/proc/to_chat_check_changed_vars(target = world) + to_chat(target, txt_changed_vars()) +#endif + +//Return a LIST for serialize_datum to encode! Not the actual json! +/datum/proc/serialize_list(list/options) + CRASH("Attempted to serialize datum [src] of type [type] without serialize_list being implemented!") + +//Accepts a LIST from deserialize_datum. Should return src or another datum. +/datum/proc/deserialize_list(json, list/options) + CRASH("Attempted to deserialize datum [src] of type [type] without deserialize_list being implemented!") + +//Serializes into JSON. Does not encode type. +/datum/proc/serialize_json(list/options) + . = serialize_list(options) + if(!islist(.)) + . = null + else + . = json_encode(.) + +//Deserializes from JSON. Does not parse type. +/datum/proc/deserialize_json(list/input, list/options) + var/list/jsonlist = json_decode(input) + . = deserialize_list(jsonlist) + if(!istype(., /datum)) + . = null + +/proc/json_serialize_datum(datum/D, list/options) + if(!istype(D)) + return + var/list/jsonlist = D.serialize_list(options) + if(islist(jsonlist)) + jsonlist["DATUM_TYPE"] = D.type + return json_encode(jsonlist) + +/proc/json_deserialize_datum(list/jsonlist, list/options, target_type, strict_target_type = FALSE) + if(!islist(jsonlist)) + if(!istext(jsonlist)) + CRASH("Invalid JSON") + return + jsonlist = json_decode(jsonlist) + if(!islist(jsonlist)) + CRASH("Invalid JSON") + return + if(!jsonlist["DATUM_TYPE"]) + return + if(!ispath(jsonlist["DATUM_TYPE"])) + if(!istext(jsonlist["DATUM_TYPE"])) + return + jsonlist["DATUM_TYPE"] = text2path(jsonlist["DATUM_TYPE"]) + if(!ispath(jsonlist["DATUM_TYPE"])) + return + if(target_type) + if(!ispath(target_type)) + return + if(strict_target_type) + if(target_type != jsonlist["DATUM_TYPE"]) + return + else if(!ispath(jsonlist["DATUM_TYPE"], target_type)) + return + var/typeofdatum = jsonlist["DATUM_TYPE"] //BYOND won't directly read if this is just put in the line below, and will instead runtime because it thinks you're trying to make a new list? + var/datum/D = new typeofdatum + var/datum/returned = D.deserialize_list(jsonlist, options) + if(!istype(returned, /datum)) + qdel(D) + else + return returned diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index dfaa6f061d..5caa491e4c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -1,1430 +1,1430 @@ -#define VV_MSG_MARKED "
Marked Object" -#define VV_MSG_EDITED "
Var Edited" -#define VV_MSG_DELETED "
Deleted" - -/datum/proc/CanProcCall(procname) - return TRUE - -/datum/proc/can_vv_get(var_name) - return TRUE - -/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited - if(var_name == NAMEOF(src, vars)) - return FALSE - vars[var_name] = var_value - datum_flags |= DF_VAR_EDITED - return TRUE - -/datum/proc/vv_get_var(var_name) - switch(var_name) - if ("vars") - return debug_variable(var_name, list(), 0, src) - return debug_variable(var_name, vars[var_name], 0, src) - -//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down -//add separaters by doing . += "---" -/datum/proc/vv_get_dropdown() - . = list() - . += "---" - .["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]" - .["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]" - .["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]" - .["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]" - - -/datum/proc/on_reagent_change(changetype) - return - - -/client/proc/debug_variables(datum/D in world) - set category = "Debug" - set name = "View Variables" - //set src in world - var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. - - if(!usr.client || !usr.client.holder) //The usr vs src abuse in this proc is intentional and must not be changed - to_chat(usr, "You need to be an administrator to access this.") - return - - if(!D) - return - - var/islist = islist(D) - if (!islist && !istype(D)) - return - - var/title = "" - var/refid = REF(D) - var/icon/sprite - var/hash - - var/type = /list - if (!islist) - type = D.type - - - - if(istype(D, /atom)) - var/atom/AT = D - if(AT.icon && AT.icon_state) - sprite = new /icon(AT.icon, AT.icon_state) - hash = md5(AT.icon) - hash = md5(hash + AT.icon_state) - src << browse_rsc(sprite, "vv[hash].png") - - title = "[D] ([REF(D)]) = [type]" - var/formatted_type = replacetext("[type]", "/", "/") - - var/sprite_text - if(sprite) - sprite_text = "" - var/list/atomsnowflake = list() - - if(istype(D, /atom)) - var/atom/A = D - if(isliving(A)) - atomsnowflake += "[D]" - atomsnowflake += "
<< [dir2text(A.dir) || A.dir] >>" - var/mob/living/M = A - atomsnowflake += {" -
[M.ckey || "No ckey"] / [M.real_name || "No real name"] -
- BRUTE:[M.getBruteLoss()] - FIRE:[M.getFireLoss()] - TOXIN:[M.getToxLoss()] - OXY:[M.getOxyLoss()] - CLONE:[M.getCloneLoss()] - BRAIN:[M.getOrganLoss(ORGAN_SLOT_BRAIN)] - STAMINA:[M.getStaminaLoss()] - AROUSAL:[M.getArousalLoss()] - "} - if(GLOB.Debug2) - atomsnowflake += {" - HEART:[M.getOrganLoss(ORGAN_SLOT_HEART)] - LIVER:[M.getOrganLoss(ORGAN_SLOT_LIVER)] - LUNGS:[M.getOrganLoss(ORGAN_SLOT_LUNGS)] - EYES:[M.getOrganLoss(ORGAN_SLOT_EYES)] - EARS:[M.getOrganLoss(ORGAN_SLOT_EARS)] - STOMACH:[M.getOrganLoss(ORGAN_SLOT_STOMACH)] - TONGUE:[M.getOrganLoss(ORGAN_SLOT_TONGUE)] - APPENDIX:[M.getOrganLoss(ORGAN_SLOT_APPENDIX)] - "} - atomsnowflake += {" - - "} - else - atomsnowflake += "[D]" - atomsnowflake += "
<< [dir2text(A.dir) || A.dir] >>" - else if("name" in D.vars) - atomsnowflake += "[D]" - else - atomsnowflake += "[formatted_type]" - formatted_type = null - - var/marked - if(holder && holder.marked_datum && holder.marked_datum == D) - marked = VV_MSG_MARKED - var/varedited_line = "" - if(!islist && (D.datum_flags & DF_VAR_EDITED)) - varedited_line = VV_MSG_EDITED - var/deleted_line - if(!islist && D.gc_destroyed) - deleted_line = VV_MSG_DELETED - - var/list/dropdownoptions = list() - if (islist) - dropdownoptions = list( - "---", - "Add Item" = "?_src_=vars;[HrefToken()];listadd=[refid]", - "Remove Nulls" = "?_src_=vars;[HrefToken()];listnulls=[refid]", - "Remove Dupes" = "?_src_=vars;[HrefToken()];listdupes=[refid]", - "Set len" = "?_src_=vars;[HrefToken()];listlen=[refid]", - "Shuffle" = "?_src_=vars;[HrefToken()];listshuffle=[refid]", - "Show VV To Player" = "?_src_=vars;[HrefToken()];expose=[refid]" - ) - else - dropdownoptions = D.vv_get_dropdown() - var/list/dropdownoptions_html = list() - - for (var/name in dropdownoptions) - var/link = dropdownoptions[name] - if (link) - dropdownoptions_html += "" - else - dropdownoptions_html += "" - - var/list/names = list() - if (!islist) - for (var/V in D.vars) - names += V - sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. - - var/list/variable_html = list() - if (islist) - var/list/L = D - for (var/i in 1 to L.len) - var/key = L[i] - var/value - if (IS_NORMAL_LIST(L) && !isnum(key)) - value = L[key] - variable_html += debug_variable(i, value, 0, D) - else - - names = sortList(names) - for (var/V in names) - if(D.can_vv_get(V)) - variable_html += D.vv_get_var(V) - - var/html = {" - - - [title] - - - - -
- - - - - -
- - - - -
- [sprite_text] -
- [atomsnowflake.Join()] -
-
-
- [formatted_type] - [marked] - [varedited_line] - [deleted_line] -
-
-
- Refresh -
- -
-
-
-
-
- - E - Edit, tries to determine the variable type by itself.
- C - Change, asks you for the var type first.
- M - Mass modify: changes this variable for all objects of this type.
-
-
- - - - - -
-
- Search: -
-
- -
-
-
    - [variable_html.Join()] -
- - - -"} - src << browse(html, "window=variables[refid];size=475x650") - - -/client/proc/vv_update_display(datum/D, span, content) - src << output("[span]:[content]", "variables[REF(D)].browser:replace_span") - - -#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) -/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) - var/header - if(DA) - if (islist(DA)) - var/index = name - if (value) - name = DA[name] //name is really the index until this line - else - value = DA[name] - header = "
  • (E) (C) (-) " - else - header = "
  • (E) (C) (M) " - else - header = "
  • " - - var/item - if (isnull(value)) - item = "[VV_HTML_ENCODE(name)] = null" - - else if (istext(value)) - item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" - - else if (isicon(value)) - #ifdef VARSICON - var/icon/I = new/icon(value) - var/rnd = rand(1,10000) - var/rname = "tmp[REF(I)][rnd].png" - usr << browse_rsc(I, rname) - item = "[VV_HTML_ENCODE(name)] = ([value]) " - #else - item = "[VV_HTML_ENCODE(name)] = /icon ([value])" - #endif - - else if (isfile(value)) - item = "[VV_HTML_ENCODE(name)] = '[value]'" - - else if (istype(value, /datum)) - var/datum/D = value - if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. - item = "[VV_HTML_ENCODE(name)] [REF(value)] = [D] [D.type]" - else - item = "[VV_HTML_ENCODE(name)] [REF(value)] = [D.type]" - - else if (islist(value)) - var/list/L = value - var/list/items = list() - - if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) - for (var/i in 1 to L.len) - var/key = L[i] - var/val - if (IS_NORMAL_LIST(L) && !isnum(key)) - val = L[key] - if (isnull(val)) // we still want to display non-null false values, such as 0 or "" - val = key - key = i - - items += debug_variable(key, val, level + 1, sanitize = sanitize) - - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " - else - item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" - - else if (name in GLOB.bitfields) - var/list/flags = list() - for (var/i in GLOB.bitfields[name]) - if (value & GLOB.bitfields[name][i]) - flags += i - item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]" - else - item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" - - return "[header][item]
  • " - -#undef VV_HTML_ENCODE - -/client/proc/view_var_Topic(href, href_list, hsrc) - if( (usr.client != src) || !src.holder || !holder.CheckAdminHref(href, href_list)) - return - if(href_list["Vars"]) - debug_variables(locate(href_list["Vars"])) - - else if(href_list["datumrefresh"]) - var/datum/DAT = locate(href_list["datumrefresh"]) - if(!DAT) //can't be an istype() because /client etc aren't datums - return - src.debug_variables(DAT) - - else if(href_list["mob_player_panel"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["mob_player_panel"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.holder.show_player_panel(M) - - else if(href_list["godmode"]) - if(!check_rights(R_ADMIN)) - return - - var/mob/M = locate(href_list["godmode"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_godmode(M) - - else if(href_list["mark_object"]) - if(!check_rights(NONE)) - return - - var/datum/D = locate(href_list["mark_object"]) - if(!istype(D)) - to_chat(usr, "This can only be done to instances of type /datum") - return - - if(holder.marked_datum) - vv_update_display(holder.marked_datum, "marked", "") - holder.marked_datum = D - vv_update_display(D, "marked", VV_MSG_MARKED) - - else if(href_list["proc_call"]) - if(!check_rights(NONE)) - return - - var/T = locate(href_list["proc_call"]) - - if(T) - callproc_datum(T) - - else if(href_list["delete"]) - if(!check_rights(R_DEBUG, 0)) - return - - var/datum/D = locate(href_list["delete"]) - if(!istype(D)) - to_chat(usr, "Unable to locate item!") - admin_delete(D) - if (isturf(D)) // show the turf that took its place - debug_variables(D) - - else if(href_list["osay"]) - if(!check_rights(R_FUN, 0)) - return - usr.client.object_say(locate(href_list["osay"])) - - else if(href_list["regenerateicons"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["regenerateicons"]) in GLOB.mob_list - if(!ismob(M)) - to_chat(usr, "This can only be done to instances of type /mob") - return - M.regenerate_icons() - else if(href_list["expose"]) - if(!check_rights(R_ADMIN, FALSE)) - return - var/thing = locate(href_list["expose"]) - if (!thing) - return - var/value = vv_get_value(VV_CLIENT) - if (value["class"] != VV_CLIENT) - return - var/client/C = value["value"] - if (!C) - return - var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No") - if (prompt != "Yes" || !usr.client) - return - message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a VV window") - log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]") - to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window") - C.debug_variables(thing) - - -//Needs +VAREDIT past this point - - else if(check_rights(R_VAREDIT)) - - - //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). - - if(href_list["rename"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["rename"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN) - if( !new_name || !M ) - return - - message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") - M.fully_replace_character_name(M.real_name,new_name) - vv_update_display(M, "name", new_name) - vv_update_display(M, "real_name", M.real_name || "No real name") - - else if(href_list["varnameedit"] && href_list["datumedit"]) - if(!check_rights(NONE)) - return - - var/datum/D = locate(href_list["datumedit"]) - if(!istype(D, /datum)) - to_chat(usr, "This can only be used on datums") - return - - if (!modify_variables(D, href_list["varnameedit"], 1)) - return - switch(href_list["varnameedit"]) - if("name") - vv_update_display(D, "name", "[D]") - if("dir") - if(isatom(D)) - var/dir = D.vars["dir"] - vv_update_display(D, "dir", dir2text(dir) || dir) - if("ckey") - if(isliving(D)) - vv_update_display(D, "ckey", D.vars["ckey"] || "No ckey") - if("real_name") - if(isliving(D)) - vv_update_display(D, "real_name", D.vars["real_name"] || "No real name") - - else if(href_list["varnamechange"] && href_list["datumchange"]) - if(!check_rights(NONE)) - return - - var/D = locate(href_list["datumchange"]) - if(!istype(D, /datum)) - to_chat(usr, "This can only be used on datums") - return - - modify_variables(D, href_list["varnamechange"], 0) - - else if(href_list["varnamemass"] && href_list["datummass"]) - if(!check_rights(NONE)) - return - - var/datum/D = locate(href_list["datummass"]) - if(!istype(D)) - to_chat(usr, "This can only be used on instances of type /datum") - return - - cmd_mass_modify_object_variables(D, href_list["varnamemass"]) - - else if(href_list["listedit"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listedit"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list(L, null, "list", "contents", index, autodetect_class = TRUE) - - else if(href_list["listchange"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listchange"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list(L, null, "list", "contents", index, autodetect_class = FALSE) - - else if(href_list["listremove"] && href_list["index"]) - var/index = text2num(href_list["index"]) - if (!index) - return - - var/list/L = locate(href_list["listremove"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - var/variable = L[index] - var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No") - if (prompt != "Yes") - return - L.Cut(index, index+1) - log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") - log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") - message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") - - else if(href_list["listadd"]) - var/list/L = locate(href_list["listadd"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - mod_list_add(L, null, "list", "contents") - - else if(href_list["listdupes"]) - var/list/L = locate(href_list["listdupes"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - uniqueList_inplace(L) - log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES") - log_admin("[key_name(src)] modified list's contents: CLEAR DUPES") - message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES") - - else if(href_list["listnulls"]) - var/list/L = locate(href_list["listnulls"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - listclearnulls(L) - log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS") - log_admin("[key_name(src)] modified list's contents: CLEAR NULLS") - message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS") - - else if(href_list["listlen"]) - var/list/L = locate(href_list["listlen"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - var/value = vv_get_value(VV_NUM) - if (value["class"] != VV_NUM) - return - - L.len = value["value"] - log_world("### ListVarEdit by [src]: /list len: [L.len]") - log_admin("[key_name(src)] modified list's len: [L.len]") - message_admins("[key_name_admin(src)] modified list's len: [L.len]") - - else if(href_list["listshuffle"]) - var/list/L = locate(href_list["listshuffle"]) - if (!istype(L)) - to_chat(usr, "This can only be used on instances of type /list") - return - - shuffle_inplace(L) - log_world("### ListVarEdit by [src]: /list contents: SHUFFLE") - log_admin("[key_name(src)] modified list's contents: SHUFFLE") - message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE") - - else if(href_list["give_spell"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["give_spell"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_spell(M) - - else if(href_list["remove_spell"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["remove_spell"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - remove_spell(M) - - else if(href_list["give_disease"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["give_disease"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_disease(M) - - else if(href_list["gib"]) - if(!check_rights(R_FUN)) - return - - var/mob/M = locate(href_list["gib"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_gib(M) - - else if(href_list["build_mode"]) - if(!check_rights(R_BUILDMODE)) - return - - var/mob/M = locate(href_list["build_mode"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - togglebuildmode(M) - - else if(href_list["drop_everything"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["drop_everything"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_admin_drop_everything(M) - - else if(href_list["direct_control"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["direct_control"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(usr.client) - usr.client.cmd_assume_direct_control(M) - - else if(href_list["offer_control"]) - if(!check_rights(NONE)) - return - - var/mob/M = locate(href_list["offer_control"]) in GLOB.mob_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - offer_control(M) - - else if (href_list["modarmor"]) - if(!check_rights(NONE)) - return - - var/obj/O = locate(href_list["modarmor"]) - if(!istype(O)) - to_chat(usr, "This can only be used on instances of type /obj") - return - - var/list/pickerlist = list() - var/list/armorlist = O.armor.getList() - - for (var/i in armorlist) - pickerlist += list(list("value" = armorlist[i], "name" = i)) - - var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) - - if (islist(result)) - if (result["button"] == 2) // If the user pressed the cancel button - return - // text2num conveniently returns a null on invalid values - O.armor = O.armor.setRating(melee = text2num(result["values"]["melee"]),\ - bullet = text2num(result["values"]["bullet"]),\ - laser = text2num(result["values"]["laser"]),\ - energy = text2num(result["values"]["energy"]),\ - bomb = text2num(result["values"]["bomb"]),\ - bio = text2num(result["values"]["bio"]),\ - rad = text2num(result["values"]["rad"]),\ - fire = text2num(result["values"]["fire"]),\ - acid = text2num(result["values"]["acid"])) - log_admin("[key_name(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]") - message_admins("[key_name_admin(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]") - else - return - - else if(href_list["delall"]) - if(!check_rights(R_DEBUG|R_SERVER)) - return - - var/obj/O = locate(href_list["delall"]) - if(!isobj(O)) - to_chat(usr, "This can only be used on instances of type /obj") - return - - var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") - if(action_type == "Cancel" || !action_type) - return - - if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") - return - - if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") - return - - var/O_type = O.type - switch(action_type) - if("Strict type") - var/i = 0 - for(var/obj/Obj in world) - if(Obj.type == O_type) - i++ - qdel(Obj) - CHECK_TICK - if(!i) - to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") - if("Type and subtypes") - var/i = 0 - for(var/obj/Obj in world) - if(istype(Obj,O_type)) - i++ - qdel(Obj) - CHECK_TICK - if(!i) - to_chat(usr, "No objects of this type exist") - return - log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") - - else if(href_list["addreagent"]) - if(!check_rights(NONE)) - return - - var/atom/A = locate(href_list["addreagent"]) - - if(!A.reagents) - var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num - if(amount) - A.create_reagents(amount) - - if(A.reagents) - var/chosen_id - switch(alert(usr, "Choose a method.", "Add Reagents", "Search", "Choose from a list", "I'm feeling lucky")) - if("Search") - var/valid_id - while(!valid_id) - chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text - if(isnull(chosen_id)) //Get me out of here! - break - if(!ispath(text2path(chosen_id))) - chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent))) - if(ispath(chosen_id)) - valid_id = TRUE - else - valid_id = TRUE - if(!valid_id) - to_chat(usr, "A reagent with that ID doesn't exist!") - if("Choose from a list") - chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in subtypesof(/datum/reagent) - if("I'm feeling lucky") - chosen_id = pick(subtypesof(/datum/reagent)) - if(chosen_id) - var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num - if(amount) - A.reagents.add_reagent(chosen_id, amount) - log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") - message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") - - else if(href_list["explode"]) - if(!check_rights(R_FUN)) - return - - var/atom/A = locate(href_list["explode"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_explosion(A) - - else if(href_list["emp"]) - if(!check_rights(R_FUN)) - return - - var/atom/A = locate(href_list["emp"]) - if(!isobj(A) && !ismob(A) && !isturf(A)) - to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") - return - - src.cmd_admin_emp(A) - - else if(href_list["modtransform"]) - if(!check_rights(R_DEBUG)) - return - - var/atom/A = locate(href_list["modtransform"]) - if(!istype(A)) - to_chat(usr, "This can only be done to atoms.") - return - - var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate") - var/matrix/M = A.transform - switch(result) - if("Scale") - var/x = input(usr, "Choose x mod","Transform Mod") as null|num - var/y = input(usr, "Choose y mod","Transform Mod") as null|num - if(!isnull(x) && !isnull(y)) - A.transform = M.Scale(x,y) - if("Translate") - var/x = input(usr, "Choose x mod","Transform Mod") as null|num - var/y = input(usr, "Choose y mod","Transform Mod") as null|num - if(!isnull(x) && !isnull(y)) - A.transform = M.Translate(x,y) - if("Rotate") - var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num - if(!isnull(angle)) - A.transform = M.Turn(angle) - - else if(href_list["rotatedatum"]) - if(!check_rights(NONE)) - return - - var/atom/A = locate(href_list["rotatedatum"]) - if(!istype(A)) - to_chat(usr, "This can only be done to instances of type /atom") - return - - switch(href_list["rotatedir"]) - if("right") - A.setDir(turn(A.dir, -45)) - if("left") - A.setDir(turn(A.dir, 45)) - vv_update_display(A, "dir", dir2text(A.dir)) - - else if(href_list["editorgans"]) - if(!check_rights(NONE)) - return - - var/mob/living/carbon/C = locate(href_list["editorgans"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - manipulate_organs(C) - - else if(href_list["givemartialart"]) - if(!check_rights(NONE)) - return - - var/mob/living/carbon/C = locate(href_list["givemartialart"]) in GLOB.carbon_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - var/list/artpaths = subtypesof(/datum/martial_art) - var/list/artnames = list() - for(var/i in artpaths) - var/datum/martial_art/M = i - artnames[initial(M.name)] = M - - var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in artnames - if(!usr) - return - if(QDELETED(C)) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - var/chosenart = artnames[result] - var/datum/martial_art/MA = new chosenart - MA.teach(C) - - else if(href_list["givetrauma"]) - if(!check_rights(NONE)) - return - - var/mob/living/carbon/C = locate(href_list["givetrauma"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - var/list/traumas = subtypesof(/datum/brain_trauma) - var/result = input(usr, "Choose the brain trauma to apply","Traumatize") as null|anything in traumas - if(!usr) - return - if(QDELETED(C)) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - C.gain_trauma(result) - - else if(href_list["curetraumas"]) - if(!check_rights(NONE)) - return - - var/mob/living/carbon/C = locate(href_list["curetraumas"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - C.cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE) - - else if(href_list["hallucinate"]) - if(!check_rights(NONE)) - return - - var/mob/living/carbon/C = locate(href_list["hallucinate"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - var/list/hallucinations = subtypesof(/datum/hallucination) - var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations - if(!usr) - return - if(QDELETED(C)) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - new result(C, TRUE) - - else if(href_list["makehuman"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/monkey/Mo = locate(href_list["makehuman"]) in GLOB.mob_list - if(!istype(Mo)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!Mo) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("humanone"=href_list["makehuman"])) - - else if(href_list["makemonkey"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["makemonkey"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) - - else if(href_list["makerobot"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["makerobot"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makerobot"=href_list["makerobot"])) - - else if(href_list["makealien"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["makealien"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makealien"=href_list["makealien"])) - - else if(href_list["makeslime"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["makeslime"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeslime"=href_list["makeslime"])) - - else if(href_list["makeai"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/H = locate(href_list["makeai"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") - return - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - holder.Topic(href, list("makeai"=href_list["makeai"])) - - else if(href_list["setspecies"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["setspecies"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list - - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - var/newtype = GLOB.species_list[result] - admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [H] to [result]") - H.set_species(newtype) - - else if(href_list["editbodypart"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/C = locate(href_list["editbodypart"]) in GLOB.mob_list - if(!istype(C)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon") - return - - var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment") - if(!edit_action) - return - var/list/limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - if(edit_action == "augment") - limb_list += BODY_ZONE_CHEST - var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list - - if(!C) - to_chat(usr, "Mob doesn't exist anymore") - return - - if(result) - var/obj/item/bodypart/BP = C.get_bodypart(result) - switch(edit_action) - if("remove") - if(BP) - BP.drop_limb() - else - to_chat(usr, "[C] doesn't have such bodypart.") - if("add") - if(BP) - to_chat(usr, "[C] already has such bodypart.") - else - if(!C.regenerate_limb(result)) - to_chat(usr, "[C] cannot have such bodypart.") - if("augment") - if(ishuman(C)) - if(BP) - BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE) - else - to_chat(usr, "[C] doesn't have such bodypart.") - else - to_chat(usr, "Only humans can be augmented.") - admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [C]") - - - else if(href_list["purrbation"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["purrbation"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - if(!ishumanbasic(H)) - to_chat(usr, "This can only be done to the basic human species at the moment.") - return - - if(!H) - to_chat(usr, "Mob doesn't exist anymore") - return - - var/success = purrbation_toggle(H) - if(success) - to_chat(usr, "Put [H] on purrbation.") - log_admin("[key_name(usr)] has put [key_name(H)] on purrbation.") - var/msg = "[key_name_admin(usr)] has put [key_name(H)] on purrbation." - message_admins(msg) - admin_ticket_log(H, msg) - - else - to_chat(usr, "Removed [H] from purrbation.") - log_admin("[key_name(usr)] has removed [key_name(H)] from purrbation.") - var/msg = "[key_name_admin(usr)] has removed [key_name(H)] from purrbation." - message_admins(msg) - admin_ticket_log(H, msg) - - else if(href_list["adjustDamage"] && href_list["mobToDamage"]) - if(!check_rights(NONE)) - return - - var/mob/living/L = locate(href_list["mobToDamage"]) in GLOB.mob_list - if(!istype(L)) - return - - var/Text = href_list["adjustDamage"] - - var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num - - if(!L) - to_chat(usr, "Mob doesn't exist anymore") - return - - var/newamt - switch(Text) - if("brute") - L.adjustBruteLoss(amount) - newamt = L.getBruteLoss() - if("fire") - L.adjustFireLoss(amount) - newamt = L.getFireLoss() - if("toxin") - L.adjustToxLoss(amount) - newamt = L.getToxLoss() - if("oxygen") - L.adjustOxyLoss(amount) - newamt = L.getOxyLoss() - if("brain") - L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_BRAIN) - if("clone") - L.adjustCloneLoss(amount) - newamt = L.getCloneLoss() - if("stamina") - L.adjustStaminaLoss(amount) - newamt = L.getStaminaLoss() - if("arousal") - L.adjustArousalLoss(amount) - newamt = L.getArousalLoss() - if("heart") - L.adjustOrganLoss(ORGAN_SLOT_HEART, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_HEART) - if("liver") - L.adjustOrganLoss(ORGAN_SLOT_LIVER, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_LIVER) - if("lungs") - L.adjustOrganLoss(ORGAN_SLOT_LUNGS, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_LUNGS) - if("eye_sight") - L.adjustOrganLoss(ORGAN_SLOT_EYES, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_EYES) - if("ears") - L.adjustOrganLoss(ORGAN_SLOT_EARS, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_EARS) - if("stomach") - L.adjustOrganLoss(ORGAN_SLOT_STOMACH, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_STOMACH) - if("tongue") - L.adjustOrganLoss(ORGAN_SLOT_TONGUE, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_TONGUE) - if("appendix") - L.adjustOrganLoss(ORGAN_SLOT_APPENDIX, amount) - newamt = L.getOrganLoss(ORGAN_SLOT_APPENDIX) - else - to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") - return - - if(amount != 0) - log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") - var/msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [L]
    " - message_admins("[msg]") - admin_ticket_log(L, msg) - vv_update_display(L, Text, "[newamt]") - else if(href_list["copyoutfit"]) - if(!check_rights(R_SPAWN)) - return - var/mob/living/carbon/human/H = locate(href_list["copyoutfit"]) in GLOB.carbon_list - if(istype(H)) - H.copy_outfit() - else if(href_list["modquirks"]) - if(!check_rights(R_SPAWN)) - return - - var/mob/living/carbon/human/H = locate(href_list["modquirks"]) in GLOB.mob_list - if(!istype(H)) - to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") - return - - var/list/options = list("Clear"="Clear") - for(var/x in subtypesof(/datum/quirk)) - var/datum/quirk/T = x - var/qname = initial(T.name) - options[H.has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T - - var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in options - if(result) - if(result == "Clear") - for(var/datum/quirk/q in H.roundstart_quirks) - H.remove_quirk(q.type) - else - var/T = options[result] - if(H.has_quirk(T)) - H.remove_quirk(T) - else - H.add_quirk(T,TRUE) +#define VV_MSG_MARKED "
    Marked Object" +#define VV_MSG_EDITED "
    Var Edited" +#define VV_MSG_DELETED "
    Deleted" + +/datum/proc/CanProcCall(procname) + return TRUE + +/datum/proc/can_vv_get(var_name) + return TRUE + +/datum/proc/vv_edit_var(var_name, var_value) //called whenever a var is edited + if(var_name == NAMEOF(src, vars)) + return FALSE + vars[var_name] = var_value + datum_flags |= DF_VAR_EDITED + return TRUE + +/datum/proc/vv_get_var(var_name) + switch(var_name) + if ("vars") + return debug_variable(var_name, list(), 0, src) + return debug_variable(var_name, vars[var_name], 0, src) + +//please call . = ..() first and append to the result, that way parent items are always at the top and child items are further down +//add separaters by doing . += "---" +/datum/proc/vv_get_dropdown() + . = list() + . += "---" + .["Call Proc"] = "?_src_=vars;[HrefToken()];proc_call=[REF(src)]" + .["Mark Object"] = "?_src_=vars;[HrefToken()];mark_object=[REF(src)]" + .["Delete"] = "?_src_=vars;[HrefToken()];delete=[REF(src)]" + .["Show VV To Player"] = "?_src_=vars;[HrefToken(TRUE)];expose=[REF(src)]" + + +/datum/proc/on_reagent_change(changetype) + return + + +/client/proc/debug_variables(datum/D in world) + set category = "Debug" + set name = "View Variables" + //set src in world + var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round. + + if(!usr.client || !usr.client.holder) //The usr vs src abuse in this proc is intentional and must not be changed + to_chat(usr, "You need to be an administrator to access this.") + return + + if(!D) + return + + var/islist = islist(D) + if (!islist && !istype(D)) + return + + var/title = "" + var/refid = REF(D) + var/icon/sprite + var/hash + + var/type = /list + if (!islist) + type = D.type + + + + if(istype(D, /atom)) + var/atom/AT = D + if(AT.icon && AT.icon_state) + sprite = new /icon(AT.icon, AT.icon_state) + hash = md5(AT.icon) + hash = md5(hash + AT.icon_state) + src << browse_rsc(sprite, "vv[hash].png") + + title = "[D] ([REF(D)]) = [type]" + var/formatted_type = replacetext("[type]", "/", "/") + + var/sprite_text + if(sprite) + sprite_text = "" + var/list/atomsnowflake = list() + + if(istype(D, /atom)) + var/atom/A = D + if(isliving(A)) + atomsnowflake += "[D]" + atomsnowflake += "
    << [dir2text(A.dir) || A.dir] >>" + var/mob/living/M = A + atomsnowflake += {" +
    [M.ckey || "No ckey"] / [M.real_name || "No real name"] +
    + BRUTE:[M.getBruteLoss()] + FIRE:[M.getFireLoss()] + TOXIN:[M.getToxLoss()] + OXY:[M.getOxyLoss()] + CLONE:[M.getCloneLoss()] + BRAIN:[M.getOrganLoss(ORGAN_SLOT_BRAIN)] + STAMINA:[M.getStaminaLoss()] + AROUSAL:[M.getArousalLoss()] + "} + if(GLOB.Debug2) + atomsnowflake += {" + HEART:[M.getOrganLoss(ORGAN_SLOT_HEART)] + LIVER:[M.getOrganLoss(ORGAN_SLOT_LIVER)] + LUNGS:[M.getOrganLoss(ORGAN_SLOT_LUNGS)] + EYES:[M.getOrganLoss(ORGAN_SLOT_EYES)] + EARS:[M.getOrganLoss(ORGAN_SLOT_EARS)] + STOMACH:[M.getOrganLoss(ORGAN_SLOT_STOMACH)] + TONGUE:[M.getOrganLoss(ORGAN_SLOT_TONGUE)] + APPENDIX:[M.getOrganLoss(ORGAN_SLOT_APPENDIX)] + "} + atomsnowflake += {" + + "} + else + atomsnowflake += "[D]" + atomsnowflake += "
    << [dir2text(A.dir) || A.dir] >>" + else if("name" in D.vars) + atomsnowflake += "[D]" + else + atomsnowflake += "[formatted_type]" + formatted_type = null + + var/marked + if(holder && holder.marked_datum && holder.marked_datum == D) + marked = VV_MSG_MARKED + var/varedited_line = "" + if(!islist && (D.datum_flags & DF_VAR_EDITED)) + varedited_line = VV_MSG_EDITED + var/deleted_line + if(!islist && D.gc_destroyed) + deleted_line = VV_MSG_DELETED + + var/list/dropdownoptions = list() + if (islist) + dropdownoptions = list( + "---", + "Add Item" = "?_src_=vars;[HrefToken()];listadd=[refid]", + "Remove Nulls" = "?_src_=vars;[HrefToken()];listnulls=[refid]", + "Remove Dupes" = "?_src_=vars;[HrefToken()];listdupes=[refid]", + "Set len" = "?_src_=vars;[HrefToken()];listlen=[refid]", + "Shuffle" = "?_src_=vars;[HrefToken()];listshuffle=[refid]", + "Show VV To Player" = "?_src_=vars;[HrefToken()];expose=[refid]" + ) + else + dropdownoptions = D.vv_get_dropdown() + var/list/dropdownoptions_html = list() + + for (var/name in dropdownoptions) + var/link = dropdownoptions[name] + if (link) + dropdownoptions_html += "" + else + dropdownoptions_html += "" + + var/list/names = list() + if (!islist) + for (var/V in D.vars) + names += V + sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects. + + var/list/variable_html = list() + if (islist) + var/list/L = D + for (var/i in 1 to L.len) + var/key = L[i] + var/value + if (IS_NORMAL_LIST(L) && !isnum(key)) + value = L[key] + variable_html += debug_variable(i, value, 0, D) + else + + names = sortList(names) + for (var/V in names) + if(D.can_vv_get(V)) + variable_html += D.vv_get_var(V) + + var/html = {" + + + [title] + + + + +
    + + + + + +
    + + + + +
    + [sprite_text] +
    + [atomsnowflake.Join()] +
    +
    +
    + [formatted_type] + [marked] + [varedited_line] + [deleted_line] +
    +
    +
    + Refresh +
    + +
    +
    +
    +
    +
    + + E - Edit, tries to determine the variable type by itself.
    + C - Change, asks you for the var type first.
    + M - Mass modify: changes this variable for all objects of this type.
    +
    +
    + + + + + +
    +
    + Search: +
    +
    + +
    +
    +
      + [variable_html.Join()] +
    + + + +"} + src << browse(html, "window=variables[refid];size=475x650") + + +/client/proc/vv_update_display(datum/D, span, content) + src << output("[span]:[content]", "variables[REF(D)].browser:replace_span") + + +#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing ) +/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE) + var/header + if(DA) + if (islist(DA)) + var/index = name + if (value) + name = DA[name] //name is really the index until this line + else + value = DA[name] + header = "
  • (E) (C) (-) " + else + header = "
  • (E) (C) (M) " + else + header = "
  • " + + var/item + if (isnull(value)) + item = "[VV_HTML_ENCODE(name)] = null" + + else if (istext(value)) + item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\"" + + else if (isicon(value)) + #ifdef VARSICON + var/icon/I = new/icon(value) + var/rnd = rand(1,10000) + var/rname = "tmp[REF(I)][rnd].png" + usr << browse_rsc(I, rname) + item = "[VV_HTML_ENCODE(name)] = ([value]) " + #else + item = "[VV_HTML_ENCODE(name)] = /icon ([value])" + #endif + + else if (isfile(value)) + item = "[VV_HTML_ENCODE(name)] = '[value]'" + + else if (istype(value, /datum)) + var/datum/D = value + if ("[D]" != "[D.type]") //if the thing as a name var, lets use it. + item = "[VV_HTML_ENCODE(name)] [REF(value)] = [D] [D.type]" + else + item = "[VV_HTML_ENCODE(name)] [REF(value)] = [D.type]" + + else if (islist(value)) + var/list/L = value + var/list/items = list() + + if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? 50 : 150))) + for (var/i in 1 to L.len) + var/key = L[i] + var/val + if (IS_NORMAL_LIST(L) && !isnum(key)) + val = L[key] + if (isnull(val)) // we still want to display non-null false values, such as 0 or "" + val = key + key = i + + items += debug_variable(key, val, level + 1, sanitize = sanitize) + + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])
      [items.Join()]
    " + else + item = "[VV_HTML_ENCODE(name)] = /list ([L.len])" + + else if (name in GLOB.bitfields) + var/list/flags = list() + for (var/i in GLOB.bitfields[name]) + if (value & GLOB.bitfields[name][i]) + flags += i + item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]" + else + item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]" + + return "[header][item]
  • " + +#undef VV_HTML_ENCODE + +/client/proc/view_var_Topic(href, href_list, hsrc) + if( (usr.client != src) || !src.holder || !holder.CheckAdminHref(href, href_list)) + return + if(href_list["Vars"]) + debug_variables(locate(href_list["Vars"])) + + else if(href_list["datumrefresh"]) + var/datum/DAT = locate(href_list["datumrefresh"]) + if(!DAT) //can't be an istype() because /client etc aren't datums + return + src.debug_variables(DAT) + + else if(href_list["mob_player_panel"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["mob_player_panel"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.holder.show_player_panel(M) + + else if(href_list["godmode"]) + if(!check_rights(R_ADMIN)) + return + + var/mob/M = locate(href_list["godmode"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.cmd_admin_godmode(M) + + else if(href_list["mark_object"]) + if(!check_rights(NONE)) + return + + var/datum/D = locate(href_list["mark_object"]) + if(!istype(D)) + to_chat(usr, "This can only be done to instances of type /datum") + return + + if(holder.marked_datum) + vv_update_display(holder.marked_datum, "marked", "") + holder.marked_datum = D + vv_update_display(D, "marked", VV_MSG_MARKED) + + else if(href_list["proc_call"]) + if(!check_rights(NONE)) + return + + var/T = locate(href_list["proc_call"]) + + if(T) + callproc_datum(T) + + else if(href_list["delete"]) + if(!check_rights(R_DEBUG, 0)) + return + + var/datum/D = locate(href_list["delete"]) + if(!istype(D)) + to_chat(usr, "Unable to locate item!") + admin_delete(D) + if (isturf(D)) // show the turf that took its place + debug_variables(D) + + else if(href_list["osay"]) + if(!check_rights(R_FUN, 0)) + return + usr.client.object_say(locate(href_list["osay"])) + + else if(href_list["regenerateicons"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["regenerateicons"]) in GLOB.mob_list + if(!ismob(M)) + to_chat(usr, "This can only be done to instances of type /mob") + return + M.regenerate_icons() + else if(href_list["expose"]) + if(!check_rights(R_ADMIN, FALSE)) + return + var/thing = locate(href_list["expose"]) + if (!thing) + return + var/value = vv_get_value(VV_CLIENT) + if (value["class"] != VV_CLIENT) + return + var/client/C = value["value"] + if (!C) + return + var/prompt = alert("Do you want to grant [C] access to view this VV window? (they will not be able to edit or change anything nor open nested vv windows unless they themselves are an admin)", "Confirm", "Yes", "No") + if (prompt != "Yes" || !usr.client) + return + message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a VV window") + log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [thing]") + to_chat(C, "[usr.client.holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window") + C.debug_variables(thing) + + +//Needs +VAREDIT past this point + + else if(check_rights(R_VAREDIT)) + + + //~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records). + + if(href_list["rename"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["rename"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN) + if( !new_name || !M ) + return + + message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].") + M.fully_replace_character_name(M.real_name,new_name) + vv_update_display(M, "name", new_name) + vv_update_display(M, "real_name", M.real_name || "No real name") + + else if(href_list["varnameedit"] && href_list["datumedit"]) + if(!check_rights(NONE)) + return + + var/datum/D = locate(href_list["datumedit"]) + if(!istype(D, /datum)) + to_chat(usr, "This can only be used on datums") + return + + if (!modify_variables(D, href_list["varnameedit"], 1)) + return + switch(href_list["varnameedit"]) + if("name") + vv_update_display(D, "name", "[D]") + if("dir") + if(isatom(D)) + var/dir = D.vars["dir"] + vv_update_display(D, "dir", dir2text(dir) || dir) + if("ckey") + if(isliving(D)) + vv_update_display(D, "ckey", D.vars["ckey"] || "No ckey") + if("real_name") + if(isliving(D)) + vv_update_display(D, "real_name", D.vars["real_name"] || "No real name") + + else if(href_list["varnamechange"] && href_list["datumchange"]) + if(!check_rights(NONE)) + return + + var/D = locate(href_list["datumchange"]) + if(!istype(D, /datum)) + to_chat(usr, "This can only be used on datums") + return + + modify_variables(D, href_list["varnamechange"], 0) + + else if(href_list["varnamemass"] && href_list["datummass"]) + if(!check_rights(NONE)) + return + + var/datum/D = locate(href_list["datummass"]) + if(!istype(D)) + to_chat(usr, "This can only be used on instances of type /datum") + return + + cmd_mass_modify_object_variables(D, href_list["varnamemass"]) + + else if(href_list["listedit"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listedit"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list(L, null, "list", "contents", index, autodetect_class = TRUE) + + else if(href_list["listchange"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listchange"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list(L, null, "list", "contents", index, autodetect_class = FALSE) + + else if(href_list["listremove"] && href_list["index"]) + var/index = text2num(href_list["index"]) + if (!index) + return + + var/list/L = locate(href_list["listremove"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + var/variable = L[index] + var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No") + if (prompt != "Yes") + return + L.Cut(index, index+1) + log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]") + log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]") + message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]") + + else if(href_list["listadd"]) + var/list/L = locate(href_list["listadd"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + mod_list_add(L, null, "list", "contents") + + else if(href_list["listdupes"]) + var/list/L = locate(href_list["listdupes"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + uniqueList_inplace(L) + log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES") + log_admin("[key_name(src)] modified list's contents: CLEAR DUPES") + message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES") + + else if(href_list["listnulls"]) + var/list/L = locate(href_list["listnulls"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + listclearnulls(L) + log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS") + log_admin("[key_name(src)] modified list's contents: CLEAR NULLS") + message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS") + + else if(href_list["listlen"]) + var/list/L = locate(href_list["listlen"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + var/value = vv_get_value(VV_NUM) + if (value["class"] != VV_NUM) + return + + L.len = value["value"] + log_world("### ListVarEdit by [src]: /list len: [L.len]") + log_admin("[key_name(src)] modified list's len: [L.len]") + message_admins("[key_name_admin(src)] modified list's len: [L.len]") + + else if(href_list["listshuffle"]) + var/list/L = locate(href_list["listshuffle"]) + if (!istype(L)) + to_chat(usr, "This can only be used on instances of type /list") + return + + shuffle_inplace(L) + log_world("### ListVarEdit by [src]: /list contents: SHUFFLE") + log_admin("[key_name(src)] modified list's contents: SHUFFLE") + message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE") + + else if(href_list["give_spell"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["give_spell"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.give_spell(M) + + else if(href_list["remove_spell"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["remove_spell"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + remove_spell(M) + + else if(href_list["give_disease"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["give_disease"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.give_disease(M) + + else if(href_list["gib"]) + if(!check_rights(R_FUN)) + return + + var/mob/M = locate(href_list["gib"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + src.cmd_admin_gib(M) + + else if(href_list["build_mode"]) + if(!check_rights(R_BUILDMODE)) + return + + var/mob/M = locate(href_list["build_mode"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + togglebuildmode(M) + + else if(href_list["drop_everything"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["drop_everything"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(usr.client) + usr.client.cmd_admin_drop_everything(M) + + else if(href_list["direct_control"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["direct_control"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + + if(usr.client) + usr.client.cmd_assume_direct_control(M) + + else if(href_list["offer_control"]) + if(!check_rights(NONE)) + return + + var/mob/M = locate(href_list["offer_control"]) in GLOB.mob_list + if(!istype(M)) + to_chat(usr, "This can only be used on instances of type /mob") + return + offer_control(M) + + else if (href_list["modarmor"]) + if(!check_rights(NONE)) + return + + var/obj/O = locate(href_list["modarmor"]) + if(!istype(O)) + to_chat(usr, "This can only be used on instances of type /obj") + return + + var/list/pickerlist = list() + var/list/armorlist = O.armor.getList() + + for (var/i in armorlist) + pickerlist += list(list("value" = armorlist[i], "name" = i)) + + var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist) + + if (islist(result)) + if (result["button"] == 2) // If the user pressed the cancel button + return + // text2num conveniently returns a null on invalid values + O.armor = O.armor.setRating(melee = text2num(result["values"]["melee"]),\ + bullet = text2num(result["values"]["bullet"]),\ + laser = text2num(result["values"]["laser"]),\ + energy = text2num(result["values"]["energy"]),\ + bomb = text2num(result["values"]["bomb"]),\ + bio = text2num(result["values"]["bio"]),\ + rad = text2num(result["values"]["rad"]),\ + fire = text2num(result["values"]["fire"]),\ + acid = text2num(result["values"]["acid"])) + log_admin("[key_name(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]") + message_admins("[key_name_admin(usr)] modified the armor on [O] ([O.type]) to melee: [O.armor.melee], bullet: [O.armor.bullet], laser: [O.armor.laser], energy: [O.armor.energy], bomb: [O.armor.bomb], bio: [O.armor.bio], rad: [O.armor.rad], fire: [O.armor.fire], acid: [O.armor.acid]") + else + return + + else if(href_list["delall"]) + if(!check_rights(R_DEBUG|R_SERVER)) + return + + var/obj/O = locate(href_list["delall"]) + if(!isobj(O)) + to_chat(usr, "This can only be used on instances of type /obj") + return + + var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel") + if(action_type == "Cancel" || !action_type) + return + + if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes") + return + + if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes") + return + + var/O_type = O.type + switch(action_type) + if("Strict type") + var/i = 0 + for(var/obj/Obj in world) + if(Obj.type == O_type) + i++ + qdel(Obj) + CHECK_TICK + if(!i) + to_chat(usr, "No objects of this type exist") + return + log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ") + if("Type and subtypes") + var/i = 0 + for(var/obj/Obj in world) + if(istype(Obj,O_type)) + i++ + qdel(Obj) + CHECK_TICK + if(!i) + to_chat(usr, "No objects of this type exist") + return + log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + message_admins("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ") + + else if(href_list["addreagent"]) + if(!check_rights(NONE)) + return + + var/atom/A = locate(href_list["addreagent"]) + + if(!A.reagents) + var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num + if(amount) + A.create_reagents(amount) + + if(A.reagents) + var/chosen_id + switch(alert(usr, "Choose a method.", "Add Reagents", "Search", "Choose from a list", "I'm feeling lucky")) + if("Search") + var/valid_id + while(!valid_id) + chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text + if(isnull(chosen_id)) //Get me out of here! + break + if(!ispath(text2path(chosen_id))) + chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent))) + if(ispath(chosen_id)) + valid_id = TRUE + else + valid_id = TRUE + if(!valid_id) + to_chat(usr, "A reagent with that ID doesn't exist!") + if("Choose from a list") + chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in subtypesof(/datum/reagent) + if("I'm feeling lucky") + chosen_id = pick(subtypesof(/datum/reagent)) + if(chosen_id) + var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num + if(amount) + A.reagents.add_reagent(chosen_id, amount) + log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") + message_admins("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]") + + else if(href_list["explode"]) + if(!check_rights(R_FUN)) + return + + var/atom/A = locate(href_list["explode"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) + to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") + return + + src.cmd_admin_explosion(A) + + else if(href_list["emp"]) + if(!check_rights(R_FUN)) + return + + var/atom/A = locate(href_list["emp"]) + if(!isobj(A) && !ismob(A) && !isturf(A)) + to_chat(usr, "This can only be done to instances of type /obj, /mob and /turf") + return + + src.cmd_admin_emp(A) + + else if(href_list["modtransform"]) + if(!check_rights(R_DEBUG)) + return + + var/atom/A = locate(href_list["modtransform"]) + if(!istype(A)) + to_chat(usr, "This can only be done to atoms.") + return + + var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate") + var/matrix/M = A.transform + switch(result) + if("Scale") + var/x = input(usr, "Choose x mod","Transform Mod") as null|num + var/y = input(usr, "Choose y mod","Transform Mod") as null|num + if(!isnull(x) && !isnull(y)) + A.transform = M.Scale(x,y) + if("Translate") + var/x = input(usr, "Choose x mod","Transform Mod") as null|num + var/y = input(usr, "Choose y mod","Transform Mod") as null|num + if(!isnull(x) && !isnull(y)) + A.transform = M.Translate(x,y) + if("Rotate") + var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num + if(!isnull(angle)) + A.transform = M.Turn(angle) + + else if(href_list["rotatedatum"]) + if(!check_rights(NONE)) + return + + var/atom/A = locate(href_list["rotatedatum"]) + if(!istype(A)) + to_chat(usr, "This can only be done to instances of type /atom") + return + + switch(href_list["rotatedir"]) + if("right") + A.setDir(turn(A.dir, -45)) + if("left") + A.setDir(turn(A.dir, 45)) + vv_update_display(A, "dir", dir2text(A.dir)) + + else if(href_list["editorgans"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["editorgans"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + manipulate_organs(C) + + else if(href_list["givemartialart"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["givemartialart"]) in GLOB.carbon_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/artpaths = subtypesof(/datum/martial_art) + var/list/artnames = list() + for(var/i in artpaths) + var/datum/martial_art/M = i + artnames[initial(M.name)] = M + + var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in artnames + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/chosenart = artnames[result] + var/datum/martial_art/MA = new chosenart + MA.teach(C) + + else if(href_list["givetrauma"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["givetrauma"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/traumas = subtypesof(/datum/brain_trauma) + var/result = input(usr, "Choose the brain trauma to apply","Traumatize") as null|anything in traumas + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + C.gain_trauma(result) + + else if(href_list["curetraumas"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["curetraumas"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + C.cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE) + + else if(href_list["hallucinate"]) + if(!check_rights(NONE)) + return + + var/mob/living/carbon/C = locate(href_list["hallucinate"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/hallucinations = subtypesof(/datum/hallucination) + var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + new result(C, TRUE) + + else if(href_list["makehuman"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/monkey/Mo = locate(href_list["makehuman"]) in GLOB.mob_list + if(!istype(Mo)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/monkey") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!Mo) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("humanone"=href_list["makehuman"])) + + else if(href_list["makemonkey"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["makemonkey"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("monkeyone"=href_list["makemonkey"])) + + else if(href_list["makerobot"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["makerobot"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makerobot"=href_list["makerobot"])) + + else if(href_list["makealien"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["makealien"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makealien"=href_list["makealien"])) + + else if(href_list["makeslime"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["makeslime"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makeslime"=href_list["makeslime"])) + + else if(href_list["makeai"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/H = locate(href_list["makeai"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") + return + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + holder.Topic(href, list("makeai"=href_list["makeai"])) + + else if(href_list["setspecies"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["setspecies"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list + + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/newtype = GLOB.species_list[result] + admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [H] to [result]") + H.set_species(newtype) + + else if(href_list["editbodypart"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/C = locate(href_list["editbodypart"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment") + if(!edit_action) + return + var/list/limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + if(edit_action == "augment") + limb_list += BODY_ZONE_CHEST + var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in limb_list + + if(!C) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/obj/item/bodypart/BP = C.get_bodypart(result) + switch(edit_action) + if("remove") + if(BP) + BP.drop_limb() + else + to_chat(usr, "[C] doesn't have such bodypart.") + if("add") + if(BP) + to_chat(usr, "[C] already has such bodypart.") + else + if(!C.regenerate_limb(result)) + to_chat(usr, "[C] cannot have such bodypart.") + if("augment") + if(ishuman(C)) + if(BP) + BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE) + else + to_chat(usr, "[C] doesn't have such bodypart.") + else + to_chat(usr, "Only humans can be augmented.") + admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [C]") + + + else if(href_list["purrbation"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["purrbation"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + if(!ishumanbasic(H)) + to_chat(usr, "This can only be done to the basic human species at the moment.") + return + + if(!H) + to_chat(usr, "Mob doesn't exist anymore") + return + + var/success = purrbation_toggle(H) + if(success) + to_chat(usr, "Put [H] on purrbation.") + log_admin("[key_name(usr)] has put [key_name(H)] on purrbation.") + var/msg = "[key_name_admin(usr)] has put [key_name(H)] on purrbation." + message_admins(msg) + admin_ticket_log(H, msg) + + else + to_chat(usr, "Removed [H] from purrbation.") + log_admin("[key_name(usr)] has removed [key_name(H)] from purrbation.") + var/msg = "[key_name_admin(usr)] has removed [key_name(H)] from purrbation." + message_admins(msg) + admin_ticket_log(H, msg) + + else if(href_list["adjustDamage"] && href_list["mobToDamage"]) + if(!check_rights(NONE)) + return + + var/mob/living/L = locate(href_list["mobToDamage"]) in GLOB.mob_list + if(!istype(L)) + return + + var/Text = href_list["adjustDamage"] + + var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num + + if(!L) + to_chat(usr, "Mob doesn't exist anymore") + return + + var/newamt + switch(Text) + if("brute") + L.adjustBruteLoss(amount) + newamt = L.getBruteLoss() + if("fire") + L.adjustFireLoss(amount) + newamt = L.getFireLoss() + if("toxin") + L.adjustToxLoss(amount) + newamt = L.getToxLoss() + if("oxygen") + L.adjustOxyLoss(amount) + newamt = L.getOxyLoss() + if("brain") + L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_BRAIN) + if("clone") + L.adjustCloneLoss(amount) + newamt = L.getCloneLoss() + if("stamina") + L.adjustStaminaLoss(amount) + newamt = L.getStaminaLoss() + if("arousal") + L.adjustArousalLoss(amount) + newamt = L.getArousalLoss() + if("heart") + L.adjustOrganLoss(ORGAN_SLOT_HEART, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_HEART) + if("liver") + L.adjustOrganLoss(ORGAN_SLOT_LIVER, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_LIVER) + if("lungs") + L.adjustOrganLoss(ORGAN_SLOT_LUNGS, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_LUNGS) + if("eye_sight") + L.adjustOrganLoss(ORGAN_SLOT_EYES, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_EYES) + if("ears") + L.adjustOrganLoss(ORGAN_SLOT_EARS, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_EARS) + if("stomach") + L.adjustOrganLoss(ORGAN_SLOT_STOMACH, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_STOMACH) + if("tongue") + L.adjustOrganLoss(ORGAN_SLOT_TONGUE, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_TONGUE) + if("appendix") + L.adjustOrganLoss(ORGAN_SLOT_APPENDIX, amount) + newamt = L.getOrganLoss(ORGAN_SLOT_APPENDIX) + else + to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]") + return + + if(amount != 0) + log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ") + var/msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [L]
    " + message_admins("[msg]") + admin_ticket_log(L, msg) + vv_update_display(L, Text, "[newamt]") + else if(href_list["copyoutfit"]) + if(!check_rights(R_SPAWN)) + return + var/mob/living/carbon/human/H = locate(href_list["copyoutfit"]) in GLOB.carbon_list + if(istype(H)) + H.copy_outfit() + else if(href_list["modquirks"]) + if(!check_rights(R_SPAWN)) + return + + var/mob/living/carbon/human/H = locate(href_list["modquirks"]) in GLOB.mob_list + if(!istype(H)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon/human") + return + + var/list/options = list("Clear"="Clear") + for(var/x in subtypesof(/datum/quirk)) + var/datum/quirk/T = x + var/qname = initial(T.name) + options[H.has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T + + var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in options + if(result) + if(result == "Clear") + for(var/datum/quirk/q in H.roundstart_quirks) + H.remove_quirk(q.type) + else + var/T = options[result] + if(H.has_quirk(T)) + H.remove_quirk(T) + else + H.add_quirk(T,TRUE) diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index a844254ef9..6b72f2fdfc 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -1,495 +1,495 @@ -/* - - Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties - which add onto the overall disease. - - If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus. - -*/ - - - - -/* - - PROPERTIES - - */ - -/datum/disease/advance - name = "Unknown" // We will always let our Virologist name our disease. - desc = "An engineered disease which can contain a multitude of symptoms." - form = "Advance Disease" // Will let med-scanners know that this disease was engineered. - agent = "advance microbes" - max_stages = 5 - spread_text = "Unknown" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - - // NEW VARS - var/list/properties = list() - var/list/symptoms = list() // The symptoms of the disease. - var/id = "" - var/processing = FALSE - var/mutable = TRUE //set to FALSE to prevent most in-game methods of altering the disease via virology - var/oldres //To prevent setting new cures unless resistance changes. - - // The order goes from easy to cure to hard to cure. Keep in mind that sentient diseases pick two cures from tier 6 and up, ensure they wont react away in bodies. - var/static/list/advance_cures = list( - list( // level 1 - /datum/reagent/copper, /datum/reagent/silver, /datum/reagent/iodine, /datum/reagent/iron, /datum/reagent/carbon - ), - list( // level 2 - /datum/reagent/potassium, /datum/reagent/consumable/ethanol, /datum/reagent/lithium, - /datum/reagent/silicon, /datum/reagent/bromine - ), - list( // level 3 - /datum/reagent/consumable/sodiumchloride, /datum/reagent/consumable/sugar, /datum/reagent/consumable/orangejuice, - /datum/reagent/consumable/tomatojuice, /datum/reagent/consumable/milk - ), - list( //level 4 - /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, - /datum/reagent/medicine/epinephrine, /datum/reagent/medicine/charcoal - ), - list( //level 5 - /datum/reagent/oil, /datum/reagent/medicine/synaptizine, /datum/reagent/medicine/mannitol, - /datum/reagent/drug/space_drugs, /datum/reagent/cryptobiolin - ), - list( // level 6 - /datum/reagent/phenol, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/oculine, /datum/reagent/medicine/antihol - ), - list( // level 7 - /datum/reagent/medicine/leporazine, /datum/reagent/toxin/mindbreaker, /datum/reagent/medicine/corazone - ), - list( // level 8 - /datum/reagent/pax, /datum/reagent/drug/happiness, /datum/reagent/medicine/ephedrine - ), - list( // level 9 - /datum/reagent/toxin/lipolicide, /datum/reagent/medicine/sal_acid - ), - list( // level 10 - /datum/reagent/medicine/haloperidol, /datum/reagent/drug/aranesp, /datum/reagent/medicine/diphenhydramine - ), - list( //level 11 - /datum/reagent/medicine/modafinil, /datum/reagent/toxin/anacea - ) - ) - -/* - - OLD PROCS - - */ - -/datum/disease/advance/New() - Refresh() - -/datum/disease/advance/Destroy() - if(processing) - for(var/datum/symptom/S in symptoms) - S.End(src) - return ..() - -/datum/disease/advance/try_infect(var/mob/living/infectee, make_copy = TRUE) - //see if we are more transmittable than enough diseases to replace them - //diseases replaced in this way do not confer immunity - var/list/advance_diseases = list() - for(var/datum/disease/advance/P in infectee.diseases) - advance_diseases += P - var/replace_num = advance_diseases.len + 1 - DISEASE_LIMIT //amount of diseases that need to be removed to fit this one - if(replace_num > 0) - sortTim(advance_diseases, /proc/cmp_advdisease_resistance_asc) - for(var/i in 1 to replace_num) - var/datum/disease/advance/competition = advance_diseases[i] - if(totalTransmittable() > competition.totalResistance()) - competition.cure(FALSE) - else - return FALSE //we are not strong enough to bully our way in - infect(infectee, make_copy) - return TRUE - -// Randomly pick a symptom to activate. -/datum/disease/advance/stage_act() - ..() - if(carrier) - return - - if(symptoms && symptoms.len) - if(!processing) - processing = TRUE - for(var/datum/symptom/S in symptoms) - if(S.Start(src)) //this will return FALSE if the symptom is neutered - S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10) - S.on_stage_change(src) - - for(var/datum/symptom/S in symptoms) - S.Activate(src) - -// Tell symptoms stage changed -/datum/disease/advance/update_stage(new_stage) - ..() - for(var/datum/symptom/S in symptoms) - S.on_stage_change(src) - -// Compares type then ID. -/datum/disease/advance/IsSame(datum/disease/advance/D) - - if(!(istype(D, /datum/disease/advance))) - return 0 - - if(GetDiseaseID() != D.GetDiseaseID()) - return 0 - return 1 - -// Returns the advance disease with a different reference memory. -/datum/disease/advance/Copy() - var/datum/disease/advance/A = ..() - QDEL_LIST(A.symptoms) - for(var/datum/symptom/S in symptoms) - A.symptoms += S.Copy() - A.properties = properties.Copy() - A.id = id - A.mutable = mutable - A.oldres = oldres - //this is a new disease starting over at stage 1, so processing is not copied - return A - -//Describe this disease to an admin in detail (for logging) -/datum/disease/advance/admin_details() - var/list/name_symptoms = list() - for(var/datum/symptom/S in symptoms) - name_symptoms += S.name - return "[name] sym:[english_list(name_symptoms)] r:[totalResistance()] s:[totalStealth()] ss:[totalStageSpeed()] t:[totalTransmittable()]" - - -/* - - NEW PROCS - - */ - -// Mix the symptoms of two diseases (the src and the argument) -/datum/disease/advance/proc/Mix(datum/disease/advance/D) - if(!(IsSame(D))) - var/list/possible_symptoms = shuffle(D.symptoms) - for(var/datum/symptom/S in possible_symptoms) - AddSymptom(S.Copy()) - -/datum/disease/advance/proc/HasSymptom(datum/symptom/S) - for(var/datum/symptom/symp in symptoms) - if(symp.type == S.type) - return 1 - return 0 - -// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated. -/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0) - - var/list/generated = list() // Symptoms we generated. - - // Generate symptoms. By default, we only choose non-deadly symptoms. - var/list/possible_symptoms = list() - for(var/symp in SSdisease.list_symptoms) - var/datum/symptom/S = new symp - if(S.naturally_occuring && S.level >= level_min && S.level <= level_max) - if(!HasSymptom(S)) - possible_symptoms += S - - if(!possible_symptoms.len) - return generated - - // Random chance to get more than one symptom - var/number_of = amount_get - if(!amount_get) - number_of = 1 - while(prob(20)) - number_of += 1 - - for(var/i = 1; number_of >= i && possible_symptoms.len; i++) - generated += pick_n_take(possible_symptoms) - - return generated - -/datum/disease/advance/proc/Refresh(new_name = FALSE) - GenerateProperties() - AssignProperties() - if(processing && symptoms && symptoms.len) - for(var/datum/symptom/S in symptoms) - S.Start(src) - S.on_stage_change(src) - id = null - - var/the_id = GetDiseaseID() - if(!SSdisease.archive_diseases[the_id]) - SSdisease.archive_diseases[the_id] = src // So we don't infinite loop - SSdisease.archive_diseases[the_id] = Copy() - if(new_name) - AssignName() - -//Generate disease properties based on the effects. Returns an associated list. -/datum/disease/advance/proc/GenerateProperties() - properties = list("resistance" = 0, "stealth" = 0, "stage_rate" = 0, "transmittable" = 0, "severity" = 0) - - for(var/datum/symptom/S in symptoms) - properties["resistance"] += S.resistance - properties["stealth"] += S.stealth - properties["stage_rate"] += S.stage_speed - properties["transmittable"] += S.transmittable - if(!S.neutered) - properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity non-neutered symptom - -// Assign the properties that are in the list. -/datum/disease/advance/proc/AssignProperties() - - if(properties && properties.len) - if(properties["stealth"] >= 2) - visibility_flags |= HIDDEN_SCANNER - else - visibility_flags &= ~HIDDEN_SCANNER - - SetSpread(CLAMP(2 ** (properties["transmittable"] - symptoms.len), DISEASE_SPREAD_BLOOD, DISEASE_SPREAD_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) - else - CRASH("Our properties were empty or null!") - - -// Assign the spread type and give it the correct description. -/datum/disease/advance/proc/SetSpread(spread_id) - switch(spread_id) - if(DISEASE_SPREAD_NON_CONTAGIOUS) - spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS - spread_text = "None" - if(DISEASE_SPREAD_SPECIAL) - spread_flags = DISEASE_SPREAD_SPECIAL - spread_text = "None" - if(DISEASE_SPREAD_BLOOD) - spread_flags = DISEASE_SPREAD_BLOOD - spread_text = "Blood" - if(DISEASE_SPREAD_CONTACT_FLUIDS) - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS - spread_text = "Fluids" - if(DISEASE_SPREAD_CONTACT_SKIN) - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS | DISEASE_SPREAD_CONTACT_SKIN - spread_text = "On contact" - if(DISEASE_SPREAD_AIRBORNE) - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_AIRBORNE - spread_text = "Airborne" - -/datum/disease/advance/proc/SetSeverity(level_sev) - - switch(level_sev) - - if(-INFINITY to 0) - severity = DISEASE_SEVERITY_POSITIVE - if(1) - severity = DISEASE_SEVERITY_NONTHREAT - if(2) - severity = DISEASE_SEVERITY_MINOR - if(3) - severity = DISEASE_SEVERITY_MEDIUM - if(4) - severity = DISEASE_SEVERITY_HARMFUL - if(5) - severity = DISEASE_SEVERITY_DANGEROUS - if(6 to INFINITY) - severity = DISEASE_SEVERITY_BIOHAZARD - else - severity = "Unknown" - - -// Will generate a random cure, the less resistance the symptoms have, the harder the cure. -/datum/disease/advance/proc/GenerateCure() - if(properties && properties.len) - var/res = CLAMP(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) - if(res == oldres) - return - cures = list(pick(advance_cures[res])) - oldres = res - - // Get the cure name from the cure_id - var/datum/reagent/D = GLOB.chemical_reagents_list[cures[1]] - cure_text = D.name - -// Randomly generate a symptom, has a chance to lose or gain a symptom. -/datum/disease/advance/proc/Evolve(min_level, max_level, ignore_mutable = FALSE) - if(!mutable && !ignore_mutable) - return - var/s = safepick(GenerateSymptoms(min_level, max_level, 1)) - if(s) - AddSymptom(s) - Refresh(TRUE) - return - -// Randomly remove a symptom. -/datum/disease/advance/proc/Devolve(ignore_mutable = FALSE) - if(!mutable && !ignore_mutable) - return - if(symptoms.len > 1) - var/s = safepick(symptoms) - if(s) - RemoveSymptom(s) - Refresh(TRUE) - -// Randomly neuter a symptom. -/datum/disease/advance/proc/Neuter(ignore_mutable = FALSE) - if(!mutable && !ignore_mutable) - return - if(symptoms.len) - var/s = safepick(symptoms) - if(s) - NeuterSymptom(s) - Refresh(TRUE) - -// Name the disease. -/datum/disease/advance/proc/AssignName(name = "Unknown") - Refresh() - var/datum/disease/advance/A = SSdisease.archive_diseases[GetDiseaseID()] - A.name = name - for(var/datum/disease/advance/AD in SSdisease.active_diseases) - AD.Refresh() - -// Return a unique ID of the disease. -/datum/disease/advance/GetDiseaseID() - if(!id) - var/list/L = list() - for(var/datum/symptom/S in symptoms) - if(S.neutered) - L += "[S.id]N" - else - L += S.id - L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in. - var/result = jointext(L, ":") - id = result - return id - - -// Add a symptom, if it is over the limit we take a random symptom away and add the new one. -/datum/disease/advance/proc/AddSymptom(datum/symptom/S) - - if(HasSymptom(S)) - return - - if(!(symptoms.len < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1))) - RemoveSymptom(pick(symptoms)) - symptoms += S - S.OnAdd(src) - -// Simply removes the symptom. -/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S) - symptoms -= S - S.OnRemove(src) - -// Neuter a symptom, so it will only affect stats -/datum/disease/advance/proc/NeuterSymptom(datum/symptom/S) - if(!S.neutered) - S.neutered = TRUE - S.name += " (neutered)" - S.OnRemove(src) - -/* - - Static Procs - -*/ - -// Mix a list of advance diseases and return the mixed result. -/proc/Advance_Mix(var/list/D_list) - var/list/diseases = list() - - for(var/datum/disease/advance/A in D_list) - diseases += A.Copy() - - if(!diseases.len) - return null - if(diseases.len <= 1) - return pick(diseases) // Just return the only entry. - - var/i = 0 - // Mix our diseases until we are left with only one result. - while(i < 20 && diseases.len > 1) - - i++ - - var/datum/disease/advance/D1 = pick(diseases) - diseases -= D1 - - var/datum/disease/advance/D2 = pick(diseases) - D2.Mix(D1) - - // Should be only 1 entry left, but if not let's only return a single entry - var/datum/disease/advance/to_return = pick(diseases) - to_return.Refresh(1) - return to_return - -/proc/SetViruses(datum/reagent/R, list/data) - if(data) - var/list/preserve = list() - if(istype(data) && data["viruses"]) - for(var/datum/disease/A in data["viruses"]) - preserve += A.Copy() - R.data = data.Copy() - if(preserve.len) - R.data["viruses"] = preserve - -/proc/AdminCreateVirus(client/user) - - if(!user) - return - - var/i = VIRUS_SYMPTOM_LIMIT - - var/datum/disease/advance/D = new() - D.symptoms = list() - - var/list/symptoms = list() - symptoms += "Done" - symptoms += SSdisease.list_symptoms.Copy() - do - if(user) - var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms - if(isnull(symptom)) - return - else if(istext(symptom)) - i = 0 - else if(ispath(symptom)) - var/datum/symptom/S = new symptom - if(!D.HasSymptom(S)) - D.symptoms += S - i -= 1 - while(i > 0) - - if(D.symptoms.len > 0) - - var/new_name = stripped_input(user, "Name your new disease.", "New Name") - if(!new_name) - return - D.AssignName(new_name) - D.Refresh() - - for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list)) - if(!is_station_level(H.z)) - continue - if(!H.HasDisease(D)) - H.ForceContractDisease(D) - break - - var/list/name_symptoms = list() - for(var/datum/symptom/S in D.symptoms) - name_symptoms += S.name - message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.admin_details()]") - log_virus("[key_name(user)] has triggered a custom virus outbreak of [D.admin_details()]!") - -/datum/disease/advance/proc/totalStageSpeed() - return properties["stage_rate"] - -/datum/disease/advance/proc/totalStealth() - return properties["stealth"] - -/datum/disease/advance/proc/totalResistance() - return properties["resistance"] - -/datum/disease/advance/proc/totalTransmittable() - return properties["transmittable"] +/* + + Advance Disease is a system for Virologist to Engineer their own disease with symptoms that have effects and properties + which add onto the overall disease. + + If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus. + +*/ + + + + +/* + + PROPERTIES + + */ + +/datum/disease/advance + name = "Unknown" // We will always let our Virologist name our disease. + desc = "An engineered disease which can contain a multitude of symptoms." + form = "Advance Disease" // Will let med-scanners know that this disease was engineered. + agent = "advance microbes" + max_stages = 5 + spread_text = "Unknown" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + + // NEW VARS + var/list/properties = list() + var/list/symptoms = list() // The symptoms of the disease. + var/id = "" + var/processing = FALSE + var/mutable = TRUE //set to FALSE to prevent most in-game methods of altering the disease via virology + var/oldres //To prevent setting new cures unless resistance changes. + + // The order goes from easy to cure to hard to cure. Keep in mind that sentient diseases pick two cures from tier 6 and up, ensure they wont react away in bodies. + var/static/list/advance_cures = list( + list( // level 1 + /datum/reagent/copper, /datum/reagent/silver, /datum/reagent/iodine, /datum/reagent/iron, /datum/reagent/carbon + ), + list( // level 2 + /datum/reagent/potassium, /datum/reagent/consumable/ethanol, /datum/reagent/lithium, + /datum/reagent/silicon, /datum/reagent/bromine + ), + list( // level 3 + /datum/reagent/consumable/sodiumchloride, /datum/reagent/consumable/sugar, /datum/reagent/consumable/orangejuice, + /datum/reagent/consumable/tomatojuice, /datum/reagent/consumable/milk + ), + list( //level 4 + /datum/reagent/medicine/spaceacillin, /datum/reagent/medicine/salglu_solution, + /datum/reagent/medicine/epinephrine, /datum/reagent/medicine/charcoal + ), + list( //level 5 + /datum/reagent/oil, /datum/reagent/medicine/synaptizine, /datum/reagent/medicine/mannitol, + /datum/reagent/drug/space_drugs, /datum/reagent/cryptobiolin + ), + list( // level 6 + /datum/reagent/phenol, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/oculine, /datum/reagent/medicine/antihol + ), + list( // level 7 + /datum/reagent/medicine/leporazine, /datum/reagent/toxin/mindbreaker, /datum/reagent/medicine/corazone + ), + list( // level 8 + /datum/reagent/pax, /datum/reagent/drug/happiness, /datum/reagent/medicine/ephedrine + ), + list( // level 9 + /datum/reagent/toxin/lipolicide, /datum/reagent/medicine/sal_acid + ), + list( // level 10 + /datum/reagent/medicine/haloperidol, /datum/reagent/drug/aranesp, /datum/reagent/medicine/diphenhydramine + ), + list( //level 11 + /datum/reagent/medicine/modafinil, /datum/reagent/toxin/anacea + ) + ) + +/* + + OLD PROCS + + */ + +/datum/disease/advance/New() + Refresh() + +/datum/disease/advance/Destroy() + if(processing) + for(var/datum/symptom/S in symptoms) + S.End(src) + return ..() + +/datum/disease/advance/try_infect(var/mob/living/infectee, make_copy = TRUE) + //see if we are more transmittable than enough diseases to replace them + //diseases replaced in this way do not confer immunity + var/list/advance_diseases = list() + for(var/datum/disease/advance/P in infectee.diseases) + advance_diseases += P + var/replace_num = advance_diseases.len + 1 - DISEASE_LIMIT //amount of diseases that need to be removed to fit this one + if(replace_num > 0) + sortTim(advance_diseases, /proc/cmp_advdisease_resistance_asc) + for(var/i in 1 to replace_num) + var/datum/disease/advance/competition = advance_diseases[i] + if(totalTransmittable() > competition.totalResistance()) + competition.cure(FALSE) + else + return FALSE //we are not strong enough to bully our way in + infect(infectee, make_copy) + return TRUE + +// Randomly pick a symptom to activate. +/datum/disease/advance/stage_act() + ..() + if(carrier) + return + + if(symptoms && symptoms.len) + if(!processing) + processing = TRUE + for(var/datum/symptom/S in symptoms) + if(S.Start(src)) //this will return FALSE if the symptom is neutered + S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10) + S.on_stage_change(src) + + for(var/datum/symptom/S in symptoms) + S.Activate(src) + +// Tell symptoms stage changed +/datum/disease/advance/update_stage(new_stage) + ..() + for(var/datum/symptom/S in symptoms) + S.on_stage_change(src) + +// Compares type then ID. +/datum/disease/advance/IsSame(datum/disease/advance/D) + + if(!(istype(D, /datum/disease/advance))) + return 0 + + if(GetDiseaseID() != D.GetDiseaseID()) + return 0 + return 1 + +// Returns the advance disease with a different reference memory. +/datum/disease/advance/Copy() + var/datum/disease/advance/A = ..() + QDEL_LIST(A.symptoms) + for(var/datum/symptom/S in symptoms) + A.symptoms += S.Copy() + A.properties = properties.Copy() + A.id = id + A.mutable = mutable + A.oldres = oldres + //this is a new disease starting over at stage 1, so processing is not copied + return A + +//Describe this disease to an admin in detail (for logging) +/datum/disease/advance/admin_details() + var/list/name_symptoms = list() + for(var/datum/symptom/S in symptoms) + name_symptoms += S.name + return "[name] sym:[english_list(name_symptoms)] r:[totalResistance()] s:[totalStealth()] ss:[totalStageSpeed()] t:[totalTransmittable()]" + + +/* + + NEW PROCS + + */ + +// Mix the symptoms of two diseases (the src and the argument) +/datum/disease/advance/proc/Mix(datum/disease/advance/D) + if(!(IsSame(D))) + var/list/possible_symptoms = shuffle(D.symptoms) + for(var/datum/symptom/S in possible_symptoms) + AddSymptom(S.Copy()) + +/datum/disease/advance/proc/HasSymptom(datum/symptom/S) + for(var/datum/symptom/symp in symptoms) + if(symp.type == S.type) + return 1 + return 0 + +// Will generate new unique symptoms, use this if there are none. Returns a list of symptoms that were generated. +/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0) + + var/list/generated = list() // Symptoms we generated. + + // Generate symptoms. By default, we only choose non-deadly symptoms. + var/list/possible_symptoms = list() + for(var/symp in SSdisease.list_symptoms) + var/datum/symptom/S = new symp + if(S.naturally_occuring && S.level >= level_min && S.level <= level_max) + if(!HasSymptom(S)) + possible_symptoms += S + + if(!possible_symptoms.len) + return generated + + // Random chance to get more than one symptom + var/number_of = amount_get + if(!amount_get) + number_of = 1 + while(prob(20)) + number_of += 1 + + for(var/i = 1; number_of >= i && possible_symptoms.len; i++) + generated += pick_n_take(possible_symptoms) + + return generated + +/datum/disease/advance/proc/Refresh(new_name = FALSE) + GenerateProperties() + AssignProperties() + if(processing && symptoms && symptoms.len) + for(var/datum/symptom/S in symptoms) + S.Start(src) + S.on_stage_change(src) + id = null + + var/the_id = GetDiseaseID() + if(!SSdisease.archive_diseases[the_id]) + SSdisease.archive_diseases[the_id] = src // So we don't infinite loop + SSdisease.archive_diseases[the_id] = Copy() + if(new_name) + AssignName() + +//Generate disease properties based on the effects. Returns an associated list. +/datum/disease/advance/proc/GenerateProperties() + properties = list("resistance" = 0, "stealth" = 0, "stage_rate" = 0, "transmittable" = 0, "severity" = 0) + + for(var/datum/symptom/S in symptoms) + properties["resistance"] += S.resistance + properties["stealth"] += S.stealth + properties["stage_rate"] += S.stage_speed + properties["transmittable"] += S.transmittable + if(!S.neutered) + properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity non-neutered symptom + +// Assign the properties that are in the list. +/datum/disease/advance/proc/AssignProperties() + + if(properties && properties.len) + if(properties["stealth"] >= 2) + visibility_flags |= HIDDEN_SCANNER + else + visibility_flags &= ~HIDDEN_SCANNER + + SetSpread(CLAMP(2 ** (properties["transmittable"] - symptoms.len), DISEASE_SPREAD_BLOOD, DISEASE_SPREAD_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) + else + CRASH("Our properties were empty or null!") + + +// Assign the spread type and give it the correct description. +/datum/disease/advance/proc/SetSpread(spread_id) + switch(spread_id) + if(DISEASE_SPREAD_NON_CONTAGIOUS) + spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS + spread_text = "None" + if(DISEASE_SPREAD_SPECIAL) + spread_flags = DISEASE_SPREAD_SPECIAL + spread_text = "None" + if(DISEASE_SPREAD_BLOOD) + spread_flags = DISEASE_SPREAD_BLOOD + spread_text = "Blood" + if(DISEASE_SPREAD_CONTACT_FLUIDS) + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS + spread_text = "Fluids" + if(DISEASE_SPREAD_CONTACT_SKIN) + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS | DISEASE_SPREAD_CONTACT_SKIN + spread_text = "On contact" + if(DISEASE_SPREAD_AIRBORNE) + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_FLUIDS | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_AIRBORNE + spread_text = "Airborne" + +/datum/disease/advance/proc/SetSeverity(level_sev) + + switch(level_sev) + + if(-INFINITY to 0) + severity = DISEASE_SEVERITY_POSITIVE + if(1) + severity = DISEASE_SEVERITY_NONTHREAT + if(2) + severity = DISEASE_SEVERITY_MINOR + if(3) + severity = DISEASE_SEVERITY_MEDIUM + if(4) + severity = DISEASE_SEVERITY_HARMFUL + if(5) + severity = DISEASE_SEVERITY_DANGEROUS + if(6 to INFINITY) + severity = DISEASE_SEVERITY_BIOHAZARD + else + severity = "Unknown" + + +// Will generate a random cure, the less resistance the symptoms have, the harder the cure. +/datum/disease/advance/proc/GenerateCure() + if(properties && properties.len) + var/res = CLAMP(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) + if(res == oldres) + return + cures = list(pick(advance_cures[res])) + oldres = res + + // Get the cure name from the cure_id + var/datum/reagent/D = GLOB.chemical_reagents_list[cures[1]] + cure_text = D.name + +// Randomly generate a symptom, has a chance to lose or gain a symptom. +/datum/disease/advance/proc/Evolve(min_level, max_level, ignore_mutable = FALSE) + if(!mutable && !ignore_mutable) + return + var/s = safepick(GenerateSymptoms(min_level, max_level, 1)) + if(s) + AddSymptom(s) + Refresh(TRUE) + return + +// Randomly remove a symptom. +/datum/disease/advance/proc/Devolve(ignore_mutable = FALSE) + if(!mutable && !ignore_mutable) + return + if(symptoms.len > 1) + var/s = safepick(symptoms) + if(s) + RemoveSymptom(s) + Refresh(TRUE) + +// Randomly neuter a symptom. +/datum/disease/advance/proc/Neuter(ignore_mutable = FALSE) + if(!mutable && !ignore_mutable) + return + if(symptoms.len) + var/s = safepick(symptoms) + if(s) + NeuterSymptom(s) + Refresh(TRUE) + +// Name the disease. +/datum/disease/advance/proc/AssignName(name = "Unknown") + Refresh() + var/datum/disease/advance/A = SSdisease.archive_diseases[GetDiseaseID()] + A.name = name + for(var/datum/disease/advance/AD in SSdisease.active_diseases) + AD.Refresh() + +// Return a unique ID of the disease. +/datum/disease/advance/GetDiseaseID() + if(!id) + var/list/L = list() + for(var/datum/symptom/S in symptoms) + if(S.neutered) + L += "[S.id]N" + else + L += S.id + L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in. + var/result = jointext(L, ":") + id = result + return id + + +// Add a symptom, if it is over the limit we take a random symptom away and add the new one. +/datum/disease/advance/proc/AddSymptom(datum/symptom/S) + + if(HasSymptom(S)) + return + + if(!(symptoms.len < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1))) + RemoveSymptom(pick(symptoms)) + symptoms += S + S.OnAdd(src) + +// Simply removes the symptom. +/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S) + symptoms -= S + S.OnRemove(src) + +// Neuter a symptom, so it will only affect stats +/datum/disease/advance/proc/NeuterSymptom(datum/symptom/S) + if(!S.neutered) + S.neutered = TRUE + S.name += " (neutered)" + S.OnRemove(src) + +/* + + Static Procs + +*/ + +// Mix a list of advance diseases and return the mixed result. +/proc/Advance_Mix(var/list/D_list) + var/list/diseases = list() + + for(var/datum/disease/advance/A in D_list) + diseases += A.Copy() + + if(!diseases.len) + return null + if(diseases.len <= 1) + return pick(diseases) // Just return the only entry. + + var/i = 0 + // Mix our diseases until we are left with only one result. + while(i < 20 && diseases.len > 1) + + i++ + + var/datum/disease/advance/D1 = pick(diseases) + diseases -= D1 + + var/datum/disease/advance/D2 = pick(diseases) + D2.Mix(D1) + + // Should be only 1 entry left, but if not let's only return a single entry + var/datum/disease/advance/to_return = pick(diseases) + to_return.Refresh(1) + return to_return + +/proc/SetViruses(datum/reagent/R, list/data) + if(data) + var/list/preserve = list() + if(istype(data) && data["viruses"]) + for(var/datum/disease/A in data["viruses"]) + preserve += A.Copy() + R.data = data.Copy() + if(preserve.len) + R.data["viruses"] = preserve + +/proc/AdminCreateVirus(client/user) + + if(!user) + return + + var/i = VIRUS_SYMPTOM_LIMIT + + var/datum/disease/advance/D = new() + D.symptoms = list() + + var/list/symptoms = list() + symptoms += "Done" + symptoms += SSdisease.list_symptoms.Copy() + do + if(user) + var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms + if(isnull(symptom)) + return + else if(istext(symptom)) + i = 0 + else if(ispath(symptom)) + var/datum/symptom/S = new symptom + if(!D.HasSymptom(S)) + D.symptoms += S + i -= 1 + while(i > 0) + + if(D.symptoms.len > 0) + + var/new_name = stripped_input(user, "Name your new disease.", "New Name") + if(!new_name) + return + D.AssignName(new_name) + D.Refresh() + + for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list)) + if(!is_station_level(H.z)) + continue + if(!H.HasDisease(D)) + H.ForceContractDisease(D) + break + + var/list/name_symptoms = list() + for(var/datum/symptom/S in D.symptoms) + name_symptoms += S.name + message_admins("[key_name_admin(user)] has triggered a custom virus outbreak of [D.admin_details()]") + log_virus("[key_name(user)] has triggered a custom virus outbreak of [D.admin_details()]!") + +/datum/disease/advance/proc/totalStageSpeed() + return properties["stage_rate"] + +/datum/disease/advance/proc/totalStealth() + return properties["stealth"] + +/datum/disease/advance/proc/totalResistance() + return properties["resistance"] + +/datum/disease/advance/proc/totalTransmittable() + return properties["transmittable"] diff --git a/code/datums/diseases/advance/presets.dm b/code/datums/diseases/advance/presets.dm index d2c4b1983f..68c3ceffea 100644 --- a/code/datums/diseases/advance/presets.dm +++ b/code/datums/diseases/advance/presets.dm @@ -1,42 +1,42 @@ -// Cold -/datum/disease/advance/cold - copy_type = /datum/disease/advance - -/datum/disease/advance/cold/New() - name = "Cold" - symptoms = list(new/datum/symptom/sneeze) - ..() - -// Flu -/datum/disease/advance/flu - copy_type = /datum/disease/advance - -/datum/disease/advance/flu/New() - name = "Flu" - symptoms = list(new/datum/symptom/cough) - ..() - -//Randomly generated Disease, for virus crates and events -/datum/disease/advance/random - name = "Experimental Disease" - copy_type = /datum/disease/advance - -/datum/disease/advance/random/New(max_symptoms, max_level = 8) - if(!max_symptoms) - max_symptoms = rand(1, VIRUS_SYMPTOM_LIMIT) - var/list/datum/symptom/possible_symptoms = list() - for(var/symptom in subtypesof(/datum/symptom)) - var/datum/symptom/S = symptom - if(initial(S.level) > max_level) - continue - if(initial(S.level) <= 0) //unobtainable symptoms - continue - possible_symptoms += S - for(var/i in 1 to max_symptoms) - var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) - if(chosen_symptom) - var/datum/symptom/S = new chosen_symptom - symptoms += S - Refresh() - +// Cold +/datum/disease/advance/cold + copy_type = /datum/disease/advance + +/datum/disease/advance/cold/New() + name = "Cold" + symptoms = list(new/datum/symptom/sneeze) + ..() + +// Flu +/datum/disease/advance/flu + copy_type = /datum/disease/advance + +/datum/disease/advance/flu/New() + name = "Flu" + symptoms = list(new/datum/symptom/cough) + ..() + +//Randomly generated Disease, for virus crates and events +/datum/disease/advance/random + name = "Experimental Disease" + copy_type = /datum/disease/advance + +/datum/disease/advance/random/New(max_symptoms, max_level = 8) + if(!max_symptoms) + max_symptoms = rand(1, VIRUS_SYMPTOM_LIMIT) + var/list/datum/symptom/possible_symptoms = list() + for(var/symptom in subtypesof(/datum/symptom)) + var/datum/symptom/S = symptom + if(initial(S.level) > max_level) + continue + if(initial(S.level) <= 0) //unobtainable symptoms + continue + possible_symptoms += S + for(var/i in 1 to max_symptoms) + var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms) + if(chosen_symptom) + var/datum/symptom/S = new chosen_symptom + symptoms += S + Refresh() + name = "Sample #[rand(1,10000)]" \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index 6b26183828..d404c95ab6 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -1,51 +1,51 @@ -/* -////////////////////////////////////// -Facial Hypertrichosis - - No change to stealth. - Increases resistance. - Increases speed. - Slighlty increases transmittability - Intense Level. - -BONUS - Makes the mob grow a massive beard, regardless of gender. - -////////////////////////////////////// -*/ - -/datum/symptom/beard - - name = "Facial Hypertrichosis" - desc = "The virus increases hair production significantly, causing rapid beard growth." - stealth = 0 - resistance = 3 - stage_speed = 2 - transmittable = 1 - level = 4 - severity = 1 - symptom_delay_min = 18 - symptom_delay_max = 36 - -/datum/symptom/beard/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - if(ishuman(M)) - var/mob/living/carbon/human/H = M - switch(A.stage) - if(1, 2) - to_chat(H, "Your chin itches.") - if(H.facial_hair_style == "Shaved") - H.facial_hair_style = "Jensen Beard" - H.update_hair() - if(3, 4) - to_chat(H, "You feel tough.") - if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard") && !(H.facial_hair_style == "Full Beard")) - H.facial_hair_style = "Full Beard" - H.update_hair() - else - to_chat(H, "You feel manly!") - if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard")) - H.facial_hair_style = pick("Dwarf Beard", "Very Long Beard") - H.update_hair() +/* +////////////////////////////////////// +Facial Hypertrichosis + + No change to stealth. + Increases resistance. + Increases speed. + Slighlty increases transmittability + Intense Level. + +BONUS + Makes the mob grow a massive beard, regardless of gender. + +////////////////////////////////////// +*/ + +/datum/symptom/beard + + name = "Facial Hypertrichosis" + desc = "The virus increases hair production significantly, causing rapid beard growth." + stealth = 0 + resistance = 3 + stage_speed = 2 + transmittable = 1 + level = 4 + severity = 1 + symptom_delay_min = 18 + symptom_delay_max = 36 + +/datum/symptom/beard/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + if(ishuman(M)) + var/mob/living/carbon/human/H = M + switch(A.stage) + if(1, 2) + to_chat(H, "Your chin itches.") + if(H.facial_hair_style == "Shaved") + H.facial_hair_style = "Jensen Beard" + H.update_hair() + if(3, 4) + to_chat(H, "You feel tough.") + if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard") && !(H.facial_hair_style == "Full Beard")) + H.facial_hair_style = "Full Beard" + H.update_hair() + else + to_chat(H, "You feel manly!") + if(!(H.facial_hair_style == "Dwarf Beard") && !(H.facial_hair_style == "Very Long Beard")) + H.facial_hair_style = pick("Dwarf Beard", "Very Long Beard") + H.update_hair() diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm index 069c62cf3f..559d8f4754 100644 --- a/code/datums/diseases/advance/symptoms/choking.dm +++ b/code/datums/diseases/advance/symptoms/choking.dm @@ -1,148 +1,148 @@ -/* -////////////////////////////////////// - -Choking - - Very very noticable. - Lowers resistance. - Decreases stage speed. - Decreases transmittablity tremendously. - Moderate Level. - -Bonus - Inflicts spikes of oxyloss - -////////////////////////////////////// -*/ - -/datum/symptom/choking - - name = "Choking" - desc = "The virus causes inflammation of the host's air conduits, leading to intermittent choking." - stealth = -3 - resistance = -2 - stage_speed = -2 - transmittable = -4 - level = 3 - severity = 3 - base_message_chance = 15 - symptom_delay_min = 10 - symptom_delay_max = 30 - threshold_desc = "Stage Speed 8: Causes choking more frequently.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/choking/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 8) - symptom_delay_min = 7 - symptom_delay_max = 24 - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - -/datum/symptom/choking/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]") - if(3, 4) - if(!suppress_warning) - to_chat(M, "[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]") - else - to_chat(M, "You feel very [pick("dizzy","woozy","faint")].") //fake bloodloss messages - Choke_stage_3_4(M, A) - M.emote("gasp") - else - to_chat(M, "[pick("You're choking!", "You can't breathe!")]") - Choke(M, A) - M.emote("gasp") - -/datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A) - M.adjustOxyLoss(rand(6,13)) - return 1 - -/datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A) - M.adjustOxyLoss(rand(10,18)) - return 1 - -/* -////////////////////////////////////// - -Asphyxiation - - Very very noticable. - Decreases stage speed. - Decreases transmittablity. - -Bonus - Inflicts large spikes of oxyloss - Introduces Asphyxiating drugs to the system - Causes cardiac arrest on dying victims. - -////////////////////////////////////// -*/ - -/datum/symptom/asphyxiation - - name = "Acute respiratory distress syndrome" - desc = "The virus causes shrinking of the host's lungs, causing severe asphyxiation. May also lead to heart attacks." - stealth = -2 - resistance = -0 - stage_speed = -1 - transmittable = -2 - level = 7 - severity = 6 - base_message_chance = 15 - symptom_delay_min = 14 - symptom_delay_max = 30 - var/paralysis = FALSE - threshold_desc = "Stage Speed 8: Additionally synthesizes pancuronium and sodium thiopental inside the host.
    \ - Transmission 8: Doubles the damage caused by the symptom." - - -/datum/symptom/asphyxiation/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 8) - paralysis = TRUE - if(A.properties["transmittable"] >= 8) - power = 2 - -/datum/symptom/asphyxiation/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(3, 4) - to_chat(M, "[pick("Your windpipe feels thin.", "Your lungs feel small.")]") - Asphyxiate_stage_3_4(M, A) - M.emote("gasp") - if(5) - to_chat(M, "[pick("Your lungs hurt!", "It hurts to breathe!")]") - Asphyxiate(M, A) - M.emote("gasp") - if(M.getOxyLoss() >= 120) - M.visible_message("[M] stops breathing, as if their lungs have totally collapsed!") - Asphyxiate_death(M, A) - return - -/datum/symptom/asphyxiation/proc/Asphyxiate_stage_3_4(mob/living/M, datum/disease/advance/A) - var/get_damage = rand(10,15) * power - M.adjustOxyLoss(get_damage) - return 1 - -/datum/symptom/asphyxiation/proc/Asphyxiate(mob/living/M, datum/disease/advance/A) - var/get_damage = rand(15,21) * power - M.adjustOxyLoss(get_damage) - if(paralysis) - M.reagents.add_reagent_list(list(/datum/reagent/toxin/pancuronium = 3, /datum/reagent/toxin/sodium_thiopental = 3)) - return 1 - -/datum/symptom/asphyxiation/proc/Asphyxiate_death(mob/living/M, datum/disease/advance/A) - var/get_damage = rand(25,35) * power - M.adjustOxyLoss(get_damage) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, get_damage/2) - return 1 +/* +////////////////////////////////////// + +Choking + + Very very noticable. + Lowers resistance. + Decreases stage speed. + Decreases transmittablity tremendously. + Moderate Level. + +Bonus + Inflicts spikes of oxyloss + +////////////////////////////////////// +*/ + +/datum/symptom/choking + + name = "Choking" + desc = "The virus causes inflammation of the host's air conduits, leading to intermittent choking." + stealth = -3 + resistance = -2 + stage_speed = -2 + transmittable = -4 + level = 3 + severity = 3 + base_message_chance = 15 + symptom_delay_min = 10 + symptom_delay_max = 30 + threshold_desc = "Stage Speed 8: Causes choking more frequently.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/choking/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 8) + symptom_delay_min = 7 + symptom_delay_max = 24 + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + +/datum/symptom/choking/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You're having difficulty breathing.", "Your breathing becomes heavy.")]") + if(3, 4) + if(!suppress_warning) + to_chat(M, "[pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")]") + else + to_chat(M, "You feel very [pick("dizzy","woozy","faint")].") //fake bloodloss messages + Choke_stage_3_4(M, A) + M.emote("gasp") + else + to_chat(M, "[pick("You're choking!", "You can't breathe!")]") + Choke(M, A) + M.emote("gasp") + +/datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A) + M.adjustOxyLoss(rand(6,13)) + return 1 + +/datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A) + M.adjustOxyLoss(rand(10,18)) + return 1 + +/* +////////////////////////////////////// + +Asphyxiation + + Very very noticable. + Decreases stage speed. + Decreases transmittablity. + +Bonus + Inflicts large spikes of oxyloss + Introduces Asphyxiating drugs to the system + Causes cardiac arrest on dying victims. + +////////////////////////////////////// +*/ + +/datum/symptom/asphyxiation + + name = "Acute respiratory distress syndrome" + desc = "The virus causes shrinking of the host's lungs, causing severe asphyxiation. May also lead to heart attacks." + stealth = -2 + resistance = -0 + stage_speed = -1 + transmittable = -2 + level = 7 + severity = 6 + base_message_chance = 15 + symptom_delay_min = 14 + symptom_delay_max = 30 + var/paralysis = FALSE + threshold_desc = "Stage Speed 8: Additionally synthesizes pancuronium and sodium thiopental inside the host.
    \ + Transmission 8: Doubles the damage caused by the symptom." + + +/datum/symptom/asphyxiation/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 8) + paralysis = TRUE + if(A.properties["transmittable"] >= 8) + power = 2 + +/datum/symptom/asphyxiation/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(3, 4) + to_chat(M, "[pick("Your windpipe feels thin.", "Your lungs feel small.")]") + Asphyxiate_stage_3_4(M, A) + M.emote("gasp") + if(5) + to_chat(M, "[pick("Your lungs hurt!", "It hurts to breathe!")]") + Asphyxiate(M, A) + M.emote("gasp") + if(M.getOxyLoss() >= 120) + M.visible_message("[M] stops breathing, as if their lungs have totally collapsed!") + Asphyxiate_death(M, A) + return + +/datum/symptom/asphyxiation/proc/Asphyxiate_stage_3_4(mob/living/M, datum/disease/advance/A) + var/get_damage = rand(10,15) * power + M.adjustOxyLoss(get_damage) + return 1 + +/datum/symptom/asphyxiation/proc/Asphyxiate(mob/living/M, datum/disease/advance/A) + var/get_damage = rand(15,21) * power + M.adjustOxyLoss(get_damage) + if(paralysis) + M.reagents.add_reagent_list(list(/datum/reagent/toxin/pancuronium = 3, /datum/reagent/toxin/sodium_thiopental = 3)) + return 1 + +/datum/symptom/asphyxiation/proc/Asphyxiate_death(mob/living/M, datum/disease/advance/A) + var/get_damage = rand(25,35) * power + M.adjustOxyLoss(get_damage) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, get_damage/2) + return 1 diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index 260c6888d7..eb6c5342f9 100644 --- a/code/datums/diseases/advance/symptoms/confusion.dm +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -1,61 +1,61 @@ -/* -////////////////////////////////////// - -Confusion - - Little bit hidden. - Lowers resistance. - Decreases stage speed. - Not very transmissibile. - Intense Level. - -Bonus - Makes the affected mob be confused for short periods of time. - -////////////////////////////////////// -*/ - -/datum/symptom/confusion - - name = "Confusion" - desc = "The virus interferes with the proper function of the neural system, leading to bouts of confusion and erratic movement." - stealth = 1 - resistance = -1 - stage_speed = -3 - transmittable = 0 - level = 4 - severity = 2 - base_message_chance = 25 - symptom_delay_min = 10 - symptom_delay_max = 30 - var/brain_damage = FALSE - threshold_desc = "Resistance 6: Causes brain damage over time.
    \ - Transmission 6: Increases confusion duration.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/confusion/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["resistance"] >= 6) - brain_damage = TRUE - if(A.properties["transmittable"] >= 6) - power = 1.5 - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - -/datum/symptom/confusion/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("Your head hurts.", "Your mind blanks for a moment.")]") - else - to_chat(M, "You can't think straight!") - M.confused = min(100 * power, M.confused + 8) - if(brain_damage) - M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3 * power, 80) - M.updatehealth() - - return +/* +////////////////////////////////////// + +Confusion + + Little bit hidden. + Lowers resistance. + Decreases stage speed. + Not very transmissibile. + Intense Level. + +Bonus + Makes the affected mob be confused for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/confusion + + name = "Confusion" + desc = "The virus interferes with the proper function of the neural system, leading to bouts of confusion and erratic movement." + stealth = 1 + resistance = -1 + stage_speed = -3 + transmittable = 0 + level = 4 + severity = 2 + base_message_chance = 25 + symptom_delay_min = 10 + symptom_delay_max = 30 + var/brain_damage = FALSE + threshold_desc = "Resistance 6: Causes brain damage over time.
    \ + Transmission 6: Increases confusion duration.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/confusion/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["resistance"] >= 6) + brain_damage = TRUE + if(A.properties["transmittable"] >= 6) + power = 1.5 + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + +/datum/symptom/confusion/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("Your head hurts.", "Your mind blanks for a moment.")]") + else + to_chat(M, "You can't think straight!") + M.confused = min(100 * power, M.confused + 8) + if(brain_damage) + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3 * power, 80) + M.updatehealth() + + return diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm index e4283101f5..b1767d7cb5 100644 --- a/code/datums/diseases/advance/symptoms/cough.dm +++ b/code/datums/diseases/advance/symptoms/cough.dm @@ -1,75 +1,75 @@ -/* -////////////////////////////////////// - -Coughing - - Noticable. - Little Resistance. - Doesn't increase stage speed much. - Transmissibile. - Low Level. - -BONUS - Will force the affected mob to drop small items! - -////////////////////////////////////// -*/ - -/datum/symptom/cough - - name = "Cough" - desc = "The virus irritates the throat of the host, causing occasional coughing." - stealth = -1 - resistance = 3 - stage_speed = 1 - transmittable = 2 - level = 1 - severity = 1 - base_message_chance = 15 - symptom_delay_min = 2 - symptom_delay_max = 15 - var/infective = FALSE - threshold_desc = "Resistance 3: Host will drop small items when coughing.
    \ - Resistance 10: Occasionally causes coughing fits that stun the host.
    \ - Stage Speed 6: Increases cough frequency.
    \ - If Airborne: Coughing will infect bystanders.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/cough/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - if(A.spread_flags &= DISEASE_SPREAD_AIRBORNE) //infect bystanders - infective = TRUE - if(A.properties["resistance"] >= 3) //strong enough to drop items - power = 1.5 - if(A.properties["resistance"] >= 10) //strong enough to stun (rarely) - power = 2 - if(A.properties["stage_rate"] >= 6) //cough more often - symptom_delay_max = 10 - -/datum/symptom/cough/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You swallow excess mucus.", "You lightly cough.")]") - else - M.emote("cough") - if(power >= 1.5) - var/obj/item/I = M.get_active_held_item() - if(I && I.w_class == WEIGHT_CLASS_TINY) - M.dropItemToGround(I) - if(power >= 2 && prob(10)) - to_chat(M, "[pick("You have a coughing fit!", "You can't stop coughing!")]") - M.Stun(20) - M.emote("cough") - addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 6) - addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 12) - addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 18) - if(infective && M.CanSpreadAirborneDisease()) - A.spread(1) - +/* +////////////////////////////////////// + +Coughing + + Noticable. + Little Resistance. + Doesn't increase stage speed much. + Transmissibile. + Low Level. + +BONUS + Will force the affected mob to drop small items! + +////////////////////////////////////// +*/ + +/datum/symptom/cough + + name = "Cough" + desc = "The virus irritates the throat of the host, causing occasional coughing." + stealth = -1 + resistance = 3 + stage_speed = 1 + transmittable = 2 + level = 1 + severity = 1 + base_message_chance = 15 + symptom_delay_min = 2 + symptom_delay_max = 15 + var/infective = FALSE + threshold_desc = "Resistance 3: Host will drop small items when coughing.
    \ + Resistance 10: Occasionally causes coughing fits that stun the host.
    \ + Stage Speed 6: Increases cough frequency.
    \ + If Airborne: Coughing will infect bystanders.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/cough/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + if(A.spread_flags &= DISEASE_SPREAD_AIRBORNE) //infect bystanders + infective = TRUE + if(A.properties["resistance"] >= 3) //strong enough to drop items + power = 1.5 + if(A.properties["resistance"] >= 10) //strong enough to stun (rarely) + power = 2 + if(A.properties["stage_rate"] >= 6) //cough more often + symptom_delay_max = 10 + +/datum/symptom/cough/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You swallow excess mucus.", "You lightly cough.")]") + else + M.emote("cough") + if(power >= 1.5) + var/obj/item/I = M.get_active_held_item() + if(I && I.w_class == WEIGHT_CLASS_TINY) + M.dropItemToGround(I) + if(power >= 2 && prob(10)) + to_chat(M, "[pick("You have a coughing fit!", "You can't stop coughing!")]") + M.Stun(20) + M.emote("cough") + addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 6) + addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 12) + addtimer(CALLBACK(M, /mob/.proc/emote, "cough"), 18) + if(infective && M.CanSpreadAirborneDisease()) + A.spread(1) + diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm index 3718104b48..e0336506e3 100644 --- a/code/datums/diseases/advance/symptoms/deafness.dm +++ b/code/datums/diseases/advance/symptoms/deafness.dm @@ -1,59 +1,59 @@ -/* -////////////////////////////////////// - -Deafness - - Slightly noticable. - Lowers resistance. - Decreases stage speed slightly. - Decreases transmittablity. - Intense Level. - -Bonus - Causes intermittent loss of hearing. - -////////////////////////////////////// -*/ - -/datum/symptom/deafness - - name = "Deafness" - desc = "The virus causes inflammation of the eardrums, causing intermittent deafness." - stealth = -1 - resistance = -2 - stage_speed = -1 - transmittable = -3 - level = 4 - severity = 4 - base_message_chance = 100 - symptom_delay_min = 25 - symptom_delay_max = 80 - threshold_desc = "Resistance 9: Causes permanent deafness, instead of intermittent.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/deafness/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - if(A.properties["resistance"] >= 9) //permanent deafness - power = 2 - -/datum/symptom/deafness/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(3, 4) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You hear a ringing in your ear.", "Your ears pop.")]") - if(5) - if(power > 2) - var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS) - if(istype(ears) && ears.damage < ears.maxHealth) - to_chat(M, "Your ears pop painfully and start bleeding!") - ears.damage = max(ears.damage, ears.maxHealth) - M.emote("scream") - else - to_chat(M, "Your ears pop and begin ringing loudly!") - M.minimumDeafTicks(20) +/* +////////////////////////////////////// + +Deafness + + Slightly noticable. + Lowers resistance. + Decreases stage speed slightly. + Decreases transmittablity. + Intense Level. + +Bonus + Causes intermittent loss of hearing. + +////////////////////////////////////// +*/ + +/datum/symptom/deafness + + name = "Deafness" + desc = "The virus causes inflammation of the eardrums, causing intermittent deafness." + stealth = -1 + resistance = -2 + stage_speed = -1 + transmittable = -3 + level = 4 + severity = 4 + base_message_chance = 100 + symptom_delay_min = 25 + symptom_delay_max = 80 + threshold_desc = "Resistance 9: Causes permanent deafness, instead of intermittent.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/deafness/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + if(A.properties["resistance"] >= 9) //permanent deafness + power = 2 + +/datum/symptom/deafness/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(3, 4) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You hear a ringing in your ear.", "Your ears pop.")]") + if(5) + if(power > 2) + var/obj/item/organ/ears/ears = M.getorganslot(ORGAN_SLOT_EARS) + if(istype(ears) && ears.damage < ears.maxHealth) + to_chat(M, "Your ears pop painfully and start bleeding!") + ears.damage = max(ears.damage, ears.maxHealth) + M.emote("scream") + else + to_chat(M, "Your ears pop and begin ringing loudly!") + M.minimumDeafTicks(20) diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index c7f7198f6b..b4b06be5ac 100644 --- a/code/datums/diseases/advance/symptoms/dizzy.dm +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -1,53 +1,53 @@ -/* -////////////////////////////////////// - -Dizziness - - Hidden. - Lowers resistance considerably. - Decreases stage speed. - Reduced transmittability - Intense Level. - -Bonus - Shakes the affected mob's screen for short periods. - -////////////////////////////////////// -*/ - -/datum/symptom/dizzy // Not the egg - - name = "Dizziness" - desc = "The virus causes inflammation of the vestibular system, leading to bouts of dizziness." - resistance = -2 - stage_speed = -3 - transmittable = -1 - level = 4 - severity = 2 - base_message_chance = 50 - symptom_delay_min = 15 - symptom_delay_max = 40 - threshold_desc = "Transmission 6: Also causes druggy vision.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/dizzy/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - if(A.properties["transmittable"] >= 6) //druggy - power = 2 - -/datum/symptom/dizzy/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You feel dizzy.", "Your head spins.")]") - else - to_chat(M, "A wave of dizziness washes over you!") - M.Dizzy(5) - if(power >= 2) +/* +////////////////////////////////////// + +Dizziness + + Hidden. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittability + Intense Level. + +Bonus + Shakes the affected mob's screen for short periods. + +////////////////////////////////////// +*/ + +/datum/symptom/dizzy // Not the egg + + name = "Dizziness" + desc = "The virus causes inflammation of the vestibular system, leading to bouts of dizziness." + resistance = -2 + stage_speed = -3 + transmittable = -1 + level = 4 + severity = 2 + base_message_chance = 50 + symptom_delay_min = 15 + symptom_delay_max = 40 + threshold_desc = "Transmission 6: Also causes druggy vision.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/dizzy/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + if(A.properties["transmittable"] >= 6) //druggy + power = 2 + +/datum/symptom/dizzy/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You feel dizzy.", "Your head spins.")]") + else + to_chat(M, "A wave of dizziness washes over you!") + M.Dizzy(5) + if(power >= 2) M.set_drugginess(5) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm index 5424e28502..a178cba196 100644 --- a/code/datums/diseases/advance/symptoms/fever.dm +++ b/code/datums/diseases/advance/symptoms/fever.dm @@ -1,60 +1,60 @@ -/* -////////////////////////////////////// - -Fever - - No change to hidden. - Increases resistance. - Increases stage speed. - Little transmittable. - Low level. - -Bonus - Heats up your body. - -////////////////////////////////////// -*/ - -/datum/symptom/fever - name = "Fever" - desc = "The virus causes a febrile response from the host, raising its body temperature." - stealth = 0 - resistance = 3 - stage_speed = 3 - transmittable = 2 - level = 2 - severity = 2 - base_message_chance = 20 - symptom_delay_min = 10 - symptom_delay_max = 30 - var/unsafe = FALSE //over the heat threshold - threshold_desc = "Resistance 5: Increases fever intensity, fever can overheat and harm the host.
    \ - Resistance 10: Further increases fever intensity." - -/datum/symptom/fever/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["resistance"] >= 5) //dangerous fever - power = 1.5 - unsafe = TRUE - if(A.properties["resistance"] >= 10) - power = 2.5 - -/datum/symptom/fever/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - if(!unsafe || A.stage < 4) - to_chat(M, "[pick("You feel hot.", "You feel like you're burning.")]") - else - to_chat(M, "[pick("You feel too hot.", "You feel like your blood is boiling.")]") - if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT || unsafe) - Heat(M, A) - -/datum/symptom/fever/proc/Heat(mob/living/M, datum/disease/advance/A) - var/get_heat = 6 * power - if(!unsafe) - M.adjust_bodytemperature(get_heat * A.stage, 0, BODYTEMP_HEAT_DAMAGE_LIMIT - 1) - else - M.adjust_bodytemperature(get_heat * A.stage) - return 1 +/* +////////////////////////////////////// + +Fever + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Heats up your body. + +////////////////////////////////////// +*/ + +/datum/symptom/fever + name = "Fever" + desc = "The virus causes a febrile response from the host, raising its body temperature." + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 2 + level = 2 + severity = 2 + base_message_chance = 20 + symptom_delay_min = 10 + symptom_delay_max = 30 + var/unsafe = FALSE //over the heat threshold + threshold_desc = "Resistance 5: Increases fever intensity, fever can overheat and harm the host.
    \ + Resistance 10: Further increases fever intensity." + +/datum/symptom/fever/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["resistance"] >= 5) //dangerous fever + power = 1.5 + unsafe = TRUE + if(A.properties["resistance"] >= 10) + power = 2.5 + +/datum/symptom/fever/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + if(!unsafe || A.stage < 4) + to_chat(M, "[pick("You feel hot.", "You feel like you're burning.")]") + else + to_chat(M, "[pick("You feel too hot.", "You feel like your blood is boiling.")]") + if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT || unsafe) + Heat(M, A) + +/datum/symptom/fever/proc/Heat(mob/living/M, datum/disease/advance/A) + var/get_heat = 6 * power + if(!unsafe) + M.adjust_bodytemperature(get_heat * A.stage, 0, BODYTEMP_HEAT_DAMAGE_LIMIT - 1) + else + M.adjust_bodytemperature(get_heat * A.stage) + return 1 diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index d1e9d3fdca..48668afc90 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -1,130 +1,130 @@ -/* -////////////////////////////////////// - -Necrotizing Fasciitis (AKA Flesh-Eating Disease) - - Very very noticable. - Lowers resistance tremendously. - No changes to stage speed. - Decreases transmittablity temrendously. - Fatal Level. - -Bonus - Deals brute damage over time. - -////////////////////////////////////// -*/ - -/datum/symptom/flesh_eating - - name = "Necrotizing Fasciitis" - desc = "The virus aggressively attacks body cells, necrotizing tissues and organs." - stealth = -3 - resistance = -4 - stage_speed = 0 - transmittable = -4 - level = 6 - severity = 5 - base_message_chance = 50 - symptom_delay_min = 15 - symptom_delay_max = 60 - var/bleed = FALSE - var/pain = FALSE - threshold_desc = "Resistance 7: Host will bleed profusely during necrosis.
    \ - Transmission 8: Causes extreme pain to the host, weakening it." - -/datum/symptom/flesh_eating/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["resistance"] >= 7) //extra bleeding - bleed = TRUE - if(A.properties["transmittable"] >= 8) //extra stamina damage - pain = TRUE - -/datum/symptom/flesh_eating/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(2,3) - if(prob(base_message_chance)) - to_chat(M, "[pick("You feel a sudden pain across your body.", "Drops of blood appear suddenly on your skin.")]") - if(4,5) - to_chat(M, "[pick("You cringe as a violent pain takes over your body.", "It feels like your body is eating itself inside out.", "IT HURTS.")]") - Flesheat(M, A) - -/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A) - var/get_damage = rand(15,25) * power - M.adjustBruteLoss(get_damage) - if(pain) - M.adjustStaminaLoss(get_damage) - if(bleed) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.bleed_rate += 5 * power - return 1 - -/* -////////////////////////////////////// - -Autophagocytosis (AKA Programmed mass cell death) - - Very noticable. - Lowers resistance. - Fast stage speed. - Decreases transmittablity. - Fatal Level. - -Bonus - Deals brute damage over time. - -////////////////////////////////////// -*/ - -/datum/symptom/flesh_death - - name = "Autophagocytosis Necrosis" - desc = "The virus rapidly consumes infected cells, leading to heavy and widespread damage." - stealth = -2 - resistance = -2 - stage_speed = 1 - transmittable = -2 - level = 7 - severity = 6 - base_message_chance = 50 - symptom_delay_min = 3 - symptom_delay_max = 6 - var/chems = FALSE - var/zombie = FALSE - threshold_desc = "Stage Speed 7: Synthesizes Heparin and Lipolicide inside the host, causing increased bleeding and hunger.
    \ - Stealth 5: The symptom remains hidden until active." - -/datum/symptom/flesh_death/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 5) - suppress_warning = TRUE - if(A.properties["stage_rate"] >= 7) //bleeding and hunger - chems = TRUE - -/datum/symptom/flesh_death/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(2,3) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You feel your body break apart.", "Your skin rubs off like dust.")]") - if(4,5) - if(prob(base_message_chance / 2)) //reduce spam - to_chat(M, "[pick("You feel your muscles weakening.", "Some of your skin detaches itself.", "You feel sandy.")]") - Flesh_death(M, A) - -/datum/symptom/flesh_death/proc/Flesh_death(mob/living/M, datum/disease/advance/A) - var/get_damage = rand(6,10) - M.adjustBruteLoss(get_damage) - if(chems) - M.reagents.add_reagent_list(list(/datum/reagent/toxin/heparin = 2, /datum/reagent/toxin/lipolicide = 2)) - if(zombie) - M.reagents.add_reagent(/datum/reagent/romerol, 1) +/* +////////////////////////////////////// + +Necrotizing Fasciitis (AKA Flesh-Eating Disease) + + Very very noticable. + Lowers resistance tremendously. + No changes to stage speed. + Decreases transmittablity temrendously. + Fatal Level. + +Bonus + Deals brute damage over time. + +////////////////////////////////////// +*/ + +/datum/symptom/flesh_eating + + name = "Necrotizing Fasciitis" + desc = "The virus aggressively attacks body cells, necrotizing tissues and organs." + stealth = -3 + resistance = -4 + stage_speed = 0 + transmittable = -4 + level = 6 + severity = 5 + base_message_chance = 50 + symptom_delay_min = 15 + symptom_delay_max = 60 + var/bleed = FALSE + var/pain = FALSE + threshold_desc = "Resistance 7: Host will bleed profusely during necrosis.
    \ + Transmission 8: Causes extreme pain to the host, weakening it." + +/datum/symptom/flesh_eating/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["resistance"] >= 7) //extra bleeding + bleed = TRUE + if(A.properties["transmittable"] >= 8) //extra stamina damage + pain = TRUE + +/datum/symptom/flesh_eating/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(2,3) + if(prob(base_message_chance)) + to_chat(M, "[pick("You feel a sudden pain across your body.", "Drops of blood appear suddenly on your skin.")]") + if(4,5) + to_chat(M, "[pick("You cringe as a violent pain takes over your body.", "It feels like your body is eating itself inside out.", "IT HURTS.")]") + Flesheat(M, A) + +/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A) + var/get_damage = rand(15,25) * power + M.adjustBruteLoss(get_damage) + if(pain) + M.adjustStaminaLoss(get_damage) + if(bleed) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.bleed_rate += 5 * power + return 1 + +/* +////////////////////////////////////// + +Autophagocytosis (AKA Programmed mass cell death) + + Very noticable. + Lowers resistance. + Fast stage speed. + Decreases transmittablity. + Fatal Level. + +Bonus + Deals brute damage over time. + +////////////////////////////////////// +*/ + +/datum/symptom/flesh_death + + name = "Autophagocytosis Necrosis" + desc = "The virus rapidly consumes infected cells, leading to heavy and widespread damage." + stealth = -2 + resistance = -2 + stage_speed = 1 + transmittable = -2 + level = 7 + severity = 6 + base_message_chance = 50 + symptom_delay_min = 3 + symptom_delay_max = 6 + var/chems = FALSE + var/zombie = FALSE + threshold_desc = "Stage Speed 7: Synthesizes Heparin and Lipolicide inside the host, causing increased bleeding and hunger.
    \ + Stealth 5: The symptom remains hidden until active." + +/datum/symptom/flesh_death/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 5) + suppress_warning = TRUE + if(A.properties["stage_rate"] >= 7) //bleeding and hunger + chems = TRUE + +/datum/symptom/flesh_death/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(2,3) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You feel your body break apart.", "Your skin rubs off like dust.")]") + if(4,5) + if(prob(base_message_chance / 2)) //reduce spam + to_chat(M, "[pick("You feel your muscles weakening.", "Some of your skin detaches itself.", "You feel sandy.")]") + Flesh_death(M, A) + +/datum/symptom/flesh_death/proc/Flesh_death(mob/living/M, datum/disease/advance/A) + var/get_damage = rand(6,10) + M.adjustBruteLoss(get_damage) + if(chems) + M.reagents.add_reagent_list(list(/datum/reagent/toxin/heparin = 2, /datum/reagent/toxin/lipolicide = 2)) + if(zombie) + M.reagents.add_reagent(/datum/reagent/romerol, 1) return 1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/genetics.dm b/code/datums/diseases/advance/symptoms/genetics.dm index c01fccee13..7f21b03dff 100644 --- a/code/datums/diseases/advance/symptoms/genetics.dm +++ b/code/datums/diseases/advance/symptoms/genetics.dm @@ -1,78 +1,78 @@ -/* -////////////////////////////////////// - -DNA Saboteur - - Very noticable. - Lowers resistance tremendously. - No changes to stage speed. - Decreases transmittablity tremendously. - Fatal Level. - -Bonus - Cleans the DNA of a person and then randomly gives them a trait. - -////////////////////////////////////// -*/ - -/datum/symptom/genetic_mutation - name = "Deoxyribonucleic Acid Saboteur" - desc = "The virus bonds with the DNA of the host, causing damaging mutations until removed." - stealth = -2 - resistance = -3 - stage_speed = 0 - transmittable = -3 - level = 6 - severity = 4 - var/list/possible_mutations - var/archived_dna = null - base_message_chance = 50 - symptom_delay_min = 60 - symptom_delay_max = 120 - var/no_reset = FALSE - threshold_desc = "Resistance 8: Causes two harmful mutations at once.
    \ - Stage Speed 10: Increases mutation frequency.
    \ - Stealth 5: The mutations persist even if the virus is cured." - -/datum/symptom/genetic_mutation/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/C = A.affected_mob - if(!C.has_dna()) - return - switch(A.stage) - if(4, 5) - to_chat(C, "[pick("Your skin feels itchy.", "You feel light headed.")]") - C.dna.remove_mutation_group(possible_mutations) - for(var/i in 1 to power) - C.randmut(possible_mutations) - -// Archive their DNA before they were infected. -/datum/symptom/genetic_mutation/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 5) //don't restore dna after curing - no_reset = TRUE - if(A.properties["stage_rate"] >= 10) //mutate more often - symptom_delay_min = 20 - symptom_delay_max = 60 - if(A.properties["resistance"] >= 8) //mutate twice - power = 2 - possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT] - var/mob/living/carbon/M = A.affected_mob - if(M) - if(!M.has_dna()) - return - archived_dna = M.dna.struc_enzymes - -// Give them back their old DNA when cured. -/datum/symptom/genetic_mutation/End(datum/disease/advance/A) - if(!..()) - return - if(!no_reset) - var/mob/living/carbon/M = A.affected_mob - if(M && archived_dna) - if(!M.has_dna()) - return - M.dna.struc_enzymes = archived_dna - M.domutcheck() +/* +////////////////////////////////////// + +DNA Saboteur + + Very noticable. + Lowers resistance tremendously. + No changes to stage speed. + Decreases transmittablity tremendously. + Fatal Level. + +Bonus + Cleans the DNA of a person and then randomly gives them a trait. + +////////////////////////////////////// +*/ + +/datum/symptom/genetic_mutation + name = "Deoxyribonucleic Acid Saboteur" + desc = "The virus bonds with the DNA of the host, causing damaging mutations until removed." + stealth = -2 + resistance = -3 + stage_speed = 0 + transmittable = -3 + level = 6 + severity = 4 + var/list/possible_mutations + var/archived_dna = null + base_message_chance = 50 + symptom_delay_min = 60 + symptom_delay_max = 120 + var/no_reset = FALSE + threshold_desc = "Resistance 8: Causes two harmful mutations at once.
    \ + Stage Speed 10: Increases mutation frequency.
    \ + Stealth 5: The mutations persist even if the virus is cured." + +/datum/symptom/genetic_mutation/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/C = A.affected_mob + if(!C.has_dna()) + return + switch(A.stage) + if(4, 5) + to_chat(C, "[pick("Your skin feels itchy.", "You feel light headed.")]") + C.dna.remove_mutation_group(possible_mutations) + for(var/i in 1 to power) + C.randmut(possible_mutations) + +// Archive their DNA before they were infected. +/datum/symptom/genetic_mutation/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 5) //don't restore dna after curing + no_reset = TRUE + if(A.properties["stage_rate"] >= 10) //mutate more often + symptom_delay_min = 20 + symptom_delay_max = 60 + if(A.properties["resistance"] >= 8) //mutate twice + power = 2 + possible_mutations = (GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT] + var/mob/living/carbon/M = A.affected_mob + if(M) + if(!M.has_dna()) + return + archived_dna = M.dna.struc_enzymes + +// Give them back their old DNA when cured. +/datum/symptom/genetic_mutation/End(datum/disease/advance/A) + if(!..()) + return + if(!no_reset) + var/mob/living/carbon/M = A.affected_mob + if(M && archived_dna) + if(!M.has_dna()) + return + M.dna.struc_enzymes = archived_dna + M.domutcheck() diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm index 39ecc61956..873d960524 100644 --- a/code/datums/diseases/advance/symptoms/hallucigen.dm +++ b/code/datums/diseases/advance/symptoms/hallucigen.dm @@ -1,65 +1,65 @@ -/* -////////////////////////////////////// - -Hallucigen - - Very noticable. - Lowers resistance considerably. - Decreases stage speed. - Reduced transmittable. - Critical Level. - -Bonus - Makes the affected mob be hallucinated for short periods of time. - -////////////////////////////////////// -*/ - -/datum/symptom/hallucigen - name = "Hallucigen" - desc = "The virus stimulates the brain, causing occasional hallucinations." - stealth = -2 - resistance = -3 - stage_speed = -3 - transmittable = -1 - level = 5 - severity = 2 - base_message_chance = 25 - symptom_delay_min = 25 - symptom_delay_max = 90 - var/fake_healthy = FALSE - threshold_desc = "Stage Speed 7: Increases the amount of hallucinations.
    \ - Stealth 4: The virus mimics positive symptoms.." - -/datum/symptom/hallucigen/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) //fake good symptom messages - fake_healthy = TRUE - base_message_chance = 50 - if(A.properties["stage_rate"] >= 7) //stronger hallucinations - power = 2 - -/datum/symptom/hallucigen/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - var/list/healthy_messages = list("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.",\ - "Your eyes feel great.", "You are now blinking manually.", "You don't feel the need to blink.") - switch(A.stage) - if(1, 2) - if(prob(base_message_chance)) - if(!fake_healthy) - to_chat(M, "[pick("Something appears in your peripheral vision, then winks out.", "You hear a faint whisper with no source.", "Your head aches.")]") - else - to_chat(M, "[pick(healthy_messages)]") - if(3, 4) - if(prob(base_message_chance)) - if(!fake_healthy) - to_chat(M, "[pick("Something is following you.", "You are being watched.", "You hear a whisper in your ear.", "Thumping footsteps slam toward you from nowhere.")]") - else - to_chat(M, "[pick(healthy_messages)]") - else - if(prob(base_message_chance)) - to_chat(M, "[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]") - M.hallucination += (45 * power) +/* +////////////////////////////////////// + +Hallucigen + + Very noticable. + Lowers resistance considerably. + Decreases stage speed. + Reduced transmittable. + Critical Level. + +Bonus + Makes the affected mob be hallucinated for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/hallucigen + name = "Hallucigen" + desc = "The virus stimulates the brain, causing occasional hallucinations." + stealth = -2 + resistance = -3 + stage_speed = -3 + transmittable = -1 + level = 5 + severity = 2 + base_message_chance = 25 + symptom_delay_min = 25 + symptom_delay_max = 90 + var/fake_healthy = FALSE + threshold_desc = "Stage Speed 7: Increases the amount of hallucinations.
    \ + Stealth 4: The virus mimics positive symptoms.." + +/datum/symptom/hallucigen/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) //fake good symptom messages + fake_healthy = TRUE + base_message_chance = 50 + if(A.properties["stage_rate"] >= 7) //stronger hallucinations + power = 2 + +/datum/symptom/hallucigen/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + var/list/healthy_messages = list("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.",\ + "Your eyes feel great.", "You are now blinking manually.", "You don't feel the need to blink.") + switch(A.stage) + if(1, 2) + if(prob(base_message_chance)) + if(!fake_healthy) + to_chat(M, "[pick("Something appears in your peripheral vision, then winks out.", "You hear a faint whisper with no source.", "Your head aches.")]") + else + to_chat(M, "[pick(healthy_messages)]") + if(3, 4) + if(prob(base_message_chance)) + if(!fake_healthy) + to_chat(M, "[pick("Something is following you.", "You are being watched.", "You hear a whisper in your ear.", "Thumping footsteps slam toward you from nowhere.")]") + else + to_chat(M, "[pick(healthy_messages)]") + else + if(prob(base_message_chance)) + to_chat(M, "[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]") + M.hallucination += (45 * power) diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm index 973de1455b..72b03000ed 100644 --- a/code/datums/diseases/advance/symptoms/headache.dm +++ b/code/datums/diseases/advance/symptoms/headache.dm @@ -1,60 +1,60 @@ -/* -////////////////////////////////////// - -Headache - - Noticable. - Highly resistant. - Increases stage speed. - Not transmittable. - Low Level. - -BONUS - Displays an annoying message! - Should be used for buffing your disease. - -////////////////////////////////////// -*/ - -/datum/symptom/headache - - name = "Headache" - desc = "The virus causes inflammation inside the brain, causing constant headaches." - stealth = -1 - resistance = 4 - stage_speed = 2 - transmittable = 0 - level = 1 - severity = 1 - base_message_chance = 100 - symptom_delay_min = 15 - symptom_delay_max = 30 - threshold_desc = "Stage Speed 6: Headaches will cause severe pain, that weakens the host.
    \ - Stage Speed 9: Headaches become less frequent but far more intense, preventing any action from the host.
    \ - Stealth 4: Reduces headache frequency until later stages." - -/datum/symptom/headache/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) - base_message_chance = 50 - if(A.properties["stage_rate"] >= 6) //severe pain - power = 2 - if(A.properties["stage_rate"] >= 9) //cluster headaches - symptom_delay_min = 30 - symptom_delay_max = 60 - power = 3 - -/datum/symptom/headache/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - if(power < 2) - if(prob(base_message_chance) || A.stage >=4) - to_chat(M, "[pick("Your head hurts.", "Your head pounds.")]") - if(power >= 2 && A.stage >= 4) - to_chat(M, "[pick("Your head hurts a lot.", "Your head pounds incessantly.")]") - M.adjustStaminaLoss(25) - if(power >= 3 && A.stage >= 5) - to_chat(M, "[pick("Your head hurts!", "You feel a burning knife inside your brain!", "A wave of pain fills your head!")]") +/* +////////////////////////////////////// + +Headache + + Noticable. + Highly resistant. + Increases stage speed. + Not transmittable. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/headache + + name = "Headache" + desc = "The virus causes inflammation inside the brain, causing constant headaches." + stealth = -1 + resistance = 4 + stage_speed = 2 + transmittable = 0 + level = 1 + severity = 1 + base_message_chance = 100 + symptom_delay_min = 15 + symptom_delay_max = 30 + threshold_desc = "Stage Speed 6: Headaches will cause severe pain, that weakens the host.
    \ + Stage Speed 9: Headaches become less frequent but far more intense, preventing any action from the host.
    \ + Stealth 4: Reduces headache frequency until later stages." + +/datum/symptom/headache/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) + base_message_chance = 50 + if(A.properties["stage_rate"] >= 6) //severe pain + power = 2 + if(A.properties["stage_rate"] >= 9) //cluster headaches + symptom_delay_min = 30 + symptom_delay_max = 60 + power = 3 + +/datum/symptom/headache/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + if(power < 2) + if(prob(base_message_chance) || A.stage >=4) + to_chat(M, "[pick("Your head hurts.", "Your head pounds.")]") + if(power >= 2 && A.stage >= 4) + to_chat(M, "[pick("Your head hurts a lot.", "Your head pounds incessantly.")]") + M.adjustStaminaLoss(25) + if(power >= 3 && A.stage >= 5) + to_chat(M, "[pick("Your head hurts!", "You feel a burning knife inside your brain!", "A wave of pain fills your head!")]") M.Stun(35) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index d41e0bf225..c1b3526f41 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -1,485 +1,485 @@ -/datum/symptom/heal - name = "Basic Healing (does nothing)" //warning for adminspawn viruses - desc = "You should not be seeing this." - stealth = 0 - resistance = 0 - stage_speed = 0 - transmittable = 0 - level = 0 //not obtainable - base_message_chance = 20 //here used for the overlays - symptom_delay_min = 1 - symptom_delay_max = 1 - var/passive_message = "" //random message to infected but not actively healing people - threshold_desc = "Stage Speed 6: Doubles healing speed.
    \ - Stealth 4: Healing will no longer be visible to onlookers." - -/datum/symptom/heal/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 6) //stronger healing - power = 2 - -/datum/symptom/heal/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(4, 5) - var/effectiveness = CanHeal(A) - if(!effectiveness) - if(passive_message && prob(2) && passive_message_condition(M)) - to_chat(M, passive_message) - return - else - Heal(M, A, effectiveness) - return - -/datum/symptom/heal/proc/CanHeal(datum/disease/advance/A) - return power - -/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A, actual_power) - return TRUE - -/datum/symptom/heal/proc/passive_message_condition(mob/living/M) - return TRUE - - -/datum/symptom/heal/starlight - name = "Starlight Condensation" - desc = "The virus reacts to direct starlight, producing regenerative chemicals. Works best against toxin-based damage." - stealth = -1 - resistance = -2 - stage_speed = 0 - transmittable = 1 - level = 6 - passive_message = "You miss the feeling of starlight on your skin." - var/nearspace_penalty = 0.3 - threshold_desc = "Stage Speed 6: Increases healing speed.
    \ - Transmission 6: Removes penalty for only being close to space." - -/datum/symptom/heal/starlight/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["transmittable"] >= 6) - nearspace_penalty = 1 - if(A.properties["stage_rate"] >= 6) - power = 2 - -/datum/symptom/heal/starlight/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob - if(istype(get_turf(M), /turf/open/space)) - return power - else - for(var/turf/T in view(M, 2)) - if(istype(T, /turf/open/space)) - return power * nearspace_penalty - -/datum/symptom/heal/starlight/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = actual_power - if(M.getToxLoss() && prob(5)) - to_chat(M, "Your skin tingles as the starlight seems to heal you.") - - M.adjustToxLoss(-(4 * heal_amt), forced = TRUE) //most effective on toxins - - var/list/parts = M.get_damaged_bodyparts(1,1) - - if(!parts.len) - return - - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) - M.update_damage_overlays() - return 1 - -/datum/symptom/heal/starlight/passive_message_condition(mob/living/M) - if(M.getBruteLoss() || M.getFireLoss() || M.getToxLoss()) - return TRUE - return FALSE - -/datum/symptom/heal/chem - name = "Toxolysis" - stealth = 0 - resistance = -2 - stage_speed = 2 - transmittable = -2 - level = 7 - var/food_conversion = FALSE - desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream." - threshold_desc = "Resistance 7: Increases chem removal speed.
    \ - Stage Speed 6: Consumed chemicals nourish the host." - -/datum/symptom/heal/chem/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 6) - food_conversion = TRUE - if(A.properties["resistance"] >= 7) - power = 2 - -/datum/symptom/heal/chem/Heal(mob/living/M, datum/disease/advance/A, actual_power) - for(var/E in M.reagents.reagent_list) //Not just toxins! - var/datum/reagent/R = E - M.reagents.remove_reagent(R.type, actual_power) - if(food_conversion) - M.nutrition += 0.3 - if(prob(2)) - to_chat(M, "You feel a mild warmth as your blood purifies itself.") - return 1 - - - -/datum/symptom/heal/metabolism - name = "Metabolic Boost" - stealth = -1 - resistance = -2 - stage_speed = 2 - transmittable = 1 - level = 7 - var/triple_metabolism = FALSE - var/reduced_hunger = FALSE - desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\ - but also causing increased hunger." - threshold_desc = "Stealth 3: Reduces hunger rate.
    \ - Stage Speed 10: Chemical metabolization is tripled instead of doubled." - -/datum/symptom/heal/metabolism/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 10) - triple_metabolism = TRUE - if(A.properties["stealth"] >= 3) - reduced_hunger = TRUE - -/datum/symptom/heal/metabolism/Heal(mob/living/carbon/C, datum/disease/advance/A, actual_power) - if(!istype(C)) - return - C.reagents.metabolize(C, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself - if(triple_metabolism) - C.reagents.metabolize(C, can_overdose=TRUE) - C.overeatduration = max(C.overeatduration - 2, 0) - var/lost_nutrition = 9 - (reduced_hunger * 5) - C.nutrition = max(C.nutrition - (lost_nutrition * HUNGER_FACTOR), 0) //Hunger depletes at 10x the normal speed - if(prob(2)) - to_chat(C, "You feel an odd gurgle in your stomach, as if it was working much faster than normal.") - return 1 - -/datum/symptom/heal/darkness - name = "Nocturnal Regeneration" - desc = "The virus is able to mend the host's flesh when in conditions of low light, repairing physical damage. More effective against brute damage." - stealth = 2 - resistance = -1 - stage_speed = -2 - transmittable = -1 - level = 6 - passive_message = "You feel tingling on your skin as light passes over it." - threshold_desc = "Stage Speed 8: Doubles healing speed." - -/datum/symptom/heal/darkness/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 8) - power = 2 - -/datum/symptom/heal/darkness/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob - var/light_amount = 0 - if(isturf(M.loc)) //else, there's considered to be no light - var/turf/T = M.loc - light_amount = min(1,T.get_lumcount()) - 0.5 - if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) - return power - -/datum/symptom/heal/darkness/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = 2 * actual_power - - var/list/parts = M.get_damaged_bodyparts(1,1) - - if(!parts.len) - return - - if(prob(5)) - to_chat(M, "The darkness soothes and mends your wounds.") - - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len * 0.5)) //more effective on brute - M.update_damage_overlays() - return 1 - -/datum/symptom/heal/darkness/passive_message_condition(mob/living/M) - if(M.getBruteLoss() || M.getFireLoss()) - return TRUE - return FALSE - -/datum/symptom/heal/coma - name = "Regenerative Coma" - desc = "The virus causes the host to fall into a death-like coma when severely damaged, then rapidly fixes the damage." - stealth = 0 - resistance = 2 - stage_speed = -3 - transmittable = -2 - level = 8 - passive_message = "The pain from your wounds makes you feel oddly sleepy..." - var/deathgasp = FALSE - var/stabilize = FALSE - var/active_coma = FALSE //to prevent multiple coma procs - threshold_desc = "Stealth 2: Host appears to die when falling into a coma.
    \ - Resistance 4: The virus also stabilizes the host while they are in critical condition.
    \ - Stage Speed 7: Increases healing speed." - -/datum/symptom/heal/coma/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 7) - power = 1.5 - if(A.properties["resistance"] >= 4) - stabilize = TRUE - if(A.properties["stealth"] >= 2) - deathgasp = TRUE - -/datum/symptom/heal/coma/on_stage_change(datum/disease/advance/A) //mostly copy+pasted from the code for self-respiration's TRAIT_NOBREATH stuff - if(!..()) - return FALSE - if(A.stage >= 4 && stabilize) - ADD_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) - else - REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) - return TRUE - -/datum/symptom/heal/coma/End(datum/disease/advance/A) - if(!..()) - return - REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) - -/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob - if(HAS_TRAIT(M, TRAIT_DEATHCOMA)) - return power - else if(M.IsUnconscious() || M.stat == UNCONSCIOUS) - return power * 0.9 - else if(M.stat == SOFT_CRIT) - return power * 0.5 - else if(M.IsSleeping()) - return power * 0.25 - else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma) - to_chat(M, "You feel yourself slip into a regenerative coma...") - active_coma = TRUE - addtimer(CALLBACK(src, .proc/coma, M), 60) - -/datum/symptom/heal/coma/proc/coma(mob/living/M) - if(deathgasp) - M.emote("deathgasp") - M.fakedeath("regenerative_coma") - M.update_stat() - M.update_canmove() - addtimer(CALLBACK(src, .proc/uncoma, M), 300) - -/datum/symptom/heal/coma/proc/uncoma(mob/living/M) - if(!active_coma) - return - active_coma = FALSE - M.cure_fakedeath("regenerative_coma") - M.update_stat() - M.update_canmove() - -/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = 4 * actual_power - - var/list/parts = M.get_damaged_bodyparts(1,1) - - if(!parts.len) - return - - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) - M.update_damage_overlays() - - if(active_coma && M.getBruteLoss() + M.getFireLoss() == 0) - uncoma(M) - - return 1 - -/datum/symptom/heal/coma/passive_message_condition(mob/living/M) - if((M.getBruteLoss() + M.getFireLoss()) > 30) - return TRUE - return FALSE - -/datum/symptom/heal/water - name = "Tissue Hydration" - desc = "The virus uses excess water inside and outside the body to repair damaged tissue cells. More effective against burns." - stealth = 0 - resistance = -1 - stage_speed = 0 - transmittable = 1 - level = 6 - passive_message = "Your skin feels oddly dry..." - var/absorption_coeff = 1 - threshold_desc = "Resistance 5: Water is consumed at a much slower rate.
    \ - Stage Speed 7: Increases healing speed." - -/datum/symptom/heal/water/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 7) - power = 2 - if(A.properties["stealth"] >= 2) - absorption_coeff = 0.25 - -/datum/symptom/heal/water/CanHeal(datum/disease/advance/A) - . = 0 - var/mob/living/M = A.affected_mob - if(M.fire_stacks < 0) - M.fire_stacks = min(M.fire_stacks + 1 * absorption_coeff, 0) - . += power - if(M.reagents.has_reagent(/datum/reagent/water/holywater)) - M.reagents.remove_reagent(/datum/reagent/water/holywater, 0.5 * absorption_coeff) - . += power * 0.75 - else if(M.reagents.has_reagent(/datum/reagent/water)) - M.reagents.remove_reagent(/datum/reagent/water, 0.5 * absorption_coeff) - . += power * 0.5 - -/datum/symptom/heal/water/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = 2 * actual_power - - var/list/parts = M.get_damaged_bodyparts(1,1) //more effective on burns - - if(!parts.len) - return - - if(prob(5)) - to_chat(M, "You feel yourself absorbing the water around you to soothe your damaged skin.") - - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len * 0.5, heal_amt/parts.len)) - M.update_damage_overlays() - - return 1 - -/datum/symptom/heal/water/passive_message_condition(mob/living/M) - if(M.getBruteLoss() || M.getFireLoss()) - return TRUE - return FALSE - -/datum/symptom/heal/plasma - name = "Plasma Fixation" - desc = "The virus draws plasma from the atmosphere and from inside the body to heal and stabilize body temperature." - stealth = 0 - resistance = 3 - stage_speed = -2 - transmittable = -2 - level = 8 - passive_message = "You feel an odd attraction to plasma." - var/temp_rate = 1 - threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
    \ - Stage Speed 7: Increases healing speed." - -/datum/symptom/heal/plasma/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 7) - power = 2 - if(A.properties["transmittable"] >= 6) - temp_rate = 4 - -/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob - var/datum/gas_mixture/environment - var/plasmamount - - . = 0 - - if(M.loc) - environment = M.loc.return_air() - if(environment) - plasmamount = environment.gases[/datum/gas/plasma] - if(plasmamount && plasmamount > GLOB.meta_gas_visibility[/datum/gas/plasma]) //if there's enough plasma in the air to see - . += power * 0.5 - if(M.reagents.has_reagent(/datum/reagent/toxin/plasma)) - . += power * 0.75 - -/datum/symptom/heal/plasma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = 4 * actual_power - - if(prob(5)) - to_chat(M, "You feel yourself absorbing plasma inside and around you...") - - if(M.bodytemperature > BODYTEMP_NORMAL) - M.adjust_bodytemperature(-20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT,BODYTEMP_NORMAL) - if(prob(5)) - to_chat(M, "You feel less hot.") - else if(M.bodytemperature < (BODYTEMP_NORMAL + 1)) - M.adjust_bodytemperature(20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT,0,BODYTEMP_NORMAL) - if(prob(5)) - to_chat(M, "You feel warmer.") - - M.adjustToxLoss(-heal_amt, forced = (temp_rate == 4)) - - var/list/parts = M.get_damaged_bodyparts(1,1) - if(!parts.len) - return - if(prob(5)) - to_chat(M, "The pain from your wounds fades rapidly.") - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) - M.update_damage_overlays() - return 1 - - -/datum/symptom/heal/radiation - name = "Radioactive Resonance" - desc = "The virus uses radiation to fix damage through dna mutations." - stealth = -1 - resistance = -2 - stage_speed = 2 - transmittable = -3 - level = 6 - symptom_delay_min = 1 - symptom_delay_max = 1 - passive_message = "Your skin glows faintly for a moment." - var/cellular_damage = FALSE - threshold_desc = "Transmission 6: Additionally heals cellular damage and toxin lovers.
    \ - Resistance 7: Increases healing speed." - -/datum/symptom/heal/radiation/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["resistance"] >= 7) - power = 2 - if(A.properties["transmittable"] >= 6) - cellular_damage = TRUE - -/datum/symptom/heal/radiation/CanHeal(datum/disease/advance/A) - var/mob/living/M = A.affected_mob - switch(M.radiation) - if(0) - return FALSE - if(1 to RAD_MOB_SAFE) - return 0.25 - if(RAD_MOB_SAFE to RAD_BURN_THRESHOLD) - return 0.5 - if(RAD_BURN_THRESHOLD to RAD_MOB_MUTATE) - return 0.75 - if(RAD_MOB_MUTATE to RAD_MOB_KNOCKDOWN) - return 1 - else - return 1.5 - -/datum/symptom/heal/radiation/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) - var/heal_amt = actual_power - - if(cellular_damage) - M.adjustCloneLoss(-heal_amt * 0.5) - - M.adjustToxLoss(-(2 * heal_amt), forced = cellular_damage) - - var/list/parts = M.get_damaged_bodyparts(1,1) - - if(!parts.len) - return - - if(prob(4)) - to_chat(M, "Your skin glows faintly, and you feel your wounds mending themselves.") - - for(var/obj/item/bodypart/L in parts) - if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) - M.update_damage_overlays() - return 1 +/datum/symptom/heal + name = "Basic Healing (does nothing)" //warning for adminspawn viruses + desc = "You should not be seeing this." + stealth = 0 + resistance = 0 + stage_speed = 0 + transmittable = 0 + level = 0 //not obtainable + base_message_chance = 20 //here used for the overlays + symptom_delay_min = 1 + symptom_delay_max = 1 + var/passive_message = "" //random message to infected but not actively healing people + threshold_desc = "Stage Speed 6: Doubles healing speed.
    \ + Stealth 4: Healing will no longer be visible to onlookers." + +/datum/symptom/heal/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 6) //stronger healing + power = 2 + +/datum/symptom/heal/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(4, 5) + var/effectiveness = CanHeal(A) + if(!effectiveness) + if(passive_message && prob(2) && passive_message_condition(M)) + to_chat(M, passive_message) + return + else + Heal(M, A, effectiveness) + return + +/datum/symptom/heal/proc/CanHeal(datum/disease/advance/A) + return power + +/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A, actual_power) + return TRUE + +/datum/symptom/heal/proc/passive_message_condition(mob/living/M) + return TRUE + + +/datum/symptom/heal/starlight + name = "Starlight Condensation" + desc = "The virus reacts to direct starlight, producing regenerative chemicals. Works best against toxin-based damage." + stealth = -1 + resistance = -2 + stage_speed = 0 + transmittable = 1 + level = 6 + passive_message = "You miss the feeling of starlight on your skin." + var/nearspace_penalty = 0.3 + threshold_desc = "Stage Speed 6: Increases healing speed.
    \ + Transmission 6: Removes penalty for only being close to space." + +/datum/symptom/heal/starlight/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["transmittable"] >= 6) + nearspace_penalty = 1 + if(A.properties["stage_rate"] >= 6) + power = 2 + +/datum/symptom/heal/starlight/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + if(istype(get_turf(M), /turf/open/space)) + return power + else + for(var/turf/T in view(M, 2)) + if(istype(T, /turf/open/space)) + return power * nearspace_penalty + +/datum/symptom/heal/starlight/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = actual_power + if(M.getToxLoss() && prob(5)) + to_chat(M, "Your skin tingles as the starlight seems to heal you.") + + M.adjustToxLoss(-(4 * heal_amt), forced = TRUE) //most effective on toxins + + var/list/parts = M.get_damaged_bodyparts(1,1) + + if(!parts.len) + return + + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) + M.update_damage_overlays() + return 1 + +/datum/symptom/heal/starlight/passive_message_condition(mob/living/M) + if(M.getBruteLoss() || M.getFireLoss() || M.getToxLoss()) + return TRUE + return FALSE + +/datum/symptom/heal/chem + name = "Toxolysis" + stealth = 0 + resistance = -2 + stage_speed = 2 + transmittable = -2 + level = 7 + var/food_conversion = FALSE + desc = "The virus rapidly breaks down any foreign chemicals in the bloodstream." + threshold_desc = "Resistance 7: Increases chem removal speed.
    \ + Stage Speed 6: Consumed chemicals nourish the host." + +/datum/symptom/heal/chem/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 6) + food_conversion = TRUE + if(A.properties["resistance"] >= 7) + power = 2 + +/datum/symptom/heal/chem/Heal(mob/living/M, datum/disease/advance/A, actual_power) + for(var/E in M.reagents.reagent_list) //Not just toxins! + var/datum/reagent/R = E + M.reagents.remove_reagent(R.type, actual_power) + if(food_conversion) + M.nutrition += 0.3 + if(prob(2)) + to_chat(M, "You feel a mild warmth as your blood purifies itself.") + return 1 + + + +/datum/symptom/heal/metabolism + name = "Metabolic Boost" + stealth = -1 + resistance = -2 + stage_speed = 2 + transmittable = 1 + level = 7 + var/triple_metabolism = FALSE + var/reduced_hunger = FALSE + desc = "The virus causes the host's metabolism to accelerate rapidly, making them process chemicals twice as fast,\ + but also causing increased hunger." + threshold_desc = "Stealth 3: Reduces hunger rate.
    \ + Stage Speed 10: Chemical metabolization is tripled instead of doubled." + +/datum/symptom/heal/metabolism/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 10) + triple_metabolism = TRUE + if(A.properties["stealth"] >= 3) + reduced_hunger = TRUE + +/datum/symptom/heal/metabolism/Heal(mob/living/carbon/C, datum/disease/advance/A, actual_power) + if(!istype(C)) + return + C.reagents.metabolize(C, can_overdose=TRUE) //this works even without a liver; it's intentional since the virus is metabolizing by itself + if(triple_metabolism) + C.reagents.metabolize(C, can_overdose=TRUE) + C.overeatduration = max(C.overeatduration - 2, 0) + var/lost_nutrition = 9 - (reduced_hunger * 5) + C.nutrition = max(C.nutrition - (lost_nutrition * HUNGER_FACTOR), 0) //Hunger depletes at 10x the normal speed + if(prob(2)) + to_chat(C, "You feel an odd gurgle in your stomach, as if it was working much faster than normal.") + return 1 + +/datum/symptom/heal/darkness + name = "Nocturnal Regeneration" + desc = "The virus is able to mend the host's flesh when in conditions of low light, repairing physical damage. More effective against brute damage." + stealth = 2 + resistance = -1 + stage_speed = -2 + transmittable = -1 + level = 6 + passive_message = "You feel tingling on your skin as light passes over it." + threshold_desc = "Stage Speed 8: Doubles healing speed." + +/datum/symptom/heal/darkness/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 8) + power = 2 + +/datum/symptom/heal/darkness/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + var/light_amount = 0 + if(isturf(M.loc)) //else, there's considered to be no light + var/turf/T = M.loc + light_amount = min(1,T.get_lumcount()) - 0.5 + if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD) + return power + +/datum/symptom/heal/darkness/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = 2 * actual_power + + var/list/parts = M.get_damaged_bodyparts(1,1) + + if(!parts.len) + return + + if(prob(5)) + to_chat(M, "The darkness soothes and mends your wounds.") + + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len * 0.5)) //more effective on brute + M.update_damage_overlays() + return 1 + +/datum/symptom/heal/darkness/passive_message_condition(mob/living/M) + if(M.getBruteLoss() || M.getFireLoss()) + return TRUE + return FALSE + +/datum/symptom/heal/coma + name = "Regenerative Coma" + desc = "The virus causes the host to fall into a death-like coma when severely damaged, then rapidly fixes the damage." + stealth = 0 + resistance = 2 + stage_speed = -3 + transmittable = -2 + level = 8 + passive_message = "The pain from your wounds makes you feel oddly sleepy..." + var/deathgasp = FALSE + var/stabilize = FALSE + var/active_coma = FALSE //to prevent multiple coma procs + threshold_desc = "Stealth 2: Host appears to die when falling into a coma.
    \ + Resistance 4: The virus also stabilizes the host while they are in critical condition.
    \ + Stage Speed 7: Increases healing speed." + +/datum/symptom/heal/coma/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 7) + power = 1.5 + if(A.properties["resistance"] >= 4) + stabilize = TRUE + if(A.properties["stealth"] >= 2) + deathgasp = TRUE + +/datum/symptom/heal/coma/on_stage_change(datum/disease/advance/A) //mostly copy+pasted from the code for self-respiration's TRAIT_NOBREATH stuff + if(!..()) + return FALSE + if(A.stage >= 4 && stabilize) + ADD_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) + else + REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) + return TRUE + +/datum/symptom/heal/coma/End(datum/disease/advance/A) + if(!..()) + return + REMOVE_TRAIT(A.affected_mob, TRAIT_NOCRITDAMAGE, DISEASE_TRAIT) + +/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + if(HAS_TRAIT(M, TRAIT_DEATHCOMA)) + return power + else if(M.IsUnconscious() || M.stat == UNCONSCIOUS) + return power * 0.9 + else if(M.stat == SOFT_CRIT) + return power * 0.5 + else if(M.IsSleeping()) + return power * 0.25 + else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma) + to_chat(M, "You feel yourself slip into a regenerative coma...") + active_coma = TRUE + addtimer(CALLBACK(src, .proc/coma, M), 60) + +/datum/symptom/heal/coma/proc/coma(mob/living/M) + if(deathgasp) + M.emote("deathgasp") + M.fakedeath("regenerative_coma") + M.update_stat() + M.update_canmove() + addtimer(CALLBACK(src, .proc/uncoma, M), 300) + +/datum/symptom/heal/coma/proc/uncoma(mob/living/M) + if(!active_coma) + return + active_coma = FALSE + M.cure_fakedeath("regenerative_coma") + M.update_stat() + M.update_canmove() + +/datum/symptom/heal/coma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = 4 * actual_power + + var/list/parts = M.get_damaged_bodyparts(1,1) + + if(!parts.len) + return + + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) + M.update_damage_overlays() + + if(active_coma && M.getBruteLoss() + M.getFireLoss() == 0) + uncoma(M) + + return 1 + +/datum/symptom/heal/coma/passive_message_condition(mob/living/M) + if((M.getBruteLoss() + M.getFireLoss()) > 30) + return TRUE + return FALSE + +/datum/symptom/heal/water + name = "Tissue Hydration" + desc = "The virus uses excess water inside and outside the body to repair damaged tissue cells. More effective against burns." + stealth = 0 + resistance = -1 + stage_speed = 0 + transmittable = 1 + level = 6 + passive_message = "Your skin feels oddly dry..." + var/absorption_coeff = 1 + threshold_desc = "Resistance 5: Water is consumed at a much slower rate.
    \ + Stage Speed 7: Increases healing speed." + +/datum/symptom/heal/water/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 7) + power = 2 + if(A.properties["stealth"] >= 2) + absorption_coeff = 0.25 + +/datum/symptom/heal/water/CanHeal(datum/disease/advance/A) + . = 0 + var/mob/living/M = A.affected_mob + if(M.fire_stacks < 0) + M.fire_stacks = min(M.fire_stacks + 1 * absorption_coeff, 0) + . += power + if(M.reagents.has_reagent(/datum/reagent/water/holywater)) + M.reagents.remove_reagent(/datum/reagent/water/holywater, 0.5 * absorption_coeff) + . += power * 0.75 + else if(M.reagents.has_reagent(/datum/reagent/water)) + M.reagents.remove_reagent(/datum/reagent/water, 0.5 * absorption_coeff) + . += power * 0.5 + +/datum/symptom/heal/water/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = 2 * actual_power + + var/list/parts = M.get_damaged_bodyparts(1,1) //more effective on burns + + if(!parts.len) + return + + if(prob(5)) + to_chat(M, "You feel yourself absorbing the water around you to soothe your damaged skin.") + + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len * 0.5, heal_amt/parts.len)) + M.update_damage_overlays() + + return 1 + +/datum/symptom/heal/water/passive_message_condition(mob/living/M) + if(M.getBruteLoss() || M.getFireLoss()) + return TRUE + return FALSE + +/datum/symptom/heal/plasma + name = "Plasma Fixation" + desc = "The virus draws plasma from the atmosphere and from inside the body to heal and stabilize body temperature." + stealth = 0 + resistance = 3 + stage_speed = -2 + transmittable = -2 + level = 8 + passive_message = "You feel an odd attraction to plasma." + var/temp_rate = 1 + threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
    \ + Stage Speed 7: Increases healing speed." + +/datum/symptom/heal/plasma/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 7) + power = 2 + if(A.properties["transmittable"] >= 6) + temp_rate = 4 + +/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + var/datum/gas_mixture/environment + var/plasmamount + + . = 0 + + if(M.loc) + environment = M.loc.return_air() + if(environment) + plasmamount = environment.gases[/datum/gas/plasma] + if(plasmamount && plasmamount > GLOB.meta_gas_visibility[/datum/gas/plasma]) //if there's enough plasma in the air to see + . += power * 0.5 + if(M.reagents.has_reagent(/datum/reagent/toxin/plasma)) + . += power * 0.75 + +/datum/symptom/heal/plasma/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = 4 * actual_power + + if(prob(5)) + to_chat(M, "You feel yourself absorbing plasma inside and around you...") + + if(M.bodytemperature > BODYTEMP_NORMAL) + M.adjust_bodytemperature(-20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT,BODYTEMP_NORMAL) + if(prob(5)) + to_chat(M, "You feel less hot.") + else if(M.bodytemperature < (BODYTEMP_NORMAL + 1)) + M.adjust_bodytemperature(20 * temp_rate * TEMPERATURE_DAMAGE_COEFFICIENT,0,BODYTEMP_NORMAL) + if(prob(5)) + to_chat(M, "You feel warmer.") + + M.adjustToxLoss(-heal_amt, forced = (temp_rate == 4)) + + var/list/parts = M.get_damaged_bodyparts(1,1) + if(!parts.len) + return + if(prob(5)) + to_chat(M, "The pain from your wounds fades rapidly.") + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) + M.update_damage_overlays() + return 1 + + +/datum/symptom/heal/radiation + name = "Radioactive Resonance" + desc = "The virus uses radiation to fix damage through dna mutations." + stealth = -1 + resistance = -2 + stage_speed = 2 + transmittable = -3 + level = 6 + symptom_delay_min = 1 + symptom_delay_max = 1 + passive_message = "Your skin glows faintly for a moment." + var/cellular_damage = FALSE + threshold_desc = "Transmission 6: Additionally heals cellular damage and toxin lovers.
    \ + Resistance 7: Increases healing speed." + +/datum/symptom/heal/radiation/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["resistance"] >= 7) + power = 2 + if(A.properties["transmittable"] >= 6) + cellular_damage = TRUE + +/datum/symptom/heal/radiation/CanHeal(datum/disease/advance/A) + var/mob/living/M = A.affected_mob + switch(M.radiation) + if(0) + return FALSE + if(1 to RAD_MOB_SAFE) + return 0.25 + if(RAD_MOB_SAFE to RAD_BURN_THRESHOLD) + return 0.5 + if(RAD_BURN_THRESHOLD to RAD_MOB_MUTATE) + return 0.75 + if(RAD_MOB_MUTATE to RAD_MOB_KNOCKDOWN) + return 1 + else + return 1.5 + +/datum/symptom/heal/radiation/Heal(mob/living/carbon/M, datum/disease/advance/A, actual_power) + var/heal_amt = actual_power + + if(cellular_damage) + M.adjustCloneLoss(-heal_amt * 0.5) + + M.adjustToxLoss(-(2 * heal_amt), forced = cellular_damage) + + var/list/parts = M.get_damaged_bodyparts(1,1) + + if(!parts.len) + return + + if(prob(4)) + to_chat(M, "Your skin glows faintly, and you feel your wounds mending themselves.") + + for(var/obj/item/bodypart/L in parts) + if(L.heal_damage(heal_amt/parts.len, heal_amt/parts.len)) + M.update_damage_overlays() + return 1 diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm index 1ede16999d..b0812e0235 100644 --- a/code/datums/diseases/advance/symptoms/itching.dm +++ b/code/datums/diseases/advance/symptoms/itching.dm @@ -1,54 +1,54 @@ -/* -////////////////////////////////////// - -Itching - - Not noticable or unnoticable. - Resistant. - Increases stage speed. - Little transmissibility. - Low Level. - -BONUS - Displays an annoying message! - Should be used for buffing your disease. - -////////////////////////////////////// -*/ - -/datum/symptom/itching - - name = "Itching" - desc = "The virus irritates the skin, causing itching." - stealth = 0 - resistance = 3 - stage_speed = 3 - transmittable = 1 - level = 1 - severity = 1 - symptom_delay_min = 5 - symptom_delay_max = 25 - var/scratch = FALSE - threshold_desc = "Transmission 6: Increases frequency of itching.
    \ - Stage Speed 7: The host will scrath itself when itching, causing superficial damage." - -/datum/symptom/itching/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["transmittable"] >= 6) //itch more often - symptom_delay_min = 1 - symptom_delay_max = 4 - if(A.properties["stage_rate"] >= 7) //scratch - scratch = TRUE - -/datum/symptom/itching/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - var/picked_bodypart = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - var/obj/item/bodypart/bodypart = M.get_bodypart(picked_bodypart) - if(bodypart && bodypart.status == BODYPART_ORGANIC && !bodypart.is_pseudopart) //robotic limbs will mean less scratching overall - var/can_scratch = scratch && !M.incapacitated() && get_location_accessible(M, picked_bodypart) - M.visible_message("[can_scratch ? "[M] scratches [M.p_their()] [bodypart.name]." : ""]", "Your [bodypart.name] itches. [can_scratch ? " You scratch it." : ""]") - if(can_scratch) +/* +////////////////////////////////////// + +Itching + + Not noticable or unnoticable. + Resistant. + Increases stage speed. + Little transmissibility. + Low Level. + +BONUS + Displays an annoying message! + Should be used for buffing your disease. + +////////////////////////////////////// +*/ + +/datum/symptom/itching + + name = "Itching" + desc = "The virus irritates the skin, causing itching." + stealth = 0 + resistance = 3 + stage_speed = 3 + transmittable = 1 + level = 1 + severity = 1 + symptom_delay_min = 5 + symptom_delay_max = 25 + var/scratch = FALSE + threshold_desc = "Transmission 6: Increases frequency of itching.
    \ + Stage Speed 7: The host will scrath itself when itching, causing superficial damage." + +/datum/symptom/itching/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["transmittable"] >= 6) //itch more often + symptom_delay_min = 1 + symptom_delay_max = 4 + if(A.properties["stage_rate"] >= 7) //scratch + scratch = TRUE + +/datum/symptom/itching/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + var/picked_bodypart = pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + var/obj/item/bodypart/bodypart = M.get_bodypart(picked_bodypart) + if(bodypart && bodypart.status == BODYPART_ORGANIC && !bodypart.is_pseudopart) //robotic limbs will mean less scratching overall + var/can_scratch = scratch && !M.incapacitated() && get_location_accessible(M, picked_bodypart) + M.visible_message("[can_scratch ? "[M] scratches [M.p_their()] [bodypart.name]." : ""]", "Your [bodypart.name] itches. [can_scratch ? " You scratch it." : ""]") + if(can_scratch) bodypart.receive_damage(0.5) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm index 65f8307101..e66bdf5ee0 100644 --- a/code/datums/diseases/advance/symptoms/oxygen.dm +++ b/code/datums/diseases/advance/symptoms/oxygen.dm @@ -1,68 +1,68 @@ -/* -////////////////////////////////////// - -Self-Respiration - - Slightly hidden. - Lowers resistance significantly. - Decreases stage speed significantly. - Decreases transmittablity tremendously. - Fatal Level. - -Bonus - The body generates salbutamol. - -////////////////////////////////////// -*/ - -/datum/symptom/oxygen - - name = "Self-Respiration" - desc = "The virus rapidly synthesizes oxygen, effectively removing the need for breathing." - stealth = 1 - resistance = -3 - stage_speed = -3 - transmittable = -4 - level = 6 - base_message_chance = 5 - symptom_delay_min = 1 - symptom_delay_max = 1 - var/regenerate_blood = FALSE - threshold_desc = "Resistance 8:Additionally regenerates lost blood.
    " - -/datum/symptom/oxygen/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["resistance"] >= 8) //blood regeneration - regenerate_blood = TRUE - -/datum/symptom/oxygen/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(4, 5) - M.adjustOxyLoss(-7, 0) - M.losebreath = max(0, M.losebreath - 4) - if(regenerate_blood && M.blood_volume < (BLOOD_VOLUME_NORMAL * M.blood_ratio)) - M.blood_volume += 1 - else - if(prob(base_message_chance)) - to_chat(M, "[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]") - return - -/datum/symptom/oxygen/on_stage_change(datum/disease/advance/A) - if(!..()) - return FALSE - var/mob/living/carbon/M = A.affected_mob - if(A.stage >= 4) - ADD_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT) - else - REMOVE_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT) - return TRUE - -/datum/symptom/oxygen/End(datum/disease/advance/A) - if(!..()) - return - if(A.stage >= 4) +/* +////////////////////////////////////// + +Self-Respiration + + Slightly hidden. + Lowers resistance significantly. + Decreases stage speed significantly. + Decreases transmittablity tremendously. + Fatal Level. + +Bonus + The body generates salbutamol. + +////////////////////////////////////// +*/ + +/datum/symptom/oxygen + + name = "Self-Respiration" + desc = "The virus rapidly synthesizes oxygen, effectively removing the need for breathing." + stealth = 1 + resistance = -3 + stage_speed = -3 + transmittable = -4 + level = 6 + base_message_chance = 5 + symptom_delay_min = 1 + symptom_delay_max = 1 + var/regenerate_blood = FALSE + threshold_desc = "Resistance 8:Additionally regenerates lost blood.
    " + +/datum/symptom/oxygen/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["resistance"] >= 8) //blood regeneration + regenerate_blood = TRUE + +/datum/symptom/oxygen/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(4, 5) + M.adjustOxyLoss(-7, 0) + M.losebreath = max(0, M.losebreath - 4) + if(regenerate_blood && M.blood_volume < (BLOOD_VOLUME_NORMAL * M.blood_ratio)) + M.blood_volume += 1 + else + if(prob(base_message_chance)) + to_chat(M, "[pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")]") + return + +/datum/symptom/oxygen/on_stage_change(datum/disease/advance/A) + if(!..()) + return FALSE + var/mob/living/carbon/M = A.affected_mob + if(A.stage >= 4) + ADD_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT) + else + REMOVE_TRAIT(M, TRAIT_NOBREATH, DISEASE_TRAIT) + return TRUE + +/datum/symptom/oxygen/End(datum/disease/advance/A) + if(!..()) + return + if(A.stage >= 4) REMOVE_TRAIT(A.affected_mob, TRAIT_NOBREATH, DISEASE_TRAIT) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index 06df320496..58357f04e2 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -1,55 +1,55 @@ -/* -////////////////////////////////////// -Alopecia - - Not Noticeable. - Increases resistance slightly. - Increases stage speed. - Transmittable. - Intense Level. - -BONUS - Makes the mob lose hair. - -////////////////////////////////////// -*/ - -/datum/symptom/shedding - name = "Alopecia" - desc = "The virus causes rapid shedding of head and body hair." - stealth = 0 - resistance = 1 - stage_speed = 2 - transmittable = 2 - level = 4 - severity = 1 - base_message_chance = 50 - symptom_delay_min = 45 - symptom_delay_max = 90 - -/datum/symptom/shedding/Activate(datum/disease/advance/A) - if(!..()) - return - - var/mob/living/M = A.affected_mob - if(prob(base_message_chance)) - to_chat(M, "[pick("Your scalp itches.", "Your skin feels flaky.")]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - switch(A.stage) - if(3, 4) - if(!(H.hair_style == "Bald") && !(H.hair_style == "Balding Hair")) - to_chat(H, "Your hair starts to fall out in clumps...") - addtimer(CALLBACK(src, .proc/Shed, H, FALSE), 50) - if(5) - if(!(H.facial_hair_style == "Shaved") || !(H.hair_style == "Bald")) - to_chat(H, "Your hair starts to fall out in clumps...") - addtimer(CALLBACK(src, .proc/Shed, H, TRUE), 50) - -/datum/symptom/shedding/proc/Shed(mob/living/carbon/human/H, fullbald) - if(fullbald) - H.facial_hair_style = "Shaved" - H.hair_style = "Bald" - else - H.hair_style = "Balding Hair" - H.update_hair() +/* +////////////////////////////////////// +Alopecia + + Not Noticeable. + Increases resistance slightly. + Increases stage speed. + Transmittable. + Intense Level. + +BONUS + Makes the mob lose hair. + +////////////////////////////////////// +*/ + +/datum/symptom/shedding + name = "Alopecia" + desc = "The virus causes rapid shedding of head and body hair." + stealth = 0 + resistance = 1 + stage_speed = 2 + transmittable = 2 + level = 4 + severity = 1 + base_message_chance = 50 + symptom_delay_min = 45 + symptom_delay_max = 90 + +/datum/symptom/shedding/Activate(datum/disease/advance/A) + if(!..()) + return + + var/mob/living/M = A.affected_mob + if(prob(base_message_chance)) + to_chat(M, "[pick("Your scalp itches.", "Your skin feels flaky.")]") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + switch(A.stage) + if(3, 4) + if(!(H.hair_style == "Bald") && !(H.hair_style == "Balding Hair")) + to_chat(H, "Your hair starts to fall out in clumps...") + addtimer(CALLBACK(src, .proc/Shed, H, FALSE), 50) + if(5) + if(!(H.facial_hair_style == "Shaved") || !(H.hair_style == "Bald")) + to_chat(H, "Your hair starts to fall out in clumps...") + addtimer(CALLBACK(src, .proc/Shed, H, TRUE), 50) + +/datum/symptom/shedding/proc/Shed(mob/living/carbon/human/H, fullbald) + if(fullbald) + H.facial_hair_style = "Shaved" + H.hair_style = "Bald" + else + H.hair_style = "Balding Hair" + H.update_hair() diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index e4bb5e1b3e..741e2a1e16 100644 --- a/code/datums/diseases/advance/symptoms/shivering.dm +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -1,59 +1,59 @@ -/* -////////////////////////////////////// - -Shivering - - No change to hidden. - Increases resistance. - Increases stage speed. - Little transmittable. - Low level. - -Bonus - Cools down your body. - -////////////////////////////////////// -*/ - -/datum/symptom/shivering - name = "Shivering" - desc = "The virus inhibits the body's thermoregulation, cooling the body down." - stealth = 0 - resistance = 2 - stage_speed = 2 - transmittable = 2 - level = 2 - severity = 2 - symptom_delay_min = 10 - symptom_delay_max = 30 - var/unsafe = FALSE //over the cold threshold - threshold_desc = "Stage Speed 5: Increases cooling speed; the host can fall below safe temperature levels.
    \ - Stage Speed 10: Further increases cooling speed." - -/datum/symptom/fever/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stage_rate"] >= 5) //dangerous cold - power = 1.5 - unsafe = TRUE - if(A.properties["stage_rate"] >= 10) - power = 2.5 - -/datum/symptom/shivering/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - if(!unsafe || A.stage < 4) - to_chat(M, "[pick("You feel cold.", "You shiver.")]") - else - to_chat(M, "[pick("You feel your blood run cold.", "You feel ice in your veins.", "You feel like you can't heat up.", "You shiver violently." )]") - if(M.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT || unsafe) - Chill(M, A) - -/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A) - var/get_cold = 6 * power - var/limit = BODYTEMP_COLD_DAMAGE_LIMIT + 1 - if(unsafe) - limit = 0 - M.adjust_bodytemperature(-get_cold * A.stage, limit) +/* +////////////////////////////////////// + +Shivering + + No change to hidden. + Increases resistance. + Increases stage speed. + Little transmittable. + Low level. + +Bonus + Cools down your body. + +////////////////////////////////////// +*/ + +/datum/symptom/shivering + name = "Shivering" + desc = "The virus inhibits the body's thermoregulation, cooling the body down." + stealth = 0 + resistance = 2 + stage_speed = 2 + transmittable = 2 + level = 2 + severity = 2 + symptom_delay_min = 10 + symptom_delay_max = 30 + var/unsafe = FALSE //over the cold threshold + threshold_desc = "Stage Speed 5: Increases cooling speed; the host can fall below safe temperature levels.
    \ + Stage Speed 10: Further increases cooling speed." + +/datum/symptom/fever/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stage_rate"] >= 5) //dangerous cold + power = 1.5 + unsafe = TRUE + if(A.properties["stage_rate"] >= 10) + power = 2.5 + +/datum/symptom/shivering/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + if(!unsafe || A.stage < 4) + to_chat(M, "[pick("You feel cold.", "You shiver.")]") + else + to_chat(M, "[pick("You feel your blood run cold.", "You feel ice in your veins.", "You feel like you can't heat up.", "You shiver violently." )]") + if(M.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT || unsafe) + Chill(M, A) + +/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A) + var/get_cold = 6 * power + var/limit = BODYTEMP_COLD_DAMAGE_LIMIT + 1 + if(unsafe) + limit = 0 + M.adjust_bodytemperature(-get_cold * A.stage, limit) return 1 \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 5e21fb3dd9..5d4d40fb95 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -1,52 +1,52 @@ -/* -////////////////////////////////////// - -Sneezing - - Very Noticable. - Increases resistance. - Doesn't increase stage speed. - Very transmissible. - Low Level. - -Bonus - Forces a spread type of AIRBORNE - with extra range! - -////////////////////////////////////// -*/ - -/datum/symptom/sneeze - name = "Sneezing" - desc = "The virus causes irritation of the nasal cavity, making the host sneeze occasionally." - stealth = -2 - resistance = 3 - stage_speed = 0 - transmittable = 4 - level = 1 - severity = 1 - symptom_delay_min = 5 - symptom_delay_max = 35 - threshold_desc = "Transmission 9: Increases sneezing range, spreading the virus over a larger area.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/sneeze/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["transmittable"] >= 9) //longer spread range - power = 2 - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - -/datum/symptom/sneeze/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3) - if(!suppress_warning) - M.emote("sniff") - else - M.emote("sneeze") - if(M.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth +/* +////////////////////////////////////// + +Sneezing + + Very Noticable. + Increases resistance. + Doesn't increase stage speed. + Very transmissible. + Low Level. + +Bonus + Forces a spread type of AIRBORNE + with extra range! + +////////////////////////////////////// +*/ + +/datum/symptom/sneeze + name = "Sneezing" + desc = "The virus causes irritation of the nasal cavity, making the host sneeze occasionally." + stealth = -2 + resistance = 3 + stage_speed = 0 + transmittable = 4 + level = 1 + severity = 1 + symptom_delay_min = 5 + symptom_delay_max = 35 + threshold_desc = "Transmission 9: Increases sneezing range, spreading the virus over a larger area.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/sneeze/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["transmittable"] >= 9) //longer spread range + power = 2 + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + +/datum/symptom/sneeze/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3) + if(!suppress_warning) + M.emote("sniff") + else + M.emote("sneeze") + if(M.CanSpreadAirborneDisease()) //don't spread germs if they covered their mouth A.spread(4 + power) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index 99dbd397a2..fef6453b3a 100644 --- a/code/datums/diseases/advance/symptoms/symptoms.dm +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -1,81 +1,81 @@ -// Symptoms are the effects that engineered advanced diseases do. - -/datum/symptom - // Buffs/Debuffs the symptom has to the overall engineered disease. - var/name = "" - var/desc = "If you see this something went very wrong." //Basic symptom description - var/threshold_desc = "" //Description of threshold effects - var/stealth = 0 - var/resistance = 0 - var/stage_speed = 0 - var/transmittable = 0 - // The type level of the symptom. Higher is harder to generate. - var/level = 0 - // The severity level of the symptom. Higher is more dangerous. - var/severity = 0 - // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!! - var/id = "" - //Base chance of sending warning messages, so it can be modified - var/base_message_chance = 10 - //If the early warnings are suppressed or not - var/suppress_warning = FALSE - //Ticks between each activation - var/next_activation = 0 - var/symptom_delay_min = 1 - var/symptom_delay_max = 1 - //Can be used to multiply virus effects - var/power = 1 - //A neutered symptom has no effect, and only affects statistics. - var/neutered = FALSE - var/list/thresholds - var/naturally_occuring = TRUE //if this symptom can appear from /datum/disease/advance/GenerateSymptoms() - -/datum/symptom/New() - var/list/S = SSdisease.list_symptoms - for(var/i = 1; i <= S.len; i++) - if(type == S[i]) - id = "[i]" - return - CRASH("We couldn't assign an ID!") - -// Called when processing of the advance disease that holds this symptom infects a host and upon each Refresh() of that advance disease. -/datum/symptom/proc/Start(datum/disease/advance/A) - if(neutered) - return FALSE - return TRUE - -// Called when the advance disease is going to be deleted or when the advance disease stops processing. -/datum/symptom/proc/End(datum/disease/advance/A) - if(neutered) - return FALSE - return TRUE - -/datum/symptom/proc/Activate(datum/disease/advance/A) - if(neutered) - return FALSE - if(world.time < next_activation) - return FALSE - else - next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10) - return TRUE - -/datum/symptom/proc/on_stage_change(datum/disease/advance/A) - if(neutered) - return FALSE - return TRUE - -/datum/symptom/proc/Copy() - var/datum/symptom/new_symp = new type - new_symp.name = name - new_symp.id = id - new_symp.neutered = neutered - return new_symp - -/datum/symptom/proc/generate_threshold_desc() - return - -/datum/symptom/proc/OnAdd(datum/disease/advance/A) //Overload when a symptom needs to be active before processing, like changing biotypes. - return - -/datum/symptom/proc/OnRemove(datum/disease/advance/A) //But dont forget to remove them too. +// Symptoms are the effects that engineered advanced diseases do. + +/datum/symptom + // Buffs/Debuffs the symptom has to the overall engineered disease. + var/name = "" + var/desc = "If you see this something went very wrong." //Basic symptom description + var/threshold_desc = "" //Description of threshold effects + var/stealth = 0 + var/resistance = 0 + var/stage_speed = 0 + var/transmittable = 0 + // The type level of the symptom. Higher is harder to generate. + var/level = 0 + // The severity level of the symptom. Higher is more dangerous. + var/severity = 0 + // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!! + var/id = "" + //Base chance of sending warning messages, so it can be modified + var/base_message_chance = 10 + //If the early warnings are suppressed or not + var/suppress_warning = FALSE + //Ticks between each activation + var/next_activation = 0 + var/symptom_delay_min = 1 + var/symptom_delay_max = 1 + //Can be used to multiply virus effects + var/power = 1 + //A neutered symptom has no effect, and only affects statistics. + var/neutered = FALSE + var/list/thresholds + var/naturally_occuring = TRUE //if this symptom can appear from /datum/disease/advance/GenerateSymptoms() + +/datum/symptom/New() + var/list/S = SSdisease.list_symptoms + for(var/i = 1; i <= S.len; i++) + if(type == S[i]) + id = "[i]" + return + CRASH("We couldn't assign an ID!") + +// Called when processing of the advance disease that holds this symptom infects a host and upon each Refresh() of that advance disease. +/datum/symptom/proc/Start(datum/disease/advance/A) + if(neutered) + return FALSE + return TRUE + +// Called when the advance disease is going to be deleted or when the advance disease stops processing. +/datum/symptom/proc/End(datum/disease/advance/A) + if(neutered) + return FALSE + return TRUE + +/datum/symptom/proc/Activate(datum/disease/advance/A) + if(neutered) + return FALSE + if(world.time < next_activation) + return FALSE + else + next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10) + return TRUE + +/datum/symptom/proc/on_stage_change(datum/disease/advance/A) + if(neutered) + return FALSE + return TRUE + +/datum/symptom/proc/Copy() + var/datum/symptom/new_symp = new type + new_symp.name = name + new_symp.id = id + new_symp.neutered = neutered + return new_symp + +/datum/symptom/proc/generate_threshold_desc() + return + +/datum/symptom/proc/OnAdd(datum/disease/advance/A) //Overload when a symptom needs to be active before processing, like changing biotypes. + return + +/datum/symptom/proc/OnRemove(datum/disease/advance/A) //But dont forget to remove them too. return \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/voice_change.dm b/code/datums/diseases/advance/symptoms/voice_change.dm index 5f0b83e5c8..8b9b7d069a 100644 --- a/code/datums/diseases/advance/symptoms/voice_change.dm +++ b/code/datums/diseases/advance/symptoms/voice_change.dm @@ -1,81 +1,81 @@ -/* -////////////////////////////////////// - -Voice Change - - Noticeable. - Lowers resistance. - Decreases stage speed. - Increased transmittable. - Fatal Level. - -Bonus - Changes the voice of the affected mob. Causing confusion in communication. - -////////////////////////////////////// -*/ - -/datum/symptom/voice_change - - name = "Voice Change" - desc = "The virus alters the pitch and tone of the host's vocal cords, changing how their voice sounds." - stealth = -1 - resistance = -2 - stage_speed = -2 - transmittable = 2 - level = 6 - severity = 2 - base_message_chance = 100 - symptom_delay_min = 60 - symptom_delay_max = 120 - var/scramble_language = FALSE - var/datum/language/current_language - var/datum/language_holder/original_language - threshold_desc = "Transmission 14: The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.
    \ - Stage Speed 7: Changes voice more often.
    \ - Stealth 3: The symptom remains hidden until active." - -/datum/symptom/voice_change/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 3) - suppress_warning = TRUE - if(A.properties["stage_rate"] >= 7) //faster change of voice - base_message_chance = 25 - symptom_delay_min = 25 - symptom_delay_max = 85 - if(A.properties["transmittable"] >= 14) //random language - scramble_language = TRUE - var/mob/living/M = A.affected_mob - var/datum/language_holder/mob_language = M.get_language_holder() - original_language = mob_language.copy() - -/datum/symptom/voice_change/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/carbon/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("Your throat hurts.", "You clear your throat.")]") - else - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.SetSpecialVoice(H.dna.species.random_name(H.gender)) - if(scramble_language) - H.remove_language(current_language) - current_language = pick(subtypesof(/datum/language) - /datum/language/common) - H.grant_language(current_language) - var/datum/language_holder/mob_language = H.get_language_holder() - mob_language.only_speaks_language = current_language - -/datum/symptom/voice_change/End(datum/disease/advance/A) - ..() - if(ishuman(A.affected_mob)) - var/mob/living/carbon/human/H = A.affected_mob - H.UnsetSpecialVoice() - if(scramble_language) - var/mob/living/M = A.affected_mob - M.copy_known_languages_from(original_language, TRUE) - current_language = null - QDEL_NULL(original_language) +/* +////////////////////////////////////// + +Voice Change + + Noticeable. + Lowers resistance. + Decreases stage speed. + Increased transmittable. + Fatal Level. + +Bonus + Changes the voice of the affected mob. Causing confusion in communication. + +////////////////////////////////////// +*/ + +/datum/symptom/voice_change + + name = "Voice Change" + desc = "The virus alters the pitch and tone of the host's vocal cords, changing how their voice sounds." + stealth = -1 + resistance = -2 + stage_speed = -2 + transmittable = 2 + level = 6 + severity = 2 + base_message_chance = 100 + symptom_delay_min = 60 + symptom_delay_max = 120 + var/scramble_language = FALSE + var/datum/language/current_language + var/datum/language_holder/original_language + threshold_desc = "Transmission 14: The host's language center of the brain is damaged, leading to complete inability to speak or understand any language.
    \ + Stage Speed 7: Changes voice more often.
    \ + Stealth 3: The symptom remains hidden until active." + +/datum/symptom/voice_change/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 3) + suppress_warning = TRUE + if(A.properties["stage_rate"] >= 7) //faster change of voice + base_message_chance = 25 + symptom_delay_min = 25 + symptom_delay_max = 85 + if(A.properties["transmittable"] >= 14) //random language + scramble_language = TRUE + var/mob/living/M = A.affected_mob + var/datum/language_holder/mob_language = M.get_language_holder() + original_language = mob_language.copy() + +/datum/symptom/voice_change/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/carbon/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("Your throat hurts.", "You clear your throat.")]") + else + if(ishuman(M)) + var/mob/living/carbon/human/H = M + H.SetSpecialVoice(H.dna.species.random_name(H.gender)) + if(scramble_language) + H.remove_language(current_language) + current_language = pick(subtypesof(/datum/language) - /datum/language/common) + H.grant_language(current_language) + var/datum/language_holder/mob_language = H.get_language_holder() + mob_language.only_speaks_language = current_language + +/datum/symptom/voice_change/End(datum/disease/advance/A) + ..() + if(ishuman(A.affected_mob)) + var/mob/living/carbon/human/H = A.affected_mob + H.UnsetSpecialVoice() + if(scramble_language) + var/mob/living/M = A.affected_mob + M.copy_known_languages_from(original_language, TRUE) + current_language = null + QDEL_NULL(original_language) diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm index 04b0778ccd..f53638bc12 100644 --- a/code/datums/diseases/advance/symptoms/vomit.dm +++ b/code/datums/diseases/advance/symptoms/vomit.dm @@ -1,63 +1,63 @@ -/* -////////////////////////////////////// - -Vomiting - - Very Very Noticable. - Decreases resistance. - Doesn't increase stage speed. - Little transmissibility. - Medium Level. - -Bonus - Forces the affected mob to vomit! - Meaning your disease can spread via - people walking on vomit. - Makes the affected mob lose nutrition and - heal toxin damage. - -////////////////////////////////////// -*/ - -/datum/symptom/vomit - - name = "Vomiting" - desc = "The virus causes nausea and irritates the stomach, causing occasional vomit." - stealth = -2 - resistance = -1 - stage_speed = 0 - transmittable = 1 - level = 3 - severity = 3 - base_message_chance = 100 - symptom_delay_min = 25 - symptom_delay_max = 80 - var/vomit_blood = FALSE - var/proj_vomit = 0 - threshold_desc = "Resistance 7: Host will vomit blood, causing internal damage.
    \ - Transmission 7: Host will projectile vomit, increasing vomiting range.
    \ - Stealth 4: The symptom remains hidden until active." - -/datum/symptom/vomit/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) - suppress_warning = TRUE - if(A.properties["resistance"] >= 7) //blood vomit - vomit_blood = TRUE - if(A.properties["transmittable"] >= 7) //projectile vomit - proj_vomit = 5 - -/datum/symptom/vomit/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("You feel nauseated.", "You feel like you're going to throw up!")]") - else - vomit(M) - -/datum/symptom/vomit/proc/vomit(mob/living/carbon/M) - M.vomit(20, vomit_blood, distance = proj_vomit) +/* +////////////////////////////////////// + +Vomiting + + Very Very Noticable. + Decreases resistance. + Doesn't increase stage speed. + Little transmissibility. + Medium Level. + +Bonus + Forces the affected mob to vomit! + Meaning your disease can spread via + people walking on vomit. + Makes the affected mob lose nutrition and + heal toxin damage. + +////////////////////////////////////// +*/ + +/datum/symptom/vomit + + name = "Vomiting" + desc = "The virus causes nausea and irritates the stomach, causing occasional vomit." + stealth = -2 + resistance = -1 + stage_speed = 0 + transmittable = 1 + level = 3 + severity = 3 + base_message_chance = 100 + symptom_delay_min = 25 + symptom_delay_max = 80 + var/vomit_blood = FALSE + var/proj_vomit = 0 + threshold_desc = "Resistance 7: Host will vomit blood, causing internal damage.
    \ + Transmission 7: Host will projectile vomit, increasing vomiting range.
    \ + Stealth 4: The symptom remains hidden until active." + +/datum/symptom/vomit/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) + suppress_warning = TRUE + if(A.properties["resistance"] >= 7) //blood vomit + vomit_blood = TRUE + if(A.properties["transmittable"] >= 7) //projectile vomit + proj_vomit = 5 + +/datum/symptom/vomit/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + if(prob(base_message_chance) && !suppress_warning) + to_chat(M, "[pick("You feel nauseated.", "You feel like you're going to throw up!")]") + else + vomit(M) + +/datum/symptom/vomit/proc/vomit(mob/living/carbon/M) + M.vomit(20, vomit_blood, distance = proj_vomit) diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index c97667733d..66fc90f1f8 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -1,51 +1,51 @@ -/* -////////////////////////////////////// - -Weight Loss - - Very Very Noticable. - Decreases resistance. - Decreases stage speed. - Reduced Transmittable. - High level. - -Bonus - Decreases the weight of the mob, - forcing it to be skinny. - -////////////////////////////////////// -*/ - -/datum/symptom/weight_loss - - name = "Weight Loss" - desc = "The virus mutates the host's metabolism, making it almost unable to gain nutrition from food." - stealth = -2 - resistance = 2 - stage_speed = -2 - transmittable = -2 - level = 3 - severity = 3 - base_message_chance = 100 - symptom_delay_min = 15 - symptom_delay_max = 45 - threshold_desc = "Stealth 4: The symptom is less noticeable." - -/datum/symptom/weight_loss/Start(datum/disease/advance/A) - if(!..()) - return - if(A.properties["stealth"] >= 4) //warn less often - base_message_chance = 25 - -/datum/symptom/weight_loss/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - switch(A.stage) - if(1, 2, 3, 4) - if(prob(base_message_chance)) - to_chat(M, "[pick("You feel hungry.", "You crave for food.")]") - else - to_chat(M, "[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]") - M.overeatduration = max(M.overeatduration - 100, 0) +/* +////////////////////////////////////// + +Weight Loss + + Very Very Noticable. + Decreases resistance. + Decreases stage speed. + Reduced Transmittable. + High level. + +Bonus + Decreases the weight of the mob, + forcing it to be skinny. + +////////////////////////////////////// +*/ + +/datum/symptom/weight_loss + + name = "Weight Loss" + desc = "The virus mutates the host's metabolism, making it almost unable to gain nutrition from food." + stealth = -2 + resistance = 2 + stage_speed = -2 + transmittable = -2 + level = 3 + severity = 3 + base_message_chance = 100 + symptom_delay_min = 15 + symptom_delay_max = 45 + threshold_desc = "Stealth 4: The symptom is less noticeable." + +/datum/symptom/weight_loss/Start(datum/disease/advance/A) + if(!..()) + return + if(A.properties["stealth"] >= 4) //warn less often + base_message_chance = 25 + +/datum/symptom/weight_loss/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + switch(A.stage) + if(1, 2, 3, 4) + if(prob(base_message_chance)) + to_chat(M, "[pick("You feel hungry.", "You crave for food.")]") + else + to_chat(M, "[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]") + M.overeatduration = max(M.overeatduration - 100, 0) M.nutrition = max(M.nutrition - 100, 0) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/youth.dm b/code/datums/diseases/advance/symptoms/youth.dm index 927be03ed9..d2712a0146 100644 --- a/code/datums/diseases/advance/symptoms/youth.dm +++ b/code/datums/diseases/advance/symptoms/youth.dm @@ -1,58 +1,58 @@ -/* -////////////////////////////////////// -Eternal Youth - - Moderate stealth boost. - Increases resistance tremendously. - Increases stage speed tremendously. - Reduces transmission tremendously. - Critical Level. - -BONUS - Gives you immortality and eternal youth!!! - Can be used to buff your virus - -////////////////////////////////////// -*/ - -/datum/symptom/youth - - name = "Eternal Youth" - desc = "The virus becomes symbiotically connected to the cells in the host's body, preventing and reversing aging. \ - The virus, in turn, becomes more resistant, spreads faster, and is harder to spot, although it doesn't thrive as well without a host." - stealth = 3 - resistance = 4 - stage_speed = 4 - transmittable = -4 - level = 5 - base_message_chance = 100 - symptom_delay_min = 25 - symptom_delay_max = 50 - -/datum/symptom/youth/Activate(datum/disease/advance/A) - if(!..()) - return - var/mob/living/M = A.affected_mob - if(ishuman(M)) - var/mob/living/carbon/human/H = M - switch(A.stage) - if(1) - if(H.age > 41) - H.age = 41 - to_chat(H, "You haven't had this much energy in years!") - if(2) - if(H.age > 36) - H.age = 36 - to_chat(H, "You're suddenly in a good mood.") - if(3) - if(H.age > 31) - H.age = 31 - to_chat(H, "You begin to feel more lithe.") - if(4) - if(H.age > 26) - H.age = 26 - to_chat(H, "You feel reinvigorated.") - if(5) - if(H.age > 21) - H.age = 21 +/* +////////////////////////////////////// +Eternal Youth + + Moderate stealth boost. + Increases resistance tremendously. + Increases stage speed tremendously. + Reduces transmission tremendously. + Critical Level. + +BONUS + Gives you immortality and eternal youth!!! + Can be used to buff your virus + +////////////////////////////////////// +*/ + +/datum/symptom/youth + + name = "Eternal Youth" + desc = "The virus becomes symbiotically connected to the cells in the host's body, preventing and reversing aging. \ + The virus, in turn, becomes more resistant, spreads faster, and is harder to spot, although it doesn't thrive as well without a host." + stealth = 3 + resistance = 4 + stage_speed = 4 + transmittable = -4 + level = 5 + base_message_chance = 100 + symptom_delay_min = 25 + symptom_delay_max = 50 + +/datum/symptom/youth/Activate(datum/disease/advance/A) + if(!..()) + return + var/mob/living/M = A.affected_mob + if(ishuman(M)) + var/mob/living/carbon/human/H = M + switch(A.stage) + if(1) + if(H.age > 41) + H.age = 41 + to_chat(H, "You haven't had this much energy in years!") + if(2) + if(H.age > 36) + H.age = 36 + to_chat(H, "You're suddenly in a good mood.") + if(3) + if(H.age > 31) + H.age = 31 + to_chat(H, "You begin to feel more lithe.") + if(4) + if(H.age > 26) + H.age = 26 + to_chat(H, "You feel reinvigorated.") + if(5) + if(H.age > 21) + H.age = 21 to_chat(H, "You feel like you can take on the world!") \ No newline at end of file diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index be7e6ceecd..7a6ea142b3 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -1,36 +1,36 @@ -/datum/disease/appendicitis - form = "Condition" - name = "Appendicitis" - max_stages = 3 - cure_text = "Surgery" - agent = "Shitty Appendix" - viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 1 - desc = "If left untreated the subject will become very weak, and may vomit often." - severity = DISEASE_SEVERITY_MEDIUM - disease_flags = CAN_CARRY|CAN_RESIST - spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS - visibility_flags = HIDDEN_PANDEMIC - required_organs = list(/obj/item/organ/appendix) - bypasses_immunity = TRUE // Immunity is based on not having an appendix; this isn't a virus - -/datum/disease/appendicitis/stage_act() - ..() - switch(stage) - if(1) - if(prob(5)) - affected_mob.emote("cough") - if(2) - var/obj/item/organ/appendix/A = affected_mob.getorgan(/obj/item/organ/appendix) - if(A) - A.inflamed = 1 - A.update_icon() - if(prob(3)) - to_chat(affected_mob, "You feel a stabbing pain in your abdomen!") - affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 5) - affected_mob.Stun(rand(40,60)) - affected_mob.adjustToxLoss(1) - if(3) - if(prob(1)) - affected_mob.vomit(95) - affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 15) +/datum/disease/appendicitis + form = "Condition" + name = "Appendicitis" + max_stages = 3 + cure_text = "Surgery" + agent = "Shitty Appendix" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 1 + desc = "If left untreated the subject will become very weak, and may vomit often." + severity = DISEASE_SEVERITY_MEDIUM + disease_flags = CAN_CARRY|CAN_RESIST + spread_flags = DISEASE_SPREAD_NON_CONTAGIOUS + visibility_flags = HIDDEN_PANDEMIC + required_organs = list(/obj/item/organ/appendix) + bypasses_immunity = TRUE // Immunity is based on not having an appendix; this isn't a virus + +/datum/disease/appendicitis/stage_act() + ..() + switch(stage) + if(1) + if(prob(5)) + affected_mob.emote("cough") + if(2) + var/obj/item/organ/appendix/A = affected_mob.getorgan(/obj/item/organ/appendix) + if(A) + A.inflamed = 1 + A.update_icon() + if(prob(3)) + to_chat(affected_mob, "You feel a stabbing pain in your abdomen!") + affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 5) + affected_mob.Stun(rand(40,60)) + affected_mob.adjustToxLoss(1) + if(3) + if(prob(1)) + affected_mob.vomit(95) + affected_mob.adjustOrganLoss(ORGAN_SLOT_APPENDIX, 15) diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index edd6f151c9..074bda0560 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -1,39 +1,39 @@ -/datum/disease/beesease - name = "Beesease" - form = "Infection" - max_stages = 4 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Sugar" - cures = list(/datum/reagent/consumable/sugar) - agent = "Apidae Infection" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - desc = "If left untreated subject will regurgitate bees." - severity = DISEASE_SEVERITY_MEDIUM - infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD) //bees nesting in corpses - -/datum/disease/beesease/stage_act() - ..() - switch(stage) - if(2) //also changes say, see say.dm - if(prob(2)) - to_chat(affected_mob, "You taste honey in your mouth.") - if(3) - if(prob(10)) - to_chat(affected_mob, "Your stomach rumbles.") - if(prob(2)) - to_chat(affected_mob, "Your stomach stings painfully.") - if(prob(20)) - affected_mob.adjustToxLoss(2) - affected_mob.updatehealth() - if(4) - if(prob(10)) - affected_mob.visible_message("[affected_mob] buzzes.", \ - "Your stomach buzzes violently!") - if(prob(5)) - to_chat(affected_mob, "You feel something moving in your throat.") - if(prob(1)) - affected_mob.visible_message("[affected_mob] coughs up a swarm of bees!", \ - "You cough up a swarm of bees!") - new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc) +/datum/disease/beesease + name = "Beesease" + form = "Infection" + max_stages = 4 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Sugar" + cures = list(/datum/reagent/consumable/sugar) + agent = "Apidae Infection" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + desc = "If left untreated subject will regurgitate bees." + severity = DISEASE_SEVERITY_MEDIUM + infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD) //bees nesting in corpses + +/datum/disease/beesease/stage_act() + ..() + switch(stage) + if(2) //also changes say, see say.dm + if(prob(2)) + to_chat(affected_mob, "You taste honey in your mouth.") + if(3) + if(prob(10)) + to_chat(affected_mob, "Your stomach rumbles.") + if(prob(2)) + to_chat(affected_mob, "Your stomach stings painfully.") + if(prob(20)) + affected_mob.adjustToxLoss(2) + affected_mob.updatehealth() + if(4) + if(prob(10)) + affected_mob.visible_message("[affected_mob] buzzes.", \ + "Your stomach buzzes violently!") + if(prob(5)) + to_chat(affected_mob, "You feel something moving in your throat.") + if(prob(1)) + affected_mob.visible_message("[affected_mob] coughs up a swarm of bees!", \ + "You cough up a swarm of bees!") + new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc) return \ No newline at end of file diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index 1028d1fff4..57628efe36 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -1,59 +1,59 @@ -/datum/disease/brainrot - name = "Brainrot" - max_stages = 4 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Mannitol" - cures = list(/datum/reagent/medicine/mannitol) - agent = "Cryptococcus Cosmosis" - viable_mobtypes = list(/mob/living/carbon/human) - cure_chance = 15//higher chance to cure, since two reagents are required - desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." - required_organs = list(/obj/item/organ/brain) - severity = DISEASE_SEVERITY_HARMFUL - -/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist -ACTUALLY Removed rather than commented out, I don't see it returning - RR - ..() - - switch(stage) - if(2) - if(prob(2)) - affected_mob.emote("blink") - if(prob(2)) - affected_mob.emote("yawn") - if(prob(2)) - to_chat(affected_mob, "You don't feel like yourself.") - if(prob(5)) - affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) - affected_mob.updatehealth() - if(3) - if(prob(2)) - affected_mob.emote("stare") - if(prob(2)) - affected_mob.emote("drool") - if(prob(10)) - affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Your try to remember something important...but can't.") - - if(4) - if(prob(2)) - affected_mob.emote("stare") - if(prob(2)) - affected_mob.emote("drool") - if(prob(15)) - affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 170) - affected_mob.updatehealth() - if(prob(2)) - to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") - if(prob(3)) - to_chat(affected_mob, "You lose consciousness...") - affected_mob.visible_message("[affected_mob] suddenly collapses") - affected_mob.Unconscious(rand(100,200)) - if(prob(1)) - affected_mob.emote("snore") - if(prob(15)) - affected_mob.stuttering += 3 - - return +/datum/disease/brainrot + name = "Brainrot" + max_stages = 4 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Mannitol" + cures = list(/datum/reagent/medicine/mannitol) + agent = "Cryptococcus Cosmosis" + viable_mobtypes = list(/mob/living/carbon/human) + cure_chance = 15//higher chance to cure, since two reagents are required + desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication." + required_organs = list(/obj/item/organ/brain) + severity = DISEASE_SEVERITY_HARMFUL + +/datum/disease/brainrot/stage_act() //Removed toxloss because damaging diseases are pretty horrible. Last round it killed the entire station because the cure didn't work -- Urist -ACTUALLY Removed rather than commented out, I don't see it returning - RR + ..() + + switch(stage) + if(2) + if(prob(2)) + affected_mob.emote("blink") + if(prob(2)) + affected_mob.emote("yawn") + if(prob(2)) + to_chat(affected_mob, "You don't feel like yourself.") + if(prob(5)) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, 170) + affected_mob.updatehealth() + if(3) + if(prob(2)) + affected_mob.emote("stare") + if(prob(2)) + affected_mob.emote("drool") + if(prob(10)) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2, 170) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Your try to remember something important...but can't.") + + if(4) + if(prob(2)) + affected_mob.emote("stare") + if(prob(2)) + affected_mob.emote("drool") + if(prob(15)) + affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 170) + affected_mob.updatehealth() + if(prob(2)) + to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") + if(prob(3)) + to_chat(affected_mob, "You lose consciousness...") + affected_mob.visible_message("[affected_mob] suddenly collapses") + affected_mob.Unconscious(rand(100,200)) + if(prob(1)) + affected_mob.emote("snore") + if(prob(15)) + affected_mob.stuttering += 3 + + return diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index 8bbb05e17c..660793ed83 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -1,53 +1,53 @@ -/datum/disease/cold - name = "The Cold" - max_stages = 3 - cure_text = "Rest & Spaceacillin" - cures = list(/datum/reagent/medicine/spaceacillin) - agent = "XY-rhinovirus" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - permeability_mod = 0.5 - desc = "If left untreated the subject will contract the flu." - severity = DISEASE_SEVERITY_NONTHREAT - -/datum/disease/cold/stage_act() - ..() - switch(stage) - if(2) - if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1) && prob(5)) - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(3) - if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1) && prob(1)) - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(1)) - to_chat(affected_mob, "Mucous runs down the back of your throat.") - if(prob(1) && prob(50)) - if(!affected_mob.disease_resistances.Find(/datum/disease/flu)) - var/datum/disease/Flu = new /datum/disease/flu() - affected_mob.ForceContractDisease(Flu, FALSE, TRUE) +/datum/disease/cold + name = "The Cold" + max_stages = 3 + cure_text = "Rest & Spaceacillin" + cures = list(/datum/reagent/medicine/spaceacillin) + agent = "XY-rhinovirus" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + permeability_mod = 0.5 + desc = "If left untreated the subject will contract the flu." + severity = DISEASE_SEVERITY_NONTHREAT + +/datum/disease/cold/stage_act() + ..() + switch(stage) + if(2) + if(affected_mob.lying && prob(40)) //changed FROM prob(10) until sleeping is fixed + to_chat(affected_mob, "You feel better.") + cure() + return + if(prob(1) && prob(5)) + to_chat(affected_mob, "You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "Mucous runs down the back of your throat.") + if(3) + if(affected_mob.lying && prob(25)) //changed FROM prob(5) until sleeping is fixed + to_chat(affected_mob, "You feel better.") + cure() + return + if(prob(1) && prob(1)) + to_chat(affected_mob, "You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "Mucous runs down the back of your throat.") + if(prob(1) && prob(50)) + if(!affected_mob.disease_resistances.Find(/datum/disease/flu)) + var/datum/disease/Flu = new /datum/disease/flu() + affected_mob.ForceContractDisease(Flu, FALSE, TRUE) cure() \ No newline at end of file diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index eea3147107..47f391ecf7 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -1,39 +1,39 @@ -/datum/disease/cold9 - name = "The Cold" - max_stages = 3 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Common Cold Anti-bodies & Spaceacillin" - cures = list(/datum/reagent/medicine/spaceacillin) - agent = "ICE9-rhinovirus" - viable_mobtypes = list(/mob/living/carbon/human) - desc = "If left untreated the subject will slow, as if partly frozen." - severity = DISEASE_SEVERITY_HARMFUL - -/datum/disease/cold9/stage_act() - ..() - switch(stage) - if(2) - affected_mob.adjust_bodytemperature(-10) - if(prob(1) && prob(10)) - to_chat(affected_mob, "You feel better.") - cure() - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(5)) - to_chat(affected_mob, "You feel stiff.") - if(3) - affected_mob.adjust_bodytemperature(-20) - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your throat feels sore.") - if(prob(10)) +/datum/disease/cold9 + name = "The Cold" + max_stages = 3 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Common Cold Anti-bodies & Spaceacillin" + cures = list(/datum/reagent/medicine/spaceacillin) + agent = "ICE9-rhinovirus" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "If left untreated the subject will slow, as if partly frozen." + severity = DISEASE_SEVERITY_HARMFUL + +/datum/disease/cold9/stage_act() + ..() + switch(stage) + if(2) + affected_mob.adjust_bodytemperature(-10) + if(prob(1) && prob(10)) + to_chat(affected_mob, "You feel better.") + cure() + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(5)) + to_chat(affected_mob, "You feel stiff.") + if(3) + affected_mob.adjust_bodytemperature(-20) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(10)) to_chat(affected_mob, "You feel stiff.") \ No newline at end of file diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index 972a7f4e18..3a67230d36 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -1,74 +1,74 @@ -/datum/disease/dnaspread - name = "Space Retrovirus" - max_stages = 4 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Mutadone" - cures = list(/datum/reagent/medicine/mutadone) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE - agent = "S4E1 retrovirus" - viable_mobtypes = list(/mob/living/carbon/human) - var/datum/dna/original_dna = null - var/transformed = 0 - desc = "This disease transplants the genetic code of the initial vector into new hosts." - severity = DISEASE_SEVERITY_MEDIUM - - -/datum/disease/dnaspread/stage_act() - ..() - if(!affected_mob.dna) - cure() - if((NOTRANSSTING in affected_mob.dna.species.species_traits) || (NO_DNA_COPY in affected_mob.dna.species.species_traits)) //Only species that can be spread by transformation sting can be spread by the retrovirus - cure() - - if(!strain_data["dna"]) - //Absorbs the target DNA. - strain_data["dna"] = new affected_mob.dna.type - affected_mob.dna.copy_dna(strain_data["dna"]) - carrier = TRUE - stage = 4 - return - - switch(stage) - if(2 || 3) //Pretend to be a cold and give time to spread. - if(prob(8)) - affected_mob.emote("sneeze") - if(prob(8)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(2) - affected_mob.updatehealth() - if(4) - if(!transformed && !carrier) - //Save original dna for when the disease is cured. - original_dna = new affected_mob.dna.type - affected_mob.dna.copy_dna(original_dna) - - to_chat(affected_mob, "You don't feel like yourself..") - var/datum/dna/transform_dna = strain_data["dna"] - - transform_dna.transfer_identity(affected_mob, transfer_SE = 1) - affected_mob.real_name = affected_mob.dna.real_name - affected_mob.updateappearance(mutcolor_update=1) - affected_mob.domutcheck() - - transformed = 1 - carrier = 1 //Just chill out at stage 4 - - return - -/datum/disease/dnaspread/Destroy() - if (original_dna && transformed && affected_mob) - original_dna.transfer_identity(affected_mob, transfer_SE = 1) - affected_mob.real_name = affected_mob.dna.real_name - affected_mob.updateappearance(mutcolor_update=1) - affected_mob.domutcheck() - - to_chat(affected_mob, "You feel more like yourself.") - return ..() +/datum/disease/dnaspread + name = "Space Retrovirus" + max_stages = 4 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Mutadone" + cures = list(/datum/reagent/medicine/mutadone) + disease_flags = CAN_CARRY|CAN_RESIST|CURABLE + agent = "S4E1 retrovirus" + viable_mobtypes = list(/mob/living/carbon/human) + var/datum/dna/original_dna = null + var/transformed = 0 + desc = "This disease transplants the genetic code of the initial vector into new hosts." + severity = DISEASE_SEVERITY_MEDIUM + + +/datum/disease/dnaspread/stage_act() + ..() + if(!affected_mob.dna) + cure() + if((NOTRANSSTING in affected_mob.dna.species.species_traits) || (NO_DNA_COPY in affected_mob.dna.species.species_traits)) //Only species that can be spread by transformation sting can be spread by the retrovirus + cure() + + if(!strain_data["dna"]) + //Absorbs the target DNA. + strain_data["dna"] = new affected_mob.dna.type + affected_mob.dna.copy_dna(strain_data["dna"]) + carrier = TRUE + stage = 4 + return + + switch(stage) + if(2 || 3) //Pretend to be a cold and give time to spread. + if(prob(8)) + affected_mob.emote("sneeze") + if(prob(8)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(2) + affected_mob.updatehealth() + if(4) + if(!transformed && !carrier) + //Save original dna for when the disease is cured. + original_dna = new affected_mob.dna.type + affected_mob.dna.copy_dna(original_dna) + + to_chat(affected_mob, "You don't feel like yourself..") + var/datum/dna/transform_dna = strain_data["dna"] + + transform_dna.transfer_identity(affected_mob, transfer_SE = 1) + affected_mob.real_name = affected_mob.dna.real_name + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() + + transformed = 1 + carrier = 1 //Just chill out at stage 4 + + return + +/datum/disease/dnaspread/Destroy() + if (original_dna && transformed && affected_mob) + original_dna.transfer_identity(affected_mob, transfer_SE = 1) + affected_mob.real_name = affected_mob.dna.real_name + affected_mob.updateappearance(mutcolor_update=1) + affected_mob.domutcheck() + + to_chat(affected_mob, "You feel more like yourself.") + return ..() diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm index 70bcc67d21..37628a5502 100644 --- a/code/datums/diseases/fake_gbs.dm +++ b/code/datums/diseases/fake_gbs.dm @@ -1,32 +1,32 @@ -/datum/disease/fake_gbs - name = "GBS" - max_stages = 5 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Synaptizine & Sulfur" - cures = list(/datum/reagent/medicine/synaptizine,/datum/reagent/sulfur) - agent = "Gravitokinetic Bipotential SADS-" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - desc = "If left untreated death will occur." - severity = DISEASE_SEVERITY_BIOHAZARD - -/datum/disease/fake_gbs/stage_act() - ..() - switch(stage) - if(2) - if(prob(1)) - affected_mob.emote("sneeze") - if(3) - if(prob(5)) - affected_mob.emote("cough") - else if(prob(5)) - affected_mob.emote("gasp") - if(prob(10)) - to_chat(affected_mob, "You're starting to feel very weak...") - if(4) - if(prob(10)) - affected_mob.emote("cough") - - if(5) - if(prob(10)) - affected_mob.emote("cough") +/datum/disease/fake_gbs + name = "GBS" + max_stages = 5 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Synaptizine & Sulfur" + cures = list(/datum/reagent/medicine/synaptizine,/datum/reagent/sulfur) + agent = "Gravitokinetic Bipotential SADS-" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + desc = "If left untreated death will occur." + severity = DISEASE_SEVERITY_BIOHAZARD + +/datum/disease/fake_gbs/stage_act() + ..() + switch(stage) + if(2) + if(prob(1)) + affected_mob.emote("sneeze") + if(3) + if(prob(5)) + affected_mob.emote("cough") + else if(prob(5)) + affected_mob.emote("gasp") + if(prob(10)) + to_chat(affected_mob, "You're starting to feel very weak...") + if(4) + if(prob(10)) + affected_mob.emote("cough") + + if(5) + if(prob(10)) + affected_mob.emote("cough") diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm index 4fc646a590..7672118774 100644 --- a/code/datums/diseases/flu.dm +++ b/code/datums/diseases/flu.dm @@ -1,54 +1,54 @@ -/datum/disease/flu - name = "The Flu" - max_stages = 3 - spread_text = "Airborne" - cure_text = "Spaceacillin" - cures = list(/datum/reagent/medicine/spaceacillin) - cure_chance = 10 - agent = "H13N1 flu virion" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - permeability_mod = 0.75 - desc = "If left untreated the subject will feel quite unwell." - severity = DISEASE_SEVERITY_MINOR - -/datum/disease/flu/stage_act() - ..() - switch(stage) - if(2) - if(affected_mob.lying && prob(20)) - to_chat(affected_mob, "You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - - if(3) - if(affected_mob.lying && prob(15)) - to_chat(affected_mob, "You feel better.") - stage-- - return - if(prob(1)) - affected_mob.emote("sneeze") - if(prob(1)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "Your muscles ache.") - if(prob(20)) - affected_mob.take_bodypart_damage(1) - if(prob(1)) - to_chat(affected_mob, "Your stomach hurts.") - if(prob(20)) - affected_mob.adjustToxLoss(1) - affected_mob.updatehealth() - return +/datum/disease/flu + name = "The Flu" + max_stages = 3 + spread_text = "Airborne" + cure_text = "Spaceacillin" + cures = list(/datum/reagent/medicine/spaceacillin) + cure_chance = 10 + agent = "H13N1 flu virion" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + permeability_mod = 0.75 + desc = "If left untreated the subject will feel quite unwell." + severity = DISEASE_SEVERITY_MINOR + +/datum/disease/flu/stage_act() + ..() + switch(stage) + if(2) + if(affected_mob.lying && prob(20)) + to_chat(affected_mob, "You feel better.") + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + + if(3) + if(affected_mob.lying && prob(15)) + to_chat(affected_mob, "You feel better.") + stage-- + return + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your muscles ache.") + if(prob(20)) + affected_mob.take_bodypart_damage(1) + if(prob(1)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + return diff --git a/code/datums/diseases/fluspanish.dm b/code/datums/diseases/fluspanish.dm index 1557ddfbd8..3297877fe9 100644 --- a/code/datums/diseases/fluspanish.dm +++ b/code/datums/diseases/fluspanish.dm @@ -1,36 +1,36 @@ -/datum/disease/fluspanish - name = "Spanish inquisition Flu" - max_stages = 3 - spread_text = "Airborne" - cure_text = "Spaceacillin & Anti-bodies to the common flu" - cures = list(/datum/reagent/medicine/spaceacillin) - cure_chance = 10 - agent = "1nqu1s1t10n flu virion" - viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 0.75 - desc = "If left untreated the subject will burn to death for being a heretic." - severity = DISEASE_SEVERITY_DANGEROUS - -/datum/disease/fluspanish/stage_act() - ..() - switch(stage) - if(2) - affected_mob.adjust_bodytemperature(10) - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(1)) - to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_bodypart_damage(0,5) - - if(3) - affected_mob.adjust_bodytemperature(20) - if(prob(5)) - affected_mob.emote("sneeze") - if(prob(5)) - affected_mob.emote("cough") - if(prob(5)) - to_chat(affected_mob, "You're burning in your own skin!") - affected_mob.take_bodypart_damage(0,5) - return +/datum/disease/fluspanish + name = "Spanish inquisition Flu" + max_stages = 3 + spread_text = "Airborne" + cure_text = "Spaceacillin & Anti-bodies to the common flu" + cures = list(/datum/reagent/medicine/spaceacillin) + cure_chance = 10 + agent = "1nqu1s1t10n flu virion" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 0.75 + desc = "If left untreated the subject will burn to death for being a heretic." + severity = DISEASE_SEVERITY_DANGEROUS + +/datum/disease/fluspanish/stage_act() + ..() + switch(stage) + if(2) + affected_mob.adjust_bodytemperature(10) + if(prob(5)) + affected_mob.emote("sneeze") + if(prob(5)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "You're burning in your own skin!") + affected_mob.take_bodypart_damage(0,5) + + if(3) + affected_mob.adjust_bodytemperature(20) + if(prob(5)) + affected_mob.emote("sneeze") + if(prob(5)) + affected_mob.emote("cough") + if(prob(5)) + to_chat(affected_mob, "You're burning in your own skin!") + affected_mob.take_bodypart_damage(0,5) + return diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 8a6eab6048..8ac1996855 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -1,31 +1,31 @@ -/datum/disease/gbs - name = "GBS" - max_stages = 4 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Synaptizine & Sulfur" - cures = list(/datum/reagent/medicine/synaptizine,/datum/reagent/sulfur) - cure_chance = 15//higher chance to cure, since two reagents are required - agent = "Gravitokinetic Bipotential SADS+" - viable_mobtypes = list(/mob/living/carbon/human) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE - permeability_mod = 1 - severity = DISEASE_SEVERITY_BIOHAZARD - -/datum/disease/gbs/stage_act() - ..() - switch(stage) - if(2) - if(prob(5)) - affected_mob.emote("cough") - if(3) - if(prob(5)) - affected_mob.emote("gasp") - if(prob(10)) - to_chat(affected_mob, "Your body hurts all over!") - if(4) - to_chat(affected_mob, "Your body feels as if it's trying to rip itself apart!") - if(prob(50)) - affected_mob.gib() - else - return +/datum/disease/gbs + name = "GBS" + max_stages = 4 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Synaptizine & Sulfur" + cures = list(/datum/reagent/medicine/synaptizine,/datum/reagent/sulfur) + cure_chance = 15//higher chance to cure, since two reagents are required + agent = "Gravitokinetic Bipotential SADS+" + viable_mobtypes = list(/mob/living/carbon/human) + disease_flags = CAN_CARRY|CAN_RESIST|CURABLE + permeability_mod = 1 + severity = DISEASE_SEVERITY_BIOHAZARD + +/datum/disease/gbs/stage_act() + ..() + switch(stage) + if(2) + if(prob(5)) + affected_mob.emote("cough") + if(3) + if(prob(5)) + affected_mob.emote("gasp") + if(prob(10)) + to_chat(affected_mob, "Your body hurts all over!") + if(4) + to_chat(affected_mob, "Your body feels as if it's trying to rip itself apart!") + if(prob(50)) + affected_mob.gib() + else + return diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index cb00f571aa..29e6657e13 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -1,68 +1,68 @@ -/datum/disease/magnitis - name = "Magnitis" - max_stages = 4 - spread_text = "Airborne" - cure_text = "Iron" - cures = list(/datum/reagent/iron) - agent = "Fukkos Miracos" - viable_mobtypes = list(/mob/living/carbon/human) - disease_flags = CAN_CARRY|CAN_RESIST|CURABLE - permeability_mod = 0.75 - desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field." - severity = DISEASE_SEVERITY_MEDIUM - infectable_biotypes = list(MOB_ORGANIC, MOB_ROBOTIC) - process_dead = TRUE - -/datum/disease/magnitis/stage_act() - ..() - switch(stage) - if(2) - if(prob(2)) - to_chat(affected_mob, "You feel a slight shock course through your body.") - if(prob(2)) - for(var/obj/M in orange(2,affected_mob)) - if(!M.anchored && (M.flags_1 & CONDUCT_1)) - step_towards(M,affected_mob) - for(var/mob/living/silicon/S in orange(2,affected_mob)) - if(isAI(S)) - continue - step_towards(S,affected_mob) - if(3) - if(prob(2)) - to_chat(affected_mob, "You feel a strong shock course through your body.") - if(prob(2)) - to_chat(affected_mob, "You feel like clowning around.") - if(prob(4)) - for(var/obj/M in orange(4,affected_mob)) - if(!M.anchored && (M.flags_1 & CONDUCT_1)) - var/i - var/iter = rand(1,2) - for(i=0,iYou feel a powerful shock course through your body.
    ") - if(prob(2)) - to_chat(affected_mob, "You query upon the nature of miracles.") - if(prob(8)) - for(var/obj/M in orange(6,affected_mob)) - if(!M.anchored && (M.flags_1 & CONDUCT_1)) - var/i - var/iter = rand(1,3) - for(i=0,iYou feel a slight shock course through your body.
    ") + if(prob(2)) + for(var/obj/M in orange(2,affected_mob)) + if(!M.anchored && (M.flags_1 & CONDUCT_1)) + step_towards(M,affected_mob) + for(var/mob/living/silicon/S in orange(2,affected_mob)) + if(isAI(S)) + continue + step_towards(S,affected_mob) + if(3) + if(prob(2)) + to_chat(affected_mob, "You feel a strong shock course through your body.") + if(prob(2)) + to_chat(affected_mob, "You feel like clowning around.") + if(prob(4)) + for(var/obj/M in orange(4,affected_mob)) + if(!M.anchored && (M.flags_1 & CONDUCT_1)) + var/i + var/iter = rand(1,2) + for(i=0,iYou feel a powerful shock course through your body.
    ") + if(prob(2)) + to_chat(affected_mob, "You query upon the nature of miracles.") + if(prob(8)) + for(var/obj/M in orange(6,affected_mob)) + if(!M.anchored && (M.flags_1 & CONDUCT_1)) + var/i + var/iter = rand(1,3) + for(i=0,iYou feel a little silly.
    ") - if(2) - if(prob(10)) - to_chat(affected_mob, "You start seeing rainbows.") - if(3) - if(prob(10)) - to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") - if(4) - if(prob(5)) - affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) , forced = "pierrot's throat") - -/datum/disease/pierrot_throat/after_add() - RegisterSignal(affected_mob, COMSIG_MOB_SAY, .proc/handle_speech) - -/datum/disease/pierrot_throat/proc/handle_speech(datum/source, list/speech_args) - var/message = speech_args[SPEECH_MESSAGE] - var/list/split_message = splittext(message, " ") //List each word in the message - var/applied = 0 - for (var/i in 1 to length(split_message)) - if(prob(3 * stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12% - if(findtext(split_message[i], "*") || findtext(split_message[i], ";") || findtext(split_message[i], ":")) - continue - split_message[i] = "HONK" - if (applied++ > stage) - break - if (applied) - speech_args[SPEECH_SPANS] |= SPAN_CLOWN // a little bonus - message = jointext(split_message, " ") - speech_args[SPEECH_MESSAGE] = message - -/datum/disease/pierrot_throat/Destroy() - UnregisterSignal(affected_mob, COMSIG_MOB_SAY) - return ..() - -/datum/disease/pierrot_throat/remove_disease() - UnregisterSignal(affected_mob, COMSIG_MOB_SAY) +/datum/disease/pierrot_throat + name = "Pierrot's Throat" + max_stages = 4 + spread_text = "Airborne" + cure_text = "Banana products, especially banana bread." + cures = list(/datum/reagent/consumable/banana) + cure_chance = 75 + agent = "H0NI<42 Virus" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 0.75 + desc = "If left untreated the subject will probably drive others to insanity." + severity = DISEASE_SEVERITY_MEDIUM + +/datum/disease/pierrot_throat/stage_act() + ..() + switch(stage) + if(1) + if(prob(10)) + to_chat(affected_mob, "You feel a little silly.") + if(2) + if(prob(10)) + to_chat(affected_mob, "You start seeing rainbows.") + if(3) + if(prob(10)) + to_chat(affected_mob, "Your thoughts are interrupted by a loud HONK!") + if(4) + if(prob(5)) + affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) , forced = "pierrot's throat") + +/datum/disease/pierrot_throat/after_add() + RegisterSignal(affected_mob, COMSIG_MOB_SAY, .proc/handle_speech) + +/datum/disease/pierrot_throat/proc/handle_speech(datum/source, list/speech_args) + var/message = speech_args[SPEECH_MESSAGE] + var/list/split_message = splittext(message, " ") //List each word in the message + var/applied = 0 + for (var/i in 1 to length(split_message)) + if(prob(3 * stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12% + if(findtext(split_message[i], "*") || findtext(split_message[i], ";") || findtext(split_message[i], ":")) + continue + split_message[i] = "HONK" + if (applied++ > stage) + break + if (applied) + speech_args[SPEECH_SPANS] |= SPAN_CLOWN // a little bonus + message = jointext(split_message, " ") + speech_args[SPEECH_MESSAGE] = message + +/datum/disease/pierrot_throat/Destroy() + UnregisterSignal(affected_mob, COMSIG_MOB_SAY) + return ..() + +/datum/disease/pierrot_throat/remove_disease() + UnregisterSignal(affected_mob, COMSIG_MOB_SAY) return ..() \ No newline at end of file diff --git a/code/datums/diseases/retrovirus.dm b/code/datums/diseases/retrovirus.dm index 5854249e54..160a9f98ad 100644 --- a/code/datums/diseases/retrovirus.dm +++ b/code/datums/diseases/retrovirus.dm @@ -1,84 +1,84 @@ -/datum/disease/dna_retrovirus - name = "Retrovirus" - max_stages = 4 - spread_text = "Contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Rest or an injection of mutadone" - cure_chance = 6 - agent = "" - viable_mobtypes = list(/mob/living/carbon/human) - desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly." - severity = DISEASE_SEVERITY_HARMFUL - permeability_mod = 0.4 - stage_prob = 2 - var/restcure = 0 - -/datum/disease/dna_retrovirus/New() - ..() - agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]" - if(prob(40)) - cures = list(/datum/reagent/medicine/mutadone) - else - restcure = 1 - -/datum/disease/dna_retrovirus/Copy() - var/datum/disease/dna_retrovirus/D = ..() - D.restcure = restcure - return D - -/datum/disease/dna_retrovirus/stage_act() - ..() - switch(stage) - if(1) - if(restcure) - if(affected_mob.lying && prob(30)) - to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(8)) - to_chat(affected_mob, "Your head hurts.") - if (prob(9)) - to_chat(affected_mob, "You feel a tingling sensation in your chest.") - if (prob(9)) - to_chat(affected_mob, "You feel angry.") - if(2) - if(restcure) - if(affected_mob.lying && prob(20)) - to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(8)) - to_chat(affected_mob, "Your skin feels loose.") - if (prob(10)) - to_chat(affected_mob, "You feel very strange.") - if (prob(4)) - to_chat(affected_mob, "You feel a stabbing pain in your head!") - affected_mob.Unconscious(40) - if (prob(4)) - to_chat(affected_mob, "Your stomach churns.") - if(3) - if(restcure) - if(affected_mob.lying && prob(20)) - to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(10)) - to_chat(affected_mob, "Your entire body vibrates.") - - if (prob(35)) - if(prob(50)) - scramble_dna(affected_mob, 1, 0, rand(15,45)) - else - scramble_dna(affected_mob, 0, 1, rand(15,45)) - - if(4) - if(restcure) - if(affected_mob.lying && prob(5)) - to_chat(affected_mob, "You feel better.") - cure() - return - if (prob(60)) - if(prob(50)) - scramble_dna(affected_mob, 1, 0, rand(50,75)) - else +/datum/disease/dna_retrovirus + name = "Retrovirus" + max_stages = 4 + spread_text = "Contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Rest or an injection of mutadone" + cure_chance = 6 + agent = "" + viable_mobtypes = list(/mob/living/carbon/human) + desc = "A DNA-altering retrovirus that scrambles the structural and unique enzymes of a host constantly." + severity = DISEASE_SEVERITY_HARMFUL + permeability_mod = 0.4 + stage_prob = 2 + var/restcure = 0 + +/datum/disease/dna_retrovirus/New() + ..() + agent = "Virus class [pick("A","B","C","D","E","F")][pick("A","B","C","D","E","F")]-[rand(50,300)]" + if(prob(40)) + cures = list(/datum/reagent/medicine/mutadone) + else + restcure = 1 + +/datum/disease/dna_retrovirus/Copy() + var/datum/disease/dna_retrovirus/D = ..() + D.restcure = restcure + return D + +/datum/disease/dna_retrovirus/stage_act() + ..() + switch(stage) + if(1) + if(restcure) + if(affected_mob.lying && prob(30)) + to_chat(affected_mob, "You feel better.") + cure() + return + if (prob(8)) + to_chat(affected_mob, "Your head hurts.") + if (prob(9)) + to_chat(affected_mob, "You feel a tingling sensation in your chest.") + if (prob(9)) + to_chat(affected_mob, "You feel angry.") + if(2) + if(restcure) + if(affected_mob.lying && prob(20)) + to_chat(affected_mob, "You feel better.") + cure() + return + if (prob(8)) + to_chat(affected_mob, "Your skin feels loose.") + if (prob(10)) + to_chat(affected_mob, "You feel very strange.") + if (prob(4)) + to_chat(affected_mob, "You feel a stabbing pain in your head!") + affected_mob.Unconscious(40) + if (prob(4)) + to_chat(affected_mob, "Your stomach churns.") + if(3) + if(restcure) + if(affected_mob.lying && prob(20)) + to_chat(affected_mob, "You feel better.") + cure() + return + if (prob(10)) + to_chat(affected_mob, "Your entire body vibrates.") + + if (prob(35)) + if(prob(50)) + scramble_dna(affected_mob, 1, 0, rand(15,45)) + else + scramble_dna(affected_mob, 0, 1, rand(15,45)) + + if(4) + if(restcure) + if(affected_mob.lying && prob(5)) + to_chat(affected_mob, "You feel better.") + cure() + return + if (prob(60)) + if(prob(50)) + scramble_dna(affected_mob, 1, 0, rand(50,75)) + else scramble_dna(affected_mob, 0, 1, rand(50,75)) \ No newline at end of file diff --git a/code/datums/diseases/rhumba_beat.dm b/code/datums/diseases/rhumba_beat.dm index da6e7da8df..1016f7b64d 100644 --- a/code/datums/diseases/rhumba_beat.dm +++ b/code/datums/diseases/rhumba_beat.dm @@ -1,45 +1,45 @@ -/datum/disease/rhumba_beat - name = "The Rhumba Beat" - max_stages = 5 - spread_text = "On contact" - spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS - cure_text = "Chick Chicky Boom!" - cures = list(/datum/reagent/toxin/plasma) - agent = "Unknown" - viable_mobtypes = list(/mob/living/carbon/human) - permeability_mod = 1 - severity = DISEASE_SEVERITY_BIOHAZARD - -/datum/disease/rhumba_beat/stage_act() - ..() - if(affected_mob.ckey == "rosham") - cure() - return - switch(stage) - if(2) - if(prob(45)) - affected_mob.adjustFireLoss(5) - affected_mob.updatehealth() - if(prob(1)) - to_chat(affected_mob, "You feel strange...") - if(3) - if(prob(5)) - to_chat(affected_mob, "You feel the urge to dance...") - else if(prob(5)) - affected_mob.emote("gasp") - else if(prob(10)) - to_chat(affected_mob, "You feel the need to chick chicky boom...") - if(4) - if(prob(20)) - if (prob(50)) - affected_mob.adjust_fire_stacks(2) - affected_mob.IgniteMob() - else - affected_mob.emote("gasp") - to_chat(affected_mob, "You feel a burning beat inside...") - if(5) - to_chat(affected_mob, "Your body is unable to contain the Rhumba Beat...") - if(prob(50)) - explosion(get_turf(affected_mob), -1, 0, 2, 3, 0, 2) // This is equivalent to a lvl 1 fireball - else - return +/datum/disease/rhumba_beat + name = "The Rhumba Beat" + max_stages = 5 + spread_text = "On contact" + spread_flags = DISEASE_SPREAD_BLOOD | DISEASE_SPREAD_CONTACT_SKIN | DISEASE_SPREAD_CONTACT_FLUIDS + cure_text = "Chick Chicky Boom!" + cures = list(/datum/reagent/toxin/plasma) + agent = "Unknown" + viable_mobtypes = list(/mob/living/carbon/human) + permeability_mod = 1 + severity = DISEASE_SEVERITY_BIOHAZARD + +/datum/disease/rhumba_beat/stage_act() + ..() + if(affected_mob.ckey == "rosham") + cure() + return + switch(stage) + if(2) + if(prob(45)) + affected_mob.adjustFireLoss(5) + affected_mob.updatehealth() + if(prob(1)) + to_chat(affected_mob, "You feel strange...") + if(3) + if(prob(5)) + to_chat(affected_mob, "You feel the urge to dance...") + else if(prob(5)) + affected_mob.emote("gasp") + else if(prob(10)) + to_chat(affected_mob, "You feel the need to chick chicky boom...") + if(4) + if(prob(20)) + if (prob(50)) + affected_mob.adjust_fire_stacks(2) + affected_mob.IgniteMob() + else + affected_mob.emote("gasp") + to_chat(affected_mob, "You feel a burning beat inside...") + if(5) + to_chat(affected_mob, "Your body is unable to contain the Rhumba Beat...") + if(prob(50)) + explosion(get_turf(affected_mob), -1, 0, 2, 3, 0, 2) // This is equivalent to a lvl 1 fireball + else + return diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 1c214c8516..bdb05346e4 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -1,327 +1,327 @@ -/datum/disease/transformation - name = "Transformation" - max_stages = 5 - spread_text = "Acute" - spread_flags = DISEASE_SPREAD_SPECIAL - cure_text = "A coder's love (theoretical)." - agent = "Shenanigans" - viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/alien) - severity = DISEASE_SEVERITY_BIOHAZARD - stage_prob = 10 - visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC - disease_flags = CURABLE - var/list/stage1 = list("You feel unremarkable.") - var/list/stage2 = list("You feel boring.") - var/list/stage3 = list("You feel utterly plain.") - var/list/stage4 = list("You feel white bread.") - var/list/stage5 = list("Oh the humanity!") - var/new_form = /mob/living/carbon/human - var/bantype - -/datum/disease/transformation/Copy() - var/datum/disease/transformation/D = ..() - D.stage1 = stage1.Copy() - D.stage2 = stage2.Copy() - D.stage3 = stage3.Copy() - D.stage4 = stage4.Copy() - D.stage5 = stage5.Copy() - D.new_form = D.new_form - return D - -/datum/disease/transformation/stage_act() - ..() - switch(stage) - if(1) - if (prob(stage_prob) && stage1) - to_chat(affected_mob, pick(stage1)) - if(2) - if (prob(stage_prob) && stage2) - to_chat(affected_mob, pick(stage2)) - if(3) - if (prob(stage_prob*2) && stage3) - to_chat(affected_mob, pick(stage3)) - if(4) - if (prob(stage_prob*2) && stage4) - to_chat(affected_mob, pick(stage4)) - if(5) - do_disease_transformation(affected_mob) - -/datum/disease/transformation/proc/do_disease_transformation(mob/living/affected_mob) - if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD) - if(stage5) - to_chat(affected_mob, pick(stage5)) - if(QDELETED(affected_mob)) - return - if(affected_mob.notransform) - return - affected_mob.notransform = 1 - for(var/obj/item/W in affected_mob.get_equipped_items(TRUE)) - affected_mob.dropItemToGround(W) - for(var/obj/item/I in affected_mob.held_items) - affected_mob.dropItemToGround(I) - var/mob/living/new_mob = new new_form(affected_mob.loc) - if(istype(new_mob)) - if(bantype && jobban_isbanned(affected_mob, bantype)) - replace_banned_player(new_mob) - new_mob.a_intent = INTENT_HARM - if(affected_mob.mind) - affected_mob.mind.transfer_to(new_mob) - else - affected_mob.transfer_ckey(new_mob) - - new_mob.name = affected_mob.real_name - new_mob.real_name = new_mob.name - qdel(affected_mob) - -/datum/disease/transformation/proc/replace_banned_player(var/mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed. - set waitfor = FALSE - - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, bantype, 50, affected_mob) - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) - to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") - message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.") - affected_mob.ghostize(0) - C.transfer_ckey(affected_mob) - else - to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!") - new_mob.death() - if (!QDELETED(new_mob)) - new_mob.ghostize(can_reenter_corpse = FALSE) - new_mob.key = null - -/datum/disease/transformation/jungle_fever - name = "Jungle Fever" - cure_text = "Death." - cures = list(/datum/reagent/medicine/adminordrazine) - spread_text = "Monkey Bites" - spread_flags = DISEASE_SPREAD_SPECIAL - viable_mobtypes = list(/mob/living/carbon/monkey, /mob/living/carbon/human) - permeability_mod = 1 - cure_chance = 1 - disease_flags = CAN_CARRY|CAN_RESIST - desc = "Monkeys with this disease will bite humans, causing humans to mutate into a monkey." - severity = DISEASE_SEVERITY_BIOHAZARD - stage_prob = 4 - visibility_flags = 0 - agent = "Kongey Vibrion M-909" - new_form = /mob/living/carbon/monkey - bantype = ROLE_MONKEY - - - stage1 = list() - stage2 = list() - stage3 = list() - stage4 = list("Your back hurts.", "You breathe through your mouth.", - "You have a craving for bananas.", "Your mind feels clouded.") - stage5 = list("You feel like monkeying around.") - -/datum/disease/transformation/jungle_fever/do_disease_transformation(mob/living/carbon/affected_mob) - if(affected_mob.mind && !is_monkey(affected_mob.mind)) - add_monkey(affected_mob.mind) - if(ishuman(affected_mob)) - var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) - M.ventcrawler = VENTCRAWLER_ALWAYS - - -/datum/disease/transformation/jungle_fever/stage_act() - ..() - switch(stage) - if(2) - if(prob(2)) - to_chat(affected_mob, "Your [pick("back", "arm", "leg", "elbow", "head")] itches.") - if(3) - if(prob(4)) - to_chat(affected_mob, "You feel a stabbing pain in your head.") - affected_mob.confused += 10 - if(4) - if(prob(3)) - affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."), forced = "jungle fever") - -/datum/disease/transformation/jungle_fever/cure() - remove_monkey(affected_mob.mind) - ..() - -/datum/disease/transformation/jungle_fever/monkeymode - visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC - disease_flags = CAN_CARRY //no vaccines! no cure! - -/datum/disease/transformation/jungle_fever/monkeymode/after_add() - if(affected_mob && !is_monkey_leader(affected_mob.mind)) - visibility_flags = NONE - - - -/datum/disease/transformation/robot - - name = "Robotic Transformation" - cure_text = "An injection of copper." - cures = list(/datum/reagent/copper) - cure_chance = 5 - agent = "R2D2 Nanomachines" - desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg." - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list() - stage2 = list("Your joints feel stiff.", "Beep...boop..") - stage3 = list("Your joints feel very stiff.", "Your skin feels loose.", "You can feel something move...inside.") - stage4 = list("Your skin feels very loose.", "You can feel... something...inside you.") - stage5 = list("Your skin feels as if it's about to burst off!") - new_form = /mob/living/silicon/robot - infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC) - bantype = "Cyborg" - -/datum/disease/transformation/robot/stage_act() - ..() - switch(stage) - if(3) - if (prob(8)) - affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"), forced = "robotic transformation") - if (prob(4)) - to_chat(affected_mob, "You feel a stabbing pain in your head.") - affected_mob.Unconscious(40) - if(4) - if (prob(20)) - affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."), forced = "robotic transformation") - - -/datum/disease/transformation/xeno - - name = "Xenomorph Transformation" - cure_text = "Spaceacillin & Glycerol" - cures = list(/datum/reagent/medicine/spaceacillin, /datum/reagent/glycerol) - cure_chance = 5 - agent = "Rip-LEY Alien Microbes" - desc = "This disease changes the victim into a xenomorph." - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list() - stage2 = list("Your throat feels scratchy.", "Kill...") - stage3 = list("Your throat feels very scratchy.", "Your skin feels tight.", "You can feel something move...inside.") - stage4 = list("Your skin feels very tight.", "Your blood boils!", "You can feel... something...inside you.") - stage5 = list("Your skin feels as if it's about to burst off!") - new_form = /mob/living/carbon/alien/humanoid/hunter - bantype = ROLE_ALIEN - -/datum/disease/transformation/xeno/stage_act() - ..() - switch(stage) - if(3) - if (prob(4)) - to_chat(affected_mob, "You feel a stabbing pain in your head.") - affected_mob.Unconscious(40) - if(4) - if (prob(20)) - affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"), forced = "xenomorph transformation") - - -/datum/disease/transformation/slime - name = "Advanced Mutation Transformation" - cure_text = "frost oil" - cures = list(/datum/reagent/consumable/frostoil) - cure_chance = 80 - agent = "Advanced Mutation Toxin" - desc = "This highly concentrated extract converts anything into more of itself." - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list("You don't feel very well.") - stage2 = list("Your skin feels a little slimy.") - stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") - stage4 = list("You are turning into a slime.") - stage5 = list("You have become a slime.") - new_form = /mob/living/simple_animal/slime/random - -/datum/disease/transformation/slime/stage_act() - ..() - switch(stage) - if(1) - if(ishuman(affected_mob) && affected_mob.dna) - if(affected_mob.dna.species.id == "slime" || affected_mob.dna.species.id == "stargazer" || affected_mob.dna.species.id == "lum") - stage = 5 - if(3) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/human = affected_mob - if(human.dna.species.id != "slime" && affected_mob.dna.species.id != "stargazer" && affected_mob.dna.species.id != "lum") - human.set_species(/datum/species/jelly/slime) - -/datum/disease/transformation/corgi - name = "The Barkening" - cure_text = "Death" - cures = list(/datum/reagent/medicine/adminordrazine) - agent = "Fell Doge Majicks" - desc = "This disease transforms the victim into a corgi." - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list("BARK.") - stage2 = list("You feel the need to wear silly hats.") - stage3 = list("Must... eat... chocolate....", "YAP") - stage4 = list("Visions of washing machines assail your mind!") - stage5 = list("AUUUUUU!!!") - new_form = /mob/living/simple_animal/pet/dog/corgi - -/datum/disease/transformation/corgi/stage_act() - ..() - switch(stage) - if(3) - if (prob(8)) - affected_mob.say(pick("YAP", "Woof!"), forced = "corgi transformation") - if(4) - if (prob(20)) - affected_mob.say(pick("Bark!", "AUUUUUU"), forced = "corgi transformation") - -/datum/disease/transformation/morph - name = "Gluttony's Blessing" - cure_text = "nothing" - cures = list(/datum/reagent/medicine/adminordrazine) - agent = "Gluttony's Blessing" - desc = "A 'gift' from somewhere terrible." - stage_prob = 20 - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list("Your stomach rumbles.") - stage2 = list("Your skin feels saggy.") - stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") - stage4 = list("You're ravenous.") - stage5 = list("You have become a morph.") - new_form = /mob/living/simple_animal/hostile/morph - infectable_biotypes = list(MOB_ORGANIC, MOB_INORGANIC, MOB_UNDEAD) //magic! - -/datum/disease/transformation/gondola - name = "Gondola Transformation" - cure_text = "Condensed Capsaicin, ingested or injected." //getting pepper sprayed doesn't help - cures = list(/datum/reagent/consumable/condensedcapsaicin) //beats the hippie crap right out of your system - cure_chance = 80 - stage_prob = 5 - agent = "Tranquility" - desc = "Consuming the flesh of a Gondola comes at a terrible price." - severity = DISEASE_SEVERITY_BIOHAZARD - visibility_flags = 0 - stage1 = list("You seem a little lighter in your step.") - stage2 = list("You catch yourself smiling for no reason.") - stage3 = list("A cruel sense of calm overcomes you.", "You can't feel your arms!", "You let go of the urge to hurt clowns.") - stage4 = list("You can't feel your arms. It does not bother you anymore.", "You forgive the clown for hurting you.") - stage5 = list("You have become a Gondola.") - new_form = /mob/living/simple_animal/pet/gondola - -/datum/disease/transformation/gondola/stage_act() - ..() - switch(stage) - if(2) - if (prob(5)) - affected_mob.emote("smile") - if (prob(20)) - affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) - if(3) - if (prob(5)) - affected_mob.emote("smile") - if (prob(20)) - affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) - if(4) - if (prob(5)) - affected_mob.emote("smile") - if (prob(20)) - affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) - if (prob(2)) - to_chat(affected_mob, "You let go of what you were holding.") - var/obj/item/I = affected_mob.get_active_held_item() - affected_mob.dropItemToGround(I) +/datum/disease/transformation + name = "Transformation" + max_stages = 5 + spread_text = "Acute" + spread_flags = DISEASE_SPREAD_SPECIAL + cure_text = "A coder's love (theoretical)." + agent = "Shenanigans" + viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey, /mob/living/carbon/alien) + severity = DISEASE_SEVERITY_BIOHAZARD + stage_prob = 10 + visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC + disease_flags = CURABLE + var/list/stage1 = list("You feel unremarkable.") + var/list/stage2 = list("You feel boring.") + var/list/stage3 = list("You feel utterly plain.") + var/list/stage4 = list("You feel white bread.") + var/list/stage5 = list("Oh the humanity!") + var/new_form = /mob/living/carbon/human + var/bantype + +/datum/disease/transformation/Copy() + var/datum/disease/transformation/D = ..() + D.stage1 = stage1.Copy() + D.stage2 = stage2.Copy() + D.stage3 = stage3.Copy() + D.stage4 = stage4.Copy() + D.stage5 = stage5.Copy() + D.new_form = D.new_form + return D + +/datum/disease/transformation/stage_act() + ..() + switch(stage) + if(1) + if (prob(stage_prob) && stage1) + to_chat(affected_mob, pick(stage1)) + if(2) + if (prob(stage_prob) && stage2) + to_chat(affected_mob, pick(stage2)) + if(3) + if (prob(stage_prob*2) && stage3) + to_chat(affected_mob, pick(stage3)) + if(4) + if (prob(stage_prob*2) && stage4) + to_chat(affected_mob, pick(stage4)) + if(5) + do_disease_transformation(affected_mob) + +/datum/disease/transformation/proc/do_disease_transformation(mob/living/affected_mob) + if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD) + if(stage5) + to_chat(affected_mob, pick(stage5)) + if(QDELETED(affected_mob)) + return + if(affected_mob.notransform) + return + affected_mob.notransform = 1 + for(var/obj/item/W in affected_mob.get_equipped_items(TRUE)) + affected_mob.dropItemToGround(W) + for(var/obj/item/I in affected_mob.held_items) + affected_mob.dropItemToGround(I) + var/mob/living/new_mob = new new_form(affected_mob.loc) + if(istype(new_mob)) + if(bantype && jobban_isbanned(affected_mob, bantype)) + replace_banned_player(new_mob) + new_mob.a_intent = INTENT_HARM + if(affected_mob.mind) + affected_mob.mind.transfer_to(new_mob) + else + affected_mob.transfer_ckey(new_mob) + + new_mob.name = affected_mob.real_name + new_mob.real_name = new_mob.name + qdel(affected_mob) + +/datum/disease/transformation/proc/replace_banned_player(var/mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed. + set waitfor = FALSE + + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, bantype, 50, affected_mob) + if(LAZYLEN(candidates)) + var/mob/dead/observer/C = pick(candidates) + to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") + message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.") + affected_mob.ghostize(0) + C.transfer_ckey(affected_mob) + else + to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!") + new_mob.death() + if (!QDELETED(new_mob)) + new_mob.ghostize(can_reenter_corpse = FALSE) + new_mob.key = null + +/datum/disease/transformation/jungle_fever + name = "Jungle Fever" + cure_text = "Death." + cures = list(/datum/reagent/medicine/adminordrazine) + spread_text = "Monkey Bites" + spread_flags = DISEASE_SPREAD_SPECIAL + viable_mobtypes = list(/mob/living/carbon/monkey, /mob/living/carbon/human) + permeability_mod = 1 + cure_chance = 1 + disease_flags = CAN_CARRY|CAN_RESIST + desc = "Monkeys with this disease will bite humans, causing humans to mutate into a monkey." + severity = DISEASE_SEVERITY_BIOHAZARD + stage_prob = 4 + visibility_flags = 0 + agent = "Kongey Vibrion M-909" + new_form = /mob/living/carbon/monkey + bantype = ROLE_MONKEY + + + stage1 = list() + stage2 = list() + stage3 = list() + stage4 = list("Your back hurts.", "You breathe through your mouth.", + "You have a craving for bananas.", "Your mind feels clouded.") + stage5 = list("You feel like monkeying around.") + +/datum/disease/transformation/jungle_fever/do_disease_transformation(mob/living/carbon/affected_mob) + if(affected_mob.mind && !is_monkey(affected_mob.mind)) + add_monkey(affected_mob.mind) + if(ishuman(affected_mob)) + var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + M.ventcrawler = VENTCRAWLER_ALWAYS + + +/datum/disease/transformation/jungle_fever/stage_act() + ..() + switch(stage) + if(2) + if(prob(2)) + to_chat(affected_mob, "Your [pick("back", "arm", "leg", "elbow", "head")] itches.") + if(3) + if(prob(4)) + to_chat(affected_mob, "You feel a stabbing pain in your head.") + affected_mob.confused += 10 + if(4) + if(prob(3)) + affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."), forced = "jungle fever") + +/datum/disease/transformation/jungle_fever/cure() + remove_monkey(affected_mob.mind) + ..() + +/datum/disease/transformation/jungle_fever/monkeymode + visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC + disease_flags = CAN_CARRY //no vaccines! no cure! + +/datum/disease/transformation/jungle_fever/monkeymode/after_add() + if(affected_mob && !is_monkey_leader(affected_mob.mind)) + visibility_flags = NONE + + + +/datum/disease/transformation/robot + + name = "Robotic Transformation" + cure_text = "An injection of copper." + cures = list(/datum/reagent/copper) + cure_chance = 5 + agent = "R2D2 Nanomachines" + desc = "This disease, actually acute nanomachine infection, converts the victim into a cyborg." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list() + stage2 = list("Your joints feel stiff.", "Beep...boop..") + stage3 = list("Your joints feel very stiff.", "Your skin feels loose.", "You can feel something move...inside.") + stage4 = list("Your skin feels very loose.", "You can feel... something...inside you.") + stage5 = list("Your skin feels as if it's about to burst off!") + new_form = /mob/living/silicon/robot + infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC) + bantype = "Cyborg" + +/datum/disease/transformation/robot/stage_act() + ..() + switch(stage) + if(3) + if (prob(8)) + affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"), forced = "robotic transformation") + if (prob(4)) + to_chat(affected_mob, "You feel a stabbing pain in your head.") + affected_mob.Unconscious(40) + if(4) + if (prob(20)) + affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."), forced = "robotic transformation") + + +/datum/disease/transformation/xeno + + name = "Xenomorph Transformation" + cure_text = "Spaceacillin & Glycerol" + cures = list(/datum/reagent/medicine/spaceacillin, /datum/reagent/glycerol) + cure_chance = 5 + agent = "Rip-LEY Alien Microbes" + desc = "This disease changes the victim into a xenomorph." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list() + stage2 = list("Your throat feels scratchy.", "Kill...") + stage3 = list("Your throat feels very scratchy.", "Your skin feels tight.", "You can feel something move...inside.") + stage4 = list("Your skin feels very tight.", "Your blood boils!", "You can feel... something...inside you.") + stage5 = list("Your skin feels as if it's about to burst off!") + new_form = /mob/living/carbon/alien/humanoid/hunter + bantype = ROLE_ALIEN + +/datum/disease/transformation/xeno/stage_act() + ..() + switch(stage) + if(3) + if (prob(4)) + to_chat(affected_mob, "You feel a stabbing pain in your head.") + affected_mob.Unconscious(40) + if(4) + if (prob(20)) + affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"), forced = "xenomorph transformation") + + +/datum/disease/transformation/slime + name = "Advanced Mutation Transformation" + cure_text = "frost oil" + cures = list(/datum/reagent/consumable/frostoil) + cure_chance = 80 + agent = "Advanced Mutation Toxin" + desc = "This highly concentrated extract converts anything into more of itself." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list("You don't feel very well.") + stage2 = list("Your skin feels a little slimy.") + stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") + stage4 = list("You are turning into a slime.") + stage5 = list("You have become a slime.") + new_form = /mob/living/simple_animal/slime/random + +/datum/disease/transformation/slime/stage_act() + ..() + switch(stage) + if(1) + if(ishuman(affected_mob) && affected_mob.dna) + if(affected_mob.dna.species.id == "slime" || affected_mob.dna.species.id == "stargazer" || affected_mob.dna.species.id == "lum") + stage = 5 + if(3) + if(ishuman(affected_mob)) + var/mob/living/carbon/human/human = affected_mob + if(human.dna.species.id != "slime" && affected_mob.dna.species.id != "stargazer" && affected_mob.dna.species.id != "lum") + human.set_species(/datum/species/jelly/slime) + +/datum/disease/transformation/corgi + name = "The Barkening" + cure_text = "Death" + cures = list(/datum/reagent/medicine/adminordrazine) + agent = "Fell Doge Majicks" + desc = "This disease transforms the victim into a corgi." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list("BARK.") + stage2 = list("You feel the need to wear silly hats.") + stage3 = list("Must... eat... chocolate....", "YAP") + stage4 = list("Visions of washing machines assail your mind!") + stage5 = list("AUUUUUU!!!") + new_form = /mob/living/simple_animal/pet/dog/corgi + +/datum/disease/transformation/corgi/stage_act() + ..() + switch(stage) + if(3) + if (prob(8)) + affected_mob.say(pick("YAP", "Woof!"), forced = "corgi transformation") + if(4) + if (prob(20)) + affected_mob.say(pick("Bark!", "AUUUUUU"), forced = "corgi transformation") + +/datum/disease/transformation/morph + name = "Gluttony's Blessing" + cure_text = "nothing" + cures = list(/datum/reagent/medicine/adminordrazine) + agent = "Gluttony's Blessing" + desc = "A 'gift' from somewhere terrible." + stage_prob = 20 + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list("Your stomach rumbles.") + stage2 = list("Your skin feels saggy.") + stage3 = list("Your appendages are melting away.", "Your limbs begin to lose their shape.") + stage4 = list("You're ravenous.") + stage5 = list("You have become a morph.") + new_form = /mob/living/simple_animal/hostile/morph + infectable_biotypes = list(MOB_ORGANIC, MOB_INORGANIC, MOB_UNDEAD) //magic! + +/datum/disease/transformation/gondola + name = "Gondola Transformation" + cure_text = "Condensed Capsaicin, ingested or injected." //getting pepper sprayed doesn't help + cures = list(/datum/reagent/consumable/condensedcapsaicin) //beats the hippie crap right out of your system + cure_chance = 80 + stage_prob = 5 + agent = "Tranquility" + desc = "Consuming the flesh of a Gondola comes at a terrible price." + severity = DISEASE_SEVERITY_BIOHAZARD + visibility_flags = 0 + stage1 = list("You seem a little lighter in your step.") + stage2 = list("You catch yourself smiling for no reason.") + stage3 = list("A cruel sense of calm overcomes you.", "You can't feel your arms!", "You let go of the urge to hurt clowns.") + stage4 = list("You can't feel your arms. It does not bother you anymore.", "You forgive the clown for hurting you.") + stage5 = list("You have become a Gondola.") + new_form = /mob/living/simple_animal/pet/gondola + +/datum/disease/transformation/gondola/stage_act() + ..() + switch(stage) + if(2) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) + if(3) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) + if(4) + if (prob(5)) + affected_mob.emote("smile") + if (prob(20)) + affected_mob.reagents.add_reagent(/datum/reagent/pax, 5) + if (prob(2)) + to_chat(affected_mob, "You let go of what you were holding.") + var/obj/item/I = affected_mob.get_active_held_item() + affected_mob.dropItemToGround(I) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index 244cc819d8..230a074bb1 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -1,117 +1,117 @@ -/datum/disease/wizarditis - name = "Wizarditis" - max_stages = 4 - spread_text = "Airborne" - cure_text = "The Manly Dorf" - cures = list(/datum/reagent/consumable/ethanol/manly_dorf) - cure_chance = 100 - agent = "Rincewindus Vulgaris" - 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 the Space Wizard Federation's existence. 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." - severity = DISEASE_SEVERITY_HARMFUL - required_organs = list(/obj/item/bodypart/head) - -/* -BIRUZ BENNAR -SCYAR NILA - teleport -NEC CANTIO - dis techno -EI NATH - shocking grasp -AULIE OXIN FIERA - knock -TARCOL MINTI ZHERI - forcewall -STI KALY - blind -*/ - -/datum/disease/wizarditis/stage_act() - ..() - - switch(stage) - if(2) - if(prob(1)&&prob(50)) - affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"), forced = "wizarditis") - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].") - - - if(3) - if(prob(1)&&prob(50)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"), forced = "wizarditis") - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].") - - if(4) - - if(prob(1)) - affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"), forced = "wizarditis") - return - if(prob(1)&&prob(50)) - to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") - spawn_wizard_clothes(50) - if(prob(1)&&prob(1)) - teleport() - return - - - -/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0) - if(ishuman(affected_mob)) - var/mob/living/carbon/human/H = affected_mob - if(prob(chance)) - if(!istype(H.head, /obj/item/clothing/head/wizard)) - if(!H.dropItemToGround(H.head)) - qdel(H.head) - H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), SLOT_HEAD) - return - if(prob(chance)) - if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe)) - if(!H.dropItemToGround(H.wear_suit)) - qdel(H.wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), SLOT_WEAR_SUIT) - return - if(prob(chance)) - if(!istype(H.shoes, /obj/item/clothing/shoes/sandal/magic)) - if(!H.dropItemToGround(H.shoes)) - qdel(H.shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), SLOT_SHOES) - return - else - var/mob/living/carbon/H = affected_mob - if(prob(chance)) - var/obj/item/staff/S = new(H) - if(!H.put_in_hands(S)) - qdel(S) - - -/datum/disease/wizarditis/proc/teleport() - var/list/theareas = get_areas_in_range(80, affected_mob) - for(var/area/space/S in theareas) - theareas -= S - - if(!theareas||!theareas.len) - return - - var/area/thearea = pick(theareas) - - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(T.z != affected_mob.z) - continue - if(T.name == "space") - continue - if(!T.density) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - - if(!L) - return - - affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!", forced = "wizarditis teleport") - affected_mob.forceMove(pick(L)) - - return +/datum/disease/wizarditis + name = "Wizarditis" + max_stages = 4 + spread_text = "Airborne" + cure_text = "The Manly Dorf" + cures = list(/datum/reagent/consumable/ethanol/manly_dorf) + cure_chance = 100 + agent = "Rincewindus Vulgaris" + 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 the Space Wizard Federation's existence. 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." + severity = DISEASE_SEVERITY_HARMFUL + required_organs = list(/obj/item/bodypart/head) + +/* +BIRUZ BENNAR +SCYAR NILA - teleport +NEC CANTIO - dis techno +EI NATH - shocking grasp +AULIE OXIN FIERA - knock +TARCOL MINTI ZHERI - forcewall +STI KALY - blind +*/ + +/datum/disease/wizarditis/stage_act() + ..() + + switch(stage) + if(2) + if(prob(1)&&prob(50)) + affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"), forced = "wizarditis") + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].") + + + if(3) + if(prob(1)&&prob(50)) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"), forced = "wizarditis") + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].") + + if(4) + + if(prob(1)) + affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"), forced = "wizarditis") + return + if(prob(1)&&prob(50)) + to_chat(affected_mob, "You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].") + spawn_wizard_clothes(50) + if(prob(1)&&prob(1)) + teleport() + return + + + +/datum/disease/wizarditis/proc/spawn_wizard_clothes(chance = 0) + if(ishuman(affected_mob)) + var/mob/living/carbon/human/H = affected_mob + if(prob(chance)) + if(!istype(H.head, /obj/item/clothing/head/wizard)) + if(!H.dropItemToGround(H.head)) + qdel(H.head) + H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(H), SLOT_HEAD) + return + if(prob(chance)) + if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe)) + if(!H.dropItemToGround(H.wear_suit)) + qdel(H.wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(H), SLOT_WEAR_SUIT) + return + if(prob(chance)) + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal/magic)) + if(!H.dropItemToGround(H.shoes)) + qdel(H.shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(H), SLOT_SHOES) + return + else + var/mob/living/carbon/H = affected_mob + if(prob(chance)) + var/obj/item/staff/S = new(H) + if(!H.put_in_hands(S)) + qdel(S) + + +/datum/disease/wizarditis/proc/teleport() + var/list/theareas = get_areas_in_range(80, affected_mob) + for(var/area/space/S in theareas) + theareas -= S + + if(!theareas||!theareas.len) + return + + var/area/thearea = pick(theareas) + + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(T.z != affected_mob.z) + continue + if(T.name == "space") + continue + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + + if(!L) + return + + affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!", forced = "wizarditis teleport") + affected_mob.forceMove(pick(L)) + + return diff --git a/code/datums/dna.dm b/code/datums/dna.dm index ccc5d97cf8..67dbbdfef7 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -1,435 +1,435 @@ - -/////////////////////////// DNA DATUM -/datum/dna - var/unique_enzymes - var/struc_enzymes - var/uni_identity - var/blood_type - var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man) - var/list/features = list("FFF") //first value is mutant color - var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings, - var/nameless = FALSE - var/custom_species //siiiiigh I guess this is important - var/list/mutations = list() //All mutations are from now on here - var/list/temporary_mutations = list() //Timers for temporary mutations - var/list/previous = list() //For temporary name/ui/ue/blood_type modifications - var/mob/living/holder - var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 - -/datum/dna/New(mob/living/new_holder) - if(istype(new_holder)) - holder = new_holder - -/datum/dna/Destroy() - if(iscarbon(holder)) - var/mob/living/carbon/cholder = holder - if(cholder.dna == src) - cholder.dna = null - holder = null - - if(delete_species) - QDEL_NULL(species) - - mutations.Cut() //This only references mutations, just dereference. - temporary_mutations.Cut() //^ - previous.Cut() //^ - - return ..() - -/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) - if(!istype(destination)) - return - destination.dna.unique_enzymes = unique_enzymes - destination.dna.uni_identity = uni_identity - destination.dna.blood_type = blood_type - destination.dna.features = features.Copy() - destination.set_species(species.type, icon_update=0) - destination.dna.real_name = real_name - destination.dna.nameless = nameless - destination.dna.custom_species = custom_species - destination.dna.temporary_mutations = temporary_mutations.Copy() - if(ishuman(destination)) - var/mob/living/carbon/human/H = destination - H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA - destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text - if(transfer_SE) - destination.dna.struc_enzymes = struc_enzymes - -/datum/dna/proc/copy_dna(datum/dna/new_dna) - new_dna.unique_enzymes = unique_enzymes - new_dna.struc_enzymes = struc_enzymes - new_dna.uni_identity = uni_identity - new_dna.blood_type = blood_type - new_dna.features = features.Copy() - new_dna.species = new species.type - new_dna.real_name = real_name - new_dna.nameless = nameless - new_dna.custom_species = custom_species - new_dna.mutations = mutations.Copy() - -/datum/dna/proc/add_mutation(mutation_name) - var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] - HM.on_acquiring(holder) - -/datum/dna/proc/remove_mutation(mutation_name) - var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] - HM.on_losing(holder) - -/datum/dna/proc/check_mutation(mutation_name) - var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] - return mutations.Find(HM) - -/datum/dna/proc/remove_all_mutations() - remove_mutation_group(mutations) - -/datum/dna/proc/remove_mutation_group(list/group) - if(!group) - return - for(var/datum/mutation/human/HM in group) - HM.force_lose(holder) - -/datum/dna/proc/generate_uni_identity() - . = "" - var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) - - L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2) - if(ishuman(holder)) - var/mob/living/carbon/human/H = holder - if(!GLOB.hair_styles_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list) - L[DNA_HAIR_STYLE_BLOCK] = construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len) - L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) - if(!GLOB.facial_hair_styles_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list) - L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len) - L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) - L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) - L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) - L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"]) - L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"]) - L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"]) - if(!GLOB.mam_tails_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list) - L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) - if(!GLOB.mam_ears_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list) - L[DNA_MUTANTEAR_BLOCK] = construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len) - if(!GLOB.mam_body_markings_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list) - L[DNA_MUTANTMARKING_BLOCK] = construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len) - if(!GLOB.taur_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list) - L[DNA_TAUR_BLOCK] = construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len) - - for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) - if(L[i]) - . += L[i] - else - . += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) - return . - -/datum/dna/proc/generate_struc_enzymes() - var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS) - var/result = "" - for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations) - if(A.name == RACEMUT && ismonkey(holder)) - sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE) - mutations |= A - else - sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6")) - - for(var/B in sorting) - result += B - return result - -/datum/dna/proc/generate_unique_enzymes() - . = "" - if(istype(holder)) - real_name = holder.real_name - . += md5(holder.real_name) - else - . += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters) - return . - -/datum/dna/proc/update_ui_block(blocknumber) - if(!blocknumber || !ishuman(holder)) - return - var/mob/living/carbon/human/H = holder - switch(blocknumber) - if(DNA_HAIR_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) - if(DNA_FACIAL_HAIR_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) - if(DNA_SKIN_TONE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) - if(DNA_EYE_COLOR_BLOCK) - setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) - if(DNA_GENDER_BLOCK) - setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2)) - if(DNA_FACIAL_HAIR_STYLE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)) - if(DNA_HAIR_STYLE_BLOCK) - setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)) - if(DNA_COLOR_ONE_BLOCK) - sanitize_hexcolor(features["mcolor"]) - if(DNA_COLOR_TWO_BLOCK) - sanitize_hexcolor(features["mcolor2"]) - if(DNA_COLOR_THREE_BLOCK) - sanitize_hexcolor(features["mcolor3"]) - if(DNA_MUTANTTAIL_BLOCK) - construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) - if(DNA_MUTANTEAR_BLOCK) - construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len) - if(DNA_MUTANTMARKING_BLOCK) - construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len) - if(DNA_TAUR_BLOCK) - construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len) - -/datum/dna/proc/is_same_as(datum/dna/D) - if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species) - if(species.type == D.species.type && features == D.features && blood_type == D.blood_type) - return 1 - return 0 - -//used to update dna UI, UE, and dna.real_name. -/datum/dna/proc/update_dna_identity() - uni_identity = generate_uni_identity() - unique_enzymes = generate_unique_enzymes() - -/datum/dna/proc/initialize_dna(newblood_type) - if(newblood_type) - blood_type = newblood_type - unique_enzymes = generate_unique_enzymes() - uni_identity = generate_uni_identity() - struc_enzymes = generate_struc_enzymes() - features = random_features() - - -/datum/dna/stored //subtype used by brain mob's stored_dna - -/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna. - return - -/datum/dna/stored/remove_mutation(mutation_name) - return - -/datum/dna/stored/check_mutation(mutation_name) - return - -/datum/dna/stored/remove_all_mutations() - return - -/datum/dna/stored/remove_mutation_group(list/group) - return - -/////////////////////////// DNA MOB-PROCS ////////////////////// - -/mob/proc/set_species(datum/species/mrace, icon_update = 1) - return - -/mob/living/brain/set_species(datum/species/mrace, icon_update = 1) - if(mrace) - if(ispath(mrace)) - stored_dna.species = new mrace() - else - stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human - - -/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) - if(mrace && has_dna()) - var/datum/species/new_race - if(ispath(mrace)) - new_race = new mrace - else if(istype(mrace)) - new_race = mrace - else - return - dna.species.on_species_loss(src, new_race, pref_load) - var/datum/species/old_species = dna.species - dna.species = new_race - dna.species.on_species_gain(src, old_species, pref_load) - -/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) - ..() - if(icon_update) - update_body() - update_hair() - update_mutations_overlay()// no lizard with human hulk overlay please. - - -/mob/proc/has_dna() - return - -/mob/living/carbon/has_dna() - return dna - - -/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures) - - if(newfeatures) - dna.features = newfeatures - flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text - - if(mrace) - var/datum/species/newrace = new mrace.type - newrace.copy_properties_from(mrace) - set_species(newrace, icon_update=0) - - if(newreal_name) - real_name = newreal_name - dna.generate_unique_enzymes() - - if(newblood_type) - dna.blood_type = newblood_type - - if(ui) - dna.uni_identity = ui - updateappearance(icon_update=0) - - if(se) - dna.struc_enzymes = se - domutcheck() - - if(mrace || newfeatures || ui) - update_body() - update_hair() - update_body_parts() - update_mutations_overlay() - - -/mob/living/carbon/proc/create_dna() - dna = new /datum/dna(src) - if(!dna.species) - var/rando_race = pick(GLOB.roundstart_races) - dna.species = new rando_race() - -//proc used to update the mob's appearance after its dna UI has been changed -/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) - if(!has_dna()) - return - gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE - -/mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) - ..() - var/structure = dna.uni_identity - hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK)) - facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) - skin_tone = GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] - eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) - facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)] - hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)] - if(icon_update) - update_body() - update_hair() - if(mutcolor_update) - update_body_parts() - if(mutations_overlay_update) - update_mutations_overlay() - - -/mob/proc/domutcheck() - return - -/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance - if(!has_dna()) - return - - for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations) - if(ismob(A.check_block(src, force_powers))) - return //we got monkeyized/humanized, this mob will be deleted, no need to continue. - - update_mutations_overlay() - - - -/////////////////////////// DNA HELPER-PROCS ////////////////////////////// -/proc/getleftblocks(input,blocknumber,blocksize) - if(blocknumber > 1) - return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) - -/proc/getrightblocks(input,blocknumber,blocksize) - if(blocknumber < (length(input)/blocksize)) - return copytext(input,blocksize*blocknumber+1,length(input)+1) - -/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) - return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) - -/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) - if(!istring || !blocknumber || !replacement || !blocksize) - return 0 - return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) - -/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2) - if(!has_dna()) - return - var/datum/mutation/human/num = pick(candidates) - . = num.force_give(src) - -/mob/living/carbon/proc/randmutb() - if(!has_dna()) - return - var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT]) - . = HM.force_give(src) - -/mob/living/carbon/proc/randmutg() - if(!has_dna()) - return - var/datum/mutation/human/HM = pick(GLOB.good_mutations) - . = HM.force_give(src) - -/mob/living/carbon/proc/randmutvg() - if(!has_dna()) - return - var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM]) - . = HM.force_give(src) - -/mob/living/carbon/proc/randmuti() - if(!has_dna()) - return - var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) - var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - dna.uni_identity = newdna - updateappearance(mutations_overlay_update=1) - -/mob/living/carbon/proc/clean_dna() - if(!has_dna()) - return - dna.remove_all_mutations() - -/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2) - clean_dna() - randmut(candidates, difficulty) - -/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) - if(!M.has_dna()) - return 0 - if(se) - for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) - if(prob(probability)) - M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - M.domutcheck() - if(ui) - for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) - if(prob(probability)) - M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) - M.updateappearance(mutations_overlay_update=1) - return 1 - -//value in range 1 to values. values must be greater than 0 -//all arguments assumed to be positive integers -/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE) - var/width = round((16**blocksize)/values) - if(value < 1) - value = 1 - value = (value * width) - rand(1,width) - return num2hex(value, blocksize) - -//value is hex -/proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE) - var/width = round((16**blocksize)/values) - value = round(hex2num(value) / width) + 1 - if(value > values) - value = values - return value - -/////////////////////////// DNA HELPER-PROCS + +/////////////////////////// DNA DATUM +/datum/dna + var/unique_enzymes + var/struc_enzymes + var/uni_identity + var/blood_type + var/datum/species/species = new /datum/species/human //The type of mutant race the player is if applicable (i.e. potato-man) + var/list/features = list("FFF") //first value is mutant color + var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings, + var/nameless = FALSE + var/custom_species //siiiiigh I guess this is important + var/list/mutations = list() //All mutations are from now on here + var/list/temporary_mutations = list() //Timers for temporary mutations + var/list/previous = list() //For temporary name/ui/ue/blood_type modifications + var/mob/living/holder + var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 + +/datum/dna/New(mob/living/new_holder) + if(istype(new_holder)) + holder = new_holder + +/datum/dna/Destroy() + if(iscarbon(holder)) + var/mob/living/carbon/cholder = holder + if(cholder.dna == src) + cholder.dna = null + holder = null + + if(delete_species) + QDEL_NULL(species) + + mutations.Cut() //This only references mutations, just dereference. + temporary_mutations.Cut() //^ + previous.Cut() //^ + + return ..() + +/datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = 0) + if(!istype(destination)) + return + destination.dna.unique_enzymes = unique_enzymes + destination.dna.uni_identity = uni_identity + destination.dna.blood_type = blood_type + destination.dna.features = features.Copy() + destination.set_species(species.type, icon_update=0) + destination.dna.real_name = real_name + destination.dna.nameless = nameless + destination.dna.custom_species = custom_species + destination.dna.temporary_mutations = temporary_mutations.Copy() + if(ishuman(destination)) + var/mob/living/carbon/human/H = destination + H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA + destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text + if(transfer_SE) + destination.dna.struc_enzymes = struc_enzymes + +/datum/dna/proc/copy_dna(datum/dna/new_dna) + new_dna.unique_enzymes = unique_enzymes + new_dna.struc_enzymes = struc_enzymes + new_dna.uni_identity = uni_identity + new_dna.blood_type = blood_type + new_dna.features = features.Copy() + new_dna.species = new species.type + new_dna.real_name = real_name + new_dna.nameless = nameless + new_dna.custom_species = custom_species + new_dna.mutations = mutations.Copy() + +/datum/dna/proc/add_mutation(mutation_name) + var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] + HM.on_acquiring(holder) + +/datum/dna/proc/remove_mutation(mutation_name) + var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] + HM.on_losing(holder) + +/datum/dna/proc/check_mutation(mutation_name) + var/datum/mutation/human/HM = GLOB.mutations_list[mutation_name] + return mutations.Find(HM) + +/datum/dna/proc/remove_all_mutations() + remove_mutation_group(mutations) + +/datum/dna/proc/remove_mutation_group(list/group) + if(!group) + return + for(var/datum/mutation/human/HM in group) + HM.force_lose(holder) + +/datum/dna/proc/generate_uni_identity() + . = "" + var/list/L = new /list(DNA_UNI_IDENTITY_BLOCKS) + + L[DNA_GENDER_BLOCK] = construct_block((holder.gender!=MALE)+1, 2) + if(ishuman(holder)) + var/mob/living/carbon/human/H = holder + if(!GLOB.hair_styles_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/hair,GLOB.hair_styles_list, GLOB.hair_styles_male_list, GLOB.hair_styles_female_list) + L[DNA_HAIR_STYLE_BLOCK] = construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len) + L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) + if(!GLOB.facial_hair_styles_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list) + L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len) + L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) + L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) + L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) + L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"]) + L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"]) + L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"]) + if(!GLOB.mam_tails_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list) + L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) + if(!GLOB.mam_ears_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list) + L[DNA_MUTANTEAR_BLOCK] = construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len) + if(!GLOB.mam_body_markings_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list) + L[DNA_MUTANTMARKING_BLOCK] = construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len) + if(!GLOB.taur_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/taur, GLOB.taur_list) + L[DNA_TAUR_BLOCK] = construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len) + + for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) + if(L[i]) + . += L[i] + else + . += random_string(DNA_BLOCK_SIZE,GLOB.hex_characters) + return . + +/datum/dna/proc/generate_struc_enzymes() + var/list/sorting = new /list(DNA_STRUC_ENZYMES_BLOCKS) + var/result = "" + for(var/datum/mutation/human/A in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations) + if(A.name == RACEMUT && ismonkey(holder)) + sorting[A.dna_block] = num2hex(A.lowest_value + rand(0, 256 * 6), DNA_BLOCK_SIZE) + mutations |= A + else + sorting[A.dna_block] = random_string(DNA_BLOCK_SIZE, list("0","1","2","3","4","5","6")) + + for(var/B in sorting) + result += B + return result + +/datum/dna/proc/generate_unique_enzymes() + . = "" + if(istype(holder)) + real_name = holder.real_name + . += md5(holder.real_name) + else + . += random_string(DNA_UNIQUE_ENZYMES_LEN, GLOB.hex_characters) + return . + +/datum/dna/proc/update_ui_block(blocknumber) + if(!blocknumber || !ishuman(holder)) + return + var/mob/living/carbon/human/H = holder + switch(blocknumber) + if(DNA_HAIR_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.hair_color)) + if(DNA_FACIAL_HAIR_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.facial_hair_color)) + if(DNA_SKIN_TONE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len)) + if(DNA_EYE_COLOR_BLOCK) + setblock(uni_identity, blocknumber, sanitize_hexcolor(H.eye_color)) + if(DNA_GENDER_BLOCK) + setblock(uni_identity, blocknumber, construct_block((H.gender!=MALE)+1, 2)) + if(DNA_FACIAL_HAIR_STYLE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(GLOB.facial_hair_styles_list.Find(H.facial_hair_style), GLOB.facial_hair_styles_list.len)) + if(DNA_HAIR_STYLE_BLOCK) + setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)) + if(DNA_COLOR_ONE_BLOCK) + sanitize_hexcolor(features["mcolor"]) + if(DNA_COLOR_TWO_BLOCK) + sanitize_hexcolor(features["mcolor2"]) + if(DNA_COLOR_THREE_BLOCK) + sanitize_hexcolor(features["mcolor3"]) + if(DNA_MUTANTTAIL_BLOCK) + construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) + if(DNA_MUTANTEAR_BLOCK) + construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len) + if(DNA_MUTANTMARKING_BLOCK) + construct_block(GLOB.mam_body_markings_list.Find(features["mam_body_markings"]), GLOB.mam_body_markings_list.len) + if(DNA_TAUR_BLOCK) + construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len) + +/datum/dna/proc/is_same_as(datum/dna/D) + if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species) + if(species.type == D.species.type && features == D.features && blood_type == D.blood_type) + return 1 + return 0 + +//used to update dna UI, UE, and dna.real_name. +/datum/dna/proc/update_dna_identity() + uni_identity = generate_uni_identity() + unique_enzymes = generate_unique_enzymes() + +/datum/dna/proc/initialize_dna(newblood_type) + if(newblood_type) + blood_type = newblood_type + unique_enzymes = generate_unique_enzymes() + uni_identity = generate_uni_identity() + struc_enzymes = generate_struc_enzymes() + features = random_features() + + +/datum/dna/stored //subtype used by brain mob's stored_dna + +/datum/dna/stored/add_mutation(mutation_name) //no mutation changes on stored dna. + return + +/datum/dna/stored/remove_mutation(mutation_name) + return + +/datum/dna/stored/check_mutation(mutation_name) + return + +/datum/dna/stored/remove_all_mutations() + return + +/datum/dna/stored/remove_mutation_group(list/group) + return + +/////////////////////////// DNA MOB-PROCS ////////////////////// + +/mob/proc/set_species(datum/species/mrace, icon_update = 1) + return + +/mob/living/brain/set_species(datum/species/mrace, icon_update = 1) + if(mrace) + if(ispath(mrace)) + stored_dna.species = new mrace() + else + stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human + + +/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) + if(mrace && has_dna()) + var/datum/species/new_race + if(ispath(mrace)) + new_race = new mrace + else if(istype(mrace)) + new_race = mrace + else + return + dna.species.on_species_loss(src, new_race, pref_load) + var/datum/species/old_species = dna.species + dna.species = new_race + dna.species.on_species_gain(src, old_species, pref_load) + +/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE) + ..() + if(icon_update) + update_body() + update_hair() + update_mutations_overlay()// no lizard with human hulk overlay please. + + +/mob/proc/has_dna() + return + +/mob/living/carbon/has_dna() + return dna + + +/mob/living/carbon/human/proc/hardset_dna(ui, se, newreal_name, newblood_type, datum/species/mrace, newfeatures) + + if(newfeatures) + dna.features = newfeatures + flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text + + if(mrace) + var/datum/species/newrace = new mrace.type + newrace.copy_properties_from(mrace) + set_species(newrace, icon_update=0) + + if(newreal_name) + real_name = newreal_name + dna.generate_unique_enzymes() + + if(newblood_type) + dna.blood_type = newblood_type + + if(ui) + dna.uni_identity = ui + updateappearance(icon_update=0) + + if(se) + dna.struc_enzymes = se + domutcheck() + + if(mrace || newfeatures || ui) + update_body() + update_hair() + update_body_parts() + update_mutations_overlay() + + +/mob/living/carbon/proc/create_dna() + dna = new /datum/dna(src) + if(!dna.species) + var/rando_race = pick(GLOB.roundstart_races) + dna.species = new rando_race() + +//proc used to update the mob's appearance after its dna UI has been changed +/mob/living/carbon/proc/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) + if(!has_dna()) + return + gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE + +/mob/living/carbon/human/updateappearance(icon_update=1, mutcolor_update=0, mutations_overlay_update=0) + ..() + var/structure = dna.uni_identity + hair_color = sanitize_hexcolor(getblock(structure, DNA_HAIR_COLOR_BLOCK)) + facial_hair_color = sanitize_hexcolor(getblock(structure, DNA_FACIAL_HAIR_COLOR_BLOCK)) + skin_tone = GLOB.skin_tones[deconstruct_block(getblock(structure, DNA_SKIN_TONE_BLOCK), GLOB.skin_tones.len)] + eye_color = sanitize_hexcolor(getblock(structure, DNA_EYE_COLOR_BLOCK)) + facial_hair_style = GLOB.facial_hair_styles_list[deconstruct_block(getblock(structure, DNA_FACIAL_HAIR_STYLE_BLOCK), GLOB.facial_hair_styles_list.len)] + hair_style = GLOB.hair_styles_list[deconstruct_block(getblock(structure, DNA_HAIR_STYLE_BLOCK), GLOB.hair_styles_list.len)] + if(icon_update) + update_body() + update_hair() + if(mutcolor_update) + update_body_parts() + if(mutations_overlay_update) + update_mutations_overlay() + + +/mob/proc/domutcheck() + return + +/mob/living/carbon/domutcheck(force_powers=0) //Set force_powers to 1 to bypass the power chance + if(!has_dna()) + return + + for(var/datum/mutation/human/A in GLOB.good_mutations | GLOB.bad_mutations | GLOB.not_good_mutations) + if(ismob(A.check_block(src, force_powers))) + return //we got monkeyized/humanized, this mob will be deleted, no need to continue. + + update_mutations_overlay() + + + +/////////////////////////// DNA HELPER-PROCS ////////////////////////////// +/proc/getleftblocks(input,blocknumber,blocksize) + if(blocknumber > 1) + return copytext(input,1,((blocksize*blocknumber)-(blocksize-1))) + +/proc/getrightblocks(input,blocknumber,blocksize) + if(blocknumber < (length(input)/blocksize)) + return copytext(input,blocksize*blocknumber+1,length(input)+1) + +/proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) + return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) + +/proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) + if(!istring || !blocknumber || !replacement || !blocksize) + return 0 + return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) + +/mob/living/carbon/proc/randmut(list/candidates, difficulty = 2) + if(!has_dna()) + return + var/datum/mutation/human/num = pick(candidates) + . = num.force_give(src) + +/mob/living/carbon/proc/randmutb() + if(!has_dna()) + return + var/datum/mutation/human/HM = pick((GLOB.bad_mutations | GLOB.not_good_mutations) - GLOB.mutations_list[RACEMUT]) + . = HM.force_give(src) + +/mob/living/carbon/proc/randmutg() + if(!has_dna()) + return + var/datum/mutation/human/HM = pick(GLOB.good_mutations) + . = HM.force_give(src) + +/mob/living/carbon/proc/randmutvg() + if(!has_dna()) + return + var/datum/mutation/human/HM = pick((GLOB.good_mutations) - GLOB.mutations_list[HULK] - GLOB.mutations_list[DWARFISM]) + . = HM.force_give(src) + +/mob/living/carbon/proc/randmuti() + if(!has_dna()) + return + var/num = rand(1, DNA_UNI_IDENTITY_BLOCKS) + var/newdna = setblock(dna.uni_identity, num, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + dna.uni_identity = newdna + updateappearance(mutations_overlay_update=1) + +/mob/living/carbon/proc/clean_dna() + if(!has_dna()) + return + dna.remove_all_mutations() + +/mob/living/carbon/proc/clean_randmut(list/candidates, difficulty = 2) + clean_dna() + randmut(candidates, difficulty) + +/proc/scramble_dna(mob/living/carbon/M, ui=FALSE, se=FALSE, probability) + if(!M.has_dna()) + return 0 + if(se) + for(var/i=1, i<=DNA_STRUC_ENZYMES_BLOCKS, i++) + if(prob(probability)) + M.dna.struc_enzymes = setblock(M.dna.struc_enzymes, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + M.domutcheck() + if(ui) + for(var/i=1, i<=DNA_UNI_IDENTITY_BLOCKS, i++) + if(prob(probability)) + M.dna.uni_identity = setblock(M.dna.uni_identity, i, random_string(DNA_BLOCK_SIZE, GLOB.hex_characters)) + M.updateappearance(mutations_overlay_update=1) + return 1 + +//value in range 1 to values. values must be greater than 0 +//all arguments assumed to be positive integers +/proc/construct_block(value, values, blocksize=DNA_BLOCK_SIZE) + var/width = round((16**blocksize)/values) + if(value < 1) + value = 1 + value = (value * width) - rand(1,width) + return num2hex(value, blocksize) + +//value is hex +/proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE) + var/width = round((16**blocksize)/values) + value = round(hex2num(value) / width) + 1 + if(value > values) + value = values + return value + +/////////////////////////// DNA HELPER-PROCS diff --git a/code/datums/forced_movement.dm b/code/datums/forced_movement.dm index 3cdf2b1fd8..33ea4a177b 100644 --- a/code/datums/forced_movement.dm +++ b/code/datums/forced_movement.dm @@ -1,90 +1,90 @@ -//Just new and forget -/datum/forced_movement - var/atom/movable/victim - var/atom/target - var/last_processed - var/steps_per_tick - var/allow_climbing - var/datum/callback/on_step - var/moved_at_all = FALSE - //as fast as ssfastprocess -/datum/forced_movement/New(atom/movable/_victim, atom/_target, _steps_per_tick = 0.5, _allow_climbing = FALSE, datum/callback/_on_step = null) - victim = _victim - target = _target - steps_per_tick = _steps_per_tick - allow_climbing = _allow_climbing - on_step = _on_step - - . = ..() - - if(_victim && _target && _steps_per_tick && !_victim.force_moving) - last_processed = world.time - _victim.force_moving = src - START_PROCESSING(SSfastprocess, src) - else - qdel(src) //if you want to overwrite the current forced movement, call qdel(victim.force_moving) before creating this - -/datum/forced_movement/Destroy() - if(victim.force_moving == src) - victim.force_moving = null - if(moved_at_all) - victim.forceMove(victim.loc) //get the side effects of moving here that require us to currently not be force_moving aka reslipping on ice - STOP_PROCESSING(SSfastprocess, src) - victim = null - target = null - return ..() - -/datum/forced_movement/process() - if(QDELETED(victim) || !victim.loc || QDELETED(target) || !target.loc) - qdel(src) - return - var/steps_to_take = round(steps_per_tick * (world.time - last_processed)) - if(steps_to_take) - for(var/i in 1 to steps_to_take) - if(TryMove()) - moved_at_all = TRUE - if(on_step) - on_step.InvokeAsync() - else - qdel(src) - return - last_processed = world.time - -/datum/forced_movement/proc/TryMove(recursive = FALSE) - var/atom/movable/vic = victim //sanic - var/atom/tar = target - - if(!recursive) - . = step_towards(vic, tar) - - //shit way for getting around corners - if(!.) - if(tar.x > vic.x) - if(step(vic, EAST)) - . = TRUE - else if(tar.x < vic.x) - if(step(vic, WEST)) - . = TRUE - - if(!.) - if(tar.y > vic.y) - if(step(vic, NORTH)) - . = TRUE - else if(tar.y < vic.y) - if(step(vic, SOUTH)) - . = TRUE - - if(!.) - if(recursive) - return FALSE - else - . = TryMove(TRUE) - - . = . && (vic.loc != tar.loc) - -/mob/Bump(atom/A) - . = ..() - if(force_moving && force_moving.allow_climbing && isstructure(A)) - var/obj/structure/S = A - if(S.climbable) - S.do_climb(src) +//Just new and forget +/datum/forced_movement + var/atom/movable/victim + var/atom/target + var/last_processed + var/steps_per_tick + var/allow_climbing + var/datum/callback/on_step + var/moved_at_all = FALSE + //as fast as ssfastprocess +/datum/forced_movement/New(atom/movable/_victim, atom/_target, _steps_per_tick = 0.5, _allow_climbing = FALSE, datum/callback/_on_step = null) + victim = _victim + target = _target + steps_per_tick = _steps_per_tick + allow_climbing = _allow_climbing + on_step = _on_step + + . = ..() + + if(_victim && _target && _steps_per_tick && !_victim.force_moving) + last_processed = world.time + _victim.force_moving = src + START_PROCESSING(SSfastprocess, src) + else + qdel(src) //if you want to overwrite the current forced movement, call qdel(victim.force_moving) before creating this + +/datum/forced_movement/Destroy() + if(victim.force_moving == src) + victim.force_moving = null + if(moved_at_all) + victim.forceMove(victim.loc) //get the side effects of moving here that require us to currently not be force_moving aka reslipping on ice + STOP_PROCESSING(SSfastprocess, src) + victim = null + target = null + return ..() + +/datum/forced_movement/process() + if(QDELETED(victim) || !victim.loc || QDELETED(target) || !target.loc) + qdel(src) + return + var/steps_to_take = round(steps_per_tick * (world.time - last_processed)) + if(steps_to_take) + for(var/i in 1 to steps_to_take) + if(TryMove()) + moved_at_all = TRUE + if(on_step) + on_step.InvokeAsync() + else + qdel(src) + return + last_processed = world.time + +/datum/forced_movement/proc/TryMove(recursive = FALSE) + var/atom/movable/vic = victim //sanic + var/atom/tar = target + + if(!recursive) + . = step_towards(vic, tar) + + //shit way for getting around corners + if(!.) + if(tar.x > vic.x) + if(step(vic, EAST)) + . = TRUE + else if(tar.x < vic.x) + if(step(vic, WEST)) + . = TRUE + + if(!.) + if(tar.y > vic.y) + if(step(vic, NORTH)) + . = TRUE + else if(tar.y < vic.y) + if(step(vic, SOUTH)) + . = TRUE + + if(!.) + if(recursive) + return FALSE + else + . = TryMove(TRUE) + + . = . && (vic.loc != tar.loc) + +/mob/Bump(atom/A) + . = ..() + if(force_moving && force_moving.allow_climbing && isstructure(A)) + var/obj/structure/S = A + if(S.climbable) + S.do_climb(src) diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index c73d359bf1..420602cc7f 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -1,122 +1,122 @@ -/datum/getrev - var/commit // git rev-parse HEAD - var/date - var/originmastercommit // git rev-parse origin/master - var/list/testmerge = list() - -/datum/getrev/New() - testmerge = world.TgsTestMerges() - var/datum/tgs_revision_information/revinfo = world.TgsRevision() - if(revinfo) - commit = revinfo.commit - originmastercommit = revinfo.origin_commit - else - commit = rustg_git_revparse("HEAD") - if(commit) - date = rustg_git_commit_date(commit) - originmastercommit = rustg_git_revparse("origin/master") - - // goes to DD log and config_error.txt - log_world(get_log_message()) - -/datum/getrev/proc/get_log_message() - var/list/msg = list() - msg += "Running /tg/ revision: [date]" - if(originmastercommit) - msg += "origin/master: [originmastercommit]" - - for(var/line in testmerge) - var/datum/tgs_revision_information/test_merge/tm = line - msg += "Test merge active of PR #[tm.number] commit [tm.commit]" - - if(commit && commit != originmastercommit) - msg += "HEAD: [commit]" - else if(!originmastercommit) - msg += "No commit information" - - return msg.Join("\n") - -/datum/getrev/proc/GetTestMergeInfo(header = TRUE) - if(!testmerge.len) - return "" - . = header ? "The following pull requests are currently test merged:
    " : "" - for(var/line in testmerge) - var/datum/tgs_revision_information/test_merge/tm = line - var/cm = tm.pull_request_commit - var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11))) - if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder)) - continue - . += "#[tm.number][details]
    " - -/client/verb/showrevinfo() - set category = "OOC" - set name = "Show Server Revision" - set desc = "Check the current server code revision" - - var/list/msg = list("") - // Round ID - if(GLOB.round_id) - msg += "Round ID: [GLOB.round_id]" - - msg += "BYOND Version: [world.byond_version].[world.byond_build]" - if(DM_VERSION != world.byond_version || DM_BUILD != world.byond_build) - msg += "Compiled with BYOND Version: [DM_VERSION].[DM_BUILD]" - - // Revision information - var/datum/getrev/revdata = GLOB.revdata - msg += "Server revision compiled on: [revdata.date]" - var/pc = revdata.originmastercommit - if(pc) - msg += "Master commit: [pc]" - if(revdata.testmerge.len) - msg += revdata.GetTestMergeInfo() - if(revdata.commit && revdata.commit != revdata.originmastercommit) - msg += "Local commit: [revdata.commit]" - else if(!pc) - msg += "No commit information" - if(world.TgsAvailable()) - msg += "Server tools version: [world.TgsVersion()]" - - // Game mode odds - msg += "
    Current Informational Settings:" - msg += "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]" - msg += "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]" - msg += "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]" - msg += "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]" - msg += "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_list/continuous))] of [config.modes.len] roundtypes" - msg += "Allow Midround Antagonists: [length(CONFIG_GET(keyed_list/midround_antag))] of [config.modes.len] roundtypes" - if(CONFIG_GET(flag/show_game_type_odds)) - var/list/probabilities = CONFIG_GET(keyed_list/probability) - if(SSticker.IsRoundInProgress()) - var/prob_sum = 0 - var/current_odds_differ = FALSE - var/list/probs = list() - var/list/modes = config.gamemode_cache - var/list/min_pop = CONFIG_GET(keyed_list/min_pop) - var/list/max_pop = CONFIG_GET(keyed_list/max_pop) - for(var/mode in modes) - var/datum/game_mode/M = mode - var/ctag = initial(M.config_tag) - if(!(ctag in probabilities)) - continue - if((min_pop[ctag] && (min_pop[ctag] > SSticker.totalPlayersReady)) || (max_pop[ctag] && (max_pop[ctag] < SSticker.totalPlayersReady)) || (initial(M.required_players) > SSticker.totalPlayersReady)) - current_odds_differ = TRUE - continue - probs[ctag] = 1 - prob_sum += probabilities[ctag] - if(current_odds_differ) - msg += "Game Mode Odds for current round:" - for(var/ctag in probs) - if(probabilities[ctag] > 0) - var/percentage = round(probabilities[ctag] / prob_sum * 100, 0.1) - msg += "[ctag] [percentage]%" - - msg += "All Game Mode Odds:" - var/sum = 0 - for(var/ctag in probabilities) - sum += probabilities[ctag] - for(var/ctag in probabilities) - if(probabilities[ctag] > 0) - var/percentage = round(probabilities[ctag] / sum * 100, 0.1) - msg += "[ctag] [percentage]%" +/datum/getrev + var/commit // git rev-parse HEAD + var/date + var/originmastercommit // git rev-parse origin/master + var/list/testmerge = list() + +/datum/getrev/New() + testmerge = world.TgsTestMerges() + var/datum/tgs_revision_information/revinfo = world.TgsRevision() + if(revinfo) + commit = revinfo.commit + originmastercommit = revinfo.origin_commit + else + commit = rustg_git_revparse("HEAD") + if(commit) + date = rustg_git_commit_date(commit) + originmastercommit = rustg_git_revparse("origin/master") + + // goes to DD log and config_error.txt + log_world(get_log_message()) + +/datum/getrev/proc/get_log_message() + var/list/msg = list() + msg += "Running /tg/ revision: [date]" + if(originmastercommit) + msg += "origin/master: [originmastercommit]" + + for(var/line in testmerge) + var/datum/tgs_revision_information/test_merge/tm = line + msg += "Test merge active of PR #[tm.number] commit [tm.commit]" + + if(commit && commit != originmastercommit) + msg += "HEAD: [commit]" + else if(!originmastercommit) + msg += "No commit information" + + return msg.Join("\n") + +/datum/getrev/proc/GetTestMergeInfo(header = TRUE) + if(!testmerge.len) + return "" + . = header ? "The following pull requests are currently test merged:
    " : "" + for(var/line in testmerge) + var/datum/tgs_revision_information/test_merge/tm = line + var/cm = tm.pull_request_commit + var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext(cm, 1, min(length(cm), 11))) + if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder)) + continue + . += "#[tm.number][details]
    " + +/client/verb/showrevinfo() + set category = "OOC" + set name = "Show Server Revision" + set desc = "Check the current server code revision" + + var/list/msg = list("") + // Round ID + if(GLOB.round_id) + msg += "Round ID: [GLOB.round_id]" + + msg += "BYOND Version: [world.byond_version].[world.byond_build]" + if(DM_VERSION != world.byond_version || DM_BUILD != world.byond_build) + msg += "Compiled with BYOND Version: [DM_VERSION].[DM_BUILD]" + + // Revision information + var/datum/getrev/revdata = GLOB.revdata + msg += "Server revision compiled on: [revdata.date]" + var/pc = revdata.originmastercommit + if(pc) + msg += "Master commit: [pc]" + if(revdata.testmerge.len) + msg += revdata.GetTestMergeInfo() + if(revdata.commit && revdata.commit != revdata.originmastercommit) + msg += "Local commit: [revdata.commit]" + else if(!pc) + msg += "No commit information" + if(world.TgsAvailable()) + msg += "Server tools version: [world.TgsVersion()]" + + // Game mode odds + msg += "
    Current Informational Settings:" + msg += "Protect Authority Roles From Traitor: [CONFIG_GET(flag/protect_roles_from_antagonist)]" + msg += "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]" + msg += "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]" + msg += "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]" + msg += "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_list/continuous))] of [config.modes.len] roundtypes" + msg += "Allow Midround Antagonists: [length(CONFIG_GET(keyed_list/midround_antag))] of [config.modes.len] roundtypes" + if(CONFIG_GET(flag/show_game_type_odds)) + var/list/probabilities = CONFIG_GET(keyed_list/probability) + if(SSticker.IsRoundInProgress()) + var/prob_sum = 0 + var/current_odds_differ = FALSE + var/list/probs = list() + var/list/modes = config.gamemode_cache + var/list/min_pop = CONFIG_GET(keyed_list/min_pop) + var/list/max_pop = CONFIG_GET(keyed_list/max_pop) + for(var/mode in modes) + var/datum/game_mode/M = mode + var/ctag = initial(M.config_tag) + if(!(ctag in probabilities)) + continue + if((min_pop[ctag] && (min_pop[ctag] > SSticker.totalPlayersReady)) || (max_pop[ctag] && (max_pop[ctag] < SSticker.totalPlayersReady)) || (initial(M.required_players) > SSticker.totalPlayersReady)) + current_odds_differ = TRUE + continue + probs[ctag] = 1 + prob_sum += probabilities[ctag] + if(current_odds_differ) + msg += "Game Mode Odds for current round:" + for(var/ctag in probs) + if(probabilities[ctag] > 0) + var/percentage = round(probabilities[ctag] / prob_sum * 100, 0.1) + msg += "[ctag] [percentage]%" + + msg += "All Game Mode Odds:" + var/sum = 0 + for(var/ctag in probabilities) + sum += probabilities[ctag] + for(var/ctag in probabilities) + if(probabilities[ctag] > 0) + var/percentage = round(probabilities[ctag] / sum * 100, 0.1) + msg += "[ctag] [percentage]%" to_chat(src, msg.Join("
    ")) \ No newline at end of file diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 74f22b5ac0..1c2ce851fe 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -1,167 +1,167 @@ -// teleatom: atom to teleport -// destination: destination to teleport to -// precision: teleport precision (0 is most precise, the default) -// effectin: effect to show right before teleportation -// effectout: effect to show right after teleportation -// asoundin: soundfile to play before teleportation -// asoundout: soundfile to play after teleportation -// no_effects: disable the default effectin/effectout of sparks -// forceMove: if false, teleport will use Move() proc (dense objects will prevent teleportation) -// forced: whether or not to ignore no_teleport -/proc/do_teleport(atom/movable/teleatom, atom/destination, precision=null, forceMove = TRUE, datum/effect_system/effectin=null, datum/effect_system/effectout=null, asoundin=null, asoundout=null, no_effects=FALSE, channel=TELEPORT_CHANNEL_BLUESPACE, forced = FALSE) - // teleporting most effects just deletes them - var/static/list/delete_atoms = typecacheof(list( - /obj/effect, - )) - typecacheof(list( - /obj/effect/dummy/chameleon, - /obj/effect/wisp, - /obj/effect/mob_spawn - )) - if(delete_atoms[teleatom.type]) - qdel(teleatom) - return FALSE - - // argument handling - // if the precision is not specified, default to 0, but apply BoH penalties - if (isnull(precision)) - precision = 0 - - switch(channel) - if(TELEPORT_CHANNEL_BLUESPACE) - if(istype(teleatom, /obj/item/storage/backpack/holding)) - precision = rand(1,100) - - var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding) - var/list/bagholding = typecache_filter_list(teleatom.GetAllContents(), bag_cache) - if(bagholding.len) - precision = max(rand(1,100)*bagholding.len,100) - if(isliving(teleatom)) - var/mob/living/MM = teleatom - to_chat(MM, "The bluespace interface on your bag of holding interferes with the teleport!") - - // if effects are not specified and not explicitly disabled, sparks - if ((!effectin || !effectout) && !no_effects) - var/datum/effect_system/spark_spread/sparks = new - sparks.set_up(5, 1, teleatom) - if (!effectin) - effectin = sparks - if (!effectout) - effectout = sparks - if(TELEPORT_CHANNEL_QUANTUM) - // if effects are not specified and not explicitly disabled, rainbow sparks - if ((!effectin || !effectout) && !no_effects) - var/datum/effect_system/spark_spread/quantum/sparks = new - sparks.set_up(5, 1, teleatom) - if (!effectin) - effectin = sparks - if (!effectout) - effectout = sparks - - // perform the teleport - var/turf/curturf = get_turf(teleatom) - var/turf/destturf = get_teleport_turf(get_turf(destination), precision) - - if(!destturf || !curturf || destturf.is_transition_turf()) - return FALSE - - var/area/A = get_area(curturf) - var/area/B = get_area(destturf) - if(!forced && (A.noteleport || B.noteleport)) - return FALSE - - if(SEND_SIGNAL(destturf, COMSIG_ATOM_INTERCEPT_TELEPORT, channel, curturf, destturf)) - return FALSE - - tele_play_specials(teleatom, curturf, effectin, asoundin) - var/success = forceMove ? teleatom.forceMove(destturf) : teleatom.Move(destturf) - if (success) - log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") - tele_play_specials(teleatom, destturf, effectout, asoundout) - if(ismegafauna(teleatom)) - message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].") - SEND_SIGNAL(teleatom, COMSIG_MOVABLE_TELEPORTED, channel, curturf, destturf) - - if(ismob(teleatom)) - var/mob/M = teleatom - M.cancel_camera() - - return TRUE - -/proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound) - if (location && !isobserver(teleatom)) - if (sound) - playsound(location, sound, 60, 1) - if (effect) - effect.attach(location) - effect.start() - -// Safe location finder -/proc/find_safe_turf(zlevel, list/zlevels, extended_safety_checks = FALSE) - if(!zlevels) - if (zlevel) - zlevels = list(zlevel) - else - zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION) - var/cycles = 1000 - for(var/cycle in 1 to cycles) - // DRUNK DIALLING WOOOOOOOOO - var/x = rand(1, world.maxx) - var/y = rand(1, world.maxy) - var/z = pick(zlevels) - var/random_location = locate(x,y,z) - - if(!isfloorturf(random_location)) - continue - var/turf/open/floor/F = random_location - if(!F.air) - continue - - var/datum/gas_mixture/A = F.air - var/list/A_gases = A.gases - var/trace_gases - for(var/id in A_gases) - if(id in GLOB.hardcoded_gases) - continue - trace_gases = TRUE - break - - // Can most things breathe? - if(trace_gases) - continue - if(A_gases[/datum/gas/oxygen] >= 16) - continue - if(A_gases[/datum/gas/plasma]) - continue - if(A_gases[/datum/gas/carbon_dioxide] >= 10) - continue - - // Aim for goldilocks temperatures and pressure - if((A.temperature <= 270) || (A.temperature >= 360)) - continue - var/pressure = A.return_pressure() - if((pressure <= 20) || (pressure >= 550)) - continue - - if(extended_safety_checks) - if(islava(F)) //chasms aren't /floor, and so are pre-filtered - var/turf/open/lava/L = F - if(!L.is_safe()) - continue - - // DING! You have passed the gauntlet, and are "probably" safe. - return F - -/proc/get_teleport_turfs(turf/center, precision = 0) - if(!precision) - return list(center) - var/list/posturfs = list() - for(var/turf/T in range(precision,center)) - if(T.is_transition_turf()) - continue // Avoid picking these. - var/area/A = T.loc - if(!A.noteleport) - posturfs.Add(T) - return posturfs - -/proc/get_teleport_turf(turf/center, precision = 0) - return safepick(get_teleport_turfs(center, precision)) +// teleatom: atom to teleport +// destination: destination to teleport to +// precision: teleport precision (0 is most precise, the default) +// effectin: effect to show right before teleportation +// effectout: effect to show right after teleportation +// asoundin: soundfile to play before teleportation +// asoundout: soundfile to play after teleportation +// no_effects: disable the default effectin/effectout of sparks +// forceMove: if false, teleport will use Move() proc (dense objects will prevent teleportation) +// forced: whether or not to ignore no_teleport +/proc/do_teleport(atom/movable/teleatom, atom/destination, precision=null, forceMove = TRUE, datum/effect_system/effectin=null, datum/effect_system/effectout=null, asoundin=null, asoundout=null, no_effects=FALSE, channel=TELEPORT_CHANNEL_BLUESPACE, forced = FALSE) + // teleporting most effects just deletes them + var/static/list/delete_atoms = typecacheof(list( + /obj/effect, + )) - typecacheof(list( + /obj/effect/dummy/chameleon, + /obj/effect/wisp, + /obj/effect/mob_spawn + )) + if(delete_atoms[teleatom.type]) + qdel(teleatom) + return FALSE + + // argument handling + // if the precision is not specified, default to 0, but apply BoH penalties + if (isnull(precision)) + precision = 0 + + switch(channel) + if(TELEPORT_CHANNEL_BLUESPACE) + if(istype(teleatom, /obj/item/storage/backpack/holding)) + precision = rand(1,100) + + var/static/list/bag_cache = typecacheof(/obj/item/storage/backpack/holding) + var/list/bagholding = typecache_filter_list(teleatom.GetAllContents(), bag_cache) + if(bagholding.len) + precision = max(rand(1,100)*bagholding.len,100) + if(isliving(teleatom)) + var/mob/living/MM = teleatom + to_chat(MM, "The bluespace interface on your bag of holding interferes with the teleport!") + + // if effects are not specified and not explicitly disabled, sparks + if ((!effectin || !effectout) && !no_effects) + var/datum/effect_system/spark_spread/sparks = new + sparks.set_up(5, 1, teleatom) + if (!effectin) + effectin = sparks + if (!effectout) + effectout = sparks + if(TELEPORT_CHANNEL_QUANTUM) + // if effects are not specified and not explicitly disabled, rainbow sparks + if ((!effectin || !effectout) && !no_effects) + var/datum/effect_system/spark_spread/quantum/sparks = new + sparks.set_up(5, 1, teleatom) + if (!effectin) + effectin = sparks + if (!effectout) + effectout = sparks + + // perform the teleport + var/turf/curturf = get_turf(teleatom) + var/turf/destturf = get_teleport_turf(get_turf(destination), precision) + + if(!destturf || !curturf || destturf.is_transition_turf()) + return FALSE + + var/area/A = get_area(curturf) + var/area/B = get_area(destturf) + if(!forced && (A.noteleport || B.noteleport)) + return FALSE + + if(SEND_SIGNAL(destturf, COMSIG_ATOM_INTERCEPT_TELEPORT, channel, curturf, destturf)) + return FALSE + + tele_play_specials(teleatom, curturf, effectin, asoundin) + var/success = forceMove ? teleatom.forceMove(destturf) : teleatom.Move(destturf) + if (success) + log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]") + tele_play_specials(teleatom, destturf, effectout, asoundout) + if(ismegafauna(teleatom)) + message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].") + SEND_SIGNAL(teleatom, COMSIG_MOVABLE_TELEPORTED, channel, curturf, destturf) + + if(ismob(teleatom)) + var/mob/M = teleatom + M.cancel_camera() + + return TRUE + +/proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound) + if (location && !isobserver(teleatom)) + if (sound) + playsound(location, sound, 60, 1) + if (effect) + effect.attach(location) + effect.start() + +// Safe location finder +/proc/find_safe_turf(zlevel, list/zlevels, extended_safety_checks = FALSE) + if(!zlevels) + if (zlevel) + zlevels = list(zlevel) + else + zlevels = SSmapping.levels_by_trait(ZTRAIT_STATION) + var/cycles = 1000 + for(var/cycle in 1 to cycles) + // DRUNK DIALLING WOOOOOOOOO + var/x = rand(1, world.maxx) + var/y = rand(1, world.maxy) + var/z = pick(zlevels) + var/random_location = locate(x,y,z) + + if(!isfloorturf(random_location)) + continue + var/turf/open/floor/F = random_location + if(!F.air) + continue + + var/datum/gas_mixture/A = F.air + var/list/A_gases = A.gases + var/trace_gases + for(var/id in A_gases) + if(id in GLOB.hardcoded_gases) + continue + trace_gases = TRUE + break + + // Can most things breathe? + if(trace_gases) + continue + if(A_gases[/datum/gas/oxygen] >= 16) + continue + if(A_gases[/datum/gas/plasma]) + continue + if(A_gases[/datum/gas/carbon_dioxide] >= 10) + continue + + // Aim for goldilocks temperatures and pressure + if((A.temperature <= 270) || (A.temperature >= 360)) + continue + var/pressure = A.return_pressure() + if((pressure <= 20) || (pressure >= 550)) + continue + + if(extended_safety_checks) + if(islava(F)) //chasms aren't /floor, and so are pre-filtered + var/turf/open/lava/L = F + if(!L.is_safe()) + continue + + // DING! You have passed the gauntlet, and are "probably" safe. + return F + +/proc/get_teleport_turfs(turf/center, precision = 0) + if(!precision) + return list(center) + var/list/posturfs = list() + for(var/turf/T in range(precision,center)) + if(T.is_transition_turf()) + continue // Avoid picking these. + var/area/A = T.loc + if(!A.noteleport) + posturfs.Add(T) + return posturfs + +/proc/get_teleport_turf(turf/center, precision = 0) + return safepick(get_teleport_turfs(center, precision)) diff --git a/code/datums/helper_datums/topic_input.dm b/code/datums/helper_datums/topic_input.dm index 3e43905f1f..d07aec067e 100644 --- a/code/datums/helper_datums/topic_input.dm +++ b/code/datums/helper_datums/topic_input.dm @@ -1,62 +1,62 @@ -/datum/topic_input - var/href - var/list/href_list - -/datum/topic_input/New(thref,list/thref_list) - href = thref - href_list = thref_list.Copy() - return - -/datum/topic_input/proc/get(i) - return listgetindex(href_list,i) - -/datum/topic_input/proc/getAndLocate(i) - var/t = get(i) - if(t) - t = locate(t) - if (istext(t)) - t = null - return t || null - -/datum/topic_input/proc/getNum(i) - var/t = get(i) - if(t) - t = text2num(t) - return isnum(t) ? t : null - -/datum/topic_input/proc/getObj(i) - var/t = getAndLocate(i) - return isobj(t) ? t : null - -/datum/topic_input/proc/getMob(i) - var/t = getAndLocate(i) - return ismob(t) ? t : null - -/datum/topic_input/proc/getTurf(i) - var/t = getAndLocate(i) - return isturf(t) ? t : null - -/datum/topic_input/proc/getAtom(i) - return getType(i, /atom) - -/datum/topic_input/proc/getArea(i) - var/t = getAndLocate(i) - return isarea(t) ? t : null - -/datum/topic_input/proc/getStr(i)//params should always be text, but... - var/t = get(i) - return istext(t) ? t : null - -/datum/topic_input/proc/getType(i,type) - var/t = getAndLocate(i) - return istype(t,type) ? t : null - -/datum/topic_input/proc/getPath(i) - var/t = get(i) - if(t) - t = text2path(t) - return ispath(t) ? t : null - -/datum/topic_input/proc/getList(i) - var/t = getAndLocate(i) - return islist(t) ? t : null +/datum/topic_input + var/href + var/list/href_list + +/datum/topic_input/New(thref,list/thref_list) + href = thref + href_list = thref_list.Copy() + return + +/datum/topic_input/proc/get(i) + return listgetindex(href_list,i) + +/datum/topic_input/proc/getAndLocate(i) + var/t = get(i) + if(t) + t = locate(t) + if (istext(t)) + t = null + return t || null + +/datum/topic_input/proc/getNum(i) + var/t = get(i) + if(t) + t = text2num(t) + return isnum(t) ? t : null + +/datum/topic_input/proc/getObj(i) + var/t = getAndLocate(i) + return isobj(t) ? t : null + +/datum/topic_input/proc/getMob(i) + var/t = getAndLocate(i) + return ismob(t) ? t : null + +/datum/topic_input/proc/getTurf(i) + var/t = getAndLocate(i) + return isturf(t) ? t : null + +/datum/topic_input/proc/getAtom(i) + return getType(i, /atom) + +/datum/topic_input/proc/getArea(i) + var/t = getAndLocate(i) + return isarea(t) ? t : null + +/datum/topic_input/proc/getStr(i)//params should always be text, but... + var/t = get(i) + return istext(t) ? t : null + +/datum/topic_input/proc/getType(i,type) + var/t = getAndLocate(i) + return istype(t,type) ? t : null + +/datum/topic_input/proc/getPath(i) + var/t = get(i) + if(t) + t = text2path(t) + return ispath(t) ? t : null + +/datum/topic_input/proc/getList(i) + var/t = getAndLocate(i) + return islist(t) ? t : null diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 4923609db8..5a4600432d 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -1,352 +1,352 @@ -#define HOLOPAD_MAX_DIAL_TIME 200 - -#define HOLORECORD_DELAY "delay" -#define HOLORECORD_SAY "say" -#define HOLORECORD_SOUND "sound" -#define HOLORECORD_LANGUAGE "lang" -#define HOLORECORD_PRESET "preset" -#define HOLORECORD_RENAME "rename" - -#define HOLORECORD_MAX_LENGTH 200 - -/mob/camera/aiEye/remote/holo/setLoc() - . = ..() - var/obj/machinery/holopad/H = origin - H.move_hologram(eye_user, loc) - -//this datum manages it's own references - -/datum/holocall - var/mob/living/user //the one that called - var/obj/machinery/holopad/calling_holopad //the one that sent the call - var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null) - var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered - - var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected - var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected - var/datum/action/innate/end_holocall/hangup //hangup action - - var/call_start_time - -//creates a holocall made by `caller` from `calling_pad` to `callees` -/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) - call_start_time = world.time - user = caller - calling_pad.outgoing_call = src - calling_holopad = calling_pad - dialed_holopads = list() - - for(var/I in callees) - var/obj/machinery/holopad/H = I - if(!QDELETED(H) && H.is_operational()) - dialed_holopads += H - H.say("Incoming call.") - LAZYADD(H.holo_calls, src) - - if(!dialed_holopads.len) - calling_pad.say("Connection failure.") - qdel(src) - return - - testing("Holocall started") - -//cleans up ALL references :) -/datum/holocall/Destroy() - QDEL_NULL(hangup) - - var/user_good = !QDELETED(user) - if(user_good) - user.reset_perspective() - user.remote_control = null - - if(!QDELETED(eye)) - QDEL_NULL(eye) - - if(connected_holopad && !QDELETED(hologram)) - hologram = null - connected_holopad.clear_holo(user) - - user = null - - //Hologram survived holopad destro - if(!QDELETED(hologram)) - hologram.HC = null - QDEL_NULL(hologram) - - for(var/I in dialed_holopads) - var/obj/machinery/holopad/H = I - LAZYREMOVE(H.holo_calls, src) - dialed_holopads.Cut() - - if(calling_holopad) - calling_holopad.outgoing_call = null - calling_holopad.SetLightsAndPower() - calling_holopad = null - if(connected_holopad) - connected_holopad.SetLightsAndPower() - connected_holopad = null - - testing("Holocall destroyed") - - return ..() - -//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection -/datum/holocall/proc/Disconnect(obj/machinery/holopad/H) - testing("Holocall disconnect") - if(H == connected_holopad) - var/area/A = get_area(connected_holopad) - calling_holopad.say("[A] holopad disconnected.") - else if(H == calling_holopad && connected_holopad) - connected_holopad.say("[user] disconnected.") - - ConnectionFailure(H, TRUE) - -//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored. -/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE) - testing("Holocall connection failure: graceful [graceful]") - if(H == connected_holopad || H == calling_holopad) - if(!graceful && H != calling_holopad) - calling_holopad.say("Connection failure.") - qdel(src) - return - - LAZYREMOVE(H.holo_calls, src) - dialed_holopads -= H - if(!dialed_holopads.len) - if(graceful) - calling_holopad.say("Call rejected.") - testing("No recipients, terminating") - qdel(src) - -//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored -/datum/holocall/proc/Answer(obj/machinery/holopad/H) - testing("Holocall answer") - if(H == calling_holopad) - CRASH("How cute, a holopad tried to answer itself.") - - if(!(H in dialed_holopads)) - return - - if(connected_holopad) - CRASH("Multi-connection holocall") - - for(var/I in dialed_holopads) - if(I == H) - continue - Disconnect(I) - - for(var/I in H.holo_calls) - var/datum/holocall/HC = I - if(HC != src) - HC.Disconnect(H) - - connected_holopad = H - - if(!Check()) - return - - hologram = H.activate_holo(user) - hologram.HC = src - - //eyeobj code is horrid, this is the best copypasta I could make - eye = new - eye.origin = H - eye.eye_initialized = TRUE - eye.eye_user = user - eye.name = "Camera Eye ([user.name])" - user.remote_control = eye - user.reset_perspective(eye) - eye.setLoc(H.loc) - - hangup = new(eye, src) - hangup.Grant(user) - -//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise -/datum/holocall/proc/Check() - for(var/I in dialed_holopads) - var/obj/machinery/holopad/H = I - if(!H.is_operational()) - ConnectionFailure(H) - - if(QDELETED(src)) - return FALSE - - . = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc - - if(.) - if(!connected_holopad) - . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) - if(!.) - calling_holopad.say("No answer received.") - calling_holopad.temp = "" - - if(!.) - testing("Holocall Check fail") - qdel(src) - -/datum/action/innate/end_holocall - name = "End Holocall" - icon_icon = 'icons/mob/actions/actions_silicon.dmi' - button_icon_state = "camera_off" - var/datum/holocall/hcall - -/datum/action/innate/end_holocall/New(Target, datum/holocall/HC) - ..() - hcall = HC - -/datum/action/innate/end_holocall/Activate() - hcall.Disconnect(hcall.calling_holopad) - - -//RECORDS -/datum/holorecord - var/caller_name = "Unknown" //Caller name - var/image/caller_image - var/list/entries = list() - var/language = /datum/language/common //Initial language, can be changed by HOLORECORD_LANGUAGE entries - -/datum/holorecord/proc/set_caller_image(mob/user) - var/olddir = user.dir - user.setDir(SOUTH) - caller_image = image(user) - user.setDir(olddir) - -/obj/item/disk/holodisk - name = "holorecord disk" - desc = "Stores recorder holocalls." - icon_state = "holodisk" - obj_flags = UNIQUE_RENAME - materials = list(MAT_METAL = 100, MAT_GLASS = 100) - var/datum/holorecord/record - //Preset variables - var/preset_image_type - var/preset_record_text - -/obj/item/disk/holodisk/Initialize(mapload) - . = ..() - if(preset_record_text) - build_record() - -/obj/item/disk/holodisk/Destroy() - QDEL_NULL(record) - return ..() - -/obj/item/disk/holodisk/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/disk/holodisk)) - var/obj/item/disk/holodisk/holodiskOriginal = W - if (holodiskOriginal.record) - if (!record) - record = new - record.caller_name = holodiskOriginal.record.caller_name - record.caller_image = holodiskOriginal.record.caller_image - record.entries = holodiskOriginal.record.entries.Copy() - record.language = holodiskOriginal.record.language - to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!") - name = holodiskOriginal.name - else - to_chat(user, "[holodiskOriginal] has no record on it!") - ..() - -/obj/item/disk/holodisk/proc/build_record() - record = new - var/list/lines = splittext(preset_record_text,"\n") - for(var/line in lines) - var/prepared_line = trim(line) - if(!length(prepared_line)) - continue - var/splitpoint = findtext(prepared_line," ") - if(!splitpoint) - continue - var/command = copytext(prepared_line,1,splitpoint) - var/value = copytext(prepared_line,splitpoint+1) - switch(command) - if("DELAY") - var/delay_value = text2num(value) - if(!delay_value) - continue - record.entries += list(list(HOLORECORD_DELAY,delay_value)) - if("NAME") - if(!record.caller_name) - record.caller_name = value - else - record.entries += list(list(HOLORECORD_RENAME,value)) - if("SAY") - record.entries += list(list(HOLORECORD_SAY,value)) - if("SOUND") - record.entries += list(list(HOLORECORD_SOUND,value)) - if("LANGUAGE") - var/lang_type = text2path(value) - if(ispath(lang_type,/datum/language)) - record.entries += list(list(HOLORECORD_LANGUAGE,lang_type)) - if("PRESET") - var/preset_type = text2path(value) - if(ispath(preset_type,/datum/preset_holoimage)) - record.entries += list(list(HOLORECORD_PRESET,preset_type)) - if(!preset_image_type) - record.caller_image = image('icons/mob/animal.dmi',"old") - else - var/datum/preset_holoimage/H = new preset_image_type - record.caller_image = H.build_image() - -//These build caller image from outfit and some additional data, for use by mappers for ruin holorecords -/datum/preset_holoimage - var/nonhuman_mobtype //Fill this if you just want something nonhuman - var/outfit_type - var/species_type = /datum/species/human - -/datum/preset_holoimage/proc/build_image() - if(nonhuman_mobtype) - var/mob/living/L = nonhuman_mobtype - . = image(initial(L.icon),initial(L.icon_state)) - else - var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy("HOLODISK_PRESET") - if(species_type) - mannequin.set_species(species_type) - if(outfit_type) - mannequin.equipOutfit(outfit_type,TRUE) - mannequin.setDir(SOUTH) - COMPILE_OVERLAYS(mannequin) - . = image(mannequin) - unset_busy_human_dummy("HOLODISK_PRESET") - -/obj/item/disk/holodisk/example - preset_image_type = /datum/preset_holoimage/clown - preset_record_text = {" - NAME Clown - DELAY 10 - SAY Why did the chaplain cross the maint ? - DELAY 20 - SAY He wanted to get to the other side! - SOUND clownstep - DELAY 30 - LANGUAGE /datum/language/narsie - SAY Helped him get there! - DELAY 10 - SAY ALSO IM SECRETLY A GORILLA - DELAY 10 - PRESET /datum/preset_holoimage/gorilla - NAME Gorilla - LANGUAGE /datum/language/common - SAY OOGA - DELAY 20"} - -/datum/preset_holoimage/engineer - outfit_type = /datum/outfit/job/engineer/gloved/rig - -/datum/preset_holoimage/researcher - outfit_type = /datum/outfit/job/scientist - -/datum/preset_holoimage/captain - outfit_type = /datum/outfit/job/captain - -/datum/preset_holoimage/nanotrasenprivatesecurity - outfit_type = /datum/outfit/nanotrasensoldiercorpse2 - -/datum/preset_holoimage/gorilla - nonhuman_mobtype = /mob/living/simple_animal/hostile/gorilla - -/datum/preset_holoimage/corgi - nonhuman_mobtype = /mob/living/simple_animal/pet/dog/corgi - -/datum/preset_holoimage/clown - outfit_type = /datum/outfit/job/clown +#define HOLOPAD_MAX_DIAL_TIME 200 + +#define HOLORECORD_DELAY "delay" +#define HOLORECORD_SAY "say" +#define HOLORECORD_SOUND "sound" +#define HOLORECORD_LANGUAGE "lang" +#define HOLORECORD_PRESET "preset" +#define HOLORECORD_RENAME "rename" + +#define HOLORECORD_MAX_LENGTH 200 + +/mob/camera/aiEye/remote/holo/setLoc() + . = ..() + var/obj/machinery/holopad/H = origin + H.move_hologram(eye_user, loc) + +//this datum manages it's own references + +/datum/holocall + var/mob/living/user //the one that called + var/obj/machinery/holopad/calling_holopad //the one that sent the call + var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null) + var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered + + var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected + var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected + var/datum/action/innate/end_holocall/hangup //hangup action + + var/call_start_time + +//creates a holocall made by `caller` from `calling_pad` to `callees` +/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) + call_start_time = world.time + user = caller + calling_pad.outgoing_call = src + calling_holopad = calling_pad + dialed_holopads = list() + + for(var/I in callees) + var/obj/machinery/holopad/H = I + if(!QDELETED(H) && H.is_operational()) + dialed_holopads += H + H.say("Incoming call.") + LAZYADD(H.holo_calls, src) + + if(!dialed_holopads.len) + calling_pad.say("Connection failure.") + qdel(src) + return + + testing("Holocall started") + +//cleans up ALL references :) +/datum/holocall/Destroy() + QDEL_NULL(hangup) + + var/user_good = !QDELETED(user) + if(user_good) + user.reset_perspective() + user.remote_control = null + + if(!QDELETED(eye)) + QDEL_NULL(eye) + + if(connected_holopad && !QDELETED(hologram)) + hologram = null + connected_holopad.clear_holo(user) + + user = null + + //Hologram survived holopad destro + if(!QDELETED(hologram)) + hologram.HC = null + QDEL_NULL(hologram) + + for(var/I in dialed_holopads) + var/obj/machinery/holopad/H = I + LAZYREMOVE(H.holo_calls, src) + dialed_holopads.Cut() + + if(calling_holopad) + calling_holopad.outgoing_call = null + calling_holopad.SetLightsAndPower() + calling_holopad = null + if(connected_holopad) + connected_holopad.SetLightsAndPower() + connected_holopad = null + + testing("Holocall destroyed") + + return ..() + +//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection +/datum/holocall/proc/Disconnect(obj/machinery/holopad/H) + testing("Holocall disconnect") + if(H == connected_holopad) + var/area/A = get_area(connected_holopad) + calling_holopad.say("[A] holopad disconnected.") + else if(H == calling_holopad && connected_holopad) + connected_holopad.say("[user] disconnected.") + + ConnectionFailure(H, TRUE) + +//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored. +/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE) + testing("Holocall connection failure: graceful [graceful]") + if(H == connected_holopad || H == calling_holopad) + if(!graceful && H != calling_holopad) + calling_holopad.say("Connection failure.") + qdel(src) + return + + LAZYREMOVE(H.holo_calls, src) + dialed_holopads -= H + if(!dialed_holopads.len) + if(graceful) + calling_holopad.say("Call rejected.") + testing("No recipients, terminating") + qdel(src) + +//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored +/datum/holocall/proc/Answer(obj/machinery/holopad/H) + testing("Holocall answer") + if(H == calling_holopad) + CRASH("How cute, a holopad tried to answer itself.") + + if(!(H in dialed_holopads)) + return + + if(connected_holopad) + CRASH("Multi-connection holocall") + + for(var/I in dialed_holopads) + if(I == H) + continue + Disconnect(I) + + for(var/I in H.holo_calls) + var/datum/holocall/HC = I + if(HC != src) + HC.Disconnect(H) + + connected_holopad = H + + if(!Check()) + return + + hologram = H.activate_holo(user) + hologram.HC = src + + //eyeobj code is horrid, this is the best copypasta I could make + eye = new + eye.origin = H + eye.eye_initialized = TRUE + eye.eye_user = user + eye.name = "Camera Eye ([user.name])" + user.remote_control = eye + user.reset_perspective(eye) + eye.setLoc(H.loc) + + hangup = new(eye, src) + hangup.Grant(user) + +//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise +/datum/holocall/proc/Check() + for(var/I in dialed_holopads) + var/obj/machinery/holopad/H = I + if(!H.is_operational()) + ConnectionFailure(H) + + if(QDELETED(src)) + return FALSE + + . = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc + + if(.) + if(!connected_holopad) + . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) + if(!.) + calling_holopad.say("No answer received.") + calling_holopad.temp = "" + + if(!.) + testing("Holocall Check fail") + qdel(src) + +/datum/action/innate/end_holocall + name = "End Holocall" + icon_icon = 'icons/mob/actions/actions_silicon.dmi' + button_icon_state = "camera_off" + var/datum/holocall/hcall + +/datum/action/innate/end_holocall/New(Target, datum/holocall/HC) + ..() + hcall = HC + +/datum/action/innate/end_holocall/Activate() + hcall.Disconnect(hcall.calling_holopad) + + +//RECORDS +/datum/holorecord + var/caller_name = "Unknown" //Caller name + var/image/caller_image + var/list/entries = list() + var/language = /datum/language/common //Initial language, can be changed by HOLORECORD_LANGUAGE entries + +/datum/holorecord/proc/set_caller_image(mob/user) + var/olddir = user.dir + user.setDir(SOUTH) + caller_image = image(user) + user.setDir(olddir) + +/obj/item/disk/holodisk + name = "holorecord disk" + desc = "Stores recorder holocalls." + icon_state = "holodisk" + obj_flags = UNIQUE_RENAME + materials = list(MAT_METAL = 100, MAT_GLASS = 100) + var/datum/holorecord/record + //Preset variables + var/preset_image_type + var/preset_record_text + +/obj/item/disk/holodisk/Initialize(mapload) + . = ..() + if(preset_record_text) + build_record() + +/obj/item/disk/holodisk/Destroy() + QDEL_NULL(record) + return ..() + +/obj/item/disk/holodisk/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/disk/holodisk)) + var/obj/item/disk/holodisk/holodiskOriginal = W + if (holodiskOriginal.record) + if (!record) + record = new + record.caller_name = holodiskOriginal.record.caller_name + record.caller_image = holodiskOriginal.record.caller_image + record.entries = holodiskOriginal.record.entries.Copy() + record.language = holodiskOriginal.record.language + to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!") + name = holodiskOriginal.name + else + to_chat(user, "[holodiskOriginal] has no record on it!") + ..() + +/obj/item/disk/holodisk/proc/build_record() + record = new + var/list/lines = splittext(preset_record_text,"\n") + for(var/line in lines) + var/prepared_line = trim(line) + if(!length(prepared_line)) + continue + var/splitpoint = findtext(prepared_line," ") + if(!splitpoint) + continue + var/command = copytext(prepared_line,1,splitpoint) + var/value = copytext(prepared_line,splitpoint+1) + switch(command) + if("DELAY") + var/delay_value = text2num(value) + if(!delay_value) + continue + record.entries += list(list(HOLORECORD_DELAY,delay_value)) + if("NAME") + if(!record.caller_name) + record.caller_name = value + else + record.entries += list(list(HOLORECORD_RENAME,value)) + if("SAY") + record.entries += list(list(HOLORECORD_SAY,value)) + if("SOUND") + record.entries += list(list(HOLORECORD_SOUND,value)) + if("LANGUAGE") + var/lang_type = text2path(value) + if(ispath(lang_type,/datum/language)) + record.entries += list(list(HOLORECORD_LANGUAGE,lang_type)) + if("PRESET") + var/preset_type = text2path(value) + if(ispath(preset_type,/datum/preset_holoimage)) + record.entries += list(list(HOLORECORD_PRESET,preset_type)) + if(!preset_image_type) + record.caller_image = image('icons/mob/animal.dmi',"old") + else + var/datum/preset_holoimage/H = new preset_image_type + record.caller_image = H.build_image() + +//These build caller image from outfit and some additional data, for use by mappers for ruin holorecords +/datum/preset_holoimage + var/nonhuman_mobtype //Fill this if you just want something nonhuman + var/outfit_type + var/species_type = /datum/species/human + +/datum/preset_holoimage/proc/build_image() + if(nonhuman_mobtype) + var/mob/living/L = nonhuman_mobtype + . = image(initial(L.icon),initial(L.icon_state)) + else + var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy("HOLODISK_PRESET") + if(species_type) + mannequin.set_species(species_type) + if(outfit_type) + mannequin.equipOutfit(outfit_type,TRUE) + mannequin.setDir(SOUTH) + COMPILE_OVERLAYS(mannequin) + . = image(mannequin) + unset_busy_human_dummy("HOLODISK_PRESET") + +/obj/item/disk/holodisk/example + preset_image_type = /datum/preset_holoimage/clown + preset_record_text = {" + NAME Clown + DELAY 10 + SAY Why did the chaplain cross the maint ? + DELAY 20 + SAY He wanted to get to the other side! + SOUND clownstep + DELAY 30 + LANGUAGE /datum/language/narsie + SAY Helped him get there! + DELAY 10 + SAY ALSO IM SECRETLY A GORILLA + DELAY 10 + PRESET /datum/preset_holoimage/gorilla + NAME Gorilla + LANGUAGE /datum/language/common + SAY OOGA + DELAY 20"} + +/datum/preset_holoimage/engineer + outfit_type = /datum/outfit/job/engineer/gloved/rig + +/datum/preset_holoimage/researcher + outfit_type = /datum/outfit/job/scientist + +/datum/preset_holoimage/captain + outfit_type = /datum/outfit/job/captain + +/datum/preset_holoimage/nanotrasenprivatesecurity + outfit_type = /datum/outfit/nanotrasensoldiercorpse2 + +/datum/preset_holoimage/gorilla + nonhuman_mobtype = /mob/living/simple_animal/hostile/gorilla + +/datum/preset_holoimage/corgi + nonhuman_mobtype = /mob/living/simple_animal/pet/dog/corgi + +/datum/preset_holoimage/clown + outfit_type = /datum/outfit/job/clown diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 169b08dc98..e2d9bc579f 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -1,130 +1,130 @@ -/* HUD DATUMS */ - -GLOBAL_LIST_EMPTY(all_huds) - -//GLOBAL HUD LIST -GLOBAL_LIST_INIT(huds, list( - DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(), - DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(), - DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), - DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), - DATA_HUD_DIAGNOSTIC_BASIC = new/datum/atom_hud/data/diagnostic/basic(), - DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), - DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(), - DATA_HUD_SENTIENT_DISEASE = new/datum/atom_hud/sentient_disease(), - DATA_HUD_AI_DETECT = new/datum/atom_hud/ai_detector(), - ANTAG_HUD_CULT = new/datum/atom_hud/antag(), - ANTAG_HUD_REV = new/datum/atom_hud/antag(), - ANTAG_HUD_OPS = new/datum/atom_hud/antag(), - ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), - ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), - ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_DEVIL = new/datum/atom_hud/antag(), - ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(), - ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(), - ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker() - )) - -/datum/atom_hud - var/list/atom/hudatoms = list() //list of all atoms which display this hud - var/list/mob/hudusers = list() //list with all mobs who can see the hud - var/list/hud_icons = list() //these will be the indexes for the atom's hud_list - - var/list/next_time_allowed = list() //mobs associated with the next time this hud can be added to them - var/list/queued_to_see = list() //mobs that have triggered the cooldown and are queued to see the hud, but do not yet - -/datum/atom_hud/New() - GLOB.all_huds += src - -/datum/atom_hud/Destroy() - for(var/v in hudusers) - remove_hud_from(v) - for(var/v in hudatoms) - remove_from_hud(v) - GLOB.all_huds -= src - return ..() - -/datum/atom_hud/proc/remove_hud_from(mob/M) - if(!M || !hudusers[M]) - return - if (!--hudusers[M]) - hudusers -= M - if(queued_to_see[M]) - queued_to_see -= M - else - for(var/atom/A in hudatoms) - remove_from_single_hud(M, A) - -/datum/atom_hud/proc/remove_from_hud(atom/A) - if(!A) - return FALSE - for(var/mob/M in hudusers) - remove_from_single_hud(M, A) - hudatoms -= A - return TRUE - -/datum/atom_hud/proc/remove_from_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client - if(!M || !M.client || !A) - return - for(var/i in hud_icons) - M.client.images -= A.hud_list[i] - -/datum/atom_hud/proc/add_hud_to(mob/M) - if(!M) - return - if(!hudusers[M]) - hudusers[M] = 1 - if(next_time_allowed[M] > world.time) - if(!queued_to_see[M]) - addtimer(CALLBACK(src, .proc/show_hud_images_after_cooldown, M), next_time_allowed[M] - world.time) - queued_to_see[M] = TRUE - else - next_time_allowed[M] = world.time + ADD_HUD_TO_COOLDOWN - for(var/atom/A in hudatoms) - add_to_single_hud(M, A) - else - hudusers[M]++ - -/datum/atom_hud/proc/show_hud_images_after_cooldown(M) - if(queued_to_see[M]) - queued_to_see -= M - next_time_allowed[M] = world.time + ADD_HUD_TO_COOLDOWN - for(var/atom/A in hudatoms) - add_to_single_hud(M, A) - -/datum/atom_hud/proc/add_to_hud(atom/A) - if(!A) - return FALSE - hudatoms |= A - for(var/mob/M in hudusers) - if(!queued_to_see[M]) - add_to_single_hud(M, A) - return TRUE - -/datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client - if(!M || !M.client || !A) - return - for(var/i in hud_icons) - if(A.hud_list[i]) - M.client.images |= A.hud_list[i] - -//MOB PROCS -/mob/proc/reload_huds() - for(var/datum/atom_hud/hud in GLOB.all_huds) - if(hud && hud.hudusers[src]) - for(var/atom/A in hud.hudatoms) - hud.add_to_single_hud(src, A) - -/mob/dead/new_player/reload_huds() - return - -/mob/proc/add_click_catcher() - client.screen += client.void - -/mob/dead/new_player/add_click_catcher() - return +/* HUD DATUMS */ + +GLOBAL_LIST_EMPTY(all_huds) + +//GLOBAL HUD LIST +GLOBAL_LIST_INIT(huds, list( + DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(), + DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(), + DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), + DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), + DATA_HUD_DIAGNOSTIC_BASIC = new/datum/atom_hud/data/diagnostic/basic(), + DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), + DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(), + DATA_HUD_SENTIENT_DISEASE = new/datum/atom_hud/sentient_disease(), + DATA_HUD_AI_DETECT = new/datum/atom_hud/ai_detector(), + ANTAG_HUD_CULT = new/datum/atom_hud/antag(), + ANTAG_HUD_REV = new/datum/atom_hud/antag(), + ANTAG_HUD_OPS = new/datum/atom_hud/antag(), + ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), + ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), + ANTAG_HUD_TRAITOR = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_NINJA = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_CHANGELING = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_ABDUCTOR = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_DEVIL = new/datum/atom_hud/antag(), + ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(), + ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(), + ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker() + )) + +/datum/atom_hud + var/list/atom/hudatoms = list() //list of all atoms which display this hud + var/list/mob/hudusers = list() //list with all mobs who can see the hud + var/list/hud_icons = list() //these will be the indexes for the atom's hud_list + + var/list/next_time_allowed = list() //mobs associated with the next time this hud can be added to them + var/list/queued_to_see = list() //mobs that have triggered the cooldown and are queued to see the hud, but do not yet + +/datum/atom_hud/New() + GLOB.all_huds += src + +/datum/atom_hud/Destroy() + for(var/v in hudusers) + remove_hud_from(v) + for(var/v in hudatoms) + remove_from_hud(v) + GLOB.all_huds -= src + return ..() + +/datum/atom_hud/proc/remove_hud_from(mob/M) + if(!M || !hudusers[M]) + return + if (!--hudusers[M]) + hudusers -= M + if(queued_to_see[M]) + queued_to_see -= M + else + for(var/atom/A in hudatoms) + remove_from_single_hud(M, A) + +/datum/atom_hud/proc/remove_from_hud(atom/A) + if(!A) + return FALSE + for(var/mob/M in hudusers) + remove_from_single_hud(M, A) + hudatoms -= A + return TRUE + +/datum/atom_hud/proc/remove_from_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client + if(!M || !M.client || !A) + return + for(var/i in hud_icons) + M.client.images -= A.hud_list[i] + +/datum/atom_hud/proc/add_hud_to(mob/M) + if(!M) + return + if(!hudusers[M]) + hudusers[M] = 1 + if(next_time_allowed[M] > world.time) + if(!queued_to_see[M]) + addtimer(CALLBACK(src, .proc/show_hud_images_after_cooldown, M), next_time_allowed[M] - world.time) + queued_to_see[M] = TRUE + else + next_time_allowed[M] = world.time + ADD_HUD_TO_COOLDOWN + for(var/atom/A in hudatoms) + add_to_single_hud(M, A) + else + hudusers[M]++ + +/datum/atom_hud/proc/show_hud_images_after_cooldown(M) + if(queued_to_see[M]) + queued_to_see -= M + next_time_allowed[M] = world.time + ADD_HUD_TO_COOLDOWN + for(var/atom/A in hudatoms) + add_to_single_hud(M, A) + +/datum/atom_hud/proc/add_to_hud(atom/A) + if(!A) + return FALSE + hudatoms |= A + for(var/mob/M in hudusers) + if(!queued_to_see[M]) + add_to_single_hud(M, A) + return TRUE + +/datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client + if(!M || !M.client || !A) + return + for(var/i in hud_icons) + if(A.hud_list[i]) + M.client.images |= A.hud_list[i] + +//MOB PROCS +/mob/proc/reload_huds() + for(var/datum/atom_hud/hud in GLOB.all_huds) + if(hud && hud.hudusers[src]) + for(var/atom/A in hud.hudatoms) + hud.add_to_single_hud(src, A) + +/mob/dead/new_player/reload_huds() + return + +/mob/proc/add_click_catcher() + client.screen += client.void + +/mob/dead/new_player/add_click_catcher() + return diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm index c859f8127d..5fcd1ae93c 100644 --- a/code/datums/map_config.dm +++ b/code/datums/map_config.dm @@ -1,163 +1,163 @@ -//used for holding information about unique properties of maps -//feed it json files that match the datum layout -//defaults to box -// -Cyberboss - -/datum/map_config - // Metadata - var/config_filename = "_maps/boxstation.json" - var/defaulted = TRUE // set to FALSE by LoadConfig() succeeding - // Config from maps.txt - var/config_max_users = 0 - var/config_min_users = 0 - var/voteweight = 1 - var/max_round_search_span = 0 //If this is nonzero, then if the map has been played more than max_rounds_played within the search span (max determined by define in persistence.dm), this map won't be available. - var/max_rounds_played = 0 - - // Config actually from the JSON - should default to Box - var/map_name = "Box Station" - var/map_path = "map_files/BoxStation" - var/map_file = "BoxStation.dmm" - - var/traits = null - var/space_ruin_levels = 2 - var/space_empty_levels = 1 - - var/minetype = "lavaland" - - var/maptype = MAP_TYPE_STATION //This should be used to adjust ingame behavior depending on the specific type of map being played. For instance, if an overmap were added, it'd be appropriate for it to only generate with a MAP_TYPE_SHIP - - var/announcertype = "standard" //Determines the announcer the map uses. standard uses the default announcer, classic, but has a random chance to use other similarly-themed announcers, like medibot - - var/allow_custom_shuttles = TRUE - var/shuttles = list( - "cargo" = "cargo_box", - "ferry" = "ferry_fancy", - "whiteship" = "whiteship_box", - "emergency" = "emergency_box") - - var/year_offset = 540 //The offset of ingame year from the actual IRL year. You know you want to make a map that takes place in the 90's. Don't lie. - -/proc/load_map_config(filename = "data/next_map.json", default_to_box, delete_after, error_if_missing = TRUE) - var/datum/map_config/config = new - if (default_to_box) - return config - if (!config.LoadConfig(filename, error_if_missing)) - qdel(config) - config = new /datum/map_config // Fall back to Box - if (delete_after) - fdel(filename) - return config - -#define CHECK_EXISTS(X) if(!istext(json[X])) { log_world("[##X] missing from json!"); return; } -/datum/map_config/proc/LoadConfig(filename, error_if_missing) - if(!fexists(filename)) - if(error_if_missing) - log_world("map_config not found: [filename]") - return - - var/json = file(filename) - if(!json) - log_world("Could not open map_config: [filename]") - return - - json = file2text(json) - if(!json) - log_world("map_config is not text: [filename]") - return - - json = json_decode(json) - if(!json) - log_world("map_config is not json: [filename]") - return - - config_filename = filename - - CHECK_EXISTS("map_name") - map_name = json["map_name"] - CHECK_EXISTS("map_path") - map_path = json["map_path"] - - map_file = json["map_file"] - // "map_file": "BoxStation.dmm" - if (istext(map_file)) - if (!fexists("_maps/[map_path]/[map_file]")) - log_world("Map file ([map_path]/[map_file]) does not exist!") - return - // "map_file": ["Lower.dmm", "Upper.dmm"] - else if (islist(map_file)) - for (var/file in map_file) - if (!fexists("_maps/[map_path]/[file]")) - log_world("Map file ([map_path]/[file]) does not exist!") - return - else - log_world("map_file missing from json!") - return - - if (islist(json["shuttles"])) - var/list/L = json["shuttles"] - for(var/key in L) - var/value = L[key] - shuttles[key] = value - else if ("shuttles" in json) - log_world("map_config shuttles is not a list!") - return - - traits = json["traits"] - // "traits": [{"Linkage": "Cross"}, {"Space Ruins": true}] - if (islist(traits)) - // "Station" is set by default, but it's assumed if you're setting - // traits you want to customize which level is cross-linked - for (var/level in traits) - if (!(ZTRAIT_STATION in level)) - level[ZTRAIT_STATION] = TRUE - // "traits": null or absent -> default - else if (!isnull(traits)) - log_world("map_config traits is not a list!") - return - - var/temp = json["space_ruin_levels"] - if (isnum(temp)) - space_ruin_levels = temp - else if (!isnull(temp)) - log_world("map_config space_ruin_levels is not a number!") - return - - temp = json["space_empty_levels"] - if (isnum(temp)) - space_empty_levels = temp - else if (!isnull(temp)) - log_world("map_config space_empty_levels is not a number!") - return - - temp = json["year_offset"] - if (isnum(temp)) - year_offset = temp - else if (!isnull(temp)) - log_world("map_config year_offset is not a number!") - return - - if ("minetype" in json) - minetype = json["minetype"] - - if ("maptype" in json) - maptype = json["maptype"] - - if ("announcertype" in json) - announcertype = json["announcertype"] - - allow_custom_shuttles = json["allow_custom_shuttles"] != FALSE - - defaulted = FALSE - return TRUE -#undef CHECK_EXISTS - -/datum/map_config/proc/GetFullMapPaths() - if (istext(map_file)) - return list("_maps/[map_path]/[map_file]") - . = list() - for (var/file in map_file) - . += "_maps/[map_path]/[file]" - -/datum/map_config/proc/MakeNextMap() - return config_filename == "data/next_map.json" || fcopy(config_filename, "data/next_map.json") +//used for holding information about unique properties of maps +//feed it json files that match the datum layout +//defaults to box +// -Cyberboss + +/datum/map_config + // Metadata + var/config_filename = "_maps/boxstation.json" + var/defaulted = TRUE // set to FALSE by LoadConfig() succeeding + // Config from maps.txt + var/config_max_users = 0 + var/config_min_users = 0 + var/voteweight = 1 + var/max_round_search_span = 0 //If this is nonzero, then if the map has been played more than max_rounds_played within the search span (max determined by define in persistence.dm), this map won't be available. + var/max_rounds_played = 0 + + // Config actually from the JSON - should default to Box + var/map_name = "Box Station" + var/map_path = "map_files/BoxStation" + var/map_file = "BoxStation.dmm" + + var/traits = null + var/space_ruin_levels = 2 + var/space_empty_levels = 1 + + var/minetype = "lavaland" + + var/maptype = MAP_TYPE_STATION //This should be used to adjust ingame behavior depending on the specific type of map being played. For instance, if an overmap were added, it'd be appropriate for it to only generate with a MAP_TYPE_SHIP + + var/announcertype = "standard" //Determines the announcer the map uses. standard uses the default announcer, classic, but has a random chance to use other similarly-themed announcers, like medibot + + var/allow_custom_shuttles = TRUE + var/shuttles = list( + "cargo" = "cargo_box", + "ferry" = "ferry_fancy", + "whiteship" = "whiteship_box", + "emergency" = "emergency_box") + + var/year_offset = 540 //The offset of ingame year from the actual IRL year. You know you want to make a map that takes place in the 90's. Don't lie. + +/proc/load_map_config(filename = "data/next_map.json", default_to_box, delete_after, error_if_missing = TRUE) + var/datum/map_config/config = new + if (default_to_box) + return config + if (!config.LoadConfig(filename, error_if_missing)) + qdel(config) + config = new /datum/map_config // Fall back to Box + if (delete_after) + fdel(filename) + return config + +#define CHECK_EXISTS(X) if(!istext(json[X])) { log_world("[##X] missing from json!"); return; } +/datum/map_config/proc/LoadConfig(filename, error_if_missing) + if(!fexists(filename)) + if(error_if_missing) + log_world("map_config not found: [filename]") + return + + var/json = file(filename) + if(!json) + log_world("Could not open map_config: [filename]") + return + + json = file2text(json) + if(!json) + log_world("map_config is not text: [filename]") + return + + json = json_decode(json) + if(!json) + log_world("map_config is not json: [filename]") + return + + config_filename = filename + + CHECK_EXISTS("map_name") + map_name = json["map_name"] + CHECK_EXISTS("map_path") + map_path = json["map_path"] + + map_file = json["map_file"] + // "map_file": "BoxStation.dmm" + if (istext(map_file)) + if (!fexists("_maps/[map_path]/[map_file]")) + log_world("Map file ([map_path]/[map_file]) does not exist!") + return + // "map_file": ["Lower.dmm", "Upper.dmm"] + else if (islist(map_file)) + for (var/file in map_file) + if (!fexists("_maps/[map_path]/[file]")) + log_world("Map file ([map_path]/[file]) does not exist!") + return + else + log_world("map_file missing from json!") + return + + if (islist(json["shuttles"])) + var/list/L = json["shuttles"] + for(var/key in L) + var/value = L[key] + shuttles[key] = value + else if ("shuttles" in json) + log_world("map_config shuttles is not a list!") + return + + traits = json["traits"] + // "traits": [{"Linkage": "Cross"}, {"Space Ruins": true}] + if (islist(traits)) + // "Station" is set by default, but it's assumed if you're setting + // traits you want to customize which level is cross-linked + for (var/level in traits) + if (!(ZTRAIT_STATION in level)) + level[ZTRAIT_STATION] = TRUE + // "traits": null or absent -> default + else if (!isnull(traits)) + log_world("map_config traits is not a list!") + return + + var/temp = json["space_ruin_levels"] + if (isnum(temp)) + space_ruin_levels = temp + else if (!isnull(temp)) + log_world("map_config space_ruin_levels is not a number!") + return + + temp = json["space_empty_levels"] + if (isnum(temp)) + space_empty_levels = temp + else if (!isnull(temp)) + log_world("map_config space_empty_levels is not a number!") + return + + temp = json["year_offset"] + if (isnum(temp)) + year_offset = temp + else if (!isnull(temp)) + log_world("map_config year_offset is not a number!") + return + + if ("minetype" in json) + minetype = json["minetype"] + + if ("maptype" in json) + maptype = json["maptype"] + + if ("announcertype" in json) + announcertype = json["announcertype"] + + allow_custom_shuttles = json["allow_custom_shuttles"] != FALSE + + defaulted = FALSE + return TRUE +#undef CHECK_EXISTS + +/datum/map_config/proc/GetFullMapPaths() + if (istext(map_file)) + return list("_maps/[map_path]/[map_file]") + . = list() + for (var/file in map_file) + . += "_maps/[map_path]/[file]" + +/datum/map_config/proc/MakeNextMap() + return config_filename == "data/next_map.json" || fcopy(config_filename, "data/next_map.json") diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 8ae45ff720..42f18b8ebb 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1,780 +1,780 @@ -/* Note from Carnie: - The way datum/mind stuff works has been changed a lot. - Minds now represent IC characters rather than following a client around constantly. - - Guidelines for using minds properly: - - - Never mind.transfer_to(ghost). The var/current and var/original of a mind must always be of type mob/living! - ghost.mind is however used as a reference to the ghost's corpse - - - When creating a new mob for an existing IC character (e.g. cloning a dead guy or borging a brain of a human) - the existing mind of the old mob should be transfered to the new mob like so: - - mind.transfer_to(new_mob) - - - You must not assign key= or ckey= after transfer_to() since the transfer_to transfers the client for you. - By setting key or ckey explicitly after transferring the mind with transfer_to you will cause bugs like DCing - the player. - - - IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you. - - - When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting - a ghost to become a xeno during an event), use this mob proc. - - mob.transfer_ckey(new_mob) - - The Login proc will handle making a new mind for that mobtype (including setting up stuff like mind.name). Simple! - However if you want that mind to have any special properties like being a traitor etc you will have to do that - yourself. - -*/ - -/datum/mind - var/key - var/name //replaces mob/var/original_name - var/mob/living/current - var/active = 0 - - var/memory - - var/assigned_role - var/special_role - var/list/restricted_roles = list() - - var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button. - - var/linglink - var/datum/martial_art/martial_art - var/static/default_martial_art = new/datum/martial_art - var/miming = 0 // Mime's vow of silence - var/list/antag_datums - 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/damnation_type = 0 - var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src - var/hasSoul = TRUE // If false, renders the character unable to sell their soul. - var/isholy = FALSE //is this person a chaplain or admin role allowed to use bibles - - var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems) - var/datum/language_holder/language_holder - var/unconvertable = FALSE - var/late_joiner = FALSE - - var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator - - var/list/learned_recipes //List of learned recipe TYPES. - -/datum/mind/New(var/key) - src.key = key - soulOwner = src - martial_art = default_martial_art - -/datum/mind/Destroy() - SSticker.minds -= src - if(islist(antag_datums)) - for(var/i in antag_datums) - var/datum/antagonist/antag_datum = i - if(antag_datum.delete_on_mind_deletion) - qdel(i) - antag_datums = null - return ..() - -/datum/mind/proc/get_language_holder() - if(!language_holder) - var/datum/language_holder/L = current.get_language_holder(shadow=FALSE) - language_holder = L.copy(src) - - return language_holder - -/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0) - var/old_character = current - var/signals = SEND_SIGNAL(new_character, COMSIG_MOB_PRE_PLAYER_CHANGE, new_character, old_character) | SEND_SIGNAL(src, COMSIG_PRE_MIND_TRANSFER, new_character, old_character) - if(signals & COMPONENT_STOP_MIND_TRANSFER) - return - if(current) // remove ourself from our old body's mind variable - current.mind = null - SStgui.on_transfer(current, new_character) - if(iscarbon(current)) - var/mob/living/carbon/C = current - if(C.combatmode) - C.toggle_combat_mode(TRUE, TRUE) - if(!language_holder) - var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE) - language_holder = mob_holder.copy(src) - - if(key) - if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours - new_character.ghostize(TRUE, TRUE) //we'll need to ghostize so that key isn't mobless. - else - key = new_character.key - - if(new_character.mind) //disassociate any mind currently in our new body's mind variable - new_character.mind.current = null - - var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list - var/mob/living/old_current = current - if(current) - current.transfer_observers_to(new_character) //transfer anyone observing the old character to the new one - current = new_character //associate ourself with our new body - new_character.mind = src //and associate our new body with ourself - for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body - var/datum/antagonist/A = a - A.on_body_transfer(old_current, current) - if(iscarbon(new_character)) - var/mob/living/carbon/C = new_character - C.last_mind = src - transfer_antag_huds(hud_to_transfer) //inherit the antag HUD - transfer_actions(new_character) - transfer_martial_arts(new_character) - if(active || force_key_move) - new_character.key = key //now transfer the key to link the client to our new body - -//CIT CHANGE - makes arousal update when transfering bodies - if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. - var/mob/living/L = new_character - if(L.client && L.client.prefs) - L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... - L.update_arousal_hud() //Removes the old icon - if (L.client.prefs.auto_ooc) - if (L.client.prefs.chat_toggles & CHAT_OOC) - L.client.prefs.chat_toggles ^= CHAT_OOC - - SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) - SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND) - -/datum/mind/proc/store_memory(new_text) - if((length(memory) + length(new_text)) <= MAX_MESSAGE_LEN) - memory += "[new_text]
    " - -/datum/mind/proc/wipe_memory() - memory = null - -// Datum antag mind procs -/datum/mind/proc/add_antag_datum(datum_type_or_instance, team) - if(!datum_type_or_instance) - return - var/datum/antagonist/A - if(!ispath(datum_type_or_instance)) - A = datum_type_or_instance - if(!istype(A)) - return - else - A = new datum_type_or_instance() - //Choose snowflake variation if antagonist handles it - var/datum/antagonist/S = A.specialization(src) - if(S && S != A) - qdel(A) - A = S - if(!A.can_be_owned(src)) - qdel(A) - return - A.owner = src - LAZYADD(antag_datums, A) - A.create_team(team) - var/datum/team/antag_team = A.get_team() - if(antag_team) - antag_team.add_member(src) - A.on_gain() - return A - -/datum/mind/proc/remove_antag_datum(datum_type) - if(!datum_type) - return - var/datum/antagonist/A = has_antag_datum(datum_type) - if(A) - A.on_removal() - return TRUE - - -/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us. - for(var/a in antag_datums) - var/datum/antagonist/A = a - A.on_removal() - -/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) - if(!datum_type) - return - . = FALSE - for(var/a in antag_datums) - var/datum/antagonist/A = a - if(check_subtypes && istype(A, datum_type)) - return A - else if(A.type == datum_type) - return A - -/* - Removes antag type's references from a mind. - objectives, uplinks, powers etc are all handled. -*/ - -/datum/mind/proc/remove_changeling() - var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) - if(C) - remove_antag_datum(/datum/antagonist/changeling) - special_role = null - -/datum/mind/proc/remove_traitor() - remove_antag_datum(/datum/antagonist/traitor) - -/datum/mind/proc/remove_brother() - if(src in SSticker.mode.brothers) - remove_antag_datum(/datum/antagonist/brother) - SSticker.mode.update_brother_icons_removed(src) - -/datum/mind/proc/remove_nukeop() - var/datum/antagonist/nukeop/nuke = has_antag_datum(/datum/antagonist/nukeop,TRUE) - if(nuke) - remove_antag_datum(nuke.type) - special_role = null - -/datum/mind/proc/remove_wizard() - remove_antag_datum(/datum/antagonist/wizard) - special_role = null - -/datum/mind/proc/remove_cultist() - if(src in SSticker.mode.cult) - SSticker.mode.remove_cultist(src, 0, 0) - special_role = null - remove_antag_equip() - -/datum/mind/proc/remove_rev() - var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev) - if(rev) - remove_antag_datum(rev.type) - special_role = null - - -/datum/mind/proc/remove_antag_equip() - var/list/Mob_Contents = current.get_contents() - for(var/obj/item/I in Mob_Contents) - var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink) -//Todo make this reset signal - if(O) - O.unlock_code = null - -/datum/mind/proc/remove_all_antag() //For the Lazy amongst us. - remove_changeling() - remove_traitor() - remove_nukeop() - remove_wizard() - remove_cultist() - remove_rev() - SSticker.mode.update_cult_icons_removed(src) - -/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner) - if(!current) - return - var/mob/living/carbon/human/traitor_mob = current - if (!istype(traitor_mob)) - return - - var/list/all_contents = traitor_mob.GetAllContents() - var/obj/item/pda/PDA = locate() in all_contents - var/obj/item/radio/R = locate() in all_contents - var/obj/item/pen/P - - if (PDA) // Prioritize PDA pen, otherwise the pocket protector pens will be chosen, which causes numerous ahelps about missing uplink - P = locate() in PDA - if (!P) // If we couldn't find a pen in the PDA, or we didn't even have a PDA, do it the old way - P = locate() in all_contents - if(!P) // I do not have a pen. - var/obj/item/pen/inowhaveapen - if(istype(traitor_mob.back,/obj/item/storage)) //ok buddy you better have a backpack! - inowhaveapen = new /obj/item/pen(traitor_mob.back) - else - inowhaveapen = new /obj/item/pen(traitor_mob.loc) - traitor_mob.put_in_hands(inowhaveapen) // I hope you don't have arms and your traitor pen gets stolen for all this trouble you've caused. - P = inowhaveapen - - var/obj/item/uplink_loc - - if(traitor_mob.client && traitor_mob.client.prefs) - switch(traitor_mob.client.prefs.uplink_spawn_loc) - if(UPLINK_PDA) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = R - if(!uplink_loc) - uplink_loc = P - if(UPLINK_RADIO) - uplink_loc = R - if(!uplink_loc) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = P - if(UPLINK_PEN) - uplink_loc = P - if(!uplink_loc) - uplink_loc = PDA - if(!uplink_loc) - uplink_loc = R - - if (!uplink_loc) - if(!silent) - to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") - . = 0 - else - . = uplink_loc - var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key) - if(!U) - CRASH("Uplink creation failed.") - U.setup_unlock_code() - if(!silent) - if(uplink_loc == R) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.") - else if(uplink_loc == PDA) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.") - else if(uplink_loc == P) - to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.") - - if(uplink_owner) - uplink_owner.antag_memory += U.unlock_note + "
    " - else - traitor_mob.mind.store_memory(U.unlock_note) - -//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does. - -/datum/mind/proc/enslave_mind_to_creator(mob/living/creator) - if(iscultist(creator)) - SSticker.mode.add_cultist(src) - - else if(is_revolutionary(creator)) - var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev,TRUE) - converter.add_revolutionary(src,FALSE) - - else if(is_servant_of_ratvar(creator)) - add_servant_of_ratvar(current) - - else if(is_nuclear_operative(creator)) - var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE) - var/datum/antagonist/nukeop/N = new() - N.send_to_spawnpoint = FALSE - N.nukeop_outfit = null - add_antag_datum(N,converter.nuke_team) - - - enslaved_to = creator - - current.faction |= creator.faction - creator.faction |= current.faction - - if(creator.mind.special_role) - message_admins("[ADMIN_LOOKUPFLW(current)] has been created by [ADMIN_LOOKUPFLW(creator)], an antagonist.") - to_chat(current, "Despite your creators current allegiances, your true master remains [creator.real_name]. If their loyalties change, so do yours. This will never change unless your creator's body is destroyed.") - -/datum/mind/proc/show_memory(mob/recipient, window=1) - if(!recipient) - recipient = current - var/output = "[current.real_name]'s Memories:
    " - output += memory - - - var/list/all_objectives = list() - for(var/datum/antagonist/A in antag_datums) - output += A.antag_memory - all_objectives |= A.objectives - - if(all_objectives.len) - output += "Objectives:" - var/obj_count = 1 - for(var/datum/objective/objective in all_objectives) - output += "
    Objective #[obj_count++]: [objective.explanation_text]" - var/list/datum/mind/other_owners = objective.get_owners() - src - if(other_owners.len) - output += "
      " - for(var/datum/mind/M in other_owners) - output += "
    • Conspirator: [M.name]
    • " - output += "
    " - - if(window) - recipient << browse(output,"window=memory") - else if(all_objectives.len || memory) - to_chat(recipient, "[output]") - -/datum/mind/Topic(href, href_list) - if(!check_rights(R_ADMIN)) - return - - var/self_antagging = usr == current - - if(href_list["add_antag"]) - add_antag_wrapper(text2path(href_list["add_antag"]),usr) - if(href_list["remove_antag"]) - var/datum/antagonist/A = locate(href_list["remove_antag"]) in antag_datums - if(!istype(A)) - to_chat(usr,"Invalid antagonist ref to be removed.") - return - A.admin_remove(usr) - - if (href_list["role_edit"]) - var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() - if (!new_role) - return - assigned_role = new_role - - else if (href_list["memory_edit"]) - var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) - if (isnull(new_memo)) - return - memory = new_memo - - else if (href_list["obj_edit"] || href_list["obj_add"]) - var/objective_pos //Edited objectives need to keep same order in antag objective list - var/def_value - var/datum/antagonist/target_antag - var/datum/objective/old_objective //The old objective we're replacing/editing - var/datum/objective/new_objective //New objective we're be adding - - if(href_list["obj_edit"]) - for(var/datum/antagonist/A in antag_datums) - old_objective = locate(href_list["obj_edit"]) in A.objectives - if(old_objective) - target_antag = A - objective_pos = A.objectives.Find(old_objective) - break - if(!old_objective) - to_chat(usr,"Invalid objective.") - return - - else - if(href_list["target_antag"]) - var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums - if(X) - target_antag = X - if(!target_antag) - switch(antag_datums.len) - if(0) - target_antag = add_antag_datum(/datum/antagonist/custom) - if(1) - target_antag = antag_datums[1] - else - var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", "(new custom antag)") as null|anything in antag_datums + "(new custom antag)" - if (QDELETED(target)) - return - else if(target == "(new custom antag)") - target_antag = add_antag_datum(/datum/antagonist/custom) - else - target_antag = target - - var/static/list/choices - if(!choices) - choices = list() - - var/list/allowed_types = list( - /datum/objective/assassinate, - /datum/objective/maroon, - /datum/objective/debrain, - /datum/objective/protect, - /datum/objective/destroy, - /datum/objective/hijack, - /datum/objective/escape, - /datum/objective/survive, - /datum/objective/martyr, - /datum/objective/steal, - /datum/objective/download, - /datum/objective/nuclear, - /datum/objective/capture, - /datum/objective/absorb, - /datum/objective/custom - ) - - for(var/T in allowed_types) - var/datum/objective/X = T - choices[initial(X.name)] = T - - if(old_objective) - if(old_objective.name in choices) - def_value = old_objective.name - - var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices - selected_type = choices[selected_type] - if (!selected_type) - return - - if(!old_objective) - //Add new one - new_objective = new selected_type - new_objective.owner = src - new_objective.admin_edit(usr) - target_antag.objectives += new_objective - - message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") - log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") - else - if(old_objective.type == selected_type) - //Edit the old - old_objective.admin_edit(usr) - new_objective = old_objective - else - //Replace the old - new_objective = new selected_type - new_objective.owner = src - new_objective.admin_edit(usr) - target_antag.objectives -= old_objective - target_antag.objectives.Insert(objective_pos, new_objective) - message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") - log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") - - else if (href_list["obj_delete"]) - var/datum/objective/objective - - for(var/datum/antagonist/A in antag_datums) - objective = locate(href_list["obj_delete"]) in A.objectives - if(istype(objective)) - break - if(!objective) - to_chat(usr,"Invalid objective.") - return - qdel(objective) //TODO: Needs cleaning objective destroys (whatever that means) - message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") - log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") - - else if(href_list["obj_completed"]) - var/datum/objective/objective - for(var/datum/antagonist/A in antag_datums) - objective = locate(href_list["obj_completed"]) in A.objectives - if(istype(objective)) - objective = objective - break - if(!objective) - to_chat(usr,"Invalid objective.") - return - objective.completed = !objective.completed - log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") - - else if (href_list["silicon"]) - switch(href_list["silicon"]) - if("unemag") - var/mob/living/silicon/robot/R = current - if (istype(R)) - R.SetEmagged(0) - message_admins("[key_name_admin(usr)] has unemag'ed [R].") - log_admin("[key_name(usr)] has unemag'ed [R].") - - if("unemagcyborgs") - if(isAI(current)) - var/mob/living/silicon/ai/ai = current - for (var/mob/living/silicon/robot/R in ai.connected_robots) - R.SetEmagged(0) - message_admins("[key_name_admin(usr)] has unemag'ed [ai]'s Cyborgs.") - log_admin("[key_name(usr)] has unemag'ed [ai]'s Cyborgs.") - - else if (href_list["common"]) - switch(href_list["common"]) - if("undress") - for(var/obj/item/W in current) - current.dropItemToGround(W, TRUE) //The 1 forces all items to drop, since this is an admin undress. - if("takeuplink") - take_uplink() - memory = null//Remove any memory they may have had. - log_admin("[key_name(usr)] removed [current]'s uplink.") - if("crystals") - if(check_rights(R_FUN, 0)) - var/datum/component/uplink/U = find_syndicate_uplink() - if(U) - var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num - if(!isnull(crystals)) - U.telecrystals = crystals - message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].") - log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].") - if("uplink") - if(!equip_traitor()) - to_chat(usr, "Equipping a syndicate failed!") - log_admin("[key_name(usr)] tried and failed to give [current] an uplink.") - else - log_admin("[key_name(usr)] gave [current] an uplink.") - - else if (href_list["obj_announce"]) - announce_objectives() - - //Something in here might have changed your mob - if(self_antagging && (!usr || !usr.client) && current.client) - usr = current - traitor_panel() - -/datum/mind/proc/get_all_objectives() - var/list/all_objectives = list() - for(var/datum/antagonist/A in antag_datums) - all_objectives |= A.objectives - return all_objectives - -/datum/mind/proc/announce_objectives() - var/obj_count = 1 - to_chat(current, "Your current objectives:") - for(var/objective in get_all_objectives()) - var/datum/objective/O = objective - to_chat(current, "Objective #[obj_count]: [O.explanation_text]") - obj_count++ - -/datum/mind/proc/find_syndicate_uplink() - var/list/L = current.GetAllContents() - for (var/i in L) - var/atom/movable/I = i - . = I.GetComponent(/datum/component/uplink) - if(.) - break - -/datum/mind/proc/take_uplink() - qdel(find_syndicate_uplink()) - -/datum/mind/proc/make_Traitor() - if(!(has_antag_datum(/datum/antagonist/traitor))) - add_antag_datum(/datum/antagonist/traitor) - -/datum/mind/proc/make_Changeling() - var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) - if(!C) - C = add_antag_datum(/datum/antagonist/changeling) - special_role = ROLE_CHANGELING - return C - -/datum/mind/proc/make_Wizard() - if(!has_antag_datum(/datum/antagonist/wizard)) - special_role = ROLE_WIZARD - assigned_role = ROLE_WIZARD - add_antag_datum(/datum/antagonist/wizard) - - -/datum/mind/proc/make_Cultist() - if(!has_antag_datum(/datum/antagonist/cult,TRUE)) - SSticker.mode.add_cultist(src,FALSE,equip=TRUE) - special_role = ROLE_CULTIST - to_chat(current, "You catch a glimpse of the Realm of Nar'Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar'Sie.") - to_chat(current, "Assist your new brethren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") - -/datum/mind/proc/make_Rev() - var/datum/antagonist/rev/head/head = new() - head.give_flash = TRUE - head.give_hud = TRUE - add_antag_datum(head) - special_role = ROLE_REV_HEAD - -/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S) - spell_list += S - S.action.Grant(current) - -/datum/mind/proc/owns_soul() - return soulOwner == src - -//To remove a specific spell from a mind -/datum/mind/proc/RemoveSpell(obj/effect/proc_holder/spell/spell) - if(!spell) - return - for(var/X in spell_list) - var/obj/effect/proc_holder/spell/S = X - if(istype(S, spell)) - spell_list -= S - qdel(S) - -/datum/mind/proc/RemoveAllSpells() - for(var/obj/effect/proc_holder/S in spell_list) - RemoveSpell(S) - -/datum/mind/proc/transfer_martial_arts(mob/living/new_character) - if(!ishuman(new_character)) - return - if(martial_art) - if(martial_art.base) //Is the martial art temporary? - martial_art.remove(new_character) - else - martial_art.teach(new_character) - -/datum/mind/proc/transfer_actions(mob/living/new_character) - if(current && current.actions) - for(var/datum/action/A in current.actions) - A.Grant(new_character) - transfer_mindbound_actions(new_character) - -/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character) - for(var/X in spell_list) - var/obj/effect/proc_holder/spell/S = X - S.action.Grant(new_character) - var/datum/antagonist/changeling/changeling = new_character.mind.has_antag_datum(/datum/antagonist/changeling) - if(changeling &&(ishuman(new_character) || ismonkey(new_character))) - for(var/P in changeling.purchasedpowers) - var/obj/effect/proc_holder/changeling/I = P - I.action.Grant(new_character) - -/datum/mind/proc/disrupt_spells(delay, list/exceptions = New()) - for(var/X in spell_list) - var/obj/effect/proc_holder/spell/S = X - for(var/type in exceptions) - if(istype(S, type)) - continue - S.charge_counter = delay - S.updateButtonIcon() - INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge) - -/datum/mind/proc/get_ghost(even_if_they_cant_reenter) - for(var/mob/dead/observer/G in GLOB.dead_mob_list) - if(G.mind == src) - if(G.can_reenter_corpse || even_if_they_cant_reenter) - return G - break - -/datum/mind/proc/grab_ghost(force) - var/mob/dead/observer/G = get_ghost(even_if_they_cant_reenter = force) - . = G - if(G) - G.reenter_corpse() - - -/datum/mind/proc/has_objective(objective_type) - for(var/datum/antagonist/A in antag_datums) - for(var/O in A.objectives) - if(istype(O,objective_type)) - return TRUE - -/mob/proc/sync_mind() - mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) - mind.active = 1 //indicates that the mind is currently synced with a client - -/datum/mind/proc/has_martialart(var/string) - if(martial_art && martial_art.id == string) - return martial_art - return FALSE - -/mob/dead/new_player/sync_mind() - return - -/mob/dead/observer/sync_mind() - return - -//Initialisation procs -/mob/proc/mind_initialize() - if(mind) - mind.key = key - - else - mind = new /datum/mind(key) - SSticker.minds += mind - SEND_SIGNAL(src, COMSIG_MOB_ON_NEW_MIND) - if(!mind.name) - mind.name = real_name - mind.current = src - -/mob/living/carbon/mind_initialize() - ..() - last_mind = mind - -//HUMAN -/mob/living/carbon/human/mind_initialize() - ..() - if(!mind.assigned_role) - mind.assigned_role = "Unassigned" //default - -//AI -/mob/living/silicon/ai/mind_initialize() - ..() - mind.assigned_role = "AI" - -//BORG -/mob/living/silicon/robot/mind_initialize() - ..() - mind.assigned_role = "Cyborg" - -//PAI -/mob/living/silicon/pai/mind_initialize() - ..() - mind.assigned_role = ROLE_PAI - mind.special_role = "" +/* Note from Carnie: + The way datum/mind stuff works has been changed a lot. + Minds now represent IC characters rather than following a client around constantly. + + Guidelines for using minds properly: + + - Never mind.transfer_to(ghost). The var/current and var/original of a mind must always be of type mob/living! + ghost.mind is however used as a reference to the ghost's corpse + + - When creating a new mob for an existing IC character (e.g. cloning a dead guy or borging a brain of a human) + the existing mind of the old mob should be transfered to the new mob like so: + + mind.transfer_to(new_mob) + + - You must not assign key= or ckey= after transfer_to() since the transfer_to transfers the client for you. + By setting key or ckey explicitly after transferring the mind with transfer_to you will cause bugs like DCing + the player. + + - IMPORTANT NOTE 2, if you want a player to become a ghost, use mob.ghostize() It does all the hard work for you. + + - When creating a new mob which will be a new IC character (e.g. putting a shade in a construct or randomly selecting + a ghost to become a xeno during an event), use this mob proc. + + mob.transfer_ckey(new_mob) + + The Login proc will handle making a new mind for that mobtype (including setting up stuff like mind.name). Simple! + However if you want that mind to have any special properties like being a traitor etc you will have to do that + yourself. + +*/ + +/datum/mind + var/key + var/name //replaces mob/var/original_name + var/mob/living/current + var/active = 0 + + var/memory + + var/assigned_role + var/special_role + var/list/restricted_roles = list() + + var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button. + + var/linglink + var/datum/martial_art/martial_art + var/static/default_martial_art = new/datum/martial_art + var/miming = 0 // Mime's vow of silence + var/list/antag_datums + 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/damnation_type = 0 + var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src + var/hasSoul = TRUE // If false, renders the character unable to sell their soul. + var/isholy = FALSE //is this person a chaplain or admin role allowed to use bibles + + var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems) + var/datum/language_holder/language_holder + var/unconvertable = FALSE + var/late_joiner = FALSE + + var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator + + var/list/learned_recipes //List of learned recipe TYPES. + +/datum/mind/New(var/key) + src.key = key + soulOwner = src + martial_art = default_martial_art + +/datum/mind/Destroy() + SSticker.minds -= src + if(islist(antag_datums)) + for(var/i in antag_datums) + var/datum/antagonist/antag_datum = i + if(antag_datum.delete_on_mind_deletion) + qdel(i) + antag_datums = null + return ..() + +/datum/mind/proc/get_language_holder() + if(!language_holder) + var/datum/language_holder/L = current.get_language_holder(shadow=FALSE) + language_holder = L.copy(src) + + return language_holder + +/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0) + var/old_character = current + var/signals = SEND_SIGNAL(new_character, COMSIG_MOB_PRE_PLAYER_CHANGE, new_character, old_character) | SEND_SIGNAL(src, COMSIG_PRE_MIND_TRANSFER, new_character, old_character) + if(signals & COMPONENT_STOP_MIND_TRANSFER) + return + if(current) // remove ourself from our old body's mind variable + current.mind = null + SStgui.on_transfer(current, new_character) + if(iscarbon(current)) + var/mob/living/carbon/C = current + if(C.combatmode) + C.toggle_combat_mode(TRUE, TRUE) + if(!language_holder) + var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE) + language_holder = mob_holder.copy(src) + + if(key) + if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours + new_character.ghostize(TRUE, TRUE) //we'll need to ghostize so that key isn't mobless. + else + key = new_character.key + + if(new_character.mind) //disassociate any mind currently in our new body's mind variable + new_character.mind.current = null + + var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list + var/mob/living/old_current = current + if(current) + current.transfer_observers_to(new_character) //transfer anyone observing the old character to the new one + current = new_character //associate ourself with our new body + new_character.mind = src //and associate our new body with ourself + for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body + var/datum/antagonist/A = a + A.on_body_transfer(old_current, current) + if(iscarbon(new_character)) + var/mob/living/carbon/C = new_character + C.last_mind = src + transfer_antag_huds(hud_to_transfer) //inherit the antag HUD + transfer_actions(new_character) + transfer_martial_arts(new_character) + if(active || force_key_move) + new_character.key = key //now transfer the key to link the client to our new body + +//CIT CHANGE - makes arousal update when transfering bodies + if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. + var/mob/living/L = new_character + if(L.client && L.client.prefs) + L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... + L.update_arousal_hud() //Removes the old icon + if (L.client.prefs.auto_ooc) + if (L.client.prefs.chat_toggles & CHAT_OOC) + L.client.prefs.chat_toggles ^= CHAT_OOC + + SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) + SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND) + +/datum/mind/proc/store_memory(new_text) + if((length(memory) + length(new_text)) <= MAX_MESSAGE_LEN) + memory += "[new_text]
    " + +/datum/mind/proc/wipe_memory() + memory = null + +// Datum antag mind procs +/datum/mind/proc/add_antag_datum(datum_type_or_instance, team) + if(!datum_type_or_instance) + return + var/datum/antagonist/A + if(!ispath(datum_type_or_instance)) + A = datum_type_or_instance + if(!istype(A)) + return + else + A = new datum_type_or_instance() + //Choose snowflake variation if antagonist handles it + var/datum/antagonist/S = A.specialization(src) + if(S && S != A) + qdel(A) + A = S + if(!A.can_be_owned(src)) + qdel(A) + return + A.owner = src + LAZYADD(antag_datums, A) + A.create_team(team) + var/datum/team/antag_team = A.get_team() + if(antag_team) + antag_team.add_member(src) + A.on_gain() + return A + +/datum/mind/proc/remove_antag_datum(datum_type) + if(!datum_type) + return + var/datum/antagonist/A = has_antag_datum(datum_type) + if(A) + A.on_removal() + return TRUE + + +/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us. + for(var/a in antag_datums) + var/datum/antagonist/A = a + A.on_removal() + +/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE) + if(!datum_type) + return + . = FALSE + for(var/a in antag_datums) + var/datum/antagonist/A = a + if(check_subtypes && istype(A, datum_type)) + return A + else if(A.type == datum_type) + return A + +/* + Removes antag type's references from a mind. + objectives, uplinks, powers etc are all handled. +*/ + +/datum/mind/proc/remove_changeling() + var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) + if(C) + remove_antag_datum(/datum/antagonist/changeling) + special_role = null + +/datum/mind/proc/remove_traitor() + remove_antag_datum(/datum/antagonist/traitor) + +/datum/mind/proc/remove_brother() + if(src in SSticker.mode.brothers) + remove_antag_datum(/datum/antagonist/brother) + SSticker.mode.update_brother_icons_removed(src) + +/datum/mind/proc/remove_nukeop() + var/datum/antagonist/nukeop/nuke = has_antag_datum(/datum/antagonist/nukeop,TRUE) + if(nuke) + remove_antag_datum(nuke.type) + special_role = null + +/datum/mind/proc/remove_wizard() + remove_antag_datum(/datum/antagonist/wizard) + special_role = null + +/datum/mind/proc/remove_cultist() + if(src in SSticker.mode.cult) + SSticker.mode.remove_cultist(src, 0, 0) + special_role = null + remove_antag_equip() + +/datum/mind/proc/remove_rev() + var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev) + if(rev) + remove_antag_datum(rev.type) + special_role = null + + +/datum/mind/proc/remove_antag_equip() + var/list/Mob_Contents = current.get_contents() + for(var/obj/item/I in Mob_Contents) + var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink) +//Todo make this reset signal + if(O) + O.unlock_code = null + +/datum/mind/proc/remove_all_antag() //For the Lazy amongst us. + remove_changeling() + remove_traitor() + remove_nukeop() + remove_wizard() + remove_cultist() + remove_rev() + SSticker.mode.update_cult_icons_removed(src) + +/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner) + if(!current) + return + var/mob/living/carbon/human/traitor_mob = current + if (!istype(traitor_mob)) + return + + var/list/all_contents = traitor_mob.GetAllContents() + var/obj/item/pda/PDA = locate() in all_contents + var/obj/item/radio/R = locate() in all_contents + var/obj/item/pen/P + + if (PDA) // Prioritize PDA pen, otherwise the pocket protector pens will be chosen, which causes numerous ahelps about missing uplink + P = locate() in PDA + if (!P) // If we couldn't find a pen in the PDA, or we didn't even have a PDA, do it the old way + P = locate() in all_contents + if(!P) // I do not have a pen. + var/obj/item/pen/inowhaveapen + if(istype(traitor_mob.back,/obj/item/storage)) //ok buddy you better have a backpack! + inowhaveapen = new /obj/item/pen(traitor_mob.back) + else + inowhaveapen = new /obj/item/pen(traitor_mob.loc) + traitor_mob.put_in_hands(inowhaveapen) // I hope you don't have arms and your traitor pen gets stolen for all this trouble you've caused. + P = inowhaveapen + + var/obj/item/uplink_loc + + if(traitor_mob.client && traitor_mob.client.prefs) + switch(traitor_mob.client.prefs.uplink_spawn_loc) + if(UPLINK_PDA) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = R + if(!uplink_loc) + uplink_loc = P + if(UPLINK_RADIO) + uplink_loc = R + if(!uplink_loc) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = P + if(UPLINK_PEN) + uplink_loc = P + if(!uplink_loc) + uplink_loc = PDA + if(!uplink_loc) + uplink_loc = R + + if (!uplink_loc) + if(!silent) + to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.") + . = 0 + else + . = uplink_loc + var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key) + if(!U) + CRASH("Uplink creation failed.") + U.setup_unlock_code() + if(!silent) + if(uplink_loc == R) + to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.") + else if(uplink_loc == PDA) + to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.") + else if(uplink_loc == P) + to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.") + + if(uplink_owner) + uplink_owner.antag_memory += U.unlock_note + "
    " + else + traitor_mob.mind.store_memory(U.unlock_note) + +//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does. + +/datum/mind/proc/enslave_mind_to_creator(mob/living/creator) + if(iscultist(creator)) + SSticker.mode.add_cultist(src) + + else if(is_revolutionary(creator)) + var/datum/antagonist/rev/converter = creator.mind.has_antag_datum(/datum/antagonist/rev,TRUE) + converter.add_revolutionary(src,FALSE) + + else if(is_servant_of_ratvar(creator)) + add_servant_of_ratvar(current) + + else if(is_nuclear_operative(creator)) + var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE) + var/datum/antagonist/nukeop/N = new() + N.send_to_spawnpoint = FALSE + N.nukeop_outfit = null + add_antag_datum(N,converter.nuke_team) + + + enslaved_to = creator + + current.faction |= creator.faction + creator.faction |= current.faction + + if(creator.mind.special_role) + message_admins("[ADMIN_LOOKUPFLW(current)] has been created by [ADMIN_LOOKUPFLW(creator)], an antagonist.") + to_chat(current, "Despite your creators current allegiances, your true master remains [creator.real_name]. If their loyalties change, so do yours. This will never change unless your creator's body is destroyed.") + +/datum/mind/proc/show_memory(mob/recipient, window=1) + if(!recipient) + recipient = current + var/output = "[current.real_name]'s Memories:
    " + output += memory + + + var/list/all_objectives = list() + for(var/datum/antagonist/A in antag_datums) + output += A.antag_memory + all_objectives |= A.objectives + + if(all_objectives.len) + output += "Objectives:" + var/obj_count = 1 + for(var/datum/objective/objective in all_objectives) + output += "
    Objective #[obj_count++]: [objective.explanation_text]" + var/list/datum/mind/other_owners = objective.get_owners() - src + if(other_owners.len) + output += "
      " + for(var/datum/mind/M in other_owners) + output += "
    • Conspirator: [M.name]
    • " + output += "
    " + + if(window) + recipient << browse(output,"window=memory") + else if(all_objectives.len || memory) + to_chat(recipient, "[output]") + +/datum/mind/Topic(href, href_list) + if(!check_rights(R_ADMIN)) + return + + var/self_antagging = usr == current + + if(href_list["add_antag"]) + add_antag_wrapper(text2path(href_list["add_antag"]),usr) + if(href_list["remove_antag"]) + var/datum/antagonist/A = locate(href_list["remove_antag"]) in antag_datums + if(!istype(A)) + to_chat(usr,"Invalid antagonist ref to be removed.") + return + A.admin_remove(usr) + + if (href_list["role_edit"]) + var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() + if (!new_role) + return + assigned_role = new_role + + else if (href_list["memory_edit"]) + var/new_memo = copytext(sanitize(input("Write new memory", "Memory", memory) as null|message),1,MAX_MESSAGE_LEN) + if (isnull(new_memo)) + return + memory = new_memo + + else if (href_list["obj_edit"] || href_list["obj_add"]) + var/objective_pos //Edited objectives need to keep same order in antag objective list + var/def_value + var/datum/antagonist/target_antag + var/datum/objective/old_objective //The old objective we're replacing/editing + var/datum/objective/new_objective //New objective we're be adding + + if(href_list["obj_edit"]) + for(var/datum/antagonist/A in antag_datums) + old_objective = locate(href_list["obj_edit"]) in A.objectives + if(old_objective) + target_antag = A + objective_pos = A.objectives.Find(old_objective) + break + if(!old_objective) + to_chat(usr,"Invalid objective.") + return + + else + if(href_list["target_antag"]) + var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums + if(X) + target_antag = X + if(!target_antag) + switch(antag_datums.len) + if(0) + target_antag = add_antag_datum(/datum/antagonist/custom) + if(1) + target_antag = antag_datums[1] + else + var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", "(new custom antag)") as null|anything in antag_datums + "(new custom antag)" + if (QDELETED(target)) + return + else if(target == "(new custom antag)") + target_antag = add_antag_datum(/datum/antagonist/custom) + else + target_antag = target + + var/static/list/choices + if(!choices) + choices = list() + + var/list/allowed_types = list( + /datum/objective/assassinate, + /datum/objective/maroon, + /datum/objective/debrain, + /datum/objective/protect, + /datum/objective/destroy, + /datum/objective/hijack, + /datum/objective/escape, + /datum/objective/survive, + /datum/objective/martyr, + /datum/objective/steal, + /datum/objective/download, + /datum/objective/nuclear, + /datum/objective/capture, + /datum/objective/absorb, + /datum/objective/custom + ) + + for(var/T in allowed_types) + var/datum/objective/X = T + choices[initial(X.name)] = T + + if(old_objective) + if(old_objective.name in choices) + def_value = old_objective.name + + var/selected_type = input("Select objective type:", "Objective type", def_value) as null|anything in choices + selected_type = choices[selected_type] + if (!selected_type) + return + + if(!old_objective) + //Add new one + new_objective = new selected_type + new_objective.owner = src + new_objective.admin_edit(usr) + target_antag.objectives += new_objective + + message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") + log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") + else + if(old_objective.type == selected_type) + //Edit the old + old_objective.admin_edit(usr) + new_objective = old_objective + else + //Replace the old + new_objective = new selected_type + new_objective.owner = src + new_objective.admin_edit(usr) + target_antag.objectives -= old_objective + target_antag.objectives.Insert(objective_pos, new_objective) + message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") + log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") + + else if (href_list["obj_delete"]) + var/datum/objective/objective + + for(var/datum/antagonist/A in antag_datums) + objective = locate(href_list["obj_delete"]) in A.objectives + if(istype(objective)) + break + if(!objective) + to_chat(usr,"Invalid objective.") + return + qdel(objective) //TODO: Needs cleaning objective destroys (whatever that means) + message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") + log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") + + else if(href_list["obj_completed"]) + var/datum/objective/objective + for(var/datum/antagonist/A in antag_datums) + objective = locate(href_list["obj_completed"]) in A.objectives + if(istype(objective)) + objective = objective + break + if(!objective) + to_chat(usr,"Invalid objective.") + return + objective.completed = !objective.completed + log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") + + else if (href_list["silicon"]) + switch(href_list["silicon"]) + if("unemag") + var/mob/living/silicon/robot/R = current + if (istype(R)) + R.SetEmagged(0) + message_admins("[key_name_admin(usr)] has unemag'ed [R].") + log_admin("[key_name(usr)] has unemag'ed [R].") + + if("unemagcyborgs") + if(isAI(current)) + var/mob/living/silicon/ai/ai = current + for (var/mob/living/silicon/robot/R in ai.connected_robots) + R.SetEmagged(0) + message_admins("[key_name_admin(usr)] has unemag'ed [ai]'s Cyborgs.") + log_admin("[key_name(usr)] has unemag'ed [ai]'s Cyborgs.") + + else if (href_list["common"]) + switch(href_list["common"]) + if("undress") + for(var/obj/item/W in current) + current.dropItemToGround(W, TRUE) //The 1 forces all items to drop, since this is an admin undress. + if("takeuplink") + take_uplink() + memory = null//Remove any memory they may have had. + log_admin("[key_name(usr)] removed [current]'s uplink.") + if("crystals") + if(check_rights(R_FUN, 0)) + var/datum/component/uplink/U = find_syndicate_uplink() + if(U) + var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.telecrystals) as null | num + if(!isnull(crystals)) + U.telecrystals = crystals + message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].") + log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].") + if("uplink") + if(!equip_traitor()) + to_chat(usr, "Equipping a syndicate failed!") + log_admin("[key_name(usr)] tried and failed to give [current] an uplink.") + else + log_admin("[key_name(usr)] gave [current] an uplink.") + + else if (href_list["obj_announce"]) + announce_objectives() + + //Something in here might have changed your mob + if(self_antagging && (!usr || !usr.client) && current.client) + usr = current + traitor_panel() + +/datum/mind/proc/get_all_objectives() + var/list/all_objectives = list() + for(var/datum/antagonist/A in antag_datums) + all_objectives |= A.objectives + return all_objectives + +/datum/mind/proc/announce_objectives() + var/obj_count = 1 + to_chat(current, "Your current objectives:") + for(var/objective in get_all_objectives()) + var/datum/objective/O = objective + to_chat(current, "Objective #[obj_count]: [O.explanation_text]") + obj_count++ + +/datum/mind/proc/find_syndicate_uplink() + var/list/L = current.GetAllContents() + for (var/i in L) + var/atom/movable/I = i + . = I.GetComponent(/datum/component/uplink) + if(.) + break + +/datum/mind/proc/take_uplink() + qdel(find_syndicate_uplink()) + +/datum/mind/proc/make_Traitor() + if(!(has_antag_datum(/datum/antagonist/traitor))) + add_antag_datum(/datum/antagonist/traitor) + +/datum/mind/proc/make_Changeling() + var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) + if(!C) + C = add_antag_datum(/datum/antagonist/changeling) + special_role = ROLE_CHANGELING + return C + +/datum/mind/proc/make_Wizard() + if(!has_antag_datum(/datum/antagonist/wizard)) + special_role = ROLE_WIZARD + assigned_role = ROLE_WIZARD + add_antag_datum(/datum/antagonist/wizard) + + +/datum/mind/proc/make_Cultist() + if(!has_antag_datum(/datum/antagonist/cult,TRUE)) + SSticker.mode.add_cultist(src,FALSE,equip=TRUE) + special_role = ROLE_CULTIST + to_chat(current, "You catch a glimpse of the Realm of Nar'Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar'Sie.") + to_chat(current, "Assist your new brethren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") + +/datum/mind/proc/make_Rev() + var/datum/antagonist/rev/head/head = new() + head.give_flash = TRUE + head.give_hud = TRUE + add_antag_datum(head) + special_role = ROLE_REV_HEAD + +/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S) + spell_list += S + S.action.Grant(current) + +/datum/mind/proc/owns_soul() + return soulOwner == src + +//To remove a specific spell from a mind +/datum/mind/proc/RemoveSpell(obj/effect/proc_holder/spell/spell) + if(!spell) + return + for(var/X in spell_list) + var/obj/effect/proc_holder/spell/S = X + if(istype(S, spell)) + spell_list -= S + qdel(S) + +/datum/mind/proc/RemoveAllSpells() + for(var/obj/effect/proc_holder/S in spell_list) + RemoveSpell(S) + +/datum/mind/proc/transfer_martial_arts(mob/living/new_character) + if(!ishuman(new_character)) + return + if(martial_art) + if(martial_art.base) //Is the martial art temporary? + martial_art.remove(new_character) + else + martial_art.teach(new_character) + +/datum/mind/proc/transfer_actions(mob/living/new_character) + if(current && current.actions) + for(var/datum/action/A in current.actions) + A.Grant(new_character) + transfer_mindbound_actions(new_character) + +/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character) + for(var/X in spell_list) + var/obj/effect/proc_holder/spell/S = X + S.action.Grant(new_character) + var/datum/antagonist/changeling/changeling = new_character.mind.has_antag_datum(/datum/antagonist/changeling) + if(changeling &&(ishuman(new_character) || ismonkey(new_character))) + for(var/P in changeling.purchasedpowers) + var/obj/effect/proc_holder/changeling/I = P + I.action.Grant(new_character) + +/datum/mind/proc/disrupt_spells(delay, list/exceptions = New()) + for(var/X in spell_list) + var/obj/effect/proc_holder/spell/S = X + for(var/type in exceptions) + if(istype(S, type)) + continue + S.charge_counter = delay + S.updateButtonIcon() + INVOKE_ASYNC(S, /obj/effect/proc_holder/spell.proc/start_recharge) + +/datum/mind/proc/get_ghost(even_if_they_cant_reenter) + for(var/mob/dead/observer/G in GLOB.dead_mob_list) + if(G.mind == src) + if(G.can_reenter_corpse || even_if_they_cant_reenter) + return G + break + +/datum/mind/proc/grab_ghost(force) + var/mob/dead/observer/G = get_ghost(even_if_they_cant_reenter = force) + . = G + if(G) + G.reenter_corpse() + + +/datum/mind/proc/has_objective(objective_type) + for(var/datum/antagonist/A in antag_datums) + for(var/O in A.objectives) + if(istype(O,objective_type)) + return TRUE + +/mob/proc/sync_mind() + mind_initialize() //updates the mind (or creates and initializes one if one doesn't exist) + mind.active = 1 //indicates that the mind is currently synced with a client + +/datum/mind/proc/has_martialart(var/string) + if(martial_art && martial_art.id == string) + return martial_art + return FALSE + +/mob/dead/new_player/sync_mind() + return + +/mob/dead/observer/sync_mind() + return + +//Initialisation procs +/mob/proc/mind_initialize() + if(mind) + mind.key = key + + else + mind = new /datum/mind(key) + SSticker.minds += mind + SEND_SIGNAL(src, COMSIG_MOB_ON_NEW_MIND) + if(!mind.name) + mind.name = real_name + mind.current = src + +/mob/living/carbon/mind_initialize() + ..() + last_mind = mind + +//HUMAN +/mob/living/carbon/human/mind_initialize() + ..() + if(!mind.assigned_role) + mind.assigned_role = "Unassigned" //default + +//AI +/mob/living/silicon/ai/mind_initialize() + ..() + mind.assigned_role = "AI" + +//BORG +/mob/living/silicon/robot/mind_initialize() + ..() + mind.assigned_role = "Cyborg" + +//PAI +/mob/living/silicon/pai/mind_initialize() + ..() + mind.assigned_role = ROLE_PAI + mind.special_role = "" diff --git a/code/datums/mood_events/drug_events.dm b/code/datums/mood_events/drug_events.dm index 1a681a8a4d..a5d7dc631d 100644 --- a/code/datums/mood_events/drug_events.dm +++ b/code/datums/mood_events/drug_events.dm @@ -1,115 +1,115 @@ -/datum/mood_event/high - mood_change = 6 - description = "Woooow duudeeeeee...I'm tripping baaalls...\n" - -/datum/mood_event/smoked - description = "I have had a smoke recently.\n" - mood_change = 2 - timeout = 3600 - -/datum/mood_event/overdose - mood_change = -8 - timeout = 3000 - -/datum/mood_event/overdose/add_effects(drug_name) - description = "I think I took a bit too much of that [drug_name]\n" - -/datum/mood_event/withdrawal_light - mood_change = -2 - -/datum/mood_event/withdrawal_light/add_effects(drug_name) - description = "I could use some [drug_name]\n" - -/datum/mood_event/withdrawal_medium - mood_change = -5 - -/datum/mood_event/withdrawal_medium/add_effects(drug_name) - description = "I really need [drug_name]\n" - -/datum/mood_event/withdrawal_severe - mood_change = -8 - -/datum/mood_event/withdrawal_severe/add_effects(drug_name) - description = "Oh god I need some [drug_name]\n" - -/datum/mood_event/withdrawal_critical - mood_change = -10 - -/datum/mood_event/withdrawal_critical/add_effects(drug_name) - description = "[drug_name]! [drug_name]! [drug_name]!\n" - -/datum/mood_event/happiness_drug - description = "I can't feel anything and I never want this to end.\n" - mood_change = 10 - -/datum/mood_event/happiness_drug_good_od - description = "YES! YES!! YES!!!\n" - mood_change = 20 - timeout = 300 - //special_screen_obj = "mood_happiness_good" Originally in tg, but I personally think they look dumb - -/datum/mood_event/happiness_drug_bad_od - description = "NO! NO!! NO!!!\n" - mood_change = -20 - timeout = 300 - //special_screen_obj = "mood_happiness_bad" Originally in tg - -/datum/mood_event/eigenstate - mood_change = -3 - description = "Where the hell am I? Is this an alternative dimension ?\n" - -/datum/mood_event/enthrall - mood_change = 5 - -/datum/mood_event/enthrall/add_effects(message) - description = "[message]\n" - -/datum/mood_event/enthrallpraise - mood_change = 10 - timeout = 1 MINUTES - -/datum/mood_event/enthrallpraise/add_effects(message) - description = "[message]\n" - -/datum/mood_event/enthrallscold - mood_change = -10 - timeout = 1 MINUTES - -/datum/mood_event/enthrallscold/add_effects(message) - description = "[message]\n"//aaa I'm not kinky enough for this - -/datum/mood_event/enthrallmissing1 - mood_change = -5 - -/datum/mood_event/enthrallmissing1/add_effects(message) - description = "[message]\n" - -/datum/mood_event/enthrallmissing2 - mood_change = -10 - -/datum/mood_event/enthrallmissing2/add_effects(message) - description = "[message]\n" - -/datum/mood_event/enthrallmissing3 - mood_change = -15 - -/datum/mood_event/enthrallmissing3/add_effects(message) - description = "[message]\n" - -/datum/mood_event/enthrallmissing4 - mood_change = -25 - -/datum/mood_event/enthrallmissing4/add_effects(message) - description = "[message]\n" - -/datum/mood_event/InLove - mood_change = 10 - -/datum/mood_event/InLove/add_effects(message) - description = "[message]\n" - -/datum/mood_event/MissingLove - mood_change = -10 - -/datum/mood_event/MissingLove/add_effects(message) - description = "[message]\n" +/datum/mood_event/high + mood_change = 6 + description = "Woooow duudeeeeee...I'm tripping baaalls...\n" + +/datum/mood_event/smoked + description = "I have had a smoke recently.\n" + mood_change = 2 + timeout = 3600 + +/datum/mood_event/overdose + mood_change = -8 + timeout = 3000 + +/datum/mood_event/overdose/add_effects(drug_name) + description = "I think I took a bit too much of that [drug_name]\n" + +/datum/mood_event/withdrawal_light + mood_change = -2 + +/datum/mood_event/withdrawal_light/add_effects(drug_name) + description = "I could use some [drug_name]\n" + +/datum/mood_event/withdrawal_medium + mood_change = -5 + +/datum/mood_event/withdrawal_medium/add_effects(drug_name) + description = "I really need [drug_name]\n" + +/datum/mood_event/withdrawal_severe + mood_change = -8 + +/datum/mood_event/withdrawal_severe/add_effects(drug_name) + description = "Oh god I need some [drug_name]\n" + +/datum/mood_event/withdrawal_critical + mood_change = -10 + +/datum/mood_event/withdrawal_critical/add_effects(drug_name) + description = "[drug_name]! [drug_name]! [drug_name]!\n" + +/datum/mood_event/happiness_drug + description = "I can't feel anything and I never want this to end.\n" + mood_change = 10 + +/datum/mood_event/happiness_drug_good_od + description = "YES! YES!! YES!!!\n" + mood_change = 20 + timeout = 300 + //special_screen_obj = "mood_happiness_good" Originally in tg, but I personally think they look dumb + +/datum/mood_event/happiness_drug_bad_od + description = "NO! NO!! NO!!!\n" + mood_change = -20 + timeout = 300 + //special_screen_obj = "mood_happiness_bad" Originally in tg + +/datum/mood_event/eigenstate + mood_change = -3 + description = "Where the hell am I? Is this an alternative dimension ?\n" + +/datum/mood_event/enthrall + mood_change = 5 + +/datum/mood_event/enthrall/add_effects(message) + description = "[message]\n" + +/datum/mood_event/enthrallpraise + mood_change = 10 + timeout = 1 MINUTES + +/datum/mood_event/enthrallpraise/add_effects(message) + description = "[message]\n" + +/datum/mood_event/enthrallscold + mood_change = -10 + timeout = 1 MINUTES + +/datum/mood_event/enthrallscold/add_effects(message) + description = "[message]\n"//aaa I'm not kinky enough for this + +/datum/mood_event/enthrallmissing1 + mood_change = -5 + +/datum/mood_event/enthrallmissing1/add_effects(message) + description = "[message]\n" + +/datum/mood_event/enthrallmissing2 + mood_change = -10 + +/datum/mood_event/enthrallmissing2/add_effects(message) + description = "[message]\n" + +/datum/mood_event/enthrallmissing3 + mood_change = -15 + +/datum/mood_event/enthrallmissing3/add_effects(message) + description = "[message]\n" + +/datum/mood_event/enthrallmissing4 + mood_change = -25 + +/datum/mood_event/enthrallmissing4/add_effects(message) + description = "[message]\n" + +/datum/mood_event/InLove + mood_change = 10 + +/datum/mood_event/InLove/add_effects(message) + description = "[message]\n" + +/datum/mood_event/MissingLove + mood_change = -10 + +/datum/mood_event/MissingLove/add_effects(message) + description = "[message]\n" diff --git a/code/datums/mood_events/mood_event.dm b/code/datums/mood_events/mood_event.dm index dfe3049bdd..c125ba054a 100644 --- a/code/datums/mood_events/mood_event.dm +++ b/code/datums/mood_events/mood_event.dm @@ -1,20 +1,20 @@ -/datum/mood_event - var/description ///For descriptions, use the span classes bold nicegreen, nicegreen, none, warning and boldwarning in order from great to horrible. - var/mood_change = 0 - var/timeout = 0 - var/hidden = FALSE//Not shown on examine - var/mob/owner - -/datum/mood_event/New(mob/M, param) - owner = M - add_effects(param) - -/datum/mood_event/Destroy() - remove_effects() - return ..() - -/datum/mood_event/proc/add_effects(param) - return - -/datum/mood_event/proc/remove_effects() - return +/datum/mood_event + var/description ///For descriptions, use the span classes bold nicegreen, nicegreen, none, warning and boldwarning in order from great to horrible. + var/mood_change = 0 + var/timeout = 0 + var/hidden = FALSE//Not shown on examine + var/mob/owner + +/datum/mood_event/New(mob/M, param) + owner = M + add_effects(param) + +/datum/mood_event/Destroy() + remove_effects() + return ..() + +/datum/mood_event/proc/add_effects(param) + return + +/datum/mood_event/proc/remove_effects() + return diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm index eb58f2aa92..962681eb94 100644 --- a/code/datums/mood_events/needs_events.dm +++ b/code/datums/mood_events/needs_events.dm @@ -1,62 +1,62 @@ -//nutrition -/datum/mood_event/fat - description = "I'm so fat...\n" //muh fatshaming - mood_change = -4 - -/datum/mood_event/wellfed - description = "I'm stuffed!\n" - mood_change = 6 - -/datum/mood_event/fed - description = "I have recently had some food.\n" - mood_change = 3 - -/datum/mood_event/hungry - description = "I'm getting a bit hungry.\n" - mood_change = -8 - -/datum/mood_event/starving - description = "I'm starving!\n" - mood_change = -15 - -//Disgust -/datum/mood_event/gross - description = "I saw something gross.\n" - mood_change = -2 - -/datum/mood_event/verygross - description = "I think I'm going to puke...\n" - mood_change = -5 - -/datum/mood_event/disgusted - description = "Oh god that's disgusting...\n" - mood_change = -8 - -/datum/mood_event/disgust/bad_smell - description = "You smell something horribly decayed inside this room.\n" - mood_change = -3 - -/datum/mood_event/disgust/nauseating_stench - description = "The stench of rotting carcasses is unbearable!\n" - mood_change = -7 - -//Generic needs events -/datum/mood_event/favorite_food - description = "I really enjoyed eating that.\n" - mood_change = 3 - timeout = 2400 - -/datum/mood_event/gross_food - description = "I really didn't like that food.\n" - mood_change = -2 - timeout = 2400 - -/datum/mood_event/disgusting_food - description = "That food was disgusting!\n" - mood_change = -4 - timeout = 2400 - -/datum/mood_event/nice_shower - description = "I have recently had a nice shower.\n" - mood_change = 2 - timeout = 3 MINUTES +//nutrition +/datum/mood_event/fat + description = "I'm so fat...\n" //muh fatshaming + mood_change = -4 + +/datum/mood_event/wellfed + description = "I'm stuffed!\n" + mood_change = 6 + +/datum/mood_event/fed + description = "I have recently had some food.\n" + mood_change = 3 + +/datum/mood_event/hungry + description = "I'm getting a bit hungry.\n" + mood_change = -8 + +/datum/mood_event/starving + description = "I'm starving!\n" + mood_change = -15 + +//Disgust +/datum/mood_event/gross + description = "I saw something gross.\n" + mood_change = -2 + +/datum/mood_event/verygross + description = "I think I'm going to puke...\n" + mood_change = -5 + +/datum/mood_event/disgusted + description = "Oh god that's disgusting...\n" + mood_change = -8 + +/datum/mood_event/disgust/bad_smell + description = "You smell something horribly decayed inside this room.\n" + mood_change = -3 + +/datum/mood_event/disgust/nauseating_stench + description = "The stench of rotting carcasses is unbearable!\n" + mood_change = -7 + +//Generic needs events +/datum/mood_event/favorite_food + description = "I really enjoyed eating that.\n" + mood_change = 3 + timeout = 2400 + +/datum/mood_event/gross_food + description = "I really didn't like that food.\n" + mood_change = -2 + timeout = 2400 + +/datum/mood_event/disgusting_food + description = "That food was disgusting!\n" + mood_change = -4 + timeout = 2400 + +/datum/mood_event/nice_shower + description = "I have recently had a nice shower.\n" + mood_change = 2 + timeout = 3 MINUTES diff --git a/code/datums/position_point_vector.dm b/code/datums/position_point_vector.dm index a33d0d2225..44ff87e8ae 100644 --- a/code/datums/position_point_vector.dm +++ b/code/datums/position_point_vector.dm @@ -1,225 +1,225 @@ -//Designed for things that need precision trajectories like projectiles. -//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels. - -//You might see places where it does - 16 - 1. This is intentionally 17 instead of 16, because of how byond's tiles work and how not doing it will result in rounding errors like things getting put on the wrong turf. - -#define RETURN_PRECISE_POSITION(A) new /datum/position(A) -#define RETURN_PRECISE_POINT(A) new /datum/point(A) - -#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)) -#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)) - -/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below. - var/datum/point/P = new - P.x = a.x + (b.x - a.x) / 2 - P.y = a.y + (b.y - a.y) / 2 - P.z = a.z - return P - -/proc/pixel_length_between_points(datum/point/a, datum/point/b) - return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2)) - -/proc/angle_between_points(datum/point/a, datum/point/b) - return ATAN2((b.y - a.y), (b.x - a.x)) - -/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess. - var/x = 0 - var/y = 0 - var/z = 0 - var/pixel_x = 0 - var/pixel_y = 0 - -/datum/position/proc/valid() - return x && y && z && !isnull(pixel_x) && !isnull(pixel_y) - -/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point. - if(istype(_x, /datum/point)) - var/datum/point/P = _x - var/turf/T = P.return_turf() - _x = T.x - _y = T.y - _z = T.z - _pixel_x = P.return_px() - _pixel_y = P.return_py() - else if(isatom(_x)) - var/atom/A = _x - _x = A.x - _y = A.y - _z = A.z - _pixel_x = A.pixel_x - _pixel_y = A.pixel_y - x = _x - y = _y - z = _z - pixel_x = _pixel_x - pixel_y = _pixel_y - -/datum/position/proc/return_turf() - return locate(x, y, z) - -/datum/position/proc/return_px() - return pixel_x - -/datum/position/proc/return_py() - return pixel_y - -/datum/position/proc/return_point() - return new /datum/point(src) - -/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP! - var/x = 0 - var/y = 0 - var/z = 0 - -/datum/point/proc/valid() - return x && y && z - -/datum/point/proc/copy_to(datum/point/p = new) - p.x = x - p.y = y - p.z = z - return p - -/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom. - if(istype(_x, /datum/position)) - var/datum/position/P = _x - _x = P.x - _y = P.y - _z = P.z - _pixel_x = P.pixel_x - _pixel_y = P.pixel_y - else if(istype(_x, /atom)) - var/atom/A = _x - _x = A.x - _y = A.y - _z = A.z - _pixel_x = A.pixel_x - _pixel_y = A.pixel_y - initialize_location(_x, _y, _z, _pixel_x, _pixel_y) - -/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) - if(!isnull(tile_x)) - x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x + 1 - if(!isnull(tile_y)) - y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2 + p_y + 1 - if(!isnull(tile_z)) - z = tile_z - -/datum/point/proc/debug_out() - var/turf/T = return_turf() - return "\ref[src] aX [x] aY [y] aZ [z] pX [return_px()] pY [return_py()] mX [T.x] mY [T.y] mZ [T.z]" - -/datum/point/proc/move_atom_to_src(atom/movable/AM) - AM.forceMove(return_turf()) - AM.pixel_x = return_px() - AM.pixel_y = return_py() - -/datum/point/proc/return_turf() - return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z) - -/datum/point/proc/return_coordinates() //[turf_x, turf_y, z] - return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z) - -/datum/point/proc/return_position() - return new /datum/position(src) - -/datum/point/proc/return_px() - return MODULUS(x, world.icon_size) - 16 - 1 - -/datum/point/proc/return_py() - return MODULUS(y, world.icon_size) - 16 - 1 - -/datum/point/vector - var/speed = 32 //pixels per iteration - var/iteration = 0 - var/angle = 0 - var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step. - var/mpy = 0 - var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location(). - var/starting_y = 0 - var/starting_z = 0 - -/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed, initial_increment = 0) - ..() - initialize_trajectory(_speed, _angle) - if(initial_increment) - increment(initial_increment) - -/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) - . = ..() - starting_x = x - starting_y = y - starting_z = z - -/datum/point/vector/copy_to(datum/point/vector/v = new) - ..(v) - v.speed = speed - v.iteration = iteration - v.angle = angle - v.mpx = mpx - v.mpy = mpy - v.starting_x = starting_x - v.starting_y = starting_y - v.starting_z = starting_z - return v - -/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle) - if(!isnull(pixel_speed)) - speed = pixel_speed - set_angle(new_angle) - -/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270. - if(isnull(angle)) - return - angle = new_angle - update_offsets() - -/datum/point/vector/proc/update_offsets() - mpx = sin(angle) * speed - mpy = cos(angle) * speed - -/datum/point/vector/proc/set_speed(new_speed) - if(isnull(new_speed) || speed == new_speed) - return - speed = new_speed - update_offsets() - -/datum/point/vector/proc/increment(multiplier = 1) - iteration++ - x += mpx * (multiplier) - y += mpy * (multiplier) - -/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE) - var/datum/point/vector/v = copy_to() - if(force_simulate) - for(var/i in 1 to amount) - v.increment(multiplier) - else - v.increment(multiplier * amount) - return v - -/datum/point/vector/proc/on_z_change() - return - -/datum/point/vector/processed //pixel_speed is per decisecond. - var/last_process = 0 - var/last_move = 0 - var/paused = FALSE - -/datum/point/vector/processed/Destroy() - STOP_PROCESSING(SSprojectiles, src) - -/datum/point/vector/processed/proc/start() - last_process = world.time - last_move = world.time - START_PROCESSING(SSprojectiles, src) - -/datum/point/vector/processed/process() - if(paused) - last_move += world.time - last_process - last_process = world.time - return - var/needed_time = world.time - last_move - last_process = world.time - last_move = world.time - increment(needed_time / SSprojectiles.wait) +//Designed for things that need precision trajectories like projectiles. +//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels. + +//You might see places where it does - 16 - 1. This is intentionally 17 instead of 16, because of how byond's tiles work and how not doing it will result in rounding errors like things getting put on the wrong turf. + +#define RETURN_PRECISE_POSITION(A) new /datum/position(A) +#define RETURN_PRECISE_POINT(A) new /datum/point(A) + +#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)) +#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)) + +/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below. + var/datum/point/P = new + P.x = a.x + (b.x - a.x) / 2 + P.y = a.y + (b.y - a.y) / 2 + P.z = a.z + return P + +/proc/pixel_length_between_points(datum/point/a, datum/point/b) + return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2)) + +/proc/angle_between_points(datum/point/a, datum/point/b) + return ATAN2((b.y - a.y), (b.x - a.x)) + +/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess. + var/x = 0 + var/y = 0 + var/z = 0 + var/pixel_x = 0 + var/pixel_y = 0 + +/datum/position/proc/valid() + return x && y && z && !isnull(pixel_x) && !isnull(pixel_y) + +/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point. + if(istype(_x, /datum/point)) + var/datum/point/P = _x + var/turf/T = P.return_turf() + _x = T.x + _y = T.y + _z = T.z + _pixel_x = P.return_px() + _pixel_y = P.return_py() + else if(isatom(_x)) + var/atom/A = _x + _x = A.x + _y = A.y + _z = A.z + _pixel_x = A.pixel_x + _pixel_y = A.pixel_y + x = _x + y = _y + z = _z + pixel_x = _pixel_x + pixel_y = _pixel_y + +/datum/position/proc/return_turf() + return locate(x, y, z) + +/datum/position/proc/return_px() + return pixel_x + +/datum/position/proc/return_py() + return pixel_y + +/datum/position/proc/return_point() + return new /datum/point(src) + +/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP! + var/x = 0 + var/y = 0 + var/z = 0 + +/datum/point/proc/valid() + return x && y && z + +/datum/point/proc/copy_to(datum/point/p = new) + p.x = x + p.y = y + p.z = z + return p + +/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom. + if(istype(_x, /datum/position)) + var/datum/position/P = _x + _x = P.x + _y = P.y + _z = P.z + _pixel_x = P.pixel_x + _pixel_y = P.pixel_y + else if(istype(_x, /atom)) + var/atom/A = _x + _x = A.x + _y = A.y + _z = A.z + _pixel_x = A.pixel_x + _pixel_y = A.pixel_y + initialize_location(_x, _y, _z, _pixel_x, _pixel_y) + +/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) + if(!isnull(tile_x)) + x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x + 1 + if(!isnull(tile_y)) + y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2 + p_y + 1 + if(!isnull(tile_z)) + z = tile_z + +/datum/point/proc/debug_out() + var/turf/T = return_turf() + return "\ref[src] aX [x] aY [y] aZ [z] pX [return_px()] pY [return_py()] mX [T.x] mY [T.y] mZ [T.z]" + +/datum/point/proc/move_atom_to_src(atom/movable/AM) + AM.forceMove(return_turf()) + AM.pixel_x = return_px() + AM.pixel_y = return_py() + +/datum/point/proc/return_turf() + return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z) + +/datum/point/proc/return_coordinates() //[turf_x, turf_y, z] + return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z) + +/datum/point/proc/return_position() + return new /datum/position(src) + +/datum/point/proc/return_px() + return MODULUS(x, world.icon_size) - 16 - 1 + +/datum/point/proc/return_py() + return MODULUS(y, world.icon_size) - 16 - 1 + +/datum/point/vector + var/speed = 32 //pixels per iteration + var/iteration = 0 + var/angle = 0 + var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step. + var/mpy = 0 + var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location(). + var/starting_y = 0 + var/starting_z = 0 + +/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed, initial_increment = 0) + ..() + initialize_trajectory(_speed, _angle) + if(initial_increment) + increment(initial_increment) + +/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0) + . = ..() + starting_x = x + starting_y = y + starting_z = z + +/datum/point/vector/copy_to(datum/point/vector/v = new) + ..(v) + v.speed = speed + v.iteration = iteration + v.angle = angle + v.mpx = mpx + v.mpy = mpy + v.starting_x = starting_x + v.starting_y = starting_y + v.starting_z = starting_z + return v + +/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle) + if(!isnull(pixel_speed)) + speed = pixel_speed + set_angle(new_angle) + +/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270. + if(isnull(angle)) + return + angle = new_angle + update_offsets() + +/datum/point/vector/proc/update_offsets() + mpx = sin(angle) * speed + mpy = cos(angle) * speed + +/datum/point/vector/proc/set_speed(new_speed) + if(isnull(new_speed) || speed == new_speed) + return + speed = new_speed + update_offsets() + +/datum/point/vector/proc/increment(multiplier = 1) + iteration++ + x += mpx * (multiplier) + y += mpy * (multiplier) + +/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE) + var/datum/point/vector/v = copy_to() + if(force_simulate) + for(var/i in 1 to amount) + v.increment(multiplier) + else + v.increment(multiplier * amount) + return v + +/datum/point/vector/proc/on_z_change() + return + +/datum/point/vector/processed //pixel_speed is per decisecond. + var/last_process = 0 + var/last_move = 0 + var/paused = FALSE + +/datum/point/vector/processed/Destroy() + STOP_PROCESSING(SSprojectiles, src) + +/datum/point/vector/processed/proc/start() + last_process = world.time + last_move = world.time + START_PROCESSING(SSprojectiles, src) + +/datum/point/vector/processed/process() + if(paused) + last_move += world.time - last_process + last_process = world.time + return + var/needed_time = world.time - last_move + last_process = world.time + last_move = world.time + increment(needed_time / SSprojectiles.wait) diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index ebbe08c525..bb7dc4cdb7 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -1,54 +1,54 @@ -/datum/spawners_menu - var/mob/dead/observer/owner - -/datum/spawners_menu/New(mob/dead/observer/new_owner) - if(!istype(new_owner)) - qdel(src) - owner = new_owner - -/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state) - ui.open() - -/datum/spawners_menu/ui_data(mob/user) - var/list/data = list() - data["spawners"] = list() - for(var/spawner in GLOB.mob_spawners) - var/list/this = list() - this["name"] = spawner - this["desc"] = "" - this["refs"] = list() - for(var/spawner_obj in GLOB.mob_spawners[spawner]) - this["refs"] += "[REF(spawner_obj)]" - if(!this["desc"]) - if(istype(spawner_obj, /obj/effect/mob_spawn)) - var/obj/effect/mob_spawn/MS = spawner_obj - this["desc"] = MS.flavour_text - else - var/obj/O = spawner_obj - this["desc"] = O.desc - this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner]) - data["spawners"] += list(this) - - return data - -/datum/spawners_menu/ui_act(action, params) - if(..()) - return - - var/spawner_ref = pick(GLOB.mob_spawners[params["name"]]) - var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list - if(!MS) - return - - switch(action) - if("jump") - if(MS) - owner.forceMove(get_turf(MS)) - . = TRUE - if("spawn") - if(MS) - MS.attack_ghost(owner) +/datum/spawners_menu + var/mob/dead/observer/owner + +/datum/spawners_menu/New(mob/dead/observer/new_owner) + if(!istype(new_owner)) + qdel(src) + owner = new_owner + +/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state) + ui.open() + +/datum/spawners_menu/ui_data(mob/user) + var/list/data = list() + data["spawners"] = list() + for(var/spawner in GLOB.mob_spawners) + var/list/this = list() + this["name"] = spawner + this["desc"] = "" + this["refs"] = list() + for(var/spawner_obj in GLOB.mob_spawners[spawner]) + this["refs"] += "[REF(spawner_obj)]" + if(!this["desc"]) + if(istype(spawner_obj, /obj/effect/mob_spawn)) + var/obj/effect/mob_spawn/MS = spawner_obj + this["desc"] = MS.flavour_text + else + var/obj/O = spawner_obj + this["desc"] = O.desc + this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner]) + data["spawners"] += list(this) + + return data + +/datum/spawners_menu/ui_act(action, params) + if(..()) + return + + var/spawner_ref = pick(GLOB.mob_spawners[params["name"]]) + var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list + if(!MS) + return + + switch(action) + if("jump") + if(MS) + owner.forceMove(get_turf(MS)) + . = TRUE + if("spawn") + if(MS) + MS.attack_ghost(owner) . = TRUE \ No newline at end of file diff --git a/code/datums/verbs.dm b/code/datums/verbs.dm index d8d7ee7433..442997288a 100644 --- a/code/datums/verbs.dm +++ b/code/datums/verbs.dm @@ -1,102 +1,102 @@ -/datum/verbs - var/name - var/list/children - var/datum/verbs/parent - var/list/verblist - var/abstract = FALSE - -//returns the master list for verbs of a type -/datum/verbs/proc/GetList() - CRASH("Abstract verblist for [type]") - -//do things for each entry in Generate_list -//return value sets Generate_list[verbpath] -/datum/verbs/proc/HandleVerb(list/entry, procpath/verbpath, ...) - return entry - -/datum/verbs/New() - var/mainlist = GetList() - var/ourentry = mainlist[type] - children = list() - verblist = list() - if (ourentry) - if (!islist(ourentry)) //some of our childern already loaded - qdel(src) - CRASH("Verb double load: [type]") - Add_children(ourentry) - - mainlist[type] = src - - Load_verbs(type, typesof("[type]/verb")) - - var/datum/verbs/parent = mainlist[parent_type] - if (!parent) - mainlist[parent_type] = list(src) - else if (islist(parent)) - parent += src - else - parent.Add_children(list(src)) - -/datum/verbs/proc/Set_parent(datum/verbs/_parent) - parent = _parent - if (abstract) - parent.Add_children(children) - var/list/verblistoftypes = list() - for(var/thing in verblist) - LAZYADD(verblistoftypes[verblist[thing]], thing) - - for(var/verbparenttype in verblistoftypes) - parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype]) - -/datum/verbs/proc/Add_children(list/kids) - if (abstract && parent) - parent.Add_children(kids) - return - - for(var/thing in kids) - var/datum/verbs/item = thing - item.Set_parent(src) - if (!item.abstract) - children += item - -/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs) - if (abstract && parent) - parent.Load_verbs(verb_parent_type, verbs) - return - - for (var/verbpath in verbs) - verblist[verbpath] = verb_parent_type - -/datum/verbs/proc/Generate_list(...) - . = list() - if (length(children)) - for (var/thing in children) - var/datum/verbs/child = thing - var/list/childlist = child.Generate_list(arglist(args)) - if (childlist) - var/childname = "[child]" - if (childname == "[child.type]") - var/list/tree = splittext(childname, "/") - childname = tree[tree.len] - .[child.type] = "parent=[url_encode(type)];name=[childname]" - . += childlist - - for (var/thing in verblist) - var/procpath/verbpath = thing - if (!verbpath) - stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]") - var/list/entry = list() - entry["parent"] = "[type]" - entry["name"] = verbpath.desc - if (copytext(verbpath.name,1,2) == "@") - entry["command"] = copytext(verbpath.name,2) - else - entry["command"] = replacetext(verbpath.name, " ", "-") - - .[verbpath] = HandleVerb(arglist(list(entry, verbpath) + args)) - -/world/proc/LoadVerbs(verb_type) - if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs) - CRASH("Invalid verb_type: [verb_type]") - for (var/typepath in subtypesof(verb_type)) - new typepath() +/datum/verbs + var/name + var/list/children + var/datum/verbs/parent + var/list/verblist + var/abstract = FALSE + +//returns the master list for verbs of a type +/datum/verbs/proc/GetList() + CRASH("Abstract verblist for [type]") + +//do things for each entry in Generate_list +//return value sets Generate_list[verbpath] +/datum/verbs/proc/HandleVerb(list/entry, procpath/verbpath, ...) + return entry + +/datum/verbs/New() + var/mainlist = GetList() + var/ourentry = mainlist[type] + children = list() + verblist = list() + if (ourentry) + if (!islist(ourentry)) //some of our childern already loaded + qdel(src) + CRASH("Verb double load: [type]") + Add_children(ourentry) + + mainlist[type] = src + + Load_verbs(type, typesof("[type]/verb")) + + var/datum/verbs/parent = mainlist[parent_type] + if (!parent) + mainlist[parent_type] = list(src) + else if (islist(parent)) + parent += src + else + parent.Add_children(list(src)) + +/datum/verbs/proc/Set_parent(datum/verbs/_parent) + parent = _parent + if (abstract) + parent.Add_children(children) + var/list/verblistoftypes = list() + for(var/thing in verblist) + LAZYADD(verblistoftypes[verblist[thing]], thing) + + for(var/verbparenttype in verblistoftypes) + parent.Load_verbs(verbparenttype, verblistoftypes[verbparenttype]) + +/datum/verbs/proc/Add_children(list/kids) + if (abstract && parent) + parent.Add_children(kids) + return + + for(var/thing in kids) + var/datum/verbs/item = thing + item.Set_parent(src) + if (!item.abstract) + children += item + +/datum/verbs/proc/Load_verbs(verb_parent_type, list/verbs) + if (abstract && parent) + parent.Load_verbs(verb_parent_type, verbs) + return + + for (var/verbpath in verbs) + verblist[verbpath] = verb_parent_type + +/datum/verbs/proc/Generate_list(...) + . = list() + if (length(children)) + for (var/thing in children) + var/datum/verbs/child = thing + var/list/childlist = child.Generate_list(arglist(args)) + if (childlist) + var/childname = "[child]" + if (childname == "[child.type]") + var/list/tree = splittext(childname, "/") + childname = tree[tree.len] + .[child.type] = "parent=[url_encode(type)];name=[childname]" + . += childlist + + for (var/thing in verblist) + var/procpath/verbpath = thing + if (!verbpath) + stack_trace("Bad VERB in [type] verblist: [english_list(verblist)]") + var/list/entry = list() + entry["parent"] = "[type]" + entry["name"] = verbpath.desc + if (copytext(verbpath.name,1,2) == "@") + entry["command"] = copytext(verbpath.name,2) + else + entry["command"] = replacetext(verbpath.name, " ", "-") + + .[verbpath] = HandleVerb(arglist(list(entry, verbpath) + args)) + +/world/proc/LoadVerbs(verb_type) + if(!ispath(verb_type, /datum/verbs) || verb_type == /datum/verbs) + CRASH("Invalid verb_type: [verb_type]") + for (var/typepath in subtypesof(verb_type)) + new typepath() diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index ac4473845d..315cfa59d6 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -1,186 +1,186 @@ -/datum/wires/airlock - holder_type = /obj/machinery/door/airlock - proper_name = "Generic Airlock" - var/wiretype - -/datum/wires/airlock/secure - randomize = TRUE - -/datum/wires/airlock/command - proper_name = "Command Airlock" - wiretype = "commandairlock" - -/datum/wires/airlock/security - proper_name = "Security Airlock" - wiretype = "securityairlock" - -/datum/wires/airlock/engineering - proper_name = "Engineering Airlock" - wiretype = "engineeringairlock" - -/datum/wires/airlock/science - proper_name = "Science Airlock" - wiretype = "scienceairlock" - -/datum/wires/airlock/medical - proper_name = "Medical Airlock" - wiretype = "medicalairlock" - -/datum/wires/airlock/cargo - proper_name = "Cargo Airlock" - wiretype = "cargoairlock" - -/datum/wires/airlock/New(atom/holder) - wires = list( - WIRE_POWER1, WIRE_POWER2, - WIRE_BACKUP1, WIRE_BACKUP2, - WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI, - WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT, - WIRE_ZAP1, WIRE_ZAP2 - ) - add_duds(2) - . = ..() - if(randomize || !wiretype) - return - if(!GLOB.wire_color_directory[wiretype]) - colors = list() - randomize() - GLOB.wire_color_directory[wiretype] = colors - GLOB.wire_name_directory[wiretype] = proper_name - else - colors = GLOB.wire_color_directory[wiretype] - -/datum/wires/airlock/interactable(mob/user) - var/obj/machinery/door/airlock/A = holder - if(!issilicon(user) && A.isElectrified() && A.shock(user, 100)) - return FALSE - if(A.panel_open) - return TRUE - -/datum/wires/airlock/get_status() - var/obj/machinery/door/airlock/A = holder - var/list/status = list() - status += "The door bolts [A.locked ? "have fallen!" : "look up."]" - status += "The test light is [A.hasPower() ? "on" : "off"]." - status += "The AI connection light is [A.aiControlDisabled || (A.obj_flags & EMAGGED) ? "off" : "on"]." - status += "The check wiring light is [A.safe ? "off" : "on"]." - status += "The timer is powered [A.autoclose ? "on" : "off"]." - status += "The speed light is [A.normalspeed ? "on" : "off"]." - status += "The emergency light is [A.emergency ? "on" : "off"]." - return status - -/datum/wires/airlock/on_pulse(wire) - set waitfor = FALSE - var/obj/machinery/door/airlock/A = holder - switch(wire) - if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power. - A.loseMainPower() - if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power. - A.loseBackupPower() - if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required). - if(A.obj_flags & EMAGGED) - return - if(!A.requiresID() || A.check_access(null)) - if(A.density) - INVOKE_ASYNC(A, /obj/machinery/door/airlock.proc/open) - else - INVOKE_ASYNC(A, /obj/machinery/door/airlock.proc/close) - else - holder.visible_message("You hear a a grinding noise coming from the airlock.") - if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on). - if(!A.locked) - A.bolt() - else - if(A.hasPower()) - A.unbolt() - A.update_icon() - if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights. - if(A.hasPower() && A.density) - A.do_animate("deny") - if(A.emergency) - A.emergency = FALSE - A.update_icon() - if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting). - if(A.aiControlDisabled == 0) - A.aiControlDisabled = 1 - else if(A.aiControlDisabled == -1) - A.aiControlDisabled = 2 - sleep(10) - if(A) - if(A.aiControlDisabled == 1) - A.aiControlDisabled = 0 - else if(A.aiControlDisabled == 2) - A.aiControlDisabled = -1 - if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. - if(!A.secondsElectrified) - A.set_electrified(30) - if(usr) - LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) - log_combat(usr, A, "electrified") - if(WIRE_SAFETY) - A.safe = !A.safe - if(!A.density) - A.close() - if(WIRE_TIMING) - A.normalspeed = !A.normalspeed - if(WIRE_LIGHT) - A.lights = !A.lights - A.update_icon() - -/datum/wires/airlock/on_cut(wire, mend) - var/obj/machinery/door/airlock/A = holder - switch(wire) - if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power. - if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2)) - A.regainMainPower() - if(usr) - A.shock(usr, 50) - else - A.loseMainPower() - if(usr) - A.shock(usr, 50) - if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power. - if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) - A.regainBackupPower() - if(usr) - A.shock(usr, 50) - else - A.loseBackupPower() - if(usr) - A.shock(usr, 50) - if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing. - if(!mend) - A.bolt() - if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable. - if(mend) - if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI - A.aiControlDisabled = 0 - else if(A.aiControlDisabled == 2) - A.aiControlDisabled = -1 - else - if(A.aiControlDisabled == 0) - A.aiControlDisabled = 1 - else if(A.aiControlDisabled == -1) - A.aiControlDisabled = 2 - if(WIRE_SHOCK) // Cut to shock the door, mend to unshock. - if(mend) - if(A.secondsElectrified) - A.set_electrified(0) - else - if(A.secondsElectrified != -1) - A.set_electrified(-1) - if(usr) - LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) - log_combat(usr, A, "electrified") - if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. - A.safe = mend - if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. - A.autoclose = mend - if(A.autoclose && !A.density) - A.close() - if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable. - A.lights = mend - A.update_icon() - if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. - if(usr) - A.shock(usr, 50) +/datum/wires/airlock + holder_type = /obj/machinery/door/airlock + proper_name = "Generic Airlock" + var/wiretype + +/datum/wires/airlock/secure + randomize = TRUE + +/datum/wires/airlock/command + proper_name = "Command Airlock" + wiretype = "commandairlock" + +/datum/wires/airlock/security + proper_name = "Security Airlock" + wiretype = "securityairlock" + +/datum/wires/airlock/engineering + proper_name = "Engineering Airlock" + wiretype = "engineeringairlock" + +/datum/wires/airlock/science + proper_name = "Science Airlock" + wiretype = "scienceairlock" + +/datum/wires/airlock/medical + proper_name = "Medical Airlock" + wiretype = "medicalairlock" + +/datum/wires/airlock/cargo + proper_name = "Cargo Airlock" + wiretype = "cargoairlock" + +/datum/wires/airlock/New(atom/holder) + wires = list( + WIRE_POWER1, WIRE_POWER2, + WIRE_BACKUP1, WIRE_BACKUP2, + WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI, + WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT, + WIRE_ZAP1, WIRE_ZAP2 + ) + add_duds(2) + . = ..() + if(randomize || !wiretype) + return + if(!GLOB.wire_color_directory[wiretype]) + colors = list() + randomize() + GLOB.wire_color_directory[wiretype] = colors + GLOB.wire_name_directory[wiretype] = proper_name + else + colors = GLOB.wire_color_directory[wiretype] + +/datum/wires/airlock/interactable(mob/user) + var/obj/machinery/door/airlock/A = holder + if(!issilicon(user) && A.isElectrified() && A.shock(user, 100)) + return FALSE + if(A.panel_open) + return TRUE + +/datum/wires/airlock/get_status() + var/obj/machinery/door/airlock/A = holder + var/list/status = list() + status += "The door bolts [A.locked ? "have fallen!" : "look up."]" + status += "The test light is [A.hasPower() ? "on" : "off"]." + status += "The AI connection light is [A.aiControlDisabled || (A.obj_flags & EMAGGED) ? "off" : "on"]." + status += "The check wiring light is [A.safe ? "off" : "on"]." + status += "The timer is powered [A.autoclose ? "on" : "off"]." + status += "The speed light is [A.normalspeed ? "on" : "off"]." + status += "The emergency light is [A.emergency ? "on" : "off"]." + return status + +/datum/wires/airlock/on_pulse(wire) + set waitfor = FALSE + var/obj/machinery/door/airlock/A = holder + switch(wire) + if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power. + A.loseMainPower() + if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power. + A.loseBackupPower() + if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required). + if(A.obj_flags & EMAGGED) + return + if(!A.requiresID() || A.check_access(null)) + if(A.density) + INVOKE_ASYNC(A, /obj/machinery/door/airlock.proc/open) + else + INVOKE_ASYNC(A, /obj/machinery/door/airlock.proc/close) + else + holder.visible_message("You hear a a grinding noise coming from the airlock.") + if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on). + if(!A.locked) + A.bolt() + else + if(A.hasPower()) + A.unbolt() + A.update_icon() + if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights. + if(A.hasPower() && A.density) + A.do_animate("deny") + if(A.emergency) + A.emergency = FALSE + A.update_icon() + if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting). + if(A.aiControlDisabled == 0) + A.aiControlDisabled = 1 + else if(A.aiControlDisabled == -1) + A.aiControlDisabled = 2 + sleep(10) + if(A) + if(A.aiControlDisabled == 1) + A.aiControlDisabled = 0 + else if(A.aiControlDisabled == 2) + A.aiControlDisabled = -1 + if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. + if(!A.secondsElectrified) + A.set_electrified(30) + if(usr) + LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) + log_combat(usr, A, "electrified") + if(WIRE_SAFETY) + A.safe = !A.safe + if(!A.density) + A.close() + if(WIRE_TIMING) + A.normalspeed = !A.normalspeed + if(WIRE_LIGHT) + A.lights = !A.lights + A.update_icon() + +/datum/wires/airlock/on_cut(wire, mend) + var/obj/machinery/door/airlock/A = holder + switch(wire) + if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power. + if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2)) + A.regainMainPower() + if(usr) + A.shock(usr, 50) + else + A.loseMainPower() + if(usr) + A.shock(usr, 50) + if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power. + if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) + A.regainBackupPower() + if(usr) + A.shock(usr, 50) + else + A.loseBackupPower() + if(usr) + A.shock(usr, 50) + if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing. + if(!mend) + A.bolt() + if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable. + if(mend) + if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI + A.aiControlDisabled = 0 + else if(A.aiControlDisabled == 2) + A.aiControlDisabled = -1 + else + if(A.aiControlDisabled == 0) + A.aiControlDisabled = 1 + else if(A.aiControlDisabled == -1) + A.aiControlDisabled = 2 + if(WIRE_SHOCK) // Cut to shock the door, mend to unshock. + if(mend) + if(A.secondsElectrified) + A.set_electrified(0) + else + if(A.secondsElectrified != -1) + A.set_electrified(-1) + if(usr) + LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) + log_combat(usr, A, "electrified") + if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. + A.safe = mend + if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. + A.autoclose = mend + if(A.autoclose && !A.density) + A.close() + if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable. + A.lights = mend + A.update_icon() + if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. + if(usr) + A.shock(usr, 50) diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm index 9aa2ca81e8..a452b46830 100644 --- a/code/datums/wires/mulebot.dm +++ b/code/datums/wires/mulebot.dm @@ -1,31 +1,31 @@ -/datum/wires/mulebot - holder_type = /mob/living/simple_animal/bot/mulebot - randomize = TRUE - -/datum/wires/mulebot/New(atom/holder) - wires = list( - WIRE_POWER1, WIRE_POWER2, - WIRE_AVOIDANCE, WIRE_LOADCHECK, - WIRE_MOTOR1, WIRE_MOTOR2, - WIRE_RX, WIRE_TX, WIRE_BEACON - ) - ..() - -/datum/wires/mulebot/interactable(mob/user) - var/mob/living/simple_animal/bot/mulebot/M = holder - if(M.open) - return TRUE - -/datum/wires/mulebot/on_pulse(wire) - var/mob/living/simple_animal/bot/mulebot/M = holder - switch(wire) - if(WIRE_POWER1, WIRE_POWER2) - holder.visible_message("[icon2html(M, viewers(holder))] The charge light flickers.") - if(WIRE_AVOIDANCE) - holder.visible_message("[icon2html(M, viewers(holder))] The external warning lights flash briefly.") - if(WIRE_LOADCHECK) - holder.visible_message("[icon2html(M, viewers(holder))] The load platform clunks.") - if(WIRE_MOTOR1, WIRE_MOTOR2) - holder.visible_message("[icon2html(M, viewers(holder))] The drive motor whines briefly.") - else +/datum/wires/mulebot + holder_type = /mob/living/simple_animal/bot/mulebot + randomize = TRUE + +/datum/wires/mulebot/New(atom/holder) + wires = list( + WIRE_POWER1, WIRE_POWER2, + WIRE_AVOIDANCE, WIRE_LOADCHECK, + WIRE_MOTOR1, WIRE_MOTOR2, + WIRE_RX, WIRE_TX, WIRE_BEACON + ) + ..() + +/datum/wires/mulebot/interactable(mob/user) + var/mob/living/simple_animal/bot/mulebot/M = holder + if(M.open) + return TRUE + +/datum/wires/mulebot/on_pulse(wire) + var/mob/living/simple_animal/bot/mulebot/M = holder + switch(wire) + if(WIRE_POWER1, WIRE_POWER2) + holder.visible_message("[icon2html(M, viewers(holder))] The charge light flickers.") + if(WIRE_AVOIDANCE) + holder.visible_message("[icon2html(M, viewers(holder))] The external warning lights flash briefly.") + if(WIRE_LOADCHECK) + holder.visible_message("[icon2html(M, viewers(holder))] The load platform clunks.") + if(WIRE_MOTOR1, WIRE_MOTOR2) + holder.visible_message("[icon2html(M, viewers(holder))] The drive motor whines briefly.") + else holder.visible_message("[icon2html(M, viewers(holder))] You hear a radio crackle.") \ No newline at end of file diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm index 4bf49dd814..af89f0d6f1 100644 --- a/code/datums/wires/particle_accelerator.dm +++ b/code/datums/wires/particle_accelerator.dm @@ -1,48 +1,48 @@ -/datum/wires/particle_accelerator/control_box - holder_type = /obj/machinery/particle_accelerator/control_box - proper_name = "Particle Accelerator" - -/datum/wires/particle_accelerator/control_box/New(atom/holder) - wires = list( - WIRE_POWER, WIRE_STRENGTH, WIRE_LIMIT, - WIRE_INTERFACE - ) - add_duds(2) - ..() - -/datum/wires/particle_accelerator/control_box/interactable(mob/user) - var/obj/machinery/particle_accelerator/control_box/C = holder - if(C.construction_state == 2) - return TRUE - -/datum/wires/particle_accelerator/control_box/on_pulse(wire) - var/obj/machinery/particle_accelerator/control_box/C = holder - switch(wire) - if(WIRE_POWER) - C.toggle_power() - if(WIRE_STRENGTH) - C.add_strength() - if(WIRE_INTERFACE) - C.interface_control = !C.interface_control - if(WIRE_LIMIT) - C.visible_message("[icon2html(C, viewers(holder))][C] makes a large whirring noise.") - -/datum/wires/particle_accelerator/control_box/on_cut(wire, mend) - var/obj/machinery/particle_accelerator/control_box/C = holder - switch(wire) - if(WIRE_POWER) - if(C.active == !mend) - C.toggle_power() - if(WIRE_STRENGTH) - for(var/i = 1; i < 3; i++) - C.remove_strength() - if(WIRE_INTERFACE) - if(!mend) - C.interface_control = FALSE - if(WIRE_LIMIT) - C.strength_upper_limit = (mend ? 2 : 3) - if(C.strength_upper_limit < C.strength) - C.remove_strength() - -/datum/wires/particle_accelerator/control_box/emp_pulse() // to prevent singulo from pulsing wires +/datum/wires/particle_accelerator/control_box + holder_type = /obj/machinery/particle_accelerator/control_box + proper_name = "Particle Accelerator" + +/datum/wires/particle_accelerator/control_box/New(atom/holder) + wires = list( + WIRE_POWER, WIRE_STRENGTH, WIRE_LIMIT, + WIRE_INTERFACE + ) + add_duds(2) + ..() + +/datum/wires/particle_accelerator/control_box/interactable(mob/user) + var/obj/machinery/particle_accelerator/control_box/C = holder + if(C.construction_state == 2) + return TRUE + +/datum/wires/particle_accelerator/control_box/on_pulse(wire) + var/obj/machinery/particle_accelerator/control_box/C = holder + switch(wire) + if(WIRE_POWER) + C.toggle_power() + if(WIRE_STRENGTH) + C.add_strength() + if(WIRE_INTERFACE) + C.interface_control = !C.interface_control + if(WIRE_LIMIT) + C.visible_message("[icon2html(C, viewers(holder))][C] makes a large whirring noise.") + +/datum/wires/particle_accelerator/control_box/on_cut(wire, mend) + var/obj/machinery/particle_accelerator/control_box/C = holder + switch(wire) + if(WIRE_POWER) + if(C.active == !mend) + C.toggle_power() + if(WIRE_STRENGTH) + for(var/i = 1; i < 3; i++) + C.remove_strength() + if(WIRE_INTERFACE) + if(!mend) + C.interface_control = FALSE + if(WIRE_LIMIT) + C.strength_upper_limit = (mend ? 2 : 3) + if(C.strength_upper_limit < C.strength) + C.remove_strength() + +/datum/wires/particle_accelerator/control_box/emp_pulse() // to prevent singulo from pulsing wires return \ No newline at end of file diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 65438830a2..5e0d0d77d0 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -1,86 +1,86 @@ -/datum/wires/robot - holder_type = /mob/living/silicon/robot - randomize = TRUE - -/datum/wires/robot/New(atom/holder) - wires = list( - WIRE_AI, WIRE_CAMERA, - WIRE_LAWSYNC, WIRE_LOCKDOWN, - WIRE_RESET_MODULE - ) - add_duds(2) - ..() - -/datum/wires/robot/interactable(mob/user) - var/mob/living/silicon/robot/R = holder - if(R.wiresexposed) - return TRUE - -/datum/wires/robot/get_status() - var/mob/living/silicon/robot/R = holder - var/list/status = list() - status += "The law sync module is [R.lawupdate ? "on" : "off"]." - status += "The intelligence link display shows [R.connected_ai ? R.connected_ai.name : "NULL"]." - status += "The camera light is [!isnull(R.builtInCamera) && R.builtInCamera.status ? "on" : "off"]." - status += "The lockdown indicator is [R.lockcharge ? "on" : "off"]." - status += "The reset module hardware light is [R.has_module() ? "on" : "off"]." - return status - -/datum/wires/robot/on_pulse(wire, user) - var/mob/living/silicon/robot/R = holder - switch(wire) - if(WIRE_AI) // Pulse to pick a new AI. - if(!R.emagged) - var/new_ai - if(user) - new_ai = select_active_ai(user) - else - new_ai = select_active_ai(R) - R.notify_ai(DISCONNECT) - if(new_ai && (new_ai != R.connected_ai)) - R.connected_ai = new_ai - if(R.shell) - R.undeploy() //If this borg is an AI shell, disconnect the controlling AI and assign ti to a new AI - R.notify_ai(AI_SHELL) - else - R.notify_ai(TRUE) - if(WIRE_CAMERA) // Pulse to disable the camera. - if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) - R.builtInCamera.toggle_cam(usr, 0) - R.visible_message("[R]'s camera lens focuses loudly.", "Your camera lens focuses loudly.") - if(WIRE_LAWSYNC) // Forces a law update if possible. - if(R.lawupdate) - R.visible_message("[R] gently chimes.", "LawSync protocol engaged.") - R.lawsync() - R.show_laws() - if(WIRE_LOCKDOWN) - R.SetLockdown(!R.lockcharge) // Toggle - if(WIRE_RESET_MODULE) - if(R.has_module()) - R.visible_message("[R]'s module servos twitch.", "Your module display flickers.") - -/datum/wires/robot/on_cut(wire, mend) - var/mob/living/silicon/robot/R = holder - switch(wire) - if(WIRE_AI) // Cut the AI wire to reset AI control. - if(!mend) - R.notify_ai(DISCONNECT) - if(R.shell) - R.undeploy() - R.connected_ai = null - if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync. - if(mend) - if(!R.emagged) - R.lawupdate = TRUE - else if(!R.deployed) //AI shells must always have the same laws as the AI - R.lawupdate = FALSE - if (WIRE_CAMERA) // Disable the camera. - if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) - R.builtInCamera.status = mend - R.builtInCamera.toggle_cam(usr, 0) - R.visible_message("[R]'s camera lens focuses loudly.", "Your camera lens focuses loudly.") - if(WIRE_LOCKDOWN) // Simple lockdown. - R.SetLockdown(!mend) - if(WIRE_RESET_MODULE) - if(R.has_module() && !mend) - R.ResetModule() +/datum/wires/robot + holder_type = /mob/living/silicon/robot + randomize = TRUE + +/datum/wires/robot/New(atom/holder) + wires = list( + WIRE_AI, WIRE_CAMERA, + WIRE_LAWSYNC, WIRE_LOCKDOWN, + WIRE_RESET_MODULE + ) + add_duds(2) + ..() + +/datum/wires/robot/interactable(mob/user) + var/mob/living/silicon/robot/R = holder + if(R.wiresexposed) + return TRUE + +/datum/wires/robot/get_status() + var/mob/living/silicon/robot/R = holder + var/list/status = list() + status += "The law sync module is [R.lawupdate ? "on" : "off"]." + status += "The intelligence link display shows [R.connected_ai ? R.connected_ai.name : "NULL"]." + status += "The camera light is [!isnull(R.builtInCamera) && R.builtInCamera.status ? "on" : "off"]." + status += "The lockdown indicator is [R.lockcharge ? "on" : "off"]." + status += "The reset module hardware light is [R.has_module() ? "on" : "off"]." + return status + +/datum/wires/robot/on_pulse(wire, user) + var/mob/living/silicon/robot/R = holder + switch(wire) + if(WIRE_AI) // Pulse to pick a new AI. + if(!R.emagged) + var/new_ai + if(user) + new_ai = select_active_ai(user) + else + new_ai = select_active_ai(R) + R.notify_ai(DISCONNECT) + if(new_ai && (new_ai != R.connected_ai)) + R.connected_ai = new_ai + if(R.shell) + R.undeploy() //If this borg is an AI shell, disconnect the controlling AI and assign ti to a new AI + R.notify_ai(AI_SHELL) + else + R.notify_ai(TRUE) + if(WIRE_CAMERA) // Pulse to disable the camera. + if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) + R.builtInCamera.toggle_cam(usr, 0) + R.visible_message("[R]'s camera lens focuses loudly.", "Your camera lens focuses loudly.") + if(WIRE_LAWSYNC) // Forces a law update if possible. + if(R.lawupdate) + R.visible_message("[R] gently chimes.", "LawSync protocol engaged.") + R.lawsync() + R.show_laws() + if(WIRE_LOCKDOWN) + R.SetLockdown(!R.lockcharge) // Toggle + if(WIRE_RESET_MODULE) + if(R.has_module()) + R.visible_message("[R]'s module servos twitch.", "Your module display flickers.") + +/datum/wires/robot/on_cut(wire, mend) + var/mob/living/silicon/robot/R = holder + switch(wire) + if(WIRE_AI) // Cut the AI wire to reset AI control. + if(!mend) + R.notify_ai(DISCONNECT) + if(R.shell) + R.undeploy() + R.connected_ai = null + if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync. + if(mend) + if(!R.emagged) + R.lawupdate = TRUE + else if(!R.deployed) //AI shells must always have the same laws as the AI + R.lawupdate = FALSE + if (WIRE_CAMERA) // Disable the camera. + if(!QDELETED(R.builtInCamera) && !R.scrambledcodes) + R.builtInCamera.status = mend + R.builtInCamera.toggle_cam(usr, 0) + R.visible_message("[R]'s camera lens focuses loudly.", "Your camera lens focuses loudly.") + if(WIRE_LOCKDOWN) // Simple lockdown. + R.SetLockdown(!mend) + if(WIRE_RESET_MODULE) + if(R.has_module() && !mend) + R.ResetModule() diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index 92cc1770b3..53c1a1b9bc 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -1,92 +1,92 @@ -/datum/wires/syndicatebomb - holder_type = /obj/machinery/syndicatebomb - randomize = TRUE - -/datum/wires/syndicatebomb/New(atom/holder) - wires = list( - WIRE_BOOM, WIRE_UNBOLT, - WIRE_ACTIVATE, WIRE_DELAY, WIRE_PROCEED - ) - ..() - -/datum/wires/syndicatebomb/interactable(mob/user) - var/obj/machinery/syndicatebomb/P = holder - if(P.open_panel) - return TRUE - -/datum/wires/syndicatebomb/on_pulse(wire) - var/obj/machinery/syndicatebomb/B = holder - switch(wire) - if(WIRE_BOOM) - if(B.active) - holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") - B.explode_now = TRUE - tell_admins(B) - if(WIRE_UNBOLT) - holder.visible_message("[icon2html(B, viewers(holder))] The bolts spin in place for a moment.") - if(WIRE_DELAY) - if(B.delayedbig) - holder.visible_message("[icon2html(B, viewers(holder))] The bomb has already been delayed.") - else - holder.visible_message("[icon2html(B, viewers(holder))] The bomb chirps.") - playsound(B, 'sound/machines/chime.ogg', 30, 1) - B.detonation_timer += 300 - B.delayedbig = TRUE - if(WIRE_PROCEED) - holder.visible_message("[icon2html(B, viewers(holder))] The bomb buzzes ominously!") - playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1) - var/seconds = B.seconds_remaining() - if(seconds >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them. - B.detonation_timer = world.time + 600 - else if(seconds >= 21) - B.detonation_timer -= 100 - else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy. - B.detonation_timer = world.time + 100 - if(WIRE_ACTIVATE) - if(!B.active && !B.defused) - holder.visible_message("[icon2html(B, viewers(holder))] You hear the bomb start ticking!") - B.activate() - B.update_icon() - else if(B.delayedlittle) - holder.visible_message("[icon2html(B, viewers(holder))] Nothing happens.") - else - holder.visible_message("[icon2html(B, viewers(holder))] The bomb seems to hesitate for a moment.") - B.detonation_timer += 100 - B.delayedlittle = TRUE - -/datum/wires/syndicatebomb/on_cut(wire, mend) - var/obj/machinery/syndicatebomb/B = holder - switch(wire) - if(WIRE_BOOM) - if(mend) - B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage. - else - if(B.active) - holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") - B.explode_now = TRUE - tell_admins(B) - else - B.defused = TRUE - if(WIRE_UNBOLT) - if(!mend && B.anchored) - holder.visible_message("[icon2html(B, viewers(holder))] The bolts lift out of the ground!") - playsound(B, 'sound/effects/stealthoff.ogg', 30, 1) - B.anchored = FALSE - if(WIRE_PROCEED) - if(!mend && B.active) - holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") - B.explode_now = TRUE - tell_admins(B) - if(WIRE_ACTIVATE) - if(!mend && B.active) - holder.visible_message("[icon2html(B, viewers(holder))] The timer stops! The bomb has been defused!") - B.active = FALSE - B.defused = TRUE - B.update_icon() - -/datum/wires/syndicatebomb/proc/tell_admins(obj/machinery/syndicatebomb/B) - if(istype(B, /obj/machinery/syndicatebomb/training)) - return - var/turf/T = get_turf(B) - log_game("\A [B] was detonated via boom wire at [AREACOORD(T)].") - message_admins("A [B.name] was detonated via boom wire at [ADMIN_VERBOSEJMP(T)].") +/datum/wires/syndicatebomb + holder_type = /obj/machinery/syndicatebomb + randomize = TRUE + +/datum/wires/syndicatebomb/New(atom/holder) + wires = list( + WIRE_BOOM, WIRE_UNBOLT, + WIRE_ACTIVATE, WIRE_DELAY, WIRE_PROCEED + ) + ..() + +/datum/wires/syndicatebomb/interactable(mob/user) + var/obj/machinery/syndicatebomb/P = holder + if(P.open_panel) + return TRUE + +/datum/wires/syndicatebomb/on_pulse(wire) + var/obj/machinery/syndicatebomb/B = holder + switch(wire) + if(WIRE_BOOM) + if(B.active) + holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") + B.explode_now = TRUE + tell_admins(B) + if(WIRE_UNBOLT) + holder.visible_message("[icon2html(B, viewers(holder))] The bolts spin in place for a moment.") + if(WIRE_DELAY) + if(B.delayedbig) + holder.visible_message("[icon2html(B, viewers(holder))] The bomb has already been delayed.") + else + holder.visible_message("[icon2html(B, viewers(holder))] The bomb chirps.") + playsound(B, 'sound/machines/chime.ogg', 30, 1) + B.detonation_timer += 300 + B.delayedbig = TRUE + if(WIRE_PROCEED) + holder.visible_message("[icon2html(B, viewers(holder))] The bomb buzzes ominously!") + playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1) + var/seconds = B.seconds_remaining() + if(seconds >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them. + B.detonation_timer = world.time + 600 + else if(seconds >= 21) + B.detonation_timer -= 100 + else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy. + B.detonation_timer = world.time + 100 + if(WIRE_ACTIVATE) + if(!B.active && !B.defused) + holder.visible_message("[icon2html(B, viewers(holder))] You hear the bomb start ticking!") + B.activate() + B.update_icon() + else if(B.delayedlittle) + holder.visible_message("[icon2html(B, viewers(holder))] Nothing happens.") + else + holder.visible_message("[icon2html(B, viewers(holder))] The bomb seems to hesitate for a moment.") + B.detonation_timer += 100 + B.delayedlittle = TRUE + +/datum/wires/syndicatebomb/on_cut(wire, mend) + var/obj/machinery/syndicatebomb/B = holder + switch(wire) + if(WIRE_BOOM) + if(mend) + B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage. + else + if(B.active) + holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") + B.explode_now = TRUE + tell_admins(B) + else + B.defused = TRUE + if(WIRE_UNBOLT) + if(!mend && B.anchored) + holder.visible_message("[icon2html(B, viewers(holder))] The bolts lift out of the ground!") + playsound(B, 'sound/effects/stealthoff.ogg', 30, 1) + B.anchored = FALSE + if(WIRE_PROCEED) + if(!mend && B.active) + holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") + B.explode_now = TRUE + tell_admins(B) + if(WIRE_ACTIVATE) + if(!mend && B.active) + holder.visible_message("[icon2html(B, viewers(holder))] The timer stops! The bomb has been defused!") + B.active = FALSE + B.defused = TRUE + B.update_icon() + +/datum/wires/syndicatebomb/proc/tell_admins(obj/machinery/syndicatebomb/B) + if(istype(B, /obj/machinery/syndicatebomb/training)) + return + var/turf/T = get_turf(B) + log_game("\A [B] was detonated via boom wire at [AREACOORD(T)].") + message_admins("A [B.name] was detonated via boom wire at [ADMIN_VERBOSEJMP(T)].") diff --git a/code/game/area/Space_Station_13_areas.dm b/code/game/area/Space_Station_13_areas.dm index fa66306302..f26cfc4cdc 100644 --- a/code/game/area/Space_Station_13_areas.dm +++ b/code/game/area/Space_Station_13_areas.dm @@ -1,1352 +1,1352 @@ -/* - -### This file contains a list of all the areas in your station. Format is as follows: - -/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want) - name = "NICE NAME" (not required but makes things really nice) - icon = 'ICON FILENAME' (defaults to 'icons/turf/areas.dmi') - icon_state = "NAME OF ICON" (defaults to "unknown" (blank)) - requires_power = FALSE (defaults to true) - music = null (defaults to nothing, look in sound/ambience for music) - -NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0 - -*/ - - -/*-----------------------------------------------------------------------------*/ - -/area/ai_monitored //stub defined ai_monitored.dm - -/area/ai_monitored/turret_protected - -/area/arrival - requires_power = FALSE - -/area/arrival/start - name = "Arrival Area" - icon_state = "start" - -/area/admin - name = "Admin room" - icon_state = "start" - -/area/space - icon_state = "space" - requires_power = TRUE - always_unpowered = TRUE - dynamic_lighting = DYNAMIC_LIGHTING_DISABLED - power_light = FALSE - power_equip = FALSE - power_environ = FALSE - valid_territory = FALSE - outdoors = TRUE - ambientsounds = SPACE - blob_allowed = FALSE //Eating up space doesn't count for victory as a blob. - -/area/space/nearstation - icon_state = "space_near" - dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT - -/area/start - name = "start area" - icon_state = "start" - requires_power = FALSE - dynamic_lighting = DYNAMIC_LIGHTING_DISABLED - has_gravity = STANDARD_GRAVITY - - -//EXTRA - -/area/asteroid - name = "Asteroid" - icon_state = "asteroid" - requires_power = FALSE - has_gravity = STANDARD_GRAVITY - blob_allowed = FALSE //Nope, no winning on the asteroid as a blob. Gotta eat the station. - valid_territory = FALSE - ambientsounds = MINING - -/area/asteroid/nearstation - dynamic_lighting = DYNAMIC_LIGHTING_FORCED - ambientsounds = RUINS - always_unpowered = FALSE - requires_power = TRUE - blob_allowed = TRUE - -/area/asteroid/nearstation/bomb_site - name = "Bomb Testing Asteroid" - -/area/asteroid/cave - name = "Asteroid - Underground" - icon_state = "cave" - requires_power = FALSE - outdoors = TRUE - -/area/asteroid/cave/space - name = "Asteroid - Space" - -/area/asteroid/artifactroom - name = "Asteroid - Artifact" - icon_state = "cave" - ambientsounds = RUINS - -/area/asteroid/artifactroom/Initialize() - . = ..() - set_dynamic_lighting() - - -//STATION13 - -//Maintenance - -/area/maintenance - ambientsounds = MAINTENANCE - valid_territory = FALSE - - -//Departments - -/area/maintenance/department/chapel - name = "Chapel Maintenance" - icon_state = "maint_chapel" - -/area/maintenance/department/chapel/monastery - name = "Monastery Maintenance" - icon_state = "maint_monastery" - -/area/maintenance/department/crew_quarters/bar - name = "Bar Maintenance" - icon_state = "maint_bar" - -/area/maintenance/department/crew_quarters/dorms - name = "Dormitory Maintenance" - icon_state = "maint_dorms" - -/area/maintenance/department/crew_quarters/locker - name = "Locker Room Maintenance" - icon_state = "maint_locker" - -/area/maintenance/department/eva - name = "EVA Maintenance" - icon_state = "maint_eva" - -/area/maintenance/department/electrical - name = "Electrical Maintenance" - icon_state = "maint_electrical" - -/area/maintenance/department/engine/atmos - name = "Atmospherics Maintenance" - icon_state = "maint_atmos" - -/area/maintenance/department/security - name = "Security Maintenance" - icon_state = "maint_sec" - -/area/maintenance/department/security/brig - name = "Brig Maintenance" - icon_state = "maint_brig" - -/area/maintenance/department/medical - name = "Medbay Maintenance" - icon_state = "medbay_maint" - -/area/maintenance/department/medical/morgue - name = "Morgue Maintenance" - icon_state = "morgue_maint" - -/area/maintenance/department/science - name = "Science Maintenance" - icon_state = "maint_sci" - -/area/maintenance/department/cargo - name = "Cargo Maintenance" - icon_state = "maint_cargo" - -/area/maintenance/department/bridge - name = "Bridge Maintenance" - icon_state = "maint_bridge" - -/area/maintenance/department/engine - name = "Engineering Maintenance" - icon_state = "maint_engi" - -/area/maintenance/department/science/xenobiology - name = "Xenobiology Maintenance" - icon_state = "xenomaint" - xenobiology_compatible = TRUE - - -//Maintenance - Generic - -/area/maintenance/arrivals/north - name = "Arrivals North Maintenance" - icon_state = "fpmaint" - -/area/maintenance/arrivals/north_2 - name = "Arrivals North Maintenance" - icon_state = "fpmaint" - -/area/maintenance/aft - name = "Aft Maintenance" - icon_state = "amaint" - -/area/maintenance/aft/secondary - name = "Aft Maintenance" - icon_state = "amaint_2" - -/area/maintenance/central - name = "Central Maintenance" - icon_state = "maintcentral" - -/area/maintenance/central/secondary - name = "Central Maintenance" - icon_state = "maintcentral" - -/area/maintenance/fore - name = "Fore Maintenance" - icon_state = "fmaint" - -/area/maintenance/fore/secondary - name = "Fore Maintenance" - icon_state = "fmaint_2" - -/area/maintenance/starboard - name = "Starboard Maintenance" - icon_state = "smaint" - -/area/maintenance/starboard/central - name = "Central Starboard Maintenance" - icon_state = "smaint" - -/area/maintenance/starboard/aft - name = "Starboard Quarter Maintenance" - icon_state = "asmaint" - -/area/maintenance/starboard/fore - name = "Starboard Bow Maintenance" - icon_state = "fsmaint" - -/area/maintenance/port - name = "Port Maintenance" - icon_state = "pmaint" - -/area/maintenance/port/central - name = "Central Port Maintenance" - icon_state = "maintcentral" - -/area/maintenance/port/aft - name = "Port Quarter Maintenance" - icon_state = "apmaint" - -/area/maintenance/port/fore - name = "Port Bow Maintenance" - icon_state = "fpmaint" - -/area/maintenance/disposal - name = "Waste Disposal" - icon_state = "disposal" - -/area/maintenance/disposal/incinerator - name = "Incinerator" - icon_state = "disposal" -/area/maintenance/bar - name = "Maintenance Bar" - icon_state = "maintbar" - -/area/maintenance/bar/cafe - name = "Abandoned Cafe" - -//Hallway - -/area/hallway/primary/aft - name = "Aft Primary Hallway" - icon_state = "hallA" - -/area/hallway/primary/fore - name = "Fore Primary Hallway" - icon_state = "hallF" - -/area/hallway/primary/starboard - name = "Starboard Primary Hallway" - icon_state = "hallS" - -/area/hallway/primary/starboard/aft - name = "Starboard Quarter Primary Hallway" - icon_state = "hallAS" - -/area/hallway/primary/starboard/fore - name = "Starboard Bow Primary Hallway" - icon_state = "hallFS" - -/area/hallway/primary/port - name = "Port Primary Hallway" - icon_state = "hallP" - -/area/hallway/primary/port/aft - name = "Port Quarter Primary Hallway" - icon_state = "hallAP" - -/area/hallway/primary/port/fore - name = "Port Bow Primary Hallway" - icon_state = "hallFP" - -/area/hallway/primary/central - name = "Central Primary Hallway" - icon_state = "hallC" - -/area/hallway/secondary/command - name = "Command Hallway" - icon_state = "bridge_hallway" - -/area/hallway/secondary/construction - name = "Construction Area" - icon_state = "construction" - -/area/hallway/secondary/exit - name = "Escape Shuttle Hallway" - icon_state = "escape" - -/area/hallway/secondary/exit/departure_lounge - name = "Departure Lounge" - icon_state = "escape_lounge" - -/area/hallway/secondary/entry - name = "Arrival Shuttle Hallway" - icon_state = "entry" - -/area/hallway/secondary/service - name = "Service Hallway" - icon_state = "hall_service" - -//Command - -/area/bridge - name = "Bridge" - icon_state = "bridge" - music = "signal" - -/area/bridge/meeting_room - name = "Heads of Staff Meeting Room" - icon_state = "meeting" - music = null - -/area/bridge/meeting_room/council - name = "Council Chamber" - icon_state = "meeting" - music = null - -/area/bridge/showroom/corporate - name = "Corporate Showroom" - icon_state = "showroom" - music = null - -/area/crew_quarters/heads/captain - name = "Captain's Office" - icon_state = "captain" - clockwork_warp_allowed = FALSE - -/area/crew_quarters/heads/captain/private - name = "Captain's Quarters" - icon_state = "captain" - -/area/crew_quarters/heads/chief - name = "Chief Engineer's Office" - icon_state = "ce_office" - -/area/crew_quarters/heads/chief/private - name = "Chief Engineer's Private Quarters" - icon_state = "ce_private" - -/area/crew_quarters/heads/cmo - name = "Chief Medical Officer's Office" - icon_state = "cmo_office" - -/area/crew_quarters/heads/cmo/private - name = "Chief Medical Officer's Private Quarters" - icon_state = "cmo_private" - -/area/crew_quarters/heads/hop - name = "Head of Personnel's Office" - icon_state = "hop_office" - -/area/crew_quarters/heads/hop/private - name = "Head of Personnel's Private Quarters" - icon_state = "hop_private" - -/area/crew_quarters/heads/hos - name = "Head of Security's Office" - icon_state = "hos_office" - -/area/crew_quarters/heads/hos/private - name = "Head of Security's Private Quarters" - icon_state = "hos_private" - -/area/crew_quarters/heads/hor - name = "Research Director's Office" - icon_state = "rd_office" - -/area/crew_quarters/heads/hor/private - name = "Research Director's Private Quarters" - icon_state = "rd_private" - -/area/comms - name = "Communications Relay" - icon_state = "tcomsatcham" - -/area/server - name = "Messaging Server Room" - icon_state = "server" - -//Crew - -/area/crew_quarters/dorms - name = "Dormitories" - icon_state = "Sleep" - safe = TRUE - -/area/crew_quarters/dorms/male - name = "Male Dorm" - icon_state = "Sleep" - -/area/crew_quarters/dorms/female - name = "Female Dorm" - icon_state = "Sleep" - -/area/crew_quarters/rehab_dome - name = "Rehabilitation Dome" - icon_state = "Sleep" - -/area/crew_quarters/toilet - name = "Dormitory Toilets" - icon_state = "toilet" - -/area/crew_quarters/toilet/auxiliary - name = "Auxiliary Restrooms" - icon_state = "toilet" - -/area/crew_quarters/toilet/locker - name = "Locker Toilets" - icon_state = "toilet" - -/area/crew_quarters/toilet/fitness - name = "Fitness Toilets" - icon_state = "toilet" - -/area/crew_quarters/toilet/female - name = "Female Toilets" - icon_state = "toilet" - -/area/crew_quarters/toilet/male - name = "Male Toilets" - icon_state = "toilet" - -/area/crew_quarters/toilet/restrooms - name = "Restrooms" - icon_state = "toilet" - -/area/crew_quarters/locker - name = "Locker Room" - icon_state = "locker" - -/area/crew_quarters/lounge - name = "Lounge" - icon_state = "yellow" - -/area/crew_quarters/fitness - name = "Fitness Room" - icon_state = "fitness" - -/area/crew_quarters/fitness/recreation - name = "Recreation Area" - icon_state = "fitness" - -/area/crew_quarters/cafeteria - name = "Cafeteria" - icon_state = "cafeteria" - -/area/crew_quarters/cafeteria/lunchroom - name = "Lunchroom" - icon_state = "cafeteria" - -/area/crew_quarters/kitchen - name = "Kitchen" - icon_state = "kitchen" - -/area/crew_quarters/kitchen/backroom - name = "Kitchen Coldroom" - icon_state = "kitchen" - -/area/crew_quarters/bar - name = "Bar" - icon_state = "bar" - -/area/crew_quarters/bar/atrium - name = "Atrium" - icon_state = "bar" - -/area/crew_quarters/electronic_marketing_den - name = "Electronic Marketing Den" - icon_state = "bar" - -/area/crew_quarters/abandoned_gambling_den - name = "Abandoned Gambling Den" - icon_state = "abandoned_g_den" - -/area/crew_quarters/abandoned_gambling_den/secondary - icon_state = "abandoned_g_den_2" - -/area/crew_quarters/theatre - name = "Theatre" - icon_state = "Theatre" - -/area/crew_quarters/theatre/abandoned - name = "Abandoned Theatre" - icon_state = "Theatre" - -/area/crew_quarters/theatre/clown - name = "Clown's Office" - -/area/crew_quarters/theatre/mime - name = "Mime's Office" - -/area/crew_quarters/cryopod - name = "Cryogenics" - icon_state = "cryosleep" - -/area/library - name = "Library" - icon_state = "library" - flags_1 = NONE - -/area/library/lounge - name = "Library Lounge" - icon_state = "library" - -/area/library/abandoned - name = "Abandoned Library" - icon_state = "library" - flags_1 = NONE - -/area/chapel - icon_state = "chapel" - ambientsounds = HOLY - flags_1 = NONE - clockwork_warp_allowed = FALSE - clockwork_warp_fail = "The consecration here prevents you from warping in." - -/area/chapel/main - name = "Chapel" - -/area/chapel/main/monastery - name = "Monastery" - -/area/chapel/office - name = "Chapel Office" - icon_state = "chapeloffice" - -/area/chapel/asteroid - name = "Chapel Asteroid" - icon_state = "explored" - -/area/chapel/asteroid/monastery - name = "Monastery Asteroid" - -/area/chapel/dock - name = "Chapel Dock" - icon_state = "construction" - -/area/lawoffice - name = "Law Office" - icon_state = "law" - - -//Engineering - -/area/engine - ambientsounds = ENGINEERING - -/area/engine/engine_smes - name = "Engineering SMES" - icon_state = "engine_smes" - -/area/engine/engineering - name = "Engineering" - icon_state = "engine" - -/area/engine/atmos - name = "Atmospherics" - icon_state = "atmos" - flags_1 = NONE - -/area/engine/atmospherics_engine - name = "Atmospherics Engine" - icon_state = "atmos_engine" - -/area/engine/supermatter - name = "Supermatter Engine" - icon_state = "engine_sm" - -/area/engine/break_room - name = "Engineering Foyer" - icon_state = "engine_foyer" - -/area/engine/gravity_generator - name = "Gravity Generator Room" - icon_state = "grav_gen" - clockwork_warp_allowed = FALSE - clockwork_warp_fail = "The gravitons generated here could throw off your warp's destination and possibly throw you into deep space." - -/area/engine/secure_construction - name = "Secure Construction Area" - icon_state = "engine" - -/area/engine/storage - name = "Engineering Storage" - icon_state = "engi_storage" - -/area/engine/storage_shared - name = "Shared Engineering Storage" - icon_state = "engi_storage" - -/area/engine/transit_tube - name = "Transit Tube" - icon_state = "transit_tube" - - -//Solars - -/area/solar - requires_power = FALSE - dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT - valid_territory = FALSE - blob_allowed = FALSE - flags_1 = NONE - ambientsounds = ENGINEERING - -/area/solar/fore - name = "Fore Solar Array" - icon_state = "yellow" - -/area/solar/aft - name = "Aft Solar Array" - icon_state = "yellow" - -/area/solar/aux/port - name = "Port Bow Auxiliary Solar Array" - icon_state = "panelsA" - -/area/solar/aux/starboard - name = "Starboard Bow Auxiliary Solar Array" - icon_state = "panelsA" - -/area/solar/starboard - name = "Starboard Solar Array" - icon_state = "panelsS" - -/area/solar/starboard/aft - name = "Starboard Quarter Solar Array" - icon_state = "panelsAS" - -/area/solar/starboard/fore - name = "Starboard Bow Solar Array" - icon_state = "panelsFS" - -/area/solar/port - name = "Port Solar Array" - icon_state = "panelsP" - -/area/solar/port/aft - name = "Port Quarter Solar Array" - icon_state = "panelsAP" - -/area/solar/port/fore - name = "Port Bow Solar Array" - icon_state = "panelsFP" - - -//Solar Maint - -/area/maintenance/solars - name = "Solar Maintenance" - icon_state = "yellow" - -/area/maintenance/solars/port - name = "Port Solar Maintenance" - icon_state = "SolarcontrolP" - -/area/maintenance/solars/port/aft - name = "Port Quarter Solar Maintenance" - icon_state = "SolarcontrolAP" - -/area/maintenance/solars/port/fore - name = "Port Bow Solar Maintenance" - icon_state = "SolarcontrolFP" - -/area/maintenance/solars/starboard - name = "Starboard Solar Maintenance" - icon_state = "SolarcontrolS" - -/area/maintenance/solars/starboard/aft - name = "Starboard Quarter Solar Maintenance" - icon_state = "SolarcontrolAS" - -/area/maintenance/solars/starboard/fore - name = "Starboard Bow Solar Maintenance" - icon_state = "SolarcontrolFS" - -/area/maintenance/solars/aux/port - name = "Port Auxiliary Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/solars/aux/port/aft - name = "Port Quarter Auxiliary Solar Maintenance" - icon_state = "SolarcontrolAP" - -/area/maintenance/solars/aux/port/fore - name = "Port Bow Auxiliary Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/solars/aux/starboard - name = "Starboard Auxiliary Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/solars/aux/starboard/aft - name = "Starboard Quarter Auxiliary Solar Maintenance" - icon_state = "SolarcontrolA" - -/area/maintenance/solars/aux/starboard/fore - name = "Starboard Bow Auxiliary Solar Maintenance" - icon_state = "SolarcontrolA" - -//Teleporter - -/area/teleporter - name = "Teleporter Room" - icon_state = "teleporter" - music = "signal" - ambientsounds = ENGINEERING - -/area/gateway - name = "Gateway" - icon_state = "gateway" - music = "signal" - ambientsounds = ENGINEERING - -//MedBay - -/area/medical - name = "Medical" - icon_state = "medbay3" - ambientsounds = MEDICAL - -/area/medical/abandoned - name = "Abandoned Medbay" - icon_state = "medbay3" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay/central - name = "Medbay Central" - icon_state = "medbay" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay/front_office - name = "Medbay Front Office" - icon_state = "medbay" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay/lobby - name = "Medbay Lobby" - icon_state = "medbay" - music = 'sound/ambience/signal.ogg' - - //Medbay is a large area, these additional areas help level out APC load. - -/area/medical/medbay/zone2 - name = "Medbay" - icon_state = "medbay2" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay/zone3 - name = "Medbay" - icon_state = "medbay3" - music = 'sound/ambience/signal.ogg' - -/area/medical/medbay/aft - name = "Medbay Aft" - icon_state = "medbay3" - music = 'sound/ambience/signal.ogg' - -/area/medical/storage - name = "Medbay Storage" - icon_state = "medbay2" - music = 'sound/ambience/signal.ogg' - -/area/medical/patients_rooms - name = "Patients' Rooms" - icon_state = "patients" - -/area/medical/patients_rooms/room_a - name = "Patient Room A" - icon_state = "patients" - -/area/medical/patients_rooms/room_b - name = "Patient Room B" - icon_state = "patients" - -/area/medical/virology - name = "Virology" - icon_state = "virology" - flags_1 = NONE - -/area/medical/morgue - name = "Morgue" - icon_state = "morgue" - ambientsounds = SPOOKY - -/area/medical/chemistry - name = "Chemistry" - icon_state = "chem" - -/area/medical/surgery - name = "Surgery" - icon_state = "surgery" - -/area/medical/cryo - name = "Cryogenics" - icon_state = "cryo" - -/area/medical/exam_room - name = "Exam Room" - icon_state = "exam_room" - -/area/medical/genetics - name = "Genetics Lab" - icon_state = "genetics" - -/area/medical/genetics/cloning - name = "Cloning Lab" - icon_state = "cloning" - -/area/medical/sleeper - name = "Medbay Treatment Center" - icon_state = "exam_room" - - -//Security - -/area/security - name = "Security" - icon_state = "security" - ambientsounds = HIGHSEC - -/area/security/main - name = "Security Office" - icon_state = "security" - -/area/security/brig - name = "Brig" - icon_state = "brig" - -/area/security/courtroom - name = "Courtroom" - icon_state = "courtroom" - -/area/security/prison - name = "Prison Wing" - icon_state = "sec_prison" - -/area/security/processing - name = "Labor Shuttle Dock" - icon_state = "sec_prison" - -/area/security/processing/cremation - name = "Security Crematorium" - icon_state = "sec_prison" - -/area/security/warden - name = "Brig Control" - icon_state = "Warden" - -/area/security/armory - name = "Armory" - icon_state = "armory" - -/area/security/detectives_office - name = "Detective's Office" - icon_state = "detective" - ambientsounds = list('sound/ambience/ambidet1.ogg','sound/ambience/ambidet2.ogg') - -/area/security/detectives_office/private_investigators_office - name = "Private Investigator's Office" - icon_state = "detective" - -/area/security/range - name = "Firing Range" - icon_state = "firingrange" - -/area/security/execution - icon_state = "execution_room" - -/area/security/execution/transfer - name = "Transfer Centre" - -/area/security/execution/education - name = "Prisoner Education Chamber" - -/area/security/nuke_storage - name = "Vault" - icon_state = "nuke_storage" - -/area/ai_monitored/nuke_storage - name = "Vault" - icon_state = "nuke_storage" - -/area/security/checkpoint - name = "Security Checkpoint" - icon_state = "checkpoint1" - -/area/security/checkpoint/auxiliary - icon_state = "checkpoint_aux" - -/area/security/checkpoint/tertiary - icon_state = "checkpoint_tert" - -/area/security/checkpoint/escape - icon_state = "checkpoint_esc" - -/area/security/checkpoint/supply - name = "Security Post - Cargo Bay" - icon_state = "checkpoint_supp" - -/area/security/checkpoint/engineering - name = "Security Post - Engineering" - icon_state = "checkpoint_engi" - -/area/security/checkpoint/medical - name = "Security Post - Medbay" - icon_state = "checkpoint_med" - -/area/security/checkpoint/science - name = "Security Post - Science" - icon_state = "checkpoint_sci" - -/area/security/checkpoint/science/research - name = "Security Post - Research Division" - icon_state = "checkpoint_res" - -/area/security/checkpoint/customs - name = "Customs" - icon_state = "customs_point" - -/area/security/checkpoint/customs/auxiliary - icon_state = "customs_point_aux" - -/area/security/vacantoffice - name = "Vacant Office" - icon_state = "security" - -/area/security/vacantoffice/a - name = "Vacant Office A" - icon_state = "security" - -/area/security/vacantoffice/b - name = "Vacant Office B" - icon_state = "security" - -/area/quartermaster - name = "Quartermasters" - icon_state = "quart" - -///////////WORK IN PROGRESS////////// - -/area/quartermaster/sorting - name = "Delivery Office" - icon_state = "cargo_delivery" - -/area/quartermaster/warehouse - name = "Warehouse" - icon_state = "cargo_warehouse" - -////////////WORK IN PROGRESS////////// - -/area/quartermaster/office - name = "Cargo Office" - icon_state = "quartoffice" - -/area/quartermaster/storage - name = "Cargo Bay" - icon_state = "cargo_bay" - -/area/quartermaster/qm - name = "Quartermaster's Office" - icon_state = "quart" - -/area/quartermaster/qm/private - name = "Quartermaster's Private Quarters" - icon_state = "quart" - -/area/quartermaster/miningdock - name = "Mining Dock" - icon_state = "mining" - -/area/quartermaster/miningdock/abandoned - name = "Abandoned Mining Dock" - icon_state = "mining" - -/area/quartermaster/miningoffice - name = "Mining Office" - icon_state = "mining" - -/area/quartermaster/miningstorage - name = "Mining Storage" - icon_state = "mining" - -/area/janitor - name = "Custodial Closet" - icon_state = "janitor" - flags_1 = NONE - -/area/hydroponics - name = "Hydroponics" - icon_state = "hydro" - -/area/hydroponics/garden - name = "Garden" - icon_state = "garden" - -/area/hydroponics/garden/abandoned - name = "Abandoned Garden" - icon_state = "abandoned_garden" - -/area/hydroponics/garden/monastery - name = "Monastery Garden" - icon_state = "hydro" - - -//Science - -/area/science - name = "Science Division" - icon_state = "toxlab" - -/area/science/lab - name = "Research and Development" - icon_state = "toxlab" - -/area/science/xenobiology - name = "Xenobiology Lab" - icon_state = "toxlab" - -/area/science/storage - name = "Toxins Storage" - icon_state = "toxstorage" - -/area/science/mineral_storeroom - name = "Mineral Storeroom" - icon_state = "toxmisc" - -/area/science/test_area - valid_territory = FALSE - name = "Toxins Test Area" - icon_state = "toxtest" - -/area/science/mixing - name = "Toxins Mixing Lab" - icon_state = "toxmix" - -/area/science/mixing/chamber - name = "Toxins Mixing Chamber" - icon_state = "toxmix" - valid_territory = FALSE - -/area/science/misc_lab - name = "Testing Lab" - icon_state = "toxmisc" - -/area/science/misc_lab/range - name = "Research Testing Range" - icon_state = "toxmisc" - -/area/science/server - name = "Research Division Server Room" - icon_state = "server" - -/area/science/explab - name = "Experimentation Lab" - icon_state = "toxmisc" - -/area/science/robotics - name = "Robotics" - icon_state = "medresearch" - -/area/science/robotics/mechbay - name = "Mech Bay" - icon_state = "mechbay" - -/area/science/robotics/mechbay_cargo - name = "Mech Bay" - icon_state = "yellow" - -/area/science/robotics/showroom - name = "Robotics Showroom" - icon_state = "showroom" - -/area/science/robotics/lab - name = "Robotics Lab" - icon_state = "ass_line" - -/area/science/research - name = "Research Division" - icon_state = "medresearch" - -/area/science/circuit - name = "Circuitry Lab" - icon_state = "cir_lab" - -/area/science/research/lobby - name = "Research Division Lobby" - icon_state = "medresearch" - -/area/science/research/abandoned - name = "Abandoned Research Lab" - icon_state = "medresearch" - -/area/science/nanite - name = "Nanite Lab" - icon_state = "toxmisc" - -//Storage - -/area/storage/tools - name = "Auxiliary Tool Storage" - icon_state = "storage" - -/area/storage/primary - name = "Primary Tool Storage" - icon_state = "primarystorage" - -/area/storage/autolathe - name = "Autolathe Storage" - icon_state = "storage" - -/area/storage/art - name = "Art Supply Storage" - icon_state = "storage" - -/area/storage/auxiliary - name = "Auxiliary Storage" - icon_state = "auxstorage" - -/area/storage/atmos - name = "Atmospherics Storage" - icon_state = "atmos" - valid_territory = FALSE - -/area/storage/tcom - name = "Telecomms Storage" - icon_state = "green" - valid_territory = FALSE - -/area/storage/eva - name = "EVA Storage" - icon_state = "eva" - clockwork_warp_allowed = FALSE - -/area/storage/secure - name = "Secure Storage" - icon_state = "storage" - clockwork_warp_allowed = FALSE - -/area/storage/emergency/starboard - name = "Starboard Emergency Storage" - icon_state = "emergencystorage" - -/area/storage/emergency/port - name = "Port Emergency Storage" - icon_state = "emergencystorage" - -/area/storage/tech - name = "Technical Storage" - icon_state = "auxstorage" - -/area/storage/testroom - requires_power = FALSE - name = "Test Room" - icon_state = "storage" - - -//Construction - -/area/construction - name = "Construction Area" - icon_state = "yellow" - ambientsounds = ENGINEERING - -/area/construction/minisat_exterior - name = "Minisat Exterior" - icon_state = "yellow" - -/area/construction/mining/aux_base - name = "Auxiliary Base Construction" - icon_state = "yellow" - -/area/construction/mining/aux_base/closet - name = "Auxiliary Closet Construction" - icon_state = "yellow" - -/area/construction/supplyshuttle - name = "Supply Shuttle" - icon_state = "yellow" - -/area/construction/quarters - name = "Engineers' Quarters" - icon_state = "yellow" - -/area/construction/qmaint - name = "Maintenance" - icon_state = "yellow" - -/area/construction/hallway - name = "Hallway" - icon_state = "yellow" - -/area/construction/solars - name = "Solar Panels" - icon_state = "yellow" - -/area/construction/solarscontrol - name = "Solar Panel Control" - icon_state = "yellow" - -/area/construction/storage - name = "Construction Site Storage" - icon_state = "yellow" - -/area/construction/storage/wing - name = "Storage Wing" - icon_state = "storage_wing" - - -//AI - -/area/ai_monitored/security/armory - name = "Armory" - icon_state = "armory" - ambientsounds = HIGHSEC - -/area/ai_monitored/storage/eva - name = "EVA Storage" - icon_state = "eva" - ambientsounds = HIGHSEC - -/area/ai_monitored/storage/satellite - name = "AI Satellite Maint" - icon_state = "storage" - ambientsounds = HIGHSEC - - //Turret_protected - -/area/ai_monitored/turret_protected - ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg') - -/area/ai_monitored/turret_protected/ai_upload - name = "AI Upload Chamber" - icon_state = "ai_upload" - -/area/ai_monitored/turret_protected/ai_upload_foyer - name = "AI Upload Access" - icon_state = "ai_foyer" - -/area/ai_monitored/turret_protected/ai - name = "AI Chamber" - icon_state = "ai_chamber" - -/area/ai_monitored/turret_protected/aisat - name = "AI Satellite" - icon_state = "ai" - -/area/ai_monitored/turret_protected/aisat/atmos - name = "AI Satellite Atmos" - icon_state = "ai" - -/area/ai_monitored/turret_protected/aisat/foyer - name = "AI Satellite Foyer" - icon_state = "ai" - -/area/ai_monitored/turret_protected/aisat/service - name = "AI Satellite Service" - icon_state = "ai" - -/area/ai_monitored/turret_protected/aisat/hallway - name = "AI Satellite Hallway" - icon_state = "ai" - -/area/aisat - name = "AI Satellite Exterior" - icon_state = "yellow" - -/area/ai_monitored/turret_protected/aisat_interior - name = "AI Satellite Antechamber" - icon_state = "ai" - -/area/ai_monitored/turret_protected/AIsatextFP - name = "AI Sat Ext" - icon_state = "storage" - -/area/ai_monitored/turret_protected/AIsatextFS - name = "AI Sat Ext" - icon_state = "storage" - -/area/ai_monitored/turret_protected/AIsatextAS - name = "AI Sat Ext" - icon_state = "storage" - -/area/ai_monitored/turret_protected/AIsatextAP - name = "AI Sat Ext" - icon_state = "storage" - - -// Telecommunications Satellite - -/area/tcommsat - clockwork_warp_allowed = FALSE - clockwork_warp_fail = "For safety reasons, warping here is disallowed; the radio and bluespace noise could cause catastrophic results." - 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/entrance - name = "Telecomms Teleporter" - icon_state = "tcomsatentrance" - -/area/tcommsat/chamber - name = "Abandoned Satellite" - icon_state = "tcomsatcham" - -/area/ai_monitored/turret_protected/tcomsat - name = "Telecomms Satellite" - icon_state = "tcomsatlob" - -/area/ai_monitored/turret_protected/tcomfoyer - name = "Telecomms Foyer" - icon_state = "tcomsatentrance" - -/area/ai_monitored/turret_protected/tcomwest - name = "Telecommunications Satellite West Wing" - icon_state = "tcomsatwest" - -/area/ai_monitored/turret_protected/tcomeast - name = "Telecommunications Satellite East Wing" - icon_state = "tcomsateast" - -/area/tcommsat/computer - name = "Telecomms Control Room" - icon_state = "tcomsatcomp" - -/area/tcommsat/server - name = "Telecomms Server Room" - icon_state = "tcomsatcham" - -/area/tcommsat/lounge - name = "Telecommunications Satellite Lounge" - icon_state = "tcomsatlounge" +/* + +### This file contains a list of all the areas in your station. Format is as follows: + +/area/CATEGORY/OR/DESCRIPTOR/NAME (you can make as many subdivisions as you want) + name = "NICE NAME" (not required but makes things really nice) + icon = 'ICON FILENAME' (defaults to 'icons/turf/areas.dmi') + icon_state = "NAME OF ICON" (defaults to "unknown" (blank)) + requires_power = FALSE (defaults to true) + music = null (defaults to nothing, look in sound/ambience for music) + +NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0 + +*/ + + +/*-----------------------------------------------------------------------------*/ + +/area/ai_monitored //stub defined ai_monitored.dm + +/area/ai_monitored/turret_protected + +/area/arrival + requires_power = FALSE + +/area/arrival/start + name = "Arrival Area" + icon_state = "start" + +/area/admin + name = "Admin room" + icon_state = "start" + +/area/space + icon_state = "space" + requires_power = TRUE + always_unpowered = TRUE + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + power_light = FALSE + power_equip = FALSE + power_environ = FALSE + valid_territory = FALSE + outdoors = TRUE + ambientsounds = SPACE + blob_allowed = FALSE //Eating up space doesn't count for victory as a blob. + +/area/space/nearstation + icon_state = "space_near" + dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT + +/area/start + name = "start area" + icon_state = "start" + requires_power = FALSE + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + has_gravity = STANDARD_GRAVITY + + +//EXTRA + +/area/asteroid + name = "Asteroid" + icon_state = "asteroid" + requires_power = FALSE + has_gravity = STANDARD_GRAVITY + blob_allowed = FALSE //Nope, no winning on the asteroid as a blob. Gotta eat the station. + valid_territory = FALSE + ambientsounds = MINING + +/area/asteroid/nearstation + dynamic_lighting = DYNAMIC_LIGHTING_FORCED + ambientsounds = RUINS + always_unpowered = FALSE + requires_power = TRUE + blob_allowed = TRUE + +/area/asteroid/nearstation/bomb_site + name = "Bomb Testing Asteroid" + +/area/asteroid/cave + name = "Asteroid - Underground" + icon_state = "cave" + requires_power = FALSE + outdoors = TRUE + +/area/asteroid/cave/space + name = "Asteroid - Space" + +/area/asteroid/artifactroom + name = "Asteroid - Artifact" + icon_state = "cave" + ambientsounds = RUINS + +/area/asteroid/artifactroom/Initialize() + . = ..() + set_dynamic_lighting() + + +//STATION13 + +//Maintenance + +/area/maintenance + ambientsounds = MAINTENANCE + valid_territory = FALSE + + +//Departments + +/area/maintenance/department/chapel + name = "Chapel Maintenance" + icon_state = "maint_chapel" + +/area/maintenance/department/chapel/monastery + name = "Monastery Maintenance" + icon_state = "maint_monastery" + +/area/maintenance/department/crew_quarters/bar + name = "Bar Maintenance" + icon_state = "maint_bar" + +/area/maintenance/department/crew_quarters/dorms + name = "Dormitory Maintenance" + icon_state = "maint_dorms" + +/area/maintenance/department/crew_quarters/locker + name = "Locker Room Maintenance" + icon_state = "maint_locker" + +/area/maintenance/department/eva + name = "EVA Maintenance" + icon_state = "maint_eva" + +/area/maintenance/department/electrical + name = "Electrical Maintenance" + icon_state = "maint_electrical" + +/area/maintenance/department/engine/atmos + name = "Atmospherics Maintenance" + icon_state = "maint_atmos" + +/area/maintenance/department/security + name = "Security Maintenance" + icon_state = "maint_sec" + +/area/maintenance/department/security/brig + name = "Brig Maintenance" + icon_state = "maint_brig" + +/area/maintenance/department/medical + name = "Medbay Maintenance" + icon_state = "medbay_maint" + +/area/maintenance/department/medical/morgue + name = "Morgue Maintenance" + icon_state = "morgue_maint" + +/area/maintenance/department/science + name = "Science Maintenance" + icon_state = "maint_sci" + +/area/maintenance/department/cargo + name = "Cargo Maintenance" + icon_state = "maint_cargo" + +/area/maintenance/department/bridge + name = "Bridge Maintenance" + icon_state = "maint_bridge" + +/area/maintenance/department/engine + name = "Engineering Maintenance" + icon_state = "maint_engi" + +/area/maintenance/department/science/xenobiology + name = "Xenobiology Maintenance" + icon_state = "xenomaint" + xenobiology_compatible = TRUE + + +//Maintenance - Generic + +/area/maintenance/arrivals/north + name = "Arrivals North Maintenance" + icon_state = "fpmaint" + +/area/maintenance/arrivals/north_2 + name = "Arrivals North Maintenance" + icon_state = "fpmaint" + +/area/maintenance/aft + name = "Aft Maintenance" + icon_state = "amaint" + +/area/maintenance/aft/secondary + name = "Aft Maintenance" + icon_state = "amaint_2" + +/area/maintenance/central + name = "Central Maintenance" + icon_state = "maintcentral" + +/area/maintenance/central/secondary + name = "Central Maintenance" + icon_state = "maintcentral" + +/area/maintenance/fore + name = "Fore Maintenance" + icon_state = "fmaint" + +/area/maintenance/fore/secondary + name = "Fore Maintenance" + icon_state = "fmaint_2" + +/area/maintenance/starboard + name = "Starboard Maintenance" + icon_state = "smaint" + +/area/maintenance/starboard/central + name = "Central Starboard Maintenance" + icon_state = "smaint" + +/area/maintenance/starboard/aft + name = "Starboard Quarter Maintenance" + icon_state = "asmaint" + +/area/maintenance/starboard/fore + name = "Starboard Bow Maintenance" + icon_state = "fsmaint" + +/area/maintenance/port + name = "Port Maintenance" + icon_state = "pmaint" + +/area/maintenance/port/central + name = "Central Port Maintenance" + icon_state = "maintcentral" + +/area/maintenance/port/aft + name = "Port Quarter Maintenance" + icon_state = "apmaint" + +/area/maintenance/port/fore + name = "Port Bow Maintenance" + icon_state = "fpmaint" + +/area/maintenance/disposal + name = "Waste Disposal" + icon_state = "disposal" + +/area/maintenance/disposal/incinerator + name = "Incinerator" + icon_state = "disposal" +/area/maintenance/bar + name = "Maintenance Bar" + icon_state = "maintbar" + +/area/maintenance/bar/cafe + name = "Abandoned Cafe" + +//Hallway + +/area/hallway/primary/aft + name = "Aft Primary Hallway" + icon_state = "hallA" + +/area/hallway/primary/fore + name = "Fore Primary Hallway" + icon_state = "hallF" + +/area/hallway/primary/starboard + name = "Starboard Primary Hallway" + icon_state = "hallS" + +/area/hallway/primary/starboard/aft + name = "Starboard Quarter Primary Hallway" + icon_state = "hallAS" + +/area/hallway/primary/starboard/fore + name = "Starboard Bow Primary Hallway" + icon_state = "hallFS" + +/area/hallway/primary/port + name = "Port Primary Hallway" + icon_state = "hallP" + +/area/hallway/primary/port/aft + name = "Port Quarter Primary Hallway" + icon_state = "hallAP" + +/area/hallway/primary/port/fore + name = "Port Bow Primary Hallway" + icon_state = "hallFP" + +/area/hallway/primary/central + name = "Central Primary Hallway" + icon_state = "hallC" + +/area/hallway/secondary/command + name = "Command Hallway" + icon_state = "bridge_hallway" + +/area/hallway/secondary/construction + name = "Construction Area" + icon_state = "construction" + +/area/hallway/secondary/exit + name = "Escape Shuttle Hallway" + icon_state = "escape" + +/area/hallway/secondary/exit/departure_lounge + name = "Departure Lounge" + icon_state = "escape_lounge" + +/area/hallway/secondary/entry + name = "Arrival Shuttle Hallway" + icon_state = "entry" + +/area/hallway/secondary/service + name = "Service Hallway" + icon_state = "hall_service" + +//Command + +/area/bridge + name = "Bridge" + icon_state = "bridge" + music = "signal" + +/area/bridge/meeting_room + name = "Heads of Staff Meeting Room" + icon_state = "meeting" + music = null + +/area/bridge/meeting_room/council + name = "Council Chamber" + icon_state = "meeting" + music = null + +/area/bridge/showroom/corporate + name = "Corporate Showroom" + icon_state = "showroom" + music = null + +/area/crew_quarters/heads/captain + name = "Captain's Office" + icon_state = "captain" + clockwork_warp_allowed = FALSE + +/area/crew_quarters/heads/captain/private + name = "Captain's Quarters" + icon_state = "captain" + +/area/crew_quarters/heads/chief + name = "Chief Engineer's Office" + icon_state = "ce_office" + +/area/crew_quarters/heads/chief/private + name = "Chief Engineer's Private Quarters" + icon_state = "ce_private" + +/area/crew_quarters/heads/cmo + name = "Chief Medical Officer's Office" + icon_state = "cmo_office" + +/area/crew_quarters/heads/cmo/private + name = "Chief Medical Officer's Private Quarters" + icon_state = "cmo_private" + +/area/crew_quarters/heads/hop + name = "Head of Personnel's Office" + icon_state = "hop_office" + +/area/crew_quarters/heads/hop/private + name = "Head of Personnel's Private Quarters" + icon_state = "hop_private" + +/area/crew_quarters/heads/hos + name = "Head of Security's Office" + icon_state = "hos_office" + +/area/crew_quarters/heads/hos/private + name = "Head of Security's Private Quarters" + icon_state = "hos_private" + +/area/crew_quarters/heads/hor + name = "Research Director's Office" + icon_state = "rd_office" + +/area/crew_quarters/heads/hor/private + name = "Research Director's Private Quarters" + icon_state = "rd_private" + +/area/comms + name = "Communications Relay" + icon_state = "tcomsatcham" + +/area/server + name = "Messaging Server Room" + icon_state = "server" + +//Crew + +/area/crew_quarters/dorms + name = "Dormitories" + icon_state = "Sleep" + safe = TRUE + +/area/crew_quarters/dorms/male + name = "Male Dorm" + icon_state = "Sleep" + +/area/crew_quarters/dorms/female + name = "Female Dorm" + icon_state = "Sleep" + +/area/crew_quarters/rehab_dome + name = "Rehabilitation Dome" + icon_state = "Sleep" + +/area/crew_quarters/toilet + name = "Dormitory Toilets" + icon_state = "toilet" + +/area/crew_quarters/toilet/auxiliary + name = "Auxiliary Restrooms" + icon_state = "toilet" + +/area/crew_quarters/toilet/locker + name = "Locker Toilets" + icon_state = "toilet" + +/area/crew_quarters/toilet/fitness + name = "Fitness Toilets" + icon_state = "toilet" + +/area/crew_quarters/toilet/female + name = "Female Toilets" + icon_state = "toilet" + +/area/crew_quarters/toilet/male + name = "Male Toilets" + icon_state = "toilet" + +/area/crew_quarters/toilet/restrooms + name = "Restrooms" + icon_state = "toilet" + +/area/crew_quarters/locker + name = "Locker Room" + icon_state = "locker" + +/area/crew_quarters/lounge + name = "Lounge" + icon_state = "yellow" + +/area/crew_quarters/fitness + name = "Fitness Room" + icon_state = "fitness" + +/area/crew_quarters/fitness/recreation + name = "Recreation Area" + icon_state = "fitness" + +/area/crew_quarters/cafeteria + name = "Cafeteria" + icon_state = "cafeteria" + +/area/crew_quarters/cafeteria/lunchroom + name = "Lunchroom" + icon_state = "cafeteria" + +/area/crew_quarters/kitchen + name = "Kitchen" + icon_state = "kitchen" + +/area/crew_quarters/kitchen/backroom + name = "Kitchen Coldroom" + icon_state = "kitchen" + +/area/crew_quarters/bar + name = "Bar" + icon_state = "bar" + +/area/crew_quarters/bar/atrium + name = "Atrium" + icon_state = "bar" + +/area/crew_quarters/electronic_marketing_den + name = "Electronic Marketing Den" + icon_state = "bar" + +/area/crew_quarters/abandoned_gambling_den + name = "Abandoned Gambling Den" + icon_state = "abandoned_g_den" + +/area/crew_quarters/abandoned_gambling_den/secondary + icon_state = "abandoned_g_den_2" + +/area/crew_quarters/theatre + name = "Theatre" + icon_state = "Theatre" + +/area/crew_quarters/theatre/abandoned + name = "Abandoned Theatre" + icon_state = "Theatre" + +/area/crew_quarters/theatre/clown + name = "Clown's Office" + +/area/crew_quarters/theatre/mime + name = "Mime's Office" + +/area/crew_quarters/cryopod + name = "Cryogenics" + icon_state = "cryosleep" + +/area/library + name = "Library" + icon_state = "library" + flags_1 = NONE + +/area/library/lounge + name = "Library Lounge" + icon_state = "library" + +/area/library/abandoned + name = "Abandoned Library" + icon_state = "library" + flags_1 = NONE + +/area/chapel + icon_state = "chapel" + ambientsounds = HOLY + flags_1 = NONE + clockwork_warp_allowed = FALSE + clockwork_warp_fail = "The consecration here prevents you from warping in." + +/area/chapel/main + name = "Chapel" + +/area/chapel/main/monastery + name = "Monastery" + +/area/chapel/office + name = "Chapel Office" + icon_state = "chapeloffice" + +/area/chapel/asteroid + name = "Chapel Asteroid" + icon_state = "explored" + +/area/chapel/asteroid/monastery + name = "Monastery Asteroid" + +/area/chapel/dock + name = "Chapel Dock" + icon_state = "construction" + +/area/lawoffice + name = "Law Office" + icon_state = "law" + + +//Engineering + +/area/engine + ambientsounds = ENGINEERING + +/area/engine/engine_smes + name = "Engineering SMES" + icon_state = "engine_smes" + +/area/engine/engineering + name = "Engineering" + icon_state = "engine" + +/area/engine/atmos + name = "Atmospherics" + icon_state = "atmos" + flags_1 = NONE + +/area/engine/atmospherics_engine + name = "Atmospherics Engine" + icon_state = "atmos_engine" + +/area/engine/supermatter + name = "Supermatter Engine" + icon_state = "engine_sm" + +/area/engine/break_room + name = "Engineering Foyer" + icon_state = "engine_foyer" + +/area/engine/gravity_generator + name = "Gravity Generator Room" + icon_state = "grav_gen" + clockwork_warp_allowed = FALSE + clockwork_warp_fail = "The gravitons generated here could throw off your warp's destination and possibly throw you into deep space." + +/area/engine/secure_construction + name = "Secure Construction Area" + icon_state = "engine" + +/area/engine/storage + name = "Engineering Storage" + icon_state = "engi_storage" + +/area/engine/storage_shared + name = "Shared Engineering Storage" + icon_state = "engi_storage" + +/area/engine/transit_tube + name = "Transit Tube" + icon_state = "transit_tube" + + +//Solars + +/area/solar + requires_power = FALSE + dynamic_lighting = DYNAMIC_LIGHTING_IFSTARLIGHT + valid_territory = FALSE + blob_allowed = FALSE + flags_1 = NONE + ambientsounds = ENGINEERING + +/area/solar/fore + name = "Fore Solar Array" + icon_state = "yellow" + +/area/solar/aft + name = "Aft Solar Array" + icon_state = "yellow" + +/area/solar/aux/port + name = "Port Bow Auxiliary Solar Array" + icon_state = "panelsA" + +/area/solar/aux/starboard + name = "Starboard Bow Auxiliary Solar Array" + icon_state = "panelsA" + +/area/solar/starboard + name = "Starboard Solar Array" + icon_state = "panelsS" + +/area/solar/starboard/aft + name = "Starboard Quarter Solar Array" + icon_state = "panelsAS" + +/area/solar/starboard/fore + name = "Starboard Bow Solar Array" + icon_state = "panelsFS" + +/area/solar/port + name = "Port Solar Array" + icon_state = "panelsP" + +/area/solar/port/aft + name = "Port Quarter Solar Array" + icon_state = "panelsAP" + +/area/solar/port/fore + name = "Port Bow Solar Array" + icon_state = "panelsFP" + + +//Solar Maint + +/area/maintenance/solars + name = "Solar Maintenance" + icon_state = "yellow" + +/area/maintenance/solars/port + name = "Port Solar Maintenance" + icon_state = "SolarcontrolP" + +/area/maintenance/solars/port/aft + name = "Port Quarter Solar Maintenance" + icon_state = "SolarcontrolAP" + +/area/maintenance/solars/port/fore + name = "Port Bow Solar Maintenance" + icon_state = "SolarcontrolFP" + +/area/maintenance/solars/starboard + name = "Starboard Solar Maintenance" + icon_state = "SolarcontrolS" + +/area/maintenance/solars/starboard/aft + name = "Starboard Quarter Solar Maintenance" + icon_state = "SolarcontrolAS" + +/area/maintenance/solars/starboard/fore + name = "Starboard Bow Solar Maintenance" + icon_state = "SolarcontrolFS" + +/area/maintenance/solars/aux/port + name = "Port Auxiliary Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/solars/aux/port/aft + name = "Port Quarter Auxiliary Solar Maintenance" + icon_state = "SolarcontrolAP" + +/area/maintenance/solars/aux/port/fore + name = "Port Bow Auxiliary Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/solars/aux/starboard + name = "Starboard Auxiliary Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/solars/aux/starboard/aft + name = "Starboard Quarter Auxiliary Solar Maintenance" + icon_state = "SolarcontrolA" + +/area/maintenance/solars/aux/starboard/fore + name = "Starboard Bow Auxiliary Solar Maintenance" + icon_state = "SolarcontrolA" + +//Teleporter + +/area/teleporter + name = "Teleporter Room" + icon_state = "teleporter" + music = "signal" + ambientsounds = ENGINEERING + +/area/gateway + name = "Gateway" + icon_state = "gateway" + music = "signal" + ambientsounds = ENGINEERING + +//MedBay + +/area/medical + name = "Medical" + icon_state = "medbay3" + ambientsounds = MEDICAL + +/area/medical/abandoned + name = "Abandoned Medbay" + icon_state = "medbay3" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay/central + name = "Medbay Central" + icon_state = "medbay" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay/front_office + name = "Medbay Front Office" + icon_state = "medbay" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay/lobby + name = "Medbay Lobby" + icon_state = "medbay" + music = 'sound/ambience/signal.ogg' + + //Medbay is a large area, these additional areas help level out APC load. + +/area/medical/medbay/zone2 + name = "Medbay" + icon_state = "medbay2" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay/zone3 + name = "Medbay" + icon_state = "medbay3" + music = 'sound/ambience/signal.ogg' + +/area/medical/medbay/aft + name = "Medbay Aft" + icon_state = "medbay3" + music = 'sound/ambience/signal.ogg' + +/area/medical/storage + name = "Medbay Storage" + icon_state = "medbay2" + music = 'sound/ambience/signal.ogg' + +/area/medical/patients_rooms + name = "Patients' Rooms" + icon_state = "patients" + +/area/medical/patients_rooms/room_a + name = "Patient Room A" + icon_state = "patients" + +/area/medical/patients_rooms/room_b + name = "Patient Room B" + icon_state = "patients" + +/area/medical/virology + name = "Virology" + icon_state = "virology" + flags_1 = NONE + +/area/medical/morgue + name = "Morgue" + icon_state = "morgue" + ambientsounds = SPOOKY + +/area/medical/chemistry + name = "Chemistry" + icon_state = "chem" + +/area/medical/surgery + name = "Surgery" + icon_state = "surgery" + +/area/medical/cryo + name = "Cryogenics" + icon_state = "cryo" + +/area/medical/exam_room + name = "Exam Room" + icon_state = "exam_room" + +/area/medical/genetics + name = "Genetics Lab" + icon_state = "genetics" + +/area/medical/genetics/cloning + name = "Cloning Lab" + icon_state = "cloning" + +/area/medical/sleeper + name = "Medbay Treatment Center" + icon_state = "exam_room" + + +//Security + +/area/security + name = "Security" + icon_state = "security" + ambientsounds = HIGHSEC + +/area/security/main + name = "Security Office" + icon_state = "security" + +/area/security/brig + name = "Brig" + icon_state = "brig" + +/area/security/courtroom + name = "Courtroom" + icon_state = "courtroom" + +/area/security/prison + name = "Prison Wing" + icon_state = "sec_prison" + +/area/security/processing + name = "Labor Shuttle Dock" + icon_state = "sec_prison" + +/area/security/processing/cremation + name = "Security Crematorium" + icon_state = "sec_prison" + +/area/security/warden + name = "Brig Control" + icon_state = "Warden" + +/area/security/armory + name = "Armory" + icon_state = "armory" + +/area/security/detectives_office + name = "Detective's Office" + icon_state = "detective" + ambientsounds = list('sound/ambience/ambidet1.ogg','sound/ambience/ambidet2.ogg') + +/area/security/detectives_office/private_investigators_office + name = "Private Investigator's Office" + icon_state = "detective" + +/area/security/range + name = "Firing Range" + icon_state = "firingrange" + +/area/security/execution + icon_state = "execution_room" + +/area/security/execution/transfer + name = "Transfer Centre" + +/area/security/execution/education + name = "Prisoner Education Chamber" + +/area/security/nuke_storage + name = "Vault" + icon_state = "nuke_storage" + +/area/ai_monitored/nuke_storage + name = "Vault" + icon_state = "nuke_storage" + +/area/security/checkpoint + name = "Security Checkpoint" + icon_state = "checkpoint1" + +/area/security/checkpoint/auxiliary + icon_state = "checkpoint_aux" + +/area/security/checkpoint/tertiary + icon_state = "checkpoint_tert" + +/area/security/checkpoint/escape + icon_state = "checkpoint_esc" + +/area/security/checkpoint/supply + name = "Security Post - Cargo Bay" + icon_state = "checkpoint_supp" + +/area/security/checkpoint/engineering + name = "Security Post - Engineering" + icon_state = "checkpoint_engi" + +/area/security/checkpoint/medical + name = "Security Post - Medbay" + icon_state = "checkpoint_med" + +/area/security/checkpoint/science + name = "Security Post - Science" + icon_state = "checkpoint_sci" + +/area/security/checkpoint/science/research + name = "Security Post - Research Division" + icon_state = "checkpoint_res" + +/area/security/checkpoint/customs + name = "Customs" + icon_state = "customs_point" + +/area/security/checkpoint/customs/auxiliary + icon_state = "customs_point_aux" + +/area/security/vacantoffice + name = "Vacant Office" + icon_state = "security" + +/area/security/vacantoffice/a + name = "Vacant Office A" + icon_state = "security" + +/area/security/vacantoffice/b + name = "Vacant Office B" + icon_state = "security" + +/area/quartermaster + name = "Quartermasters" + icon_state = "quart" + +///////////WORK IN PROGRESS////////// + +/area/quartermaster/sorting + name = "Delivery Office" + icon_state = "cargo_delivery" + +/area/quartermaster/warehouse + name = "Warehouse" + icon_state = "cargo_warehouse" + +////////////WORK IN PROGRESS////////// + +/area/quartermaster/office + name = "Cargo Office" + icon_state = "quartoffice" + +/area/quartermaster/storage + name = "Cargo Bay" + icon_state = "cargo_bay" + +/area/quartermaster/qm + name = "Quartermaster's Office" + icon_state = "quart" + +/area/quartermaster/qm/private + name = "Quartermaster's Private Quarters" + icon_state = "quart" + +/area/quartermaster/miningdock + name = "Mining Dock" + icon_state = "mining" + +/area/quartermaster/miningdock/abandoned + name = "Abandoned Mining Dock" + icon_state = "mining" + +/area/quartermaster/miningoffice + name = "Mining Office" + icon_state = "mining" + +/area/quartermaster/miningstorage + name = "Mining Storage" + icon_state = "mining" + +/area/janitor + name = "Custodial Closet" + icon_state = "janitor" + flags_1 = NONE + +/area/hydroponics + name = "Hydroponics" + icon_state = "hydro" + +/area/hydroponics/garden + name = "Garden" + icon_state = "garden" + +/area/hydroponics/garden/abandoned + name = "Abandoned Garden" + icon_state = "abandoned_garden" + +/area/hydroponics/garden/monastery + name = "Monastery Garden" + icon_state = "hydro" + + +//Science + +/area/science + name = "Science Division" + icon_state = "toxlab" + +/area/science/lab + name = "Research and Development" + icon_state = "toxlab" + +/area/science/xenobiology + name = "Xenobiology Lab" + icon_state = "toxlab" + +/area/science/storage + name = "Toxins Storage" + icon_state = "toxstorage" + +/area/science/mineral_storeroom + name = "Mineral Storeroom" + icon_state = "toxmisc" + +/area/science/test_area + valid_territory = FALSE + name = "Toxins Test Area" + icon_state = "toxtest" + +/area/science/mixing + name = "Toxins Mixing Lab" + icon_state = "toxmix" + +/area/science/mixing/chamber + name = "Toxins Mixing Chamber" + icon_state = "toxmix" + valid_territory = FALSE + +/area/science/misc_lab + name = "Testing Lab" + icon_state = "toxmisc" + +/area/science/misc_lab/range + name = "Research Testing Range" + icon_state = "toxmisc" + +/area/science/server + name = "Research Division Server Room" + icon_state = "server" + +/area/science/explab + name = "Experimentation Lab" + icon_state = "toxmisc" + +/area/science/robotics + name = "Robotics" + icon_state = "medresearch" + +/area/science/robotics/mechbay + name = "Mech Bay" + icon_state = "mechbay" + +/area/science/robotics/mechbay_cargo + name = "Mech Bay" + icon_state = "yellow" + +/area/science/robotics/showroom + name = "Robotics Showroom" + icon_state = "showroom" + +/area/science/robotics/lab + name = "Robotics Lab" + icon_state = "ass_line" + +/area/science/research + name = "Research Division" + icon_state = "medresearch" + +/area/science/circuit + name = "Circuitry Lab" + icon_state = "cir_lab" + +/area/science/research/lobby + name = "Research Division Lobby" + icon_state = "medresearch" + +/area/science/research/abandoned + name = "Abandoned Research Lab" + icon_state = "medresearch" + +/area/science/nanite + name = "Nanite Lab" + icon_state = "toxmisc" + +//Storage + +/area/storage/tools + name = "Auxiliary Tool Storage" + icon_state = "storage" + +/area/storage/primary + name = "Primary Tool Storage" + icon_state = "primarystorage" + +/area/storage/autolathe + name = "Autolathe Storage" + icon_state = "storage" + +/area/storage/art + name = "Art Supply Storage" + icon_state = "storage" + +/area/storage/auxiliary + name = "Auxiliary Storage" + icon_state = "auxstorage" + +/area/storage/atmos + name = "Atmospherics Storage" + icon_state = "atmos" + valid_territory = FALSE + +/area/storage/tcom + name = "Telecomms Storage" + icon_state = "green" + valid_territory = FALSE + +/area/storage/eva + name = "EVA Storage" + icon_state = "eva" + clockwork_warp_allowed = FALSE + +/area/storage/secure + name = "Secure Storage" + icon_state = "storage" + clockwork_warp_allowed = FALSE + +/area/storage/emergency/starboard + name = "Starboard Emergency Storage" + icon_state = "emergencystorage" + +/area/storage/emergency/port + name = "Port Emergency Storage" + icon_state = "emergencystorage" + +/area/storage/tech + name = "Technical Storage" + icon_state = "auxstorage" + +/area/storage/testroom + requires_power = FALSE + name = "Test Room" + icon_state = "storage" + + +//Construction + +/area/construction + name = "Construction Area" + icon_state = "yellow" + ambientsounds = ENGINEERING + +/area/construction/minisat_exterior + name = "Minisat Exterior" + icon_state = "yellow" + +/area/construction/mining/aux_base + name = "Auxiliary Base Construction" + icon_state = "yellow" + +/area/construction/mining/aux_base/closet + name = "Auxiliary Closet Construction" + icon_state = "yellow" + +/area/construction/supplyshuttle + name = "Supply Shuttle" + icon_state = "yellow" + +/area/construction/quarters + name = "Engineers' Quarters" + icon_state = "yellow" + +/area/construction/qmaint + name = "Maintenance" + icon_state = "yellow" + +/area/construction/hallway + name = "Hallway" + icon_state = "yellow" + +/area/construction/solars + name = "Solar Panels" + icon_state = "yellow" + +/area/construction/solarscontrol + name = "Solar Panel Control" + icon_state = "yellow" + +/area/construction/storage + name = "Construction Site Storage" + icon_state = "yellow" + +/area/construction/storage/wing + name = "Storage Wing" + icon_state = "storage_wing" + + +//AI + +/area/ai_monitored/security/armory + name = "Armory" + icon_state = "armory" + ambientsounds = HIGHSEC + +/area/ai_monitored/storage/eva + name = "EVA Storage" + icon_state = "eva" + ambientsounds = HIGHSEC + +/area/ai_monitored/storage/satellite + name = "AI Satellite Maint" + icon_state = "storage" + ambientsounds = HIGHSEC + + //Turret_protected + +/area/ai_monitored/turret_protected + ambientsounds = list('sound/ambience/ambimalf.ogg', 'sound/ambience/ambitech.ogg', 'sound/ambience/ambitech2.ogg', 'sound/ambience/ambiatmos.ogg', 'sound/ambience/ambiatmos2.ogg') + +/area/ai_monitored/turret_protected/ai_upload + name = "AI Upload Chamber" + icon_state = "ai_upload" + +/area/ai_monitored/turret_protected/ai_upload_foyer + name = "AI Upload Access" + icon_state = "ai_foyer" + +/area/ai_monitored/turret_protected/ai + name = "AI Chamber" + icon_state = "ai_chamber" + +/area/ai_monitored/turret_protected/aisat + name = "AI Satellite" + icon_state = "ai" + +/area/ai_monitored/turret_protected/aisat/atmos + name = "AI Satellite Atmos" + icon_state = "ai" + +/area/ai_monitored/turret_protected/aisat/foyer + name = "AI Satellite Foyer" + icon_state = "ai" + +/area/ai_monitored/turret_protected/aisat/service + name = "AI Satellite Service" + icon_state = "ai" + +/area/ai_monitored/turret_protected/aisat/hallway + name = "AI Satellite Hallway" + icon_state = "ai" + +/area/aisat + name = "AI Satellite Exterior" + icon_state = "yellow" + +/area/ai_monitored/turret_protected/aisat_interior + name = "AI Satellite Antechamber" + icon_state = "ai" + +/area/ai_monitored/turret_protected/AIsatextFP + name = "AI Sat Ext" + icon_state = "storage" + +/area/ai_monitored/turret_protected/AIsatextFS + name = "AI Sat Ext" + icon_state = "storage" + +/area/ai_monitored/turret_protected/AIsatextAS + name = "AI Sat Ext" + icon_state = "storage" + +/area/ai_monitored/turret_protected/AIsatextAP + name = "AI Sat Ext" + icon_state = "storage" + + +// Telecommunications Satellite + +/area/tcommsat + clockwork_warp_allowed = FALSE + clockwork_warp_fail = "For safety reasons, warping here is disallowed; the radio and bluespace noise could cause catastrophic results." + 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/entrance + name = "Telecomms Teleporter" + icon_state = "tcomsatentrance" + +/area/tcommsat/chamber + name = "Abandoned Satellite" + icon_state = "tcomsatcham" + +/area/ai_monitored/turret_protected/tcomsat + name = "Telecomms Satellite" + icon_state = "tcomsatlob" + +/area/ai_monitored/turret_protected/tcomfoyer + name = "Telecomms Foyer" + icon_state = "tcomsatentrance" + +/area/ai_monitored/turret_protected/tcomwest + name = "Telecommunications Satellite West Wing" + icon_state = "tcomsatwest" + +/area/ai_monitored/turret_protected/tcomeast + name = "Telecommunications Satellite East Wing" + icon_state = "tcomsateast" + +/area/tcommsat/computer + name = "Telecomms Control Room" + icon_state = "tcomsatcomp" + +/area/tcommsat/server + name = "Telecomms Server Room" + icon_state = "tcomsatcham" + +/area/tcommsat/lounge + name = "Telecommunications Satellite Lounge" + icon_state = "tcomsatlounge" diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm index 9d42b67bf9..87b44291f5 100644 --- a/code/game/area/ai_monitored.dm +++ b/code/game/area/ai_monitored.dm @@ -1,31 +1,31 @@ -/area/ai_monitored - name = "AI Monitored Area" - clockwork_warp_allowed = FALSE - var/list/obj/machinery/camera/motioncameras = list() - var/list/datum/weakref/motionTargets = list() - -/area/ai_monitored/Initialize(mapload) - . = ..() - if(mapload) - for (var/obj/machinery/camera/M in src) - if(M.isMotion()) - motioncameras.Add(M) - M.area_motion = src - -//Only need to use one camera - -/area/ai_monitored/Entered(atom/movable/O) - ..() - if (ismob(O) && motioncameras.len) - for(var/X in motioncameras) - var/obj/machinery/camera/cam = X - cam.newTarget(O) - return - -/area/ai_monitored/Exited(atom/movable/O) - ..() - if (ismob(O) && motioncameras.len) - for(var/X in motioncameras) - var/obj/machinery/camera/cam = X - cam.lostTargetRef(WEAKREF(O)) +/area/ai_monitored + name = "AI Monitored Area" + clockwork_warp_allowed = FALSE + var/list/obj/machinery/camera/motioncameras = list() + var/list/datum/weakref/motionTargets = list() + +/area/ai_monitored/Initialize(mapload) + . = ..() + if(mapload) + for (var/obj/machinery/camera/M in src) + if(M.isMotion()) + motioncameras.Add(M) + M.area_motion = src + +//Only need to use one camera + +/area/ai_monitored/Entered(atom/movable/O) + ..() + if (ismob(O) && motioncameras.len) + for(var/X in motioncameras) + var/obj/machinery/camera/cam = X + cam.newTarget(O) + return + +/area/ai_monitored/Exited(atom/movable/O) + ..() + if (ismob(O) && motioncameras.len) + for(var/X in motioncameras) + var/obj/machinery/camera/cam = X + cam.lostTargetRef(WEAKREF(O)) return \ No newline at end of file diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 36b701aae1..9a6d992991 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,866 +1,866 @@ -/atom - layer = TURF_LAYER - plane = GAME_PLANE - var/level = 2 - var/article // If non-null, overrides a/an/some in all cases - - var/flags_1 = NONE - var/interaction_flags_atom = NONE - var/datum/reagents/reagents = null - - //This atom's HUD (med/sec, etc) images. Associative list. - var/list/image/hud_list = null - //HUD images that this atom can provide. - var/list/hud_possible - - //Value used to increment ex_act() if reactionary_explosions is on - var/explosion_block = 0 - - var/list/atom_colours //used to store the different colors on an atom - //its inherent color, the colored paint applied on it, special color effect etc... - - var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. - var/list/remove_overlays // a very temporary list of overlays to remove - var/list/add_overlays // a very temporary list of overlays to add - - var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays - ///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc - var/list/managed_overlays - - var/datum/proximity_monitor/proximity_monitor - var/buckle_message_cooldown = 0 - var/fingerprintslast - - var/list/filter_data //For handling persistent filters - - var/datum/component/orbiter/orbiters - - var/rad_flags = NONE // Will move to flags_1 when i can be arsed to - var/rad_insulation = RAD_NO_INSULATION - - var/icon/blood_splatter_icon - var/list/fingerprints - var/list/fingerprintshidden - var/list/blood_DNA - var/list/suit_fibers - -/atom/New(loc, ...) - //atom creation method that preloads variables at creation - if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() - world.preloader_load(src) - - if(datum_flags & DF_USE_TAG) - GenerateTag() - - var/do_initialize = SSatoms.initialized - if(do_initialize != INITIALIZATION_INSSATOMS) - args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD - if(SSatoms.InitAtom(src, args)) - //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 -//must not sleep -//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE -//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm - -//Note: the following functions don't call the base for optimization and must copypasta: -// /turf/Initialize -// /turf/open/space/Initialize - -/atom/proc/Initialize(mapload, ...) - if(flags_1 & INITIALIZED_1) - stack_trace("Warning: [src]([type]) initialized multiple times!") - flags_1 |= INITIALIZED_1 - - //atom color stuff - if(color) - add_atom_colour(color, FIXED_COLOUR_PRIORITY) - - if (light_power && light_range) - update_light() - - if (opacity && isturf(loc)) - var/turf/T = loc - T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. - - if (canSmoothWith) - canSmoothWith = typelist("canSmoothWith", canSmoothWith) - - ComponentInitialize() - - return INITIALIZE_HINT_NORMAL - -//called if Initialize returns INITIALIZE_HINT_LATELOAD -/atom/proc/LateInitialize() - return - -// Put your AddComponent() calls here -/atom/proc/ComponentInitialize() - return - -/atom/Destroy() - if(alternate_appearances) - for(var/K in alternate_appearances) - var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K] - AA.remove_from_hud(src) - - if(reagents) - qdel(reagents) - - LAZYCLEARLIST(overlays) - LAZYCLEARLIST(priority_overlays) - - QDEL_NULL(light) - - return ..() - -/atom/proc/handle_ricochet(obj/item/projectile/P) - return - -/atom/proc/CanPass(atom/movable/mover, turf/target) - return !density - -/atom/proc/onCentCom() - var/turf/T = get_turf(src) - if(!T) - return FALSE - - if(is_reserved_level(T.z)) - for(var/A in SSshuttle.mobile) - var/obj/docking_port/mobile/M = A - if(M.launch_status == ENDGAME_TRANSIT) - for(var/place in M.shuttle_areas) - var/area/shuttle/shuttle_area = place - if(T in shuttle_area) - return TRUE - - if(!is_centcom_level(T.z))//if not, don't bother - return FALSE - - //Check for centcom itself - if(istype(T.loc, /area/centcom)) - return TRUE - - //Check for centcom shuttles - for(var/A in SSshuttle.mobile) - var/obj/docking_port/mobile/M = A - if(M.launch_status == ENDGAME_LAUNCHED) - for(var/place in M.shuttle_areas) - var/area/shuttle/shuttle_area = place - if(T in shuttle_area) - return TRUE - -/atom/proc/onSyndieBase() - var/turf/T = get_turf(src) - if(!T) - return FALSE - - if(!is_centcom_level(T.z))//if not, don't bother - return FALSE - - if(istype(T.loc, /area/shuttle/syndicate) || istype(T.loc, /area/syndicate_mothership) || istype(T.loc, /area/shuttle/assault_pod)) - return TRUE - - return FALSE - -/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) - SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) - if(does_attack_animation) - user.changeNext_move(CLICK_CD_MELEE) - log_combat(user, src, "punched", "hulk powers") - user.do_attack_animation(src, ATTACK_EFFECT_SMASH) - -/atom/proc/CheckParts(list/parts_list) - for(var/A in parts_list) - if(istype(A, /datum/reagent)) - if(!reagents) - reagents = new() - reagents.reagent_list.Add(A) - reagents.conditional_update() - else if(ismovableatom(A)) - var/atom/movable/M = A - if(isliving(M.loc)) - var/mob/living/L = M.loc - L.transferItemToLoc(M, src) - else - M.forceMove(src) - -//common name -/atom/proc/update_multiz(prune_on_fail = FALSE) - return FALSE - -/atom/proc/assume_air(datum/gas_mixture/giver) - qdel(giver) - return null - -/atom/proc/remove_air(amount) - return null - -/atom/proc/return_air() - if(loc) - return loc.return_air() - else - return null - -/atom/proc/check_eye(mob/user) - return - -/atom/proc/Bumped(atom/movable/AM) - set waitfor = FALSE - -// Convenience procs to see if a container is open for chemistry handling -/atom/proc/is_open_container() - return is_refillable() && is_drainable() - -/atom/proc/is_injectable(allowmobs = TRUE) - return reagents && (reagents.reagents_holder_flags & (INJECTABLE | REFILLABLE)) - -/atom/proc/is_drawable(allowmobs = TRUE) - return reagents && (reagents.reagents_holder_flags & (DRAWABLE | DRAINABLE)) - -/atom/proc/is_refillable() - return reagents && (reagents.reagents_holder_flags & REFILLABLE) - -/atom/proc/is_drainable() - return reagents && (reagents.reagents_holder_flags & DRAINABLE) - - -/atom/proc/AllowDrop() - return FALSE - -/atom/proc/CheckExit() - return TRUE - -/atom/proc/HasProximity(atom/movable/AM as mob|obj) - return - -/atom/proc/emp_act(severity) - var/protection = SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity) - if(!(protection & EMP_PROTECT_WIRES) && istype(wires)) - wires.emp_pulse() - return protection // Pass the protection value collected here upwards - -/atom/proc/bullet_act(obj/item/projectile/P, def_zone) - SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone) - . = P.on_hit(src, 0, def_zone) - -//used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it. -// IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first. -/atom/proc/shove_act(mob/living/target, mob/living/user) - return FALSE - -/atom/proc/in_contents_of(container)//can take class or object instance as argument - if(ispath(container)) - if(istype(src.loc, container)) - return TRUE - else if(src in container) - return TRUE - return FALSE - -/atom/proc/get_examine_name(mob/user) - . = "\a [src]" - var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") - if(article) - . = "[article] [src]" - override[EXAMINE_POSITION_ARTICLE] = article - - var/should_override = FALSE - - if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) - should_override = TRUE - - - if(blood_DNA && !istype(src, /obj/effect/decal)) - override[EXAMINE_POSITION_BEFORE] = " blood-stained " - should_override = TRUE - - if(should_override) - . = override.Join("") - -///Generate the full examine string of this atom (including icon for goonchat) -/atom/proc/get_examine_string(mob/user, thats = FALSE) - return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]" - -/atom/proc/examine(mob/user) - . = list("[get_examine_string(user, TRUE)].") - - if(desc) - . += desc - - if(reagents) - if(reagents.reagents_holder_flags & TRANSPARENT) - . += "It contains:" - if(length(reagents.reagent_list)) - if(user.can_see_reagents()) //Show each individual reagent - for(var/datum/reagent/R in reagents.reagent_list) - . += "[R.volume] units of [R.name]" - else //Otherwise, just show the total volume - var/total_volume = 0 - for(var/datum/reagent/R in reagents.reagent_list) - total_volume += R.volume - . += "[total_volume] units of various reagents" - else - . += "Nothing." - else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE) - if(reagents.total_volume) - . += "It has [reagents.total_volume] unit\s left." - else - . += "It's empty." - - SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) - -/// Updates the icon of the atom -/atom/proc/update_icon() - // I expect we're going to need more return flags and options in this proc - var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON) - - if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE)) - update_icon_state() - - if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS)) - var/list/new_overlays = update_overlays() - if(managed_overlays) - cut_overlay(managed_overlays) - managed_overlays = null - if(length(new_overlays)) - managed_overlays = new_overlays - add_overlay(new_overlays) - -/// Updates the icon state of the atom -/atom/proc/update_icon_state() - -/// Updates the overlays of the atom -/atom/proc/update_overlays() - SHOULD_CALL_PARENT(1) - . = list() - SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) - -/atom/proc/relaymove(mob/user) - if(buckle_message_cooldown <= world.time) - buckle_message_cooldown = world.time + 50 - to_chat(user, "You can't move while buckled to [src]!") - return - -/atom/proc/contents_explosion(severity, target) - return //For handling the effects of explosions on contents that would not normally be effected - -/atom/proc/ex_act(severity, target) - set waitfor = FALSE - contents_explosion(severity, target) - SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target) - -/atom/proc/blob_act(obj/structure/blob/B) - SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B) - return - -/atom/proc/fire_act(exposed_temperature, exposed_volume) - SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) - return - -/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) - if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). - addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) - -/atom/proc/hitby_react(atom/movable/AM) - if(AM && isturf(AM.loc)) - step(AM, turn(AM.dir, 180)) - -/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube) - return - -//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list -/mob/living/proc/get_blood_dna_list() - var/blood_id = get_blood_id() - if(!(blood_id =="blood" || blood_id == "jellyblood")) - return - return list("ANIMAL DNA" = "Y-") - -/mob/living/carbon/get_blood_dna_list() - var/blood_id = get_blood_id() - if(!(blood_id =="blood" || blood_id == "jellyblood")) - return - var/list/blood_dna = list() - if(dna) - blood_dna[dna.unique_enzymes] = dna.blood_type - else - blood_dna["UNKNOWN DNA"] = "X*" - return blood_dna - -/mob/living/carbon/alien/get_blood_dna_list() - return list("UNKNOWN DNA" = "X*") - -//to add a mob's dna info into an object's blood_DNA list. -/atom/proc/transfer_mob_blood_dna(mob/living/L) - // Returns 0 if we have that blood already - var/new_blood_dna = L.get_blood_dna_list() - if(!new_blood_dna) - return FALSE - LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it. - var/old_length = blood_DNA.len - blood_DNA |= new_blood_dna - if(blood_DNA.len == old_length) - return FALSE - return TRUE - -//to add blood dna info to the object's blood_DNA list -/atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases) - LAZYINITLIST(blood_DNA) - var/old_length = blood_DNA.len - blood_DNA |= blood_dna - if(blood_DNA.len > old_length) - 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 FALSE - return add_blood_DNA(blood_dna, M.diseases) - -//to add blood onto something, with blood dna info to include. -/atom/proc/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - return FALSE - -/obj/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - return transfer_blood_dna(blood_dna, diseases) - -/obj/item/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - . = ..() - if(!.) - return - add_blood_overlay() - -/obj/item/proc/add_blood_overlay() - if(!blood_DNA.len) - return - if(initial(icon) && initial(icon_state)) - blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object - blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) - blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant - blood_splatter_icon.Blend(blood_DNA_to_color(), ICON_MULTIPLY) - add_overlay(blood_splatter_icon) - -/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - . = ..() - transfer_blood = rand(2, 4) - -/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src - if(!B) - B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) - B.transfer_blood_dna(blood_dna, diseases) //give blood info to the blood decal. - return TRUE //we bloodied the floor - -/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - if(head) - head.add_blood_DNA(blood_dna, diseases) - update_inv_head() - else if(wear_mask) - wear_mask.add_blood_DNA(blood_dna, diseases) - update_inv_wear_mask() - if(wear_neck) - wear_neck.add_blood_DNA(blood_dna, diseases) - update_inv_neck() - if(wear_suit) - wear_suit.add_blood_DNA(blood_dna, diseases) - update_inv_wear_suit() - else if(w_uniform) - w_uniform.add_blood_DNA(blood_dna, diseases) - update_inv_w_uniform() - if(gloves) - var/obj/item/clothing/gloves/G = gloves - G.add_blood_DNA(blood_dna, diseases) - else - transfer_blood_dna(blood_dna, diseases) - bloody_hands = rand(2, 4) - update_inv_gloves() //handles bloody hands overlays and updating - return TRUE - -/atom/proc/blood_DNA_to_color() - var/list/colors = list()//first we make a list of all bloodtypes present - for(var/bloop in blood_DNA) - if(colors[blood_DNA[bloop]]) - colors[blood_DNA[bloop]]++ - else - colors[blood_DNA[bloop]] = 1 - - var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up - - if(colors.len) - var/sum = 0 //this is all shitcode, but it works; trust me - final_rgb = bloodtype_to_color(colors[1]) - sum = colors[colors[1]] - if(colors.len > 1) - var/i = 2 - while(i <= colors.len) - var/tmp = colors[colors[i]] - final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum)) - sum += tmp - i++ - - return final_rgb - -/atom/proc/clean_blood() - if(islist(blood_DNA)) - blood_DNA = null - return TRUE - -/atom/proc/wash_cream() - return TRUE - -/atom/proc/isinspace() - if(isspaceturf(get_turf(src))) - return TRUE - else - return FALSE - -/atom/proc/handle_fall() - return - -/atom/proc/singularity_act() - return - -/atom/proc/singularity_pull(obj/singularity/S, current_size) - SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, S, current_size) - -/atom/proc/acid_act(acidpwr, acid_volume) - SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) - -/atom/proc/emag_act() - return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) - -/atom/proc/rad_act(strength) - SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength) - -/atom/proc/narsie_act() - SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT) - -/atom/proc/ratvar_act() - SEND_SIGNAL(src, COMSIG_ATOM_RATVAR_ACT) - -/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - return FALSE - -/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) - SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode) - return FALSE - -/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user) - if(GetComponent(/datum/component/storage)) - return component_storage_contents_dump_act(src_object, user) - return FALSE - -/atom/proc/component_storage_contents_dump_act(datum/component/storage/src_object, mob/user) - var/list/things = src_object.contents() - var/datum/progressbar/progress = new(user, things.len, src) - var/datum/component/storage/STR = GetComponent(/datum/component/storage) - while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(STR, /datum/component/storage.proc/handle_mass_item_insertion, things, src_object, user, progress))) - stoplag(1) - qdel(progress) - to_chat(user, "You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.") - STR.orient2hud(user) - src_object.orient2hud(user) - if(user.active_storage) //refresh the HUD to show the transfered contents - user.active_storage.close(user) - user.active_storage.show_to(user) - return TRUE - -/atom/proc/get_dumping_location(obj/item/storage/source,mob/user) - return null - -//This proc is called on the location of an atom when the atom is Destroy()'d -/atom/proc/handle_atom_del(atom/A) - SEND_SIGNAL(src, COMSIG_ATOM_CONTENTS_DEL, A) - -//called when the turf the atom resides on is ChangeTurfed -/atom/proc/HandleTurfChange(turf/T) - for(var/a in src) - var/atom/A = a - A.HandleTurfChange(T) - -//the vision impairment to give to the mob whose perspective is set to that atom (e.g. an unfocused camera giving you an impaired vision when looking through it) -/atom/proc/get_remote_view_fullscreens(mob/user) - return - -//the sight changes to give to the mob whose perspective is set to that atom (e.g. A mob with nightvision loses its nightvision while looking through a normal camera) -/atom/proc/update_remote_sight(mob/living/user) - return - - -//Hook for running code when a dir change occurs -/atom/proc/setDir(newdir, ismousemovement=FALSE) - SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) - dir = newdir - -/atom/proc/mech_melee_attack(obj/mecha/M) - return - -//If a mob logouts/logins in side of an object you can use this proc -/atom/proc/on_log(login) - if(loc) - loc.on_log(login) - - -/* - Atom Colour Priority System - A System that gives finer control over which atom colour to colour the atom with. - The "highest priority" one is always displayed as opposed to the default of - "whichever was set last is displayed" -*/ - - -/* - Adds an instance of colour_type to the atom's atom_colours list -*/ -/atom/proc/add_atom_colour(coloration, colour_priority) - if(!atom_colours || !atom_colours.len) - atom_colours = list() - atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. - if(!coloration) - return - if(colour_priority > atom_colours.len) - return - atom_colours[colour_priority] = coloration - update_atom_colour() - - -/* - Removes an instance of colour_type from the atom's atom_colours list -*/ -/atom/proc/remove_atom_colour(colour_priority, coloration) - if(!atom_colours) - atom_colours = list() - atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. - if(colour_priority > atom_colours.len) - return - if(coloration && atom_colours[colour_priority] != coloration) - return //if we don't have the expected color (for a specific priority) to remove, do nothing - 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 -*/ -/atom/proc/update_atom_colour() - if(!atom_colours) - atom_colours = list() - atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. - color = null - for(var/C in atom_colours) - if(islist(C)) - var/list/L = C - if(L.len) - color = L - return - else if(C) - color = C - return - -/atom/vv_edit_var(var_name, var_value) - if(!GLOB.Debug2) - flags_1 |= ADMIN_SPAWNED_1 - . = ..() - switch(var_name) - if("color") - add_atom_colour(color, ADMIN_COLOUR_PRIORITY) - -/atom/vv_get_dropdown() - . = ..() - . += "---" - var/turf/curturf = get_turf(src) - if (curturf) - .["Jump to"] = "?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]" - .["Modify Transform"] = "?_src_=vars;[HrefToken()];modtransform=[REF(src)]" - .["Add reagent"] = "?_src_=vars;[HrefToken()];addreagent=[REF(src)]" - .["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]" - .["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]" - -/atom/proc/drop_location() - var/atom/L = loc - if(!L) - return null - return L.AllowDrop() ? L : L.drop_location() - -/atom/Entered(atom/movable/AM, atom/oldLoc) - SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc) - -/atom/Exit(atom/movable/AM, atom/newLoc) - . = ..() - if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT) - return FALSE - -/atom/Exited(atom/movable/AM, atom/newLoc) - SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc) - -/atom/proc/return_temperature() - return - -// Tool behavior procedure. Redirects to tool-specific procs by default. -// You can override it to catch all tool interactions, for use in complex deconstruction procs. -// Just don't forget to return ..() in the end. -/atom/proc/tool_act(mob/living/user, obj/item/I, tool_type) - switch(tool_type) - if(TOOL_CROWBAR) - return crowbar_act(user, I) - if(TOOL_MULTITOOL) - return multitool_act(user, I) - if(TOOL_SCREWDRIVER) - return screwdriver_act(user, I) - if(TOOL_WRENCH) - return wrench_act(user, I) - if(TOOL_WIRECUTTER) - return wirecutter_act(user, I) - if(TOOL_WELDER) - return welder_act(user, I) - if(TOOL_ANALYZER) - return analyzer_act(user, I) - -// Tool-specific behavior procs. To be overridden in subtypes. -/atom/proc/crowbar_act(mob/living/user, obj/item/I) - return - -/atom/proc/multitool_act(mob/living/user, obj/item/I) - return - -/atom/proc/screwdriver_act(mob/living/user, obj/item/I) - SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) - -/atom/proc/wrench_act(mob/living/user, obj/item/I) - return - -/atom/proc/wirecutter_act(mob/living/user, obj/item/I) - return - -/atom/proc/welder_act(mob/living/user, obj/item/I) - return - -/atom/proc/analyzer_act(mob/living/user, obj/item/I) - return - -/atom/proc/GenerateTag() - return - -// Generic logging helper -/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE) - if(!log_globally) - return - - var/log_text = "[key_name(src)] [message] [loc_name(src)]" - switch(message_type) - if(LOG_ATTACK) - log_attack(log_text) - if(LOG_SAY) - log_say(log_text) - if(LOG_WHISPER) - log_whisper(log_text) - if(LOG_EMOTE) - log_emote(log_text) - if(LOG_DSAY) - log_dsay(log_text) - if(LOG_PDA) - log_pda(log_text) - if(LOG_CHAT) - log_chat(log_text) - if(LOG_COMMENT) - log_comment(log_text) - if(LOG_TELECOMMS) - log_telecomms(log_text) - if(LOG_OOC) - log_ooc(log_text) - if(LOG_ADMIN) - log_admin(log_text) - if(LOG_ADMIN_PRIVATE) - log_admin_private(log_text) - if(LOG_ASAY) - log_adminsay(log_text) - if(LOG_OWNERSHIP) - log_game(log_text) - if(LOG_GAME) - log_game(log_text) - else - stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).") - log_game(log_text) - -// Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements) -/atom/proc/log_talk(message, message_type, tag=null, log_globally=TRUE, forced_by=null) - var/prefix = tag ? "([tag]) " : "" - var/suffix = forced_by ? " FORCED by [forced_by]" : "" - log_message("[prefix]\"[message]\"[suffix]", message_type, log_globally=log_globally) - -// Helper for logging of messages with only one sender and receiver -/proc/log_directed_talk(atom/source, atom/target, message, message_type, tag) - if(!tag) - stack_trace("Unspecified tag for private message") - tag = "UNKNOWN" - - source.log_talk(message, message_type, tag="[tag] to [key_name(target)]") - if(source != target) - target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) - -/* -Proc for attack log creation, because really why not -1 argument is the actor performing the action -2 argument is the target of the action -3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) -4 is a tool with which the action was made (usually an item) -5 is any additional text, which will be appended to the rest of the log line -*/ - -/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) - var/ssource = key_name(user) - var/starget = key_name(target) - - var/mob/living/living_target = target - var/hp = istype(living_target) ? " (NEWHP: [living_target.health]) " : "" - - var/sobject = "" - if(object) - sobject = " with [key_name(object)]" - var/saddition = "" - if(addition) - saddition = " [addition]" - - var/postfix = "[sobject][saddition][hp]" - - var/message = "has [what_done] [starget][postfix]" - user.log_message(message, LOG_ATTACK, color="red") - - if(user != target) - var/reverse_message = "has been [what_done] by [ssource][postfix]" - target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) - -// Filter stuff -/atom/movable/proc/add_filter(name,priority,list/params) - LAZYINITLIST(filter_data) - var/list/p = params.Copy() - p["priority"] = priority - filter_data[name] = p - update_filters() - -/atom/movable/proc/update_filters() - filters = null - filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE) - for(var/f in filter_data) - var/list/data = filter_data[f] - var/list/arguments = data.Copy() - arguments -= "priority" - filters += filter(arglist(arguments)) - -/atom/movable/proc/get_filter(name) - if(filter_data && filter_data[name]) - return filters[filter_data.Find(name)] - -/atom/movable/proc/remove_filter(name) - if(filter_data && filter_data[name]) - filter_data -= name - update_filters() - return TRUE - -/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1) +/atom + layer = TURF_LAYER + plane = GAME_PLANE + var/level = 2 + var/article // If non-null, overrides a/an/some in all cases + + var/flags_1 = NONE + var/interaction_flags_atom = NONE + var/datum/reagents/reagents = null + + //This atom's HUD (med/sec, etc) images. Associative list. + var/list/image/hud_list = null + //HUD images that this atom can provide. + var/list/hud_possible + + //Value used to increment ex_act() if reactionary_explosions is on + var/explosion_block = 0 + + var/list/atom_colours //used to store the different colors on an atom + //its inherent color, the colored paint applied on it, special color effect etc... + + var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. + var/list/remove_overlays // a very temporary list of overlays to remove + var/list/add_overlays // a very temporary list of overlays to add + + var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays + ///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc + var/list/managed_overlays + + var/datum/proximity_monitor/proximity_monitor + var/buckle_message_cooldown = 0 + var/fingerprintslast + + var/list/filter_data //For handling persistent filters + + var/datum/component/orbiter/orbiters + + var/rad_flags = NONE // Will move to flags_1 when i can be arsed to + var/rad_insulation = RAD_NO_INSULATION + + var/icon/blood_splatter_icon + var/list/fingerprints + var/list/fingerprintshidden + var/list/blood_DNA + var/list/suit_fibers + +/atom/New(loc, ...) + //atom creation method that preloads variables at creation + if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() + world.preloader_load(src) + + if(datum_flags & DF_USE_TAG) + GenerateTag() + + var/do_initialize = SSatoms.initialized + if(do_initialize != INITIALIZATION_INSSATOMS) + args[1] = do_initialize == INITIALIZATION_INNEW_MAPLOAD + if(SSatoms.InitAtom(src, args)) + //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 +//must not sleep +//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE +//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm + +//Note: the following functions don't call the base for optimization and must copypasta: +// /turf/Initialize +// /turf/open/space/Initialize + +/atom/proc/Initialize(mapload, ...) + if(flags_1 & INITIALIZED_1) + stack_trace("Warning: [src]([type]) initialized multiple times!") + flags_1 |= INITIALIZED_1 + + //atom color stuff + if(color) + add_atom_colour(color, FIXED_COLOUR_PRIORITY) + + if (light_power && light_range) + update_light() + + if (opacity && isturf(loc)) + var/turf/T = loc + T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. + + if (canSmoothWith) + canSmoothWith = typelist("canSmoothWith", canSmoothWith) + + ComponentInitialize() + + return INITIALIZE_HINT_NORMAL + +//called if Initialize returns INITIALIZE_HINT_LATELOAD +/atom/proc/LateInitialize() + return + +// Put your AddComponent() calls here +/atom/proc/ComponentInitialize() + return + +/atom/Destroy() + if(alternate_appearances) + for(var/K in alternate_appearances) + var/datum/atom_hud/alternate_appearance/AA = alternate_appearances[K] + AA.remove_from_hud(src) + + if(reagents) + qdel(reagents) + + LAZYCLEARLIST(overlays) + LAZYCLEARLIST(priority_overlays) + + QDEL_NULL(light) + + return ..() + +/atom/proc/handle_ricochet(obj/item/projectile/P) + return + +/atom/proc/CanPass(atom/movable/mover, turf/target) + return !density + +/atom/proc/onCentCom() + var/turf/T = get_turf(src) + if(!T) + return FALSE + + if(is_reserved_level(T.z)) + for(var/A in SSshuttle.mobile) + var/obj/docking_port/mobile/M = A + if(M.launch_status == ENDGAME_TRANSIT) + for(var/place in M.shuttle_areas) + var/area/shuttle/shuttle_area = place + if(T in shuttle_area) + return TRUE + + if(!is_centcom_level(T.z))//if not, don't bother + return FALSE + + //Check for centcom itself + if(istype(T.loc, /area/centcom)) + return TRUE + + //Check for centcom shuttles + for(var/A in SSshuttle.mobile) + var/obj/docking_port/mobile/M = A + if(M.launch_status == ENDGAME_LAUNCHED) + for(var/place in M.shuttle_areas) + var/area/shuttle/shuttle_area = place + if(T in shuttle_area) + return TRUE + +/atom/proc/onSyndieBase() + var/turf/T = get_turf(src) + if(!T) + return FALSE + + if(!is_centcom_level(T.z))//if not, don't bother + return FALSE + + if(istype(T.loc, /area/shuttle/syndicate) || istype(T.loc, /area/syndicate_mothership) || istype(T.loc, /area/shuttle/assault_pod)) + return TRUE + + return FALSE + +/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) + SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) + if(does_attack_animation) + user.changeNext_move(CLICK_CD_MELEE) + log_combat(user, src, "punched", "hulk powers") + user.do_attack_animation(src, ATTACK_EFFECT_SMASH) + +/atom/proc/CheckParts(list/parts_list) + for(var/A in parts_list) + if(istype(A, /datum/reagent)) + if(!reagents) + reagents = new() + reagents.reagent_list.Add(A) + reagents.conditional_update() + else if(ismovableatom(A)) + var/atom/movable/M = A + if(isliving(M.loc)) + var/mob/living/L = M.loc + L.transferItemToLoc(M, src) + else + M.forceMove(src) + +//common name +/atom/proc/update_multiz(prune_on_fail = FALSE) + return FALSE + +/atom/proc/assume_air(datum/gas_mixture/giver) + qdel(giver) + return null + +/atom/proc/remove_air(amount) + return null + +/atom/proc/return_air() + if(loc) + return loc.return_air() + else + return null + +/atom/proc/check_eye(mob/user) + return + +/atom/proc/Bumped(atom/movable/AM) + set waitfor = FALSE + +// Convenience procs to see if a container is open for chemistry handling +/atom/proc/is_open_container() + return is_refillable() && is_drainable() + +/atom/proc/is_injectable(allowmobs = TRUE) + return reagents && (reagents.reagents_holder_flags & (INJECTABLE | REFILLABLE)) + +/atom/proc/is_drawable(allowmobs = TRUE) + return reagents && (reagents.reagents_holder_flags & (DRAWABLE | DRAINABLE)) + +/atom/proc/is_refillable() + return reagents && (reagents.reagents_holder_flags & REFILLABLE) + +/atom/proc/is_drainable() + return reagents && (reagents.reagents_holder_flags & DRAINABLE) + + +/atom/proc/AllowDrop() + return FALSE + +/atom/proc/CheckExit() + return TRUE + +/atom/proc/HasProximity(atom/movable/AM as mob|obj) + return + +/atom/proc/emp_act(severity) + var/protection = SEND_SIGNAL(src, COMSIG_ATOM_EMP_ACT, severity) + if(!(protection & EMP_PROTECT_WIRES) && istype(wires)) + wires.emp_pulse() + return protection // Pass the protection value collected here upwards + +/atom/proc/bullet_act(obj/item/projectile/P, def_zone) + SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone) + . = P.on_hit(src, 0, def_zone) + +//used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it. +// IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first. +/atom/proc/shove_act(mob/living/target, mob/living/user) + return FALSE + +/atom/proc/in_contents_of(container)//can take class or object instance as argument + if(ispath(container)) + if(istype(src.loc, container)) + return TRUE + else if(src in container) + return TRUE + return FALSE + +/atom/proc/get_examine_name(mob/user) + . = "\a [src]" + var/list/override = list(gender == PLURAL ? "some" : "a", " ", "[name]") + if(article) + . = "[article] [src]" + override[EXAMINE_POSITION_ARTICLE] = article + + var/should_override = FALSE + + if(SEND_SIGNAL(src, COMSIG_ATOM_GET_EXAMINE_NAME, user, override) & COMPONENT_EXNAME_CHANGED) + should_override = TRUE + + + if(blood_DNA && !istype(src, /obj/effect/decal)) + override[EXAMINE_POSITION_BEFORE] = " blood-stained " + should_override = TRUE + + if(should_override) + . = override.Join("") + +///Generate the full examine string of this atom (including icon for goonchat) +/atom/proc/get_examine_string(mob/user, thats = FALSE) + return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]" + +/atom/proc/examine(mob/user) + . = list("[get_examine_string(user, TRUE)].") + + if(desc) + . += desc + + if(reagents) + if(reagents.reagents_holder_flags & TRANSPARENT) + . += "It contains:" + if(length(reagents.reagent_list)) + if(user.can_see_reagents()) //Show each individual reagent + for(var/datum/reagent/R in reagents.reagent_list) + . += "[R.volume] units of [R.name]" + else //Otherwise, just show the total volume + var/total_volume = 0 + for(var/datum/reagent/R in reagents.reagent_list) + total_volume += R.volume + . += "[total_volume] units of various reagents" + else + . += "Nothing." + else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE) + if(reagents.total_volume) + . += "It has [reagents.total_volume] unit\s left." + else + . += "It's empty." + + SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) + +/// Updates the icon of the atom +/atom/proc/update_icon() + // I expect we're going to need more return flags and options in this proc + var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON) + + if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE)) + update_icon_state() + + if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS)) + var/list/new_overlays = update_overlays() + if(managed_overlays) + cut_overlay(managed_overlays) + managed_overlays = null + if(length(new_overlays)) + managed_overlays = new_overlays + add_overlay(new_overlays) + +/// Updates the icon state of the atom +/atom/proc/update_icon_state() + +/// Updates the overlays of the atom +/atom/proc/update_overlays() + SHOULD_CALL_PARENT(1) + . = list() + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) + +/atom/proc/relaymove(mob/user) + if(buckle_message_cooldown <= world.time) + buckle_message_cooldown = world.time + 50 + to_chat(user, "You can't move while buckled to [src]!") + return + +/atom/proc/contents_explosion(severity, target) + return //For handling the effects of explosions on contents that would not normally be effected + +/atom/proc/ex_act(severity, target) + set waitfor = FALSE + contents_explosion(severity, target) + SEND_SIGNAL(src, COMSIG_ATOM_EX_ACT, severity, target) + +/atom/proc/blob_act(obj/structure/blob/B) + SEND_SIGNAL(src, COMSIG_ATOM_BLOB_ACT, B) + return + +/atom/proc/fire_act(exposed_temperature, exposed_volume) + SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) + return + +/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) + if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). + addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) + +/atom/proc/hitby_react(atom/movable/AM) + if(AM && isturf(AM.loc)) + step(AM, turn(AM.dir, 180)) + +/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube) + return + +//returns the mob's dna info as a list, to be inserted in an object's blood_DNA list +/mob/living/proc/get_blood_dna_list() + var/blood_id = get_blood_id() + if(!(blood_id =="blood" || blood_id == "jellyblood")) + return + return list("ANIMAL DNA" = "Y-") + +/mob/living/carbon/get_blood_dna_list() + var/blood_id = get_blood_id() + if(!(blood_id =="blood" || blood_id == "jellyblood")) + return + var/list/blood_dna = list() + if(dna) + blood_dna[dna.unique_enzymes] = dna.blood_type + else + blood_dna["UNKNOWN DNA"] = "X*" + return blood_dna + +/mob/living/carbon/alien/get_blood_dna_list() + return list("UNKNOWN DNA" = "X*") + +//to add a mob's dna info into an object's blood_DNA list. +/atom/proc/transfer_mob_blood_dna(mob/living/L) + // Returns 0 if we have that blood already + var/new_blood_dna = L.get_blood_dna_list() + if(!new_blood_dna) + return FALSE + LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it. + var/old_length = blood_DNA.len + blood_DNA |= new_blood_dna + if(blood_DNA.len == old_length) + return FALSE + return TRUE + +//to add blood dna info to the object's blood_DNA list +/atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases) + LAZYINITLIST(blood_DNA) + var/old_length = blood_DNA.len + blood_DNA |= blood_dna + if(blood_DNA.len > old_length) + 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 FALSE + return add_blood_DNA(blood_dna, M.diseases) + +//to add blood onto something, with blood dna info to include. +/atom/proc/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + return FALSE + +/obj/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + return transfer_blood_dna(blood_dna, diseases) + +/obj/item/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + . = ..() + if(!.) + return + add_blood_overlay() + +/obj/item/proc/add_blood_overlay() + if(!blood_DNA.len) + return + if(initial(icon) && initial(icon_state)) + blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object + blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) + blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant + blood_splatter_icon.Blend(blood_DNA_to_color(), ICON_MULTIPLY) + add_overlay(blood_splatter_icon) + +/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + . = ..() + transfer_blood = rand(2, 4) + +/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src + if(!B) + B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) + B.transfer_blood_dna(blood_dna, diseases) //give blood info to the blood decal. + return TRUE //we bloodied the floor + +/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) + if(head) + head.add_blood_DNA(blood_dna, diseases) + update_inv_head() + else if(wear_mask) + wear_mask.add_blood_DNA(blood_dna, diseases) + update_inv_wear_mask() + if(wear_neck) + wear_neck.add_blood_DNA(blood_dna, diseases) + update_inv_neck() + if(wear_suit) + wear_suit.add_blood_DNA(blood_dna, diseases) + update_inv_wear_suit() + else if(w_uniform) + w_uniform.add_blood_DNA(blood_dna, diseases) + update_inv_w_uniform() + if(gloves) + var/obj/item/clothing/gloves/G = gloves + G.add_blood_DNA(blood_dna, diseases) + else + transfer_blood_dna(blood_dna, diseases) + bloody_hands = rand(2, 4) + update_inv_gloves() //handles bloody hands overlays and updating + return TRUE + +/atom/proc/blood_DNA_to_color() + var/list/colors = list()//first we make a list of all bloodtypes present + for(var/bloop in blood_DNA) + if(colors[blood_DNA[bloop]]) + colors[blood_DNA[bloop]]++ + else + colors[blood_DNA[bloop]] = 1 + + var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up + + if(colors.len) + var/sum = 0 //this is all shitcode, but it works; trust me + final_rgb = bloodtype_to_color(colors[1]) + sum = colors[colors[1]] + if(colors.len > 1) + var/i = 2 + while(i <= colors.len) + var/tmp = colors[colors[i]] + final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum)) + sum += tmp + i++ + + return final_rgb + +/atom/proc/clean_blood() + if(islist(blood_DNA)) + blood_DNA = null + return TRUE + +/atom/proc/wash_cream() + return TRUE + +/atom/proc/isinspace() + if(isspaceturf(get_turf(src))) + return TRUE + else + return FALSE + +/atom/proc/handle_fall() + return + +/atom/proc/singularity_act() + return + +/atom/proc/singularity_pull(obj/singularity/S, current_size) + SEND_SIGNAL(src, COMSIG_ATOM_SING_PULL, S, current_size) + +/atom/proc/acid_act(acidpwr, acid_volume) + SEND_SIGNAL(src, COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume) + +/atom/proc/emag_act() + return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) + +/atom/proc/rad_act(strength) + SEND_SIGNAL(src, COMSIG_ATOM_RAD_ACT, strength) + +/atom/proc/narsie_act() + SEND_SIGNAL(src, COMSIG_ATOM_NARSIE_ACT) + +/atom/proc/ratvar_act() + SEND_SIGNAL(src, COMSIG_ATOM_RATVAR_ACT) + +/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + return FALSE + +/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + SEND_SIGNAL(src, COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode) + return FALSE + +/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user) + if(GetComponent(/datum/component/storage)) + return component_storage_contents_dump_act(src_object, user) + return FALSE + +/atom/proc/component_storage_contents_dump_act(datum/component/storage/src_object, mob/user) + var/list/things = src_object.contents() + var/datum/progressbar/progress = new(user, things.len, src) + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(STR, /datum/component/storage.proc/handle_mass_item_insertion, things, src_object, user, progress))) + stoplag(1) + qdel(progress) + to_chat(user, "You dump as much of [src_object.parent]'s contents into [STR.insert_preposition]to [src] as you can.") + STR.orient2hud(user) + src_object.orient2hud(user) + if(user.active_storage) //refresh the HUD to show the transfered contents + user.active_storage.close(user) + user.active_storage.show_to(user) + return TRUE + +/atom/proc/get_dumping_location(obj/item/storage/source,mob/user) + return null + +//This proc is called on the location of an atom when the atom is Destroy()'d +/atom/proc/handle_atom_del(atom/A) + SEND_SIGNAL(src, COMSIG_ATOM_CONTENTS_DEL, A) + +//called when the turf the atom resides on is ChangeTurfed +/atom/proc/HandleTurfChange(turf/T) + for(var/a in src) + var/atom/A = a + A.HandleTurfChange(T) + +//the vision impairment to give to the mob whose perspective is set to that atom (e.g. an unfocused camera giving you an impaired vision when looking through it) +/atom/proc/get_remote_view_fullscreens(mob/user) + return + +//the sight changes to give to the mob whose perspective is set to that atom (e.g. A mob with nightvision loses its nightvision while looking through a normal camera) +/atom/proc/update_remote_sight(mob/living/user) + return + + +//Hook for running code when a dir change occurs +/atom/proc/setDir(newdir, ismousemovement=FALSE) + SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, newdir) + dir = newdir + +/atom/proc/mech_melee_attack(obj/mecha/M) + return + +//If a mob logouts/logins in side of an object you can use this proc +/atom/proc/on_log(login) + if(loc) + loc.on_log(login) + + +/* + Atom Colour Priority System + A System that gives finer control over which atom colour to colour the atom with. + The "highest priority" one is always displayed as opposed to the default of + "whichever was set last is displayed" +*/ + + +/* + Adds an instance of colour_type to the atom's atom_colours list +*/ +/atom/proc/add_atom_colour(coloration, colour_priority) + if(!atom_colours || !atom_colours.len) + atom_colours = list() + atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. + if(!coloration) + return + if(colour_priority > atom_colours.len) + return + atom_colours[colour_priority] = coloration + update_atom_colour() + + +/* + Removes an instance of colour_type from the atom's atom_colours list +*/ +/atom/proc/remove_atom_colour(colour_priority, coloration) + if(!atom_colours) + atom_colours = list() + atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. + if(colour_priority > atom_colours.len) + return + if(coloration && atom_colours[colour_priority] != coloration) + return //if we don't have the expected color (for a specific priority) to remove, do nothing + 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 +*/ +/atom/proc/update_atom_colour() + if(!atom_colours) + atom_colours = list() + atom_colours.len = COLOUR_PRIORITY_AMOUNT //four priority levels currently. + color = null + for(var/C in atom_colours) + if(islist(C)) + var/list/L = C + if(L.len) + color = L + return + else if(C) + color = C + return + +/atom/vv_edit_var(var_name, var_value) + if(!GLOB.Debug2) + flags_1 |= ADMIN_SPAWNED_1 + . = ..() + switch(var_name) + if("color") + add_atom_colour(color, ADMIN_COLOUR_PRIORITY) + +/atom/vv_get_dropdown() + . = ..() + . += "---" + var/turf/curturf = get_turf(src) + if (curturf) + .["Jump to"] = "?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]" + .["Modify Transform"] = "?_src_=vars;[HrefToken()];modtransform=[REF(src)]" + .["Add reagent"] = "?_src_=vars;[HrefToken()];addreagent=[REF(src)]" + .["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]" + .["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]" + +/atom/proc/drop_location() + var/atom/L = loc + if(!L) + return null + return L.AllowDrop() ? L : L.drop_location() + +/atom/Entered(atom/movable/AM, atom/oldLoc) + SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc) + +/atom/Exit(atom/movable/AM, atom/newLoc) + . = ..() + if(SEND_SIGNAL(src, COMSIG_ATOM_EXIT, AM, newLoc) & COMPONENT_ATOM_BLOCK_EXIT) + return FALSE + +/atom/Exited(atom/movable/AM, atom/newLoc) + SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, newLoc) + +/atom/proc/return_temperature() + return + +// Tool behavior procedure. Redirects to tool-specific procs by default. +// You can override it to catch all tool interactions, for use in complex deconstruction procs. +// Just don't forget to return ..() in the end. +/atom/proc/tool_act(mob/living/user, obj/item/I, tool_type) + switch(tool_type) + if(TOOL_CROWBAR) + return crowbar_act(user, I) + if(TOOL_MULTITOOL) + return multitool_act(user, I) + if(TOOL_SCREWDRIVER) + return screwdriver_act(user, I) + if(TOOL_WRENCH) + return wrench_act(user, I) + if(TOOL_WIRECUTTER) + return wirecutter_act(user, I) + if(TOOL_WELDER) + return welder_act(user, I) + if(TOOL_ANALYZER) + return analyzer_act(user, I) + +// Tool-specific behavior procs. To be overridden in subtypes. +/atom/proc/crowbar_act(mob/living/user, obj/item/I) + return + +/atom/proc/multitool_act(mob/living/user, obj/item/I) + return + +/atom/proc/screwdriver_act(mob/living/user, obj/item/I) + SEND_SIGNAL(src, COMSIG_ATOM_SCREWDRIVER_ACT, user, I) + +/atom/proc/wrench_act(mob/living/user, obj/item/I) + return + +/atom/proc/wirecutter_act(mob/living/user, obj/item/I) + return + +/atom/proc/welder_act(mob/living/user, obj/item/I) + return + +/atom/proc/analyzer_act(mob/living/user, obj/item/I) + return + +/atom/proc/GenerateTag() + return + +// Generic logging helper +/atom/proc/log_message(message, message_type, color=null, log_globally=TRUE) + if(!log_globally) + return + + var/log_text = "[key_name(src)] [message] [loc_name(src)]" + switch(message_type) + if(LOG_ATTACK) + log_attack(log_text) + if(LOG_SAY) + log_say(log_text) + if(LOG_WHISPER) + log_whisper(log_text) + if(LOG_EMOTE) + log_emote(log_text) + if(LOG_DSAY) + log_dsay(log_text) + if(LOG_PDA) + log_pda(log_text) + if(LOG_CHAT) + log_chat(log_text) + if(LOG_COMMENT) + log_comment(log_text) + if(LOG_TELECOMMS) + log_telecomms(log_text) + if(LOG_OOC) + log_ooc(log_text) + if(LOG_ADMIN) + log_admin(log_text) + if(LOG_ADMIN_PRIVATE) + log_admin_private(log_text) + if(LOG_ASAY) + log_adminsay(log_text) + if(LOG_OWNERSHIP) + log_game(log_text) + if(LOG_GAME) + log_game(log_text) + else + stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).") + log_game(log_text) + +// Helper for logging chat messages or other logs with arbitrary inputs (e.g. announcements) +/atom/proc/log_talk(message, message_type, tag=null, log_globally=TRUE, forced_by=null) + var/prefix = tag ? "([tag]) " : "" + var/suffix = forced_by ? " FORCED by [forced_by]" : "" + log_message("[prefix]\"[message]\"[suffix]", message_type, log_globally=log_globally) + +// Helper for logging of messages with only one sender and receiver +/proc/log_directed_talk(atom/source, atom/target, message, message_type, tag) + if(!tag) + stack_trace("Unspecified tag for private message") + tag = "UNKNOWN" + + source.log_talk(message, message_type, tag="[tag] to [key_name(target)]") + if(source != target) + target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) + +/* +Proc for attack log creation, because really why not +1 argument is the actor performing the action +2 argument is the target of the action +3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) +4 is a tool with which the action was made (usually an item) +5 is any additional text, which will be appended to the rest of the log line +*/ + +/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) + var/ssource = key_name(user) + var/starget = key_name(target) + + var/mob/living/living_target = target + var/hp = istype(living_target) ? " (NEWHP: [living_target.health]) " : "" + + var/sobject = "" + if(object) + sobject = " with [key_name(object)]" + var/saddition = "" + if(addition) + saddition = " [addition]" + + var/postfix = "[sobject][saddition][hp]" + + var/message = "has [what_done] [starget][postfix]" + user.log_message(message, LOG_ATTACK, color="red") + + if(user != target) + var/reverse_message = "has been [what_done] by [ssource][postfix]" + target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) + +// Filter stuff +/atom/movable/proc/add_filter(name,priority,list/params) + LAZYINITLIST(filter_data) + var/list/p = params.Copy() + p["priority"] = priority + filter_data[name] = p + update_filters() + +/atom/movable/proc/update_filters() + filters = null + filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE) + for(var/f in filter_data) + var/list/data = filter_data[f] + var/list/arguments = data.Copy() + arguments -= "priority" + filters += filter(arglist(arguments)) + +/atom/movable/proc/get_filter(name) + if(filter_data && filter_data[name]) + return filters[filter_data.Find(name)] + +/atom/movable/proc/remove_filter(name) + if(filter_data && filter_data[name]) + filter_data -= name + update_filters() + return TRUE + +/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1) . |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels) \ No newline at end of file diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 7c57de74a4..00a08d62b2 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,874 +1,874 @@ -/atom/movable - layer = OBJ_LAYER - var/last_move = null - var/last_move_time = 0 - var/anchored = FALSE - var/datum/thrownthing/throwing = null - var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported - var/throw_range = 7 - var/mob/pulledby = null - var/initial_language_holder = /datum/language_holder - var/datum/language_holder/language_holder - var/verb_say = "says" - var/verb_ask = "asks" - var/verb_exclaim = "exclaims" - var/verb_whisper = "whispers" - var/verb_yell = "yells" - var/speech_span - var/inertia_dir = 0 - var/atom/inertia_last_loc - var/inertia_moving = 0 - var/inertia_next_move = 0 - var/inertia_move_delay = 5 - var/pass_flags = 0 - var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move - var/list/client_mobs_in_contents // This contains all the client mobs within this container - var/list/acted_explosions //for explosion dodging - glide_size = 8 - appearance_flags = TILE_BOUND|PIXEL_SCALE - var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm - var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. - var/atom/movable/pulling - var/grab_state = 0 - var/throwforce = 0 - var/datum/component/orbiter/orbiting - var/can_be_z_moved = TRUE - - var/zfalling = FALSE - -/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction) - if(!direction) - direction = DOWN - if(!source) - source = get_turf(src) - if(!source) - return FALSE - if(!target) - target = get_step_multiz(source, direction) - if(!target) - return FALSE - return !(movement_type & FLYING) && has_gravity(source) && !throwing - -/atom/movable/proc/onZImpact(turf/T, levels) - var/atom/highest = T - for(var/i in T.contents) - var/atom/A = i - if(!A.density) - continue - if(isobj(A) || ismob(A)) - if(A.layer > highest.layer) - highest = A - INVOKE_ASYNC(src, .proc/SpinAnimation, 5, 2) - throw_impact(highest) - return TRUE - -//For physical constraints to travelling up/down. -/atom/movable/proc/can_zTravel(turf/destination, direction) - var/turf/T = get_turf(src) - if(!T) - return FALSE - if(!direction) - if(!destination) - return FALSE - direction = get_dir(T, destination) - if(direction != UP && direction != DOWN) - return FALSE - if(!destination) - destination = get_step_multiz(src, direction) - if(!destination) - return FALSE - return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T) - -/atom/movable/vv_edit_var(var_name, var_value) - var/static/list/banned_edits = list("step_x", "step_y", "step_size") - var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height") - if(var_name in banned_edits) - return FALSE //PLEASE no. - if((var_name in careful_edits) && (var_value % world.icon_size) != 0) - return FALSE - switch(var_name) - if("x") - var/turf/T = locate(var_value, y, z) - if(T) - forceMove(T) - return TRUE - return FALSE - if("y") - var/turf/T = locate(x, var_value, z) - if(T) - forceMove(T) - return TRUE - return FALSE - if("z") - var/turf/T = locate(x, y, var_value) - if(T) - forceMove(T) - return TRUE - return FALSE - if("loc") - if(istype(var_value, /atom)) - forceMove(var_value) - return TRUE - else if(isnull(var_value)) - moveToNullspace() - return TRUE - return FALSE - return ..() - -/atom/movable/proc/start_pulling(atom/movable/AM,gs) - if(QDELETED(AM)) - return FALSE - if(!(AM.can_be_pulled(src))) - return FALSE - - // If we're pulling something then drop what we're currently pulling and pull this instead. - if(pulling) - if(gs==0) - stop_pulling() - return FALSE - // Are we trying to pull something we are already pulling? Then enter grab cycle and end. - if(AM == pulling) - grab_state = gs - if(istype(AM,/mob/living)) - var/mob/living/AMob = AM - AMob.grabbedby(src) - return TRUE - stop_pulling() - if(AM.pulledby) - log_combat(AM, AM.pulledby, "pulled from", src) - AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. - pulling = AM - AM.pulledby = src - grab_state = gs - if(ismob(AM)) - var/mob/M = AM - log_combat(src, M, "grabbed", addition="passive grab") - visible_message("[src] has grabbed [M] passively!") - return TRUE - -/atom/movable/proc/stop_pulling() - if(pulling) - pulling.pulledby = null - var/mob/living/ex_pulled = pulling - pulling = null - grab_state = 0 - if(isliving(ex_pulled)) - var/mob/living/L = ex_pulled - L.update_canmove()// mob gets up if it was lyng down in a chokehold - -/atom/movable/proc/Move_Pulled(atom/A) - if(!pulling) - return - if(pulling.anchored || !pulling.Adjacent(src)) - stop_pulling() - return - if(isliving(pulling)) - var/mob/living/L = pulling - if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it - stop_pulling() - return - if(A == loc && pulling.density) - return - if(!Process_Spacemove(get_dir(pulling.loc, A))) - return - step(pulling, get_dir(pulling.loc, A)) - -/atom/movable/proc/check_pulling() - if(pulling) - var/atom/movable/pullee = pulling - if(pullee && get_dist(src, pullee) > 1) - stop_pulling() - return - if(!isturf(loc)) - stop_pulling() - return - if(pullee && !isturf(pullee.loc) && pullee.loc != loc) //to be removed once all code that changes an object's loc uses forceMove(). - log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") - stop_pulling() - return - if(pulling.anchored) - stop_pulling() - return - -//////////////////////////////////////// -// Here's where we rewrite how byond handles movement except slightly different -// To be removed on step_ conversion -// All this work to prevent a second bump -/atom/movable/Move(atom/newloc, direct=0) - . = FALSE - if(!newloc || newloc == loc) - return - - if(!direct) - direct = get_dir(src, newloc) - setDir(direct) - - if(!loc.Exit(src, newloc)) - return - - if(!newloc.Enter(src, src.loc)) - return - - // Past this is the point of no return - var/atom/oldloc = loc - var/area/oldarea = get_area(oldloc) - var/area/newarea = get_area(newloc) - loc = newloc - . = TRUE - oldloc.Exited(src, newloc) - if(oldarea != newarea) - oldarea.Exited(src, newloc) - - for(var/i in oldloc) - if(i == src) // Multi tile objects - continue - var/atom/movable/thing = i - thing.Uncrossed(src) - - newloc.Entered(src, oldloc) - if(oldarea != newarea) - newarea.Entered(src, oldloc) - - for(var/i in loc) - if(i == src) // Multi tile objects - continue - var/atom/movable/thing = i - thing.Crossed(src) -// -//////////////////////////////////////// - -/atom/movable/Move(atom/newloc, direct) - var/atom/movable/pullee = pulling - var/turf/T = loc - if(pulling) - if(pullee && get_dist(src, pullee) > 1) - stop_pulling() - - if(pullee && pullee.loc != loc && !isturf(pullee.loc) ) //to be removed once all code that changes an object's loc uses forceMove(). - log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") - stop_pulling() - if(!loc || !newloc) - return FALSE - var/atom/oldloc = loc - - if(loc != newloc) - if (!(direct & (direct - 1))) //Cardinal move - . = ..() - else //Diagonal move, split it into cardinal moves - moving_diagonally = FIRST_DIAG_STEP - var/first_step_dir - // The `&& moving_diagonally` checks are so that a forceMove taking - // place due to a Crossed, Bumped, etc. call will interrupt - // the second half of the diagonal movement, or the second attempt - // at a first half if step() fails because we hit something. - if (direct & NORTH) - if (direct & EAST) - if (step(src, NORTH) && moving_diagonally) - first_step_dir = NORTH - moving_diagonally = SECOND_DIAG_STEP - . = step(src, EAST) - else if (moving_diagonally && step(src, EAST)) - first_step_dir = EAST - moving_diagonally = SECOND_DIAG_STEP - . = step(src, NORTH) - else if (direct & WEST) - if (step(src, NORTH) && moving_diagonally) - first_step_dir = NORTH - moving_diagonally = SECOND_DIAG_STEP - . = step(src, WEST) - else if (moving_diagonally && step(src, WEST)) - first_step_dir = WEST - moving_diagonally = SECOND_DIAG_STEP - . = step(src, NORTH) - else if (direct & SOUTH) - if (direct & EAST) - if (step(src, SOUTH) && moving_diagonally) - first_step_dir = SOUTH - moving_diagonally = SECOND_DIAG_STEP - . = step(src, EAST) - else if (moving_diagonally && step(src, EAST)) - first_step_dir = EAST - moving_diagonally = SECOND_DIAG_STEP - . = step(src, SOUTH) - else if (direct & WEST) - if (step(src, SOUTH) && moving_diagonally) - first_step_dir = SOUTH - moving_diagonally = SECOND_DIAG_STEP - . = step(src, WEST) - else if (moving_diagonally && step(src, WEST)) - first_step_dir = WEST - moving_diagonally = SECOND_DIAG_STEP - . = step(src, SOUTH) - if(moving_diagonally == SECOND_DIAG_STEP) - if(!.) - setDir(first_step_dir) - else if (!inertia_moving) - inertia_next_move = world.time + inertia_move_delay - newtonian_move(direct) - moving_diagonally = 0 - return - - if(!loc || (loc == oldloc && oldloc != newloc)) - last_move = 0 - return - - if(.) - Moved(oldloc, direct) - if(. && pulling && pulling == pullee) //we were pulling a thing and didn't lose it during our move. - if(pulling.anchored) - stop_pulling() - else - var/pull_dir = get_dir(src, pulling) - //puller and pullee more than one tile away or in diagonal position - if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) - pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position - if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up - stop_pulling() - if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move. - pulledby.stop_pulling() - - - last_move = direct - setDir(direct) - if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s) - return FALSE - -//Called after a successful Move(). By this point, we've already moved -/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE) - SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced) - if (!inertia_moving) - inertia_next_move = world.time + inertia_move_delay - newtonian_move(Dir) - if (length(client_mobs_in_contents)) - update_parallax_contents() - - return TRUE - -/atom/movable/Destroy(force) - QDEL_NULL(proximity_monitor) - QDEL_NULL(language_holder) - - unbuckle_all_mobs(force=1) - - . = ..() - if(loc) - //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) - if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) - CanAtmosPass = ATMOS_PASS_YES - air_update_turf(TRUE) - loc.handle_atom_del(src) - for(var/atom/movable/AM in contents) - qdel(AM) - moveToNullspace() - invisibility = INVISIBILITY_ABSTRACT - if(pulledby) - pulledby.stop_pulling() - - if(orbiting) - orbiting.end_orbit(src) - orbiting = null - -// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly. -// You probably want CanPass() -/atom/movable/Cross(atom/movable/AM) - . = TRUE - SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM) - return CanPass(AM, AM.loc, TRUE) - -//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called! -/atom/movable/Crossed(atom/movable/AM, oldloc) - SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) - -/atom/movable/Uncross(atom/movable/AM, atom/newloc) - . = ..() - if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS) - return FALSE - if(isturf(newloc) && !CheckExit(AM, newloc)) - return FALSE - -/atom/movable/Uncrossed(atom/movable/AM) - SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM) - -/atom/movable/Bump(atom/A) - if(!A) - CRASH("Bump was called with no argument.") - SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A) - . = ..() - if(!QDELETED(throwing)) - throwing.hit_atom(A) - . = TRUE - if(QDELETED(A)) - return - A.Bumped(src) - -/atom/movable/proc/forceMove(atom/destination) - . = FALSE - if(destination) - . = doMove(destination) - else - CRASH("No valid destination passed into forceMove") - -/atom/movable/proc/moveToNullspace() - return doMove(null) - -/atom/movable/proc/doMove(atom/destination) - . = FALSE - if(destination) - if(pulledby) - pulledby.stop_pulling() - var/atom/oldloc = loc - var/same_loc = oldloc == destination - var/area/old_area = get_area(oldloc) - var/area/destarea = get_area(destination) - - loc = destination - moving_diagonally = 0 - - if(!same_loc) - if(oldloc) - oldloc.Exited(src, destination) - if(old_area && old_area != destarea) - old_area.Exited(src, destination) - for(var/atom/movable/AM in oldloc) - AM.Uncrossed(src) - var/turf/oldturf = get_turf(oldloc) - var/turf/destturf = get_turf(destination) - var/old_z = (oldturf ? oldturf.z : null) - var/dest_z = (destturf ? destturf.z : null) - if (old_z != dest_z) - onTransitZ(old_z, dest_z) - destination.Entered(src, oldloc) - if(destarea && old_area != destarea) - destarea.Entered(src, oldloc) - - for(var/atom/movable/AM in destination) - if(AM == src) - continue - AM.Crossed(src, oldloc) - - Moved(oldloc, NONE, TRUE) - . = TRUE - - //If no destination, move the atom into nullspace (don't do this unless you know what you're doing) - else - . = TRUE - if (loc) - var/atom/oldloc = loc - var/area/old_area = get_area(oldloc) - oldloc.Exited(src, null) - if(old_area) - old_area.Exited(src, null) - loc = null - -/atom/movable/proc/onTransitZ(old_z,new_z) - SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z) - for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care. - var/atom/movable/AM = item - AM.onTransitZ(old_z,new_z) - -/atom/movable/proc/setMovetype(newval) - movement_type = newval - -//Called whenever an object moves and by mobs when they attempt to move themselves through space -//And when an object or action applies a force on src, see newtonian_move() below -//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting -//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm -//movement_dir == 0 when stopping or any dir when trying to move -/atom/movable/proc/Process_Spacemove(movement_dir = 0) - if(has_gravity(src)) - return 1 - - if(pulledby) - return 1 - - if(throwing) - return 1 - - if(!isturf(loc)) - return 1 - - if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier - return 1 - - return 0 - - -/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity - if(!loc || Process_Spacemove(0)) - inertia_dir = 0 - return 0 - - inertia_dir = direction - if(!direction) - return 1 - inertia_last_loc = loc - SSspacedrift.processing[src] = src - return 1 - -/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - set waitfor = 0 - SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) - return hit_atom.hitby(src) - -/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked) - if(!anchored && hitpush) - step(src, AM.dir) - ..() - -/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) - return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, messy_throw) - -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) //If this returns FALSE then callback will not be called. - . = FALSE - if (!target || speed <= 0) - return - - if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_THROW, args) & COMPONENT_CANCEL_THROW) - return - - if (pulledby) - pulledby.stop_pulling() - - //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? - if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) - var/user_momentum = thrower.movement_delay() - if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. - user_momentum = world.tick_lag - - user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses. - - if (get_dir(thrower, target) & last_move) - user_momentum = user_momentum //basically a noop, but needed - else if (get_dir(target, thrower) & last_move) - user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly - else - user_momentum = 0 - - - if (user_momentum) - //first lets add that momentum to range. - range *= (user_momentum / speed) + 1 - //then lets add it to speed - speed += user_momentum - if (speed <= 0) - return//no throw speed, the user was moving too fast. - - . = TRUE // No failure conditions past this point. - - var/datum/thrownthing/TT = new() - TT.thrownthing = src - TT.target = target - TT.target_turf = get_turf(target) - TT.init_dir = get_dir(src, target) - TT.maxrange = range - TT.speed = speed - TT.thrower = thrower - TT.diagonals_first = diagonals_first - TT.callback = callback - if(!QDELETED(thrower)) - TT.target_zone = thrower.zone_selected - - var/dist_x = abs(target.x - src.x) - var/dist_y = abs(target.y - src.y) - var/dx = (target.x > src.x) ? EAST : WEST - var/dy = (target.y > src.y) ? NORTH : SOUTH - - if (dist_x == dist_y) - TT.pure_diagonal = 1 - - else if(dist_x <= dist_y) - var/olddist_x = dist_x - var/olddx = dx - dist_x = dist_y - dist_y = olddist_x - dx = dy - dy = olddx - TT.dist_x = dist_x - TT.dist_y = dist_y - TT.dx = dx - TT.dy = dy - TT.diagonal_error = dist_x/2 - dist_y - TT.start_time = world.time - - if(pulledby) - pulledby.stop_pulling() - - throwing = TT - if(spin) - SpinAnimation(5, 1) - - SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, TT, spin) - SSthrowing.processing[src] = TT - if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) - SSthrowing.currentrun[src] = TT - TT.tick() - -/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) - for(var/m in buckled_mobs) - var/mob/living/buckled_mob = m - if(!buckled_mob.Move(newloc, direct)) - forceMove(buckled_mob.loc) - last_move = buckled_mob.last_move - inertia_dir = last_move - buckled_mob.inertia_dir = last_move - return 0 - return 1 - -/atom/movable/CanPass(atom/movable/mover, turf/target) - if(mover in buckled_mobs) - return 1 - return ..() - -// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. -/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) - return - -// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. -/atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S) - return - -/atom/movable/proc/get_spacemove_backup() - var/atom/movable/dense_object_backup - for(var/A in orange(1, get_turf(src))) - if(isarea(A)) - continue - else if(isturf(A)) - var/turf/turf = A - if(!turf.density) - continue - return turf - else - var/atom/movable/AM = A - if(!AM.CanPass(src) || AM.density) - if(AM.anchored) - return AM - dense_object_backup = AM - break - . = dense_object_backup - -//called when a mob resists while inside a container that is itself inside something. -/atom/movable/proc/relay_container_resist(mob/living/user, obj/O) - return - - -/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) - - if(A == src) - return //don't do an animation if attacking self - var/pixel_x_diff = 0 - var/pixel_y_diff = 0 - - var/direction = get_dir(src, A) - if(direction & NORTH) - pixel_y_diff = 8 - else if(direction & SOUTH) - pixel_y_diff = -8 - - if(direction & EAST) - pixel_x_diff = 8 - else if(direction & WEST) - pixel_x_diff = -8 - - var/matrix/OM = matrix(transform) - var/matrix/M = matrix(transform) - M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16)) - - animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2) - animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, time = 2) - -/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item) - var/image/I - if(visual_effect_icon) - I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1) - else if(used_item) - I = image(icon = used_item, loc = A, layer = A.layer + 0.1) - I.plane = GAME_PLANE - - // Scale the icon. - I.transform *= 0.75 - // The icon should not rotate. - I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - - // Set the direction of the icon animation. - var/direction = get_dir(src, A) - if(direction & NORTH) - I.pixel_y = -16 - else if(direction & SOUTH) - I.pixel_y = 16 - - if(direction & EAST) - I.pixel_x = -16 - else if(direction & WEST) - I.pixel_x = 16 - - if(!direction) // Attacked self?! - I.pixel_z = 16 - - if(!I) - return - - flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second - - // And animate the attack! - animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) - -/atom/movable/vv_get_dropdown() - . = ..() - . -= "Jump to" - .["Follow"] = "?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]" - .["Get"] = "?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]" - -/atom/movable/proc/ex_check(ex_id) - if(!ex_id) - return TRUE - LAZYINITLIST(acted_explosions) - if(ex_id in acted_explosions) - return FALSE - acted_explosions += ex_id - return TRUE - -//TODO: Better floating -/atom/movable/proc/float(on) - if(throwing) - return - if(on && !(movement_type & FLOATING)) - animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1) - sleep(10) - animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1) - setMovetype(movement_type | FLOATING) - else if (!on && (movement_type & FLOATING)) - animate(src, pixel_y = initial(pixel_y), time = 10) - setMovetype(movement_type & ~FLOATING) - -/* Language procs */ -/atom/movable/proc/get_language_holder(shadow=TRUE) - if(language_holder) - return language_holder - else - language_holder = new initial_language_holder(src) - return language_holder - -/atom/movable/proc/grant_language(datum/language/dt, body = FALSE) - var/datum/language_holder/H = get_language_holder(!body) - H.grant_language(dt, body) - -/atom/movable/proc/grant_all_languages(omnitongue=FALSE) - var/datum/language_holder/H = get_language_holder() - H.grant_all_languages(omnitongue) - -/atom/movable/proc/get_random_understood_language() - var/datum/language_holder/H = get_language_holder() - . = H.get_random_understood_language() - -/atom/movable/proc/remove_language(datum/language/dt, body = FALSE) - var/datum/language_holder/H = get_language_holder(!body) - H.remove_language(dt, body) - -/atom/movable/proc/remove_all_languages() - var/datum/language_holder/H = get_language_holder() - H.remove_all_languages() - -/atom/movable/proc/has_language(datum/language/dt) - var/datum/language_holder/H = get_language_holder() - . = H.has_language(dt) - -/atom/movable/proc/copy_known_languages_from(thing, replace=FALSE) - var/datum/language_holder/H = get_language_holder() - . = H.copy_known_languages_from(thing, replace) - -// Whether an AM can speak in a language or not, independent of whether -// it KNOWS the language -/atom/movable/proc/could_speak_in_language(datum/language/dt) - . = TRUE - -/atom/movable/proc/can_speak_in_language(datum/language/dt) - var/datum/language_holder/H = get_language_holder() - - if(!H.has_language(dt)) - return FALSE - else if(H.omnitongue) - return TRUE - else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt)) - return TRUE - else - return FALSE - -/atom/movable/proc/get_default_language() - // if no language is specified, and we want to say() something, which - // language do we use? - var/datum/language_holder/H = get_language_holder() - - if(H.selected_default_language) - if(can_speak_in_language(H.selected_default_language)) - return H.selected_default_language - else - H.selected_default_language = null - - - var/datum/language/chosen_langtype - var/highest_priority - - for(var/lt in H.languages) - var/datum/language/langtype = lt - if(!can_speak_in_language(langtype)) - continue - - var/pri = initial(langtype.default_priority) - if(!highest_priority || (pri > highest_priority)) - chosen_langtype = langtype - highest_priority = pri - - H.selected_default_language = . - . = chosen_langtype - -/* End language procs */ -/atom/movable/proc/ConveyorMove(movedir) - set waitfor = FALSE - if(!anchored && has_gravity()) - step(src, movedir) - -//Returns an atom's power cell, if it has one. Overload for individual items. -/atom/movable/proc/get_cell() - return - -/atom/movable/proc/can_be_pulled(user) - if(src == user || !isturf(loc)) - return FALSE - if(anchored || throwing) - return FALSE - return TRUE - - -/obj/item/proc/do_pickup_animation(atom/target) - set waitfor = FALSE - if(!istype(loc, /turf)) - return - var/image/I = image(icon = src, loc = loc, layer = layer + 0.1) - I.plane = GAME_PLANE - I.transform *= 0.75 - I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA - var/turf/T = get_turf(src) - var/direction - var/to_x = 0 - var/to_y = 0 - - if(!QDELETED(T) && !QDELETED(target)) - direction = get_dir(T, target) - if(direction & NORTH) - to_y = 32 - else if(direction & SOUTH) - to_y = -32 - if(direction & EAST) - to_x = 32 - else if(direction & WEST) - to_x = -32 - if(!direction) - to_y = 16 - flick_overlay(I, GLOB.clients, 6) - var/matrix/M = new - M.Turn(pick(-30, 30)) - animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) - sleep(1) - animate(I, alpha = 0, transform = matrix(), time = 1) +/atom/movable + layer = OBJ_LAYER + var/last_move = null + var/last_move_time = 0 + var/anchored = FALSE + var/datum/thrownthing/throwing = null + var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported + var/throw_range = 7 + var/mob/pulledby = null + var/initial_language_holder = /datum/language_holder + var/datum/language_holder/language_holder + var/verb_say = "says" + var/verb_ask = "asks" + var/verb_exclaim = "exclaims" + var/verb_whisper = "whispers" + var/verb_yell = "yells" + var/speech_span + var/inertia_dir = 0 + var/atom/inertia_last_loc + var/inertia_moving = 0 + var/inertia_next_move = 0 + var/inertia_move_delay = 5 + var/pass_flags = 0 + var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move + var/list/client_mobs_in_contents // This contains all the client mobs within this container + var/list/acted_explosions //for explosion dodging + glide_size = 8 + appearance_flags = TILE_BOUND|PIXEL_SCALE + var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm + var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. + var/atom/movable/pulling + var/grab_state = 0 + var/throwforce = 0 + var/datum/component/orbiter/orbiting + var/can_be_z_moved = TRUE + + var/zfalling = FALSE + +/atom/movable/proc/can_zFall(turf/source, levels = 1, turf/target, direction) + if(!direction) + direction = DOWN + if(!source) + source = get_turf(src) + if(!source) + return FALSE + if(!target) + target = get_step_multiz(source, direction) + if(!target) + return FALSE + return !(movement_type & FLYING) && has_gravity(source) && !throwing + +/atom/movable/proc/onZImpact(turf/T, levels) + var/atom/highest = T + for(var/i in T.contents) + var/atom/A = i + if(!A.density) + continue + if(isobj(A) || ismob(A)) + if(A.layer > highest.layer) + highest = A + INVOKE_ASYNC(src, .proc/SpinAnimation, 5, 2) + throw_impact(highest) + return TRUE + +//For physical constraints to travelling up/down. +/atom/movable/proc/can_zTravel(turf/destination, direction) + var/turf/T = get_turf(src) + if(!T) + return FALSE + if(!direction) + if(!destination) + return FALSE + direction = get_dir(T, destination) + if(direction != UP && direction != DOWN) + return FALSE + if(!destination) + destination = get_step_multiz(src, direction) + if(!destination) + return FALSE + return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T) + +/atom/movable/vv_edit_var(var_name, var_value) + var/static/list/banned_edits = list("step_x", "step_y", "step_size") + var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height") + if(var_name in banned_edits) + return FALSE //PLEASE no. + if((var_name in careful_edits) && (var_value % world.icon_size) != 0) + return FALSE + switch(var_name) + if("x") + var/turf/T = locate(var_value, y, z) + if(T) + forceMove(T) + return TRUE + return FALSE + if("y") + var/turf/T = locate(x, var_value, z) + if(T) + forceMove(T) + return TRUE + return FALSE + if("z") + var/turf/T = locate(x, y, var_value) + if(T) + forceMove(T) + return TRUE + return FALSE + if("loc") + if(istype(var_value, /atom)) + forceMove(var_value) + return TRUE + else if(isnull(var_value)) + moveToNullspace() + return TRUE + return FALSE + return ..() + +/atom/movable/proc/start_pulling(atom/movable/AM,gs) + if(QDELETED(AM)) + return FALSE + if(!(AM.can_be_pulled(src))) + return FALSE + + // If we're pulling something then drop what we're currently pulling and pull this instead. + if(pulling) + if(gs==0) + stop_pulling() + return FALSE + // Are we trying to pull something we are already pulling? Then enter grab cycle and end. + if(AM == pulling) + grab_state = gs + if(istype(AM,/mob/living)) + var/mob/living/AMob = AM + AMob.grabbedby(src) + return TRUE + stop_pulling() + if(AM.pulledby) + log_combat(AM, AM.pulledby, "pulled from", src) + AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. + pulling = AM + AM.pulledby = src + grab_state = gs + if(ismob(AM)) + var/mob/M = AM + log_combat(src, M, "grabbed", addition="passive grab") + visible_message("[src] has grabbed [M] passively!") + return TRUE + +/atom/movable/proc/stop_pulling() + if(pulling) + pulling.pulledby = null + var/mob/living/ex_pulled = pulling + pulling = null + grab_state = 0 + if(isliving(ex_pulled)) + var/mob/living/L = ex_pulled + L.update_canmove()// mob gets up if it was lyng down in a chokehold + +/atom/movable/proc/Move_Pulled(atom/A) + if(!pulling) + return + if(pulling.anchored || !pulling.Adjacent(src)) + stop_pulling() + return + if(isliving(pulling)) + var/mob/living/L = pulling + if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it + stop_pulling() + return + if(A == loc && pulling.density) + return + if(!Process_Spacemove(get_dir(pulling.loc, A))) + return + step(pulling, get_dir(pulling.loc, A)) + +/atom/movable/proc/check_pulling() + if(pulling) + var/atom/movable/pullee = pulling + if(pullee && get_dist(src, pullee) > 1) + stop_pulling() + return + if(!isturf(loc)) + stop_pulling() + return + if(pullee && !isturf(pullee.loc) && pullee.loc != loc) //to be removed once all code that changes an object's loc uses forceMove(). + log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") + stop_pulling() + return + if(pulling.anchored) + stop_pulling() + return + +//////////////////////////////////////// +// Here's where we rewrite how byond handles movement except slightly different +// To be removed on step_ conversion +// All this work to prevent a second bump +/atom/movable/Move(atom/newloc, direct=0) + . = FALSE + if(!newloc || newloc == loc) + return + + if(!direct) + direct = get_dir(src, newloc) + setDir(direct) + + if(!loc.Exit(src, newloc)) + return + + if(!newloc.Enter(src, src.loc)) + return + + // Past this is the point of no return + var/atom/oldloc = loc + var/area/oldarea = get_area(oldloc) + var/area/newarea = get_area(newloc) + loc = newloc + . = TRUE + oldloc.Exited(src, newloc) + if(oldarea != newarea) + oldarea.Exited(src, newloc) + + for(var/i in oldloc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Uncrossed(src) + + newloc.Entered(src, oldloc) + if(oldarea != newarea) + newarea.Entered(src, oldloc) + + for(var/i in loc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Crossed(src) +// +//////////////////////////////////////// + +/atom/movable/Move(atom/newloc, direct) + var/atom/movable/pullee = pulling + var/turf/T = loc + if(pulling) + if(pullee && get_dist(src, pullee) > 1) + stop_pulling() + + if(pullee && pullee.loc != loc && !isturf(pullee.loc) ) //to be removed once all code that changes an object's loc uses forceMove(). + log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") + stop_pulling() + if(!loc || !newloc) + return FALSE + var/atom/oldloc = loc + + if(loc != newloc) + if (!(direct & (direct - 1))) //Cardinal move + . = ..() + else //Diagonal move, split it into cardinal moves + moving_diagonally = FIRST_DIAG_STEP + var/first_step_dir + // The `&& moving_diagonally` checks are so that a forceMove taking + // place due to a Crossed, Bumped, etc. call will interrupt + // the second half of the diagonal movement, or the second attempt + // at a first half if step() fails because we hit something. + if (direct & NORTH) + if (direct & EAST) + if (step(src, NORTH) && moving_diagonally) + first_step_dir = NORTH + moving_diagonally = SECOND_DIAG_STEP + . = step(src, EAST) + else if (moving_diagonally && step(src, EAST)) + first_step_dir = EAST + moving_diagonally = SECOND_DIAG_STEP + . = step(src, NORTH) + else if (direct & WEST) + if (step(src, NORTH) && moving_diagonally) + first_step_dir = NORTH + moving_diagonally = SECOND_DIAG_STEP + . = step(src, WEST) + else if (moving_diagonally && step(src, WEST)) + first_step_dir = WEST + moving_diagonally = SECOND_DIAG_STEP + . = step(src, NORTH) + else if (direct & SOUTH) + if (direct & EAST) + if (step(src, SOUTH) && moving_diagonally) + first_step_dir = SOUTH + moving_diagonally = SECOND_DIAG_STEP + . = step(src, EAST) + else if (moving_diagonally && step(src, EAST)) + first_step_dir = EAST + moving_diagonally = SECOND_DIAG_STEP + . = step(src, SOUTH) + else if (direct & WEST) + if (step(src, SOUTH) && moving_diagonally) + first_step_dir = SOUTH + moving_diagonally = SECOND_DIAG_STEP + . = step(src, WEST) + else if (moving_diagonally && step(src, WEST)) + first_step_dir = WEST + moving_diagonally = SECOND_DIAG_STEP + . = step(src, SOUTH) + if(moving_diagonally == SECOND_DIAG_STEP) + if(!.) + setDir(first_step_dir) + else if (!inertia_moving) + inertia_next_move = world.time + inertia_move_delay + newtonian_move(direct) + moving_diagonally = 0 + return + + if(!loc || (loc == oldloc && oldloc != newloc)) + last_move = 0 + return + + if(.) + Moved(oldloc, direct) + if(. && pulling && pulling == pullee) //we were pulling a thing and didn't lose it during our move. + if(pulling.anchored) + stop_pulling() + else + var/pull_dir = get_dir(src, pulling) + //puller and pullee more than one tile away or in diagonal position + if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) + pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position + if(pulling && get_dist(src, pulling) > 1) //the pullee couldn't keep up + stop_pulling() + if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1)//separated from our puller and not in the middle of a diagonal move. + pulledby.stop_pulling() + + + last_move = direct + setDir(direct) + if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s) + return FALSE + +//Called after a successful Move(). By this point, we've already moved +/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE) + SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced) + if (!inertia_moving) + inertia_next_move = world.time + inertia_move_delay + newtonian_move(Dir) + if (length(client_mobs_in_contents)) + update_parallax_contents() + + return TRUE + +/atom/movable/Destroy(force) + QDEL_NULL(proximity_monitor) + QDEL_NULL(language_holder) + + unbuckle_all_mobs(force=1) + + . = ..() + if(loc) + //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) + if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) + CanAtmosPass = ATMOS_PASS_YES + air_update_turf(TRUE) + loc.handle_atom_del(src) + for(var/atom/movable/AM in contents) + qdel(AM) + moveToNullspace() + invisibility = INVISIBILITY_ABSTRACT + if(pulledby) + pulledby.stop_pulling() + + if(orbiting) + orbiting.end_orbit(src) + orbiting = null + +// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly. +// You probably want CanPass() +/atom/movable/Cross(atom/movable/AM) + . = TRUE + SEND_SIGNAL(src, COMSIG_MOVABLE_CROSS, AM) + return CanPass(AM, AM.loc, TRUE) + +//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called! +/atom/movable/Crossed(atom/movable/AM, oldloc) + SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) + +/atom/movable/Uncross(atom/movable/AM, atom/newloc) + . = ..() + if(SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSS, AM) & COMPONENT_MOVABLE_BLOCK_UNCROSS) + return FALSE + if(isturf(newloc) && !CheckExit(AM, newloc)) + return FALSE + +/atom/movable/Uncrossed(atom/movable/AM) + SEND_SIGNAL(src, COMSIG_MOVABLE_UNCROSSED, AM) + +/atom/movable/Bump(atom/A) + if(!A) + CRASH("Bump was called with no argument.") + SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A) + . = ..() + if(!QDELETED(throwing)) + throwing.hit_atom(A) + . = TRUE + if(QDELETED(A)) + return + A.Bumped(src) + +/atom/movable/proc/forceMove(atom/destination) + . = FALSE + if(destination) + . = doMove(destination) + else + CRASH("No valid destination passed into forceMove") + +/atom/movable/proc/moveToNullspace() + return doMove(null) + +/atom/movable/proc/doMove(atom/destination) + . = FALSE + if(destination) + if(pulledby) + pulledby.stop_pulling() + var/atom/oldloc = loc + var/same_loc = oldloc == destination + var/area/old_area = get_area(oldloc) + var/area/destarea = get_area(destination) + + loc = destination + moving_diagonally = 0 + + if(!same_loc) + if(oldloc) + oldloc.Exited(src, destination) + if(old_area && old_area != destarea) + old_area.Exited(src, destination) + for(var/atom/movable/AM in oldloc) + AM.Uncrossed(src) + var/turf/oldturf = get_turf(oldloc) + var/turf/destturf = get_turf(destination) + var/old_z = (oldturf ? oldturf.z : null) + var/dest_z = (destturf ? destturf.z : null) + if (old_z != dest_z) + onTransitZ(old_z, dest_z) + destination.Entered(src, oldloc) + if(destarea && old_area != destarea) + destarea.Entered(src, oldloc) + + for(var/atom/movable/AM in destination) + if(AM == src) + continue + AM.Crossed(src, oldloc) + + Moved(oldloc, NONE, TRUE) + . = TRUE + + //If no destination, move the atom into nullspace (don't do this unless you know what you're doing) + else + . = TRUE + if (loc) + var/atom/oldloc = loc + var/area/old_area = get_area(oldloc) + oldloc.Exited(src, null) + if(old_area) + old_area.Exited(src, null) + loc = null + +/atom/movable/proc/onTransitZ(old_z,new_z) + SEND_SIGNAL(src, COMSIG_MOVABLE_Z_CHANGED, old_z, new_z) + for (var/item in src) // Notify contents of Z-transition. This can be overridden IF we know the items contents do not care. + var/atom/movable/AM = item + AM.onTransitZ(old_z,new_z) + +/atom/movable/proc/setMovetype(newval) + movement_type = newval + +//Called whenever an object moves and by mobs when they attempt to move themselves through space +//And when an object or action applies a force on src, see newtonian_move() below +//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting +//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm +//movement_dir == 0 when stopping or any dir when trying to move +/atom/movable/proc/Process_Spacemove(movement_dir = 0) + if(has_gravity(src)) + return 1 + + if(pulledby) + return 1 + + if(throwing) + return 1 + + if(!isturf(loc)) + return 1 + + if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier + return 1 + + return 0 + + +/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity + if(!loc || Process_Spacemove(0)) + inertia_dir = 0 + return 0 + + inertia_dir = direction + if(!direction) + return 1 + inertia_last_loc = loc + SSspacedrift.processing[src] = src + return 1 + +/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + set waitfor = 0 + SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) + return hit_atom.hitby(src) + +/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked) + if(!anchored && hitpush) + step(src, AM.dir) + ..() + +/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) + return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, messy_throw) + +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) //If this returns FALSE then callback will not be called. + . = FALSE + if (!target || speed <= 0) + return + + if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_THROW, args) & COMPONENT_CANCEL_THROW) + return + + if (pulledby) + pulledby.stop_pulling() + + //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? + if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) + var/user_momentum = thrower.movement_delay() + if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. + user_momentum = world.tick_lag + + user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses. + + if (get_dir(thrower, target) & last_move) + user_momentum = user_momentum //basically a noop, but needed + else if (get_dir(target, thrower) & last_move) + user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly + else + user_momentum = 0 + + + if (user_momentum) + //first lets add that momentum to range. + range *= (user_momentum / speed) + 1 + //then lets add it to speed + speed += user_momentum + if (speed <= 0) + return//no throw speed, the user was moving too fast. + + . = TRUE // No failure conditions past this point. + + var/datum/thrownthing/TT = new() + TT.thrownthing = src + TT.target = target + TT.target_turf = get_turf(target) + TT.init_dir = get_dir(src, target) + TT.maxrange = range + TT.speed = speed + TT.thrower = thrower + TT.diagonals_first = diagonals_first + TT.callback = callback + if(!QDELETED(thrower)) + TT.target_zone = thrower.zone_selected + + var/dist_x = abs(target.x - src.x) + var/dist_y = abs(target.y - src.y) + var/dx = (target.x > src.x) ? EAST : WEST + var/dy = (target.y > src.y) ? NORTH : SOUTH + + if (dist_x == dist_y) + TT.pure_diagonal = 1 + + else if(dist_x <= dist_y) + var/olddist_x = dist_x + var/olddx = dx + dist_x = dist_y + dist_y = olddist_x + dx = dy + dy = olddx + TT.dist_x = dist_x + TT.dist_y = dist_y + TT.dx = dx + TT.dy = dy + TT.diagonal_error = dist_x/2 - dist_y + TT.start_time = world.time + + if(pulledby) + pulledby.stop_pulling() + + throwing = TT + if(spin) + SpinAnimation(5, 1) + + SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, TT, spin) + SSthrowing.processing[src] = TT + if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) + SSthrowing.currentrun[src] = TT + TT.tick() + +/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) + for(var/m in buckled_mobs) + var/mob/living/buckled_mob = m + if(!buckled_mob.Move(newloc, direct)) + forceMove(buckled_mob.loc) + last_move = buckled_mob.last_move + inertia_dir = last_move + buckled_mob.inertia_dir = last_move + return 0 + return 1 + +/atom/movable/CanPass(atom/movable/mover, turf/target) + if(mover in buckled_mobs) + return 1 + return ..() + +// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. +/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) + return + +// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. +/atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S) + return + +/atom/movable/proc/get_spacemove_backup() + var/atom/movable/dense_object_backup + for(var/A in orange(1, get_turf(src))) + if(isarea(A)) + continue + else if(isturf(A)) + var/turf/turf = A + if(!turf.density) + continue + return turf + else + var/atom/movable/AM = A + if(!AM.CanPass(src) || AM.density) + if(AM.anchored) + return AM + dense_object_backup = AM + break + . = dense_object_backup + +//called when a mob resists while inside a container that is itself inside something. +/atom/movable/proc/relay_container_resist(mob/living/user, obj/O) + return + + +/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) + + if(A == src) + return //don't do an animation if attacking self + var/pixel_x_diff = 0 + var/pixel_y_diff = 0 + + var/direction = get_dir(src, A) + if(direction & NORTH) + pixel_y_diff = 8 + else if(direction & SOUTH) + pixel_y_diff = -8 + + if(direction & EAST) + pixel_x_diff = 8 + else if(direction & WEST) + pixel_x_diff = -8 + + var/matrix/OM = matrix(transform) + var/matrix/M = matrix(transform) + M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16)) + + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2) + animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, time = 2) + +/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item) + var/image/I + if(visual_effect_icon) + I = image('icons/effects/effects.dmi', A, visual_effect_icon, A.layer + 0.1) + else if(used_item) + I = image(icon = used_item, loc = A, layer = A.layer + 0.1) + I.plane = GAME_PLANE + + // Scale the icon. + I.transform *= 0.75 + // The icon should not rotate. + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + + // Set the direction of the icon animation. + var/direction = get_dir(src, A) + if(direction & NORTH) + I.pixel_y = -16 + else if(direction & SOUTH) + I.pixel_y = 16 + + if(direction & EAST) + I.pixel_x = -16 + else if(direction & WEST) + I.pixel_x = 16 + + if(!direction) // Attacked self?! + I.pixel_z = 16 + + if(!I) + return + + flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second + + // And animate the attack! + animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) + +/atom/movable/vv_get_dropdown() + . = ..() + . -= "Jump to" + .["Follow"] = "?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]" + .["Get"] = "?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]" + +/atom/movable/proc/ex_check(ex_id) + if(!ex_id) + return TRUE + LAZYINITLIST(acted_explosions) + if(ex_id in acted_explosions) + return FALSE + acted_explosions += ex_id + return TRUE + +//TODO: Better floating +/atom/movable/proc/float(on) + if(throwing) + return + if(on && !(movement_type & FLOATING)) + animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1) + sleep(10) + animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1) + setMovetype(movement_type | FLOATING) + else if (!on && (movement_type & FLOATING)) + animate(src, pixel_y = initial(pixel_y), time = 10) + setMovetype(movement_type & ~FLOATING) + +/* Language procs */ +/atom/movable/proc/get_language_holder(shadow=TRUE) + if(language_holder) + return language_holder + else + language_holder = new initial_language_holder(src) + return language_holder + +/atom/movable/proc/grant_language(datum/language/dt, body = FALSE) + var/datum/language_holder/H = get_language_holder(!body) + H.grant_language(dt, body) + +/atom/movable/proc/grant_all_languages(omnitongue=FALSE) + var/datum/language_holder/H = get_language_holder() + H.grant_all_languages(omnitongue) + +/atom/movable/proc/get_random_understood_language() + var/datum/language_holder/H = get_language_holder() + . = H.get_random_understood_language() + +/atom/movable/proc/remove_language(datum/language/dt, body = FALSE) + var/datum/language_holder/H = get_language_holder(!body) + H.remove_language(dt, body) + +/atom/movable/proc/remove_all_languages() + var/datum/language_holder/H = get_language_holder() + H.remove_all_languages() + +/atom/movable/proc/has_language(datum/language/dt) + var/datum/language_holder/H = get_language_holder() + . = H.has_language(dt) + +/atom/movable/proc/copy_known_languages_from(thing, replace=FALSE) + var/datum/language_holder/H = get_language_holder() + . = H.copy_known_languages_from(thing, replace) + +// Whether an AM can speak in a language or not, independent of whether +// it KNOWS the language +/atom/movable/proc/could_speak_in_language(datum/language/dt) + . = TRUE + +/atom/movable/proc/can_speak_in_language(datum/language/dt) + var/datum/language_holder/H = get_language_holder() + + if(!H.has_language(dt)) + return FALSE + else if(H.omnitongue) + return TRUE + else if(could_speak_in_language(dt) && (!H.only_speaks_language || H.only_speaks_language == dt)) + return TRUE + else + return FALSE + +/atom/movable/proc/get_default_language() + // if no language is specified, and we want to say() something, which + // language do we use? + var/datum/language_holder/H = get_language_holder() + + if(H.selected_default_language) + if(can_speak_in_language(H.selected_default_language)) + return H.selected_default_language + else + H.selected_default_language = null + + + var/datum/language/chosen_langtype + var/highest_priority + + for(var/lt in H.languages) + var/datum/language/langtype = lt + if(!can_speak_in_language(langtype)) + continue + + var/pri = initial(langtype.default_priority) + if(!highest_priority || (pri > highest_priority)) + chosen_langtype = langtype + highest_priority = pri + + H.selected_default_language = . + . = chosen_langtype + +/* End language procs */ +/atom/movable/proc/ConveyorMove(movedir) + set waitfor = FALSE + if(!anchored && has_gravity()) + step(src, movedir) + +//Returns an atom's power cell, if it has one. Overload for individual items. +/atom/movable/proc/get_cell() + return + +/atom/movable/proc/can_be_pulled(user) + if(src == user || !isturf(loc)) + return FALSE + if(anchored || throwing) + return FALSE + return TRUE + + +/obj/item/proc/do_pickup_animation(atom/target) + set waitfor = FALSE + if(!istype(loc, /turf)) + return + var/image/I = image(icon = src, loc = loc, layer = layer + 0.1) + I.plane = GAME_PLANE + I.transform *= 0.75 + I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + var/turf/T = get_turf(src) + var/direction + var/to_x = 0 + var/to_y = 0 + + if(!QDELETED(T) && !QDELETED(target)) + direction = get_dir(T, target) + if(direction & NORTH) + to_y = 32 + else if(direction & SOUTH) + to_y = -32 + if(direction & EAST) + to_x = 32 + else if(direction & WEST) + to_x = -32 + if(!direction) + to_y = 16 + flick_overlay(I, GLOB.clients, 6) + var/matrix/M = new + M.Turn(pick(-30, 30)) + animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) + sleep(1) + animate(I, alpha = 0, transform = matrix(), time = 1) diff --git a/code/game/communications.dm b/code/game/communications.dm index ed470473d9..696b942434 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -1,199 +1,199 @@ -/* - HOW IT WORKS - - The SSradio is a global object maintaining all radio transmissions, think about it as about "ether". - Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way. - procs: - - add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null) - Adds listening object. - parameters: - device - device receiving signals, must have proc receive_signal (see description below). - one device may listen several frequencies, but not same frequency twice. - new_frequency - see possibly frequencies below; - filter - thing for optimization. Optional, but recommended. - All filters should be consolidated in this file, see defines later. - Device without listening filter will receive all signals (on specified frequency). - Device with filter will receive any signals sent without filter. - Device with filter will not receive any signals sent with different filter. - returns: - Reference to frequency object. - - remove_object (obj/device, old_frequency) - Obliviously, after calling this proc, device will not receive any signals on old_frequency. - Other frequencies will left unaffected. - - return_frequency(var/frequency as num) - returns: - Reference to frequency object. Use it if you need to send and do not need to listen. - - radio_frequency is a global object maintaining list of devices that listening specific frequency. - procs: - - post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null) - Sends signal to all devices that wants such signal. - parameters: - source - object, emitted signal. Usually, devices will not receive their own signals. - signal - see description below. - filter - described above. - range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels. - - obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param) - Handler from received signals. By default does nothing. Define your own for your object. - Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please. - parameters: - signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return! - receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO. - TRANSMISSION_WIRE is currently unused. - receive_param - for TRANSMISSION_RADIO here comes frequency. - - datum/signal - vars: - source - an object that emitted signal. Used for debug and bearing. - data - list with transmitting data. Usual use pattern: - data["msg"] = "hello world" - encryption - Some number symbolizing "encryption key". - Note that game actually do not use any cryptography here. - If receiving object don't know right key, it must ignore encrypted signal in its receive_signal. - -*/ -/* the radio controller is a confusing piece of shit and didnt work - so i made radios not use the radio controller. -*/ -GLOBAL_LIST_EMPTY(all_radios) -/proc/add_radio(obj/item/radio, freq) - if(!freq || !radio) - return - if(!GLOB.all_radios["[freq]"]) - GLOB.all_radios["[freq]"] = list(radio) - return freq - - GLOB.all_radios["[freq]"] |= radio - return freq - -/proc/remove_radio(obj/item/radio, freq) - if(!freq || !radio) - return - if(!GLOB.all_radios["[freq]"]) - return - - GLOB.all_radios["[freq]"] -= radio - -/proc/remove_radio_all(obj/item/radio) - for(var/freq in GLOB.all_radios) - GLOB.all_radios["[freq]"] -= radio - -// For information on what objects or departments use what frequencies, -// see __DEFINES/radio.dm. Mappers may also select additional frequencies for -// use in maps, such as in intercoms. - -GLOBAL_LIST_INIT(radiochannels, list( - RADIO_CHANNEL_COMMON = FREQ_COMMON, - RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE, - RADIO_CHANNEL_COMMAND = FREQ_COMMAND, - RADIO_CHANNEL_MEDICAL = FREQ_MEDICAL, - RADIO_CHANNEL_ENGINEERING = FREQ_ENGINEERING, - RADIO_CHANNEL_SECURITY = FREQ_SECURITY, - RADIO_CHANNEL_CENTCOM = FREQ_CENTCOM, - RADIO_CHANNEL_SYNDICATE = FREQ_SYNDICATE, - RADIO_CHANNEL_SUPPLY = FREQ_SUPPLY, - RADIO_CHANNEL_SERVICE = FREQ_SERVICE, - RADIO_CHANNEL_AI_PRIVATE = FREQ_AI_PRIVATE, - RADIO_CHANNEL_CTF_RED = FREQ_CTF_RED, - RADIO_CHANNEL_CTF_BLUE = FREQ_CTF_BLUE -)) - -GLOBAL_LIST_INIT(reverseradiochannels, list( - "[FREQ_COMMON]" = RADIO_CHANNEL_COMMON, - "[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE, - "[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND, - "[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL, - "[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING, - "[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY, - "[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM, - "[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE, - "[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY, - "[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE, - "[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE, - "[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED, - "[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE -)) - -/datum/radio_frequency - var/frequency as num - var/list/list/obj/devices = list() - -/datum/radio_frequency/New(freq) - frequency = freq - -//If range > 0, only post to devices on the same z_level and within range -//Use range = -1, to restrain to the same z_level without limiting range -/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null) - // Ensure the signal's data is fully filled - signal.source = source - signal.frequency = frequency - - //Apply filter to the signal. If none supply, broadcast to every devices - //_default channel is always checked - var/list/filter_list - - if(filter) - filter_list = list(filter,"_default") - else - filter_list = devices - - //If checking range, find the source turf - var/turf/start_point - if(range) - start_point = get_turf(source) - if(!start_point) - return 0 - - //Send the data - for(var/current_filter in filter_list) - for(var/obj/device in devices[current_filter]) - if(device == source) - continue - if(range) - var/turf/end_point = get_turf(device) - if(!end_point) - continue - if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range)) - continue - device.receive_signal(signal) - -/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null) - if (!filter) - filter = "_default" - - var/list/devices_line = devices[filter] - if(!devices_line) - devices[filter] = devices_line = list() - devices_line += device - - -/datum/radio_frequency/proc/remove_listener(obj/device) - for(var/devices_filter in devices) - var/list/devices_line = devices[devices_filter] - if(!devices_line) - devices -= devices_filter - devices_line -= device - if(!devices_line.len) - devices -= devices_filter - - -/obj/proc/receive_signal(datum/signal/signal) - return - -/datum/signal - var/obj/source - var/frequency = 0 - var/transmission_method - var/list/data - -/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO) - src.data = data || list() - src.transmission_method = transmission_method +/* + HOW IT WORKS + + The SSradio is a global object maintaining all radio transmissions, think about it as about "ether". + Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way. + procs: + + add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null) + Adds listening object. + parameters: + device - device receiving signals, must have proc receive_signal (see description below). + one device may listen several frequencies, but not same frequency twice. + new_frequency - see possibly frequencies below; + filter - thing for optimization. Optional, but recommended. + All filters should be consolidated in this file, see defines later. + Device without listening filter will receive all signals (on specified frequency). + Device with filter will receive any signals sent without filter. + Device with filter will not receive any signals sent with different filter. + returns: + Reference to frequency object. + + remove_object (obj/device, old_frequency) + Obliviously, after calling this proc, device will not receive any signals on old_frequency. + Other frequencies will left unaffected. + + return_frequency(var/frequency as num) + returns: + Reference to frequency object. Use it if you need to send and do not need to listen. + + radio_frequency is a global object maintaining list of devices that listening specific frequency. + procs: + + post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null) + Sends signal to all devices that wants such signal. + parameters: + source - object, emitted signal. Usually, devices will not receive their own signals. + signal - see description below. + filter - described above. + range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels. + + obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param) + Handler from received signals. By default does nothing. Define your own for your object. + Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please. + parameters: + signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return! + receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO. + TRANSMISSION_WIRE is currently unused. + receive_param - for TRANSMISSION_RADIO here comes frequency. + + datum/signal + vars: + source + an object that emitted signal. Used for debug and bearing. + data + list with transmitting data. Usual use pattern: + data["msg"] = "hello world" + encryption + Some number symbolizing "encryption key". + Note that game actually do not use any cryptography here. + If receiving object don't know right key, it must ignore encrypted signal in its receive_signal. + +*/ +/* the radio controller is a confusing piece of shit and didnt work + so i made radios not use the radio controller. +*/ +GLOBAL_LIST_EMPTY(all_radios) +/proc/add_radio(obj/item/radio, freq) + if(!freq || !radio) + return + if(!GLOB.all_radios["[freq]"]) + GLOB.all_radios["[freq]"] = list(radio) + return freq + + GLOB.all_radios["[freq]"] |= radio + return freq + +/proc/remove_radio(obj/item/radio, freq) + if(!freq || !radio) + return + if(!GLOB.all_radios["[freq]"]) + return + + GLOB.all_radios["[freq]"] -= radio + +/proc/remove_radio_all(obj/item/radio) + for(var/freq in GLOB.all_radios) + GLOB.all_radios["[freq]"] -= radio + +// For information on what objects or departments use what frequencies, +// see __DEFINES/radio.dm. Mappers may also select additional frequencies for +// use in maps, such as in intercoms. + +GLOBAL_LIST_INIT(radiochannels, list( + RADIO_CHANNEL_COMMON = FREQ_COMMON, + RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE, + RADIO_CHANNEL_COMMAND = FREQ_COMMAND, + RADIO_CHANNEL_MEDICAL = FREQ_MEDICAL, + RADIO_CHANNEL_ENGINEERING = FREQ_ENGINEERING, + RADIO_CHANNEL_SECURITY = FREQ_SECURITY, + RADIO_CHANNEL_CENTCOM = FREQ_CENTCOM, + RADIO_CHANNEL_SYNDICATE = FREQ_SYNDICATE, + RADIO_CHANNEL_SUPPLY = FREQ_SUPPLY, + RADIO_CHANNEL_SERVICE = FREQ_SERVICE, + RADIO_CHANNEL_AI_PRIVATE = FREQ_AI_PRIVATE, + RADIO_CHANNEL_CTF_RED = FREQ_CTF_RED, + RADIO_CHANNEL_CTF_BLUE = FREQ_CTF_BLUE +)) + +GLOBAL_LIST_INIT(reverseradiochannels, list( + "[FREQ_COMMON]" = RADIO_CHANNEL_COMMON, + "[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE, + "[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND, + "[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL, + "[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING, + "[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY, + "[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM, + "[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE, + "[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY, + "[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE, + "[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE, + "[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED, + "[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE +)) + +/datum/radio_frequency + var/frequency as num + var/list/list/obj/devices = list() + +/datum/radio_frequency/New(freq) + frequency = freq + +//If range > 0, only post to devices on the same z_level and within range +//Use range = -1, to restrain to the same z_level without limiting range +/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null) + // Ensure the signal's data is fully filled + signal.source = source + signal.frequency = frequency + + //Apply filter to the signal. If none supply, broadcast to every devices + //_default channel is always checked + var/list/filter_list + + if(filter) + filter_list = list(filter,"_default") + else + filter_list = devices + + //If checking range, find the source turf + var/turf/start_point + if(range) + start_point = get_turf(source) + if(!start_point) + return 0 + + //Send the data + for(var/current_filter in filter_list) + for(var/obj/device in devices[current_filter]) + if(device == source) + continue + if(range) + var/turf/end_point = get_turf(device) + if(!end_point) + continue + if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range)) + continue + device.receive_signal(signal) + +/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null) + if (!filter) + filter = "_default" + + var/list/devices_line = devices[filter] + if(!devices_line) + devices[filter] = devices_line = list() + devices_line += device + + +/datum/radio_frequency/proc/remove_listener(obj/device) + for(var/devices_filter in devices) + var/list/devices_line = devices[devices_filter] + if(!devices_line) + devices -= devices_filter + devices_line -= device + if(!devices_line.len) + devices -= devices_filter + + +/obj/proc/receive_signal(datum/signal/signal) + return + +/datum/signal + var/obj/source + var/frequency = 0 + var/transmission_method + var/list/data + +/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO) + src.data = data || list() + src.transmission_method = transmission_method diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 8bbe7f54ed..df4a38cf60 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -1,72 +1,72 @@ -/datum/game_mode - var/list/datum/mind/brothers = list() - var/list/datum/team/brother_team/brother_teams = list() - -/datum/game_mode/traitor/bros - name = "traitor+brothers" - config_tag = "traitorbro" - restricted_jobs = list("AI", "Cyborg") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") - - announce_span = "danger" - announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\ - Traitors: Accomplish your objectives.\n\ - Blood Brothers: Accomplish your objectives.\n\ - Crew: Do not let the traitors or brothers succeed!" - - var/list/datum/team/brother_team/pre_brother_teams = list() - var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off - var/const/min_team_size = 2 - traitors_required = FALSE //Only teams are possible - -/datum/game_mode/traitor/bros/pre_setup() - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - - var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER) - - var/num_teams = team_amount - var/bsc = CONFIG_GET(number/brother_scaling_coeff) - if(bsc) - num_teams = max(1, round(num_players() / bsc)) - - for(var/j = 1 to num_teams) - if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies) - break - var/datum/team/brother_team/team = new - var/team_size = prob(10) ? min(3, possible_brothers.len) : 2 - for(var/k = 1 to team_size) - var/datum/mind/bro = antag_pick(possible_brothers) - possible_brothers -= bro - antag_candidates -= bro - team.add_member(bro) - bro.special_role = "brother" - bro.restricted_roles = restricted_jobs - log_game("[key_name(bro)] has been selected as a Brother") - pre_brother_teams += team - return ..() - -/datum/game_mode/traitor/bros/post_setup() - for(var/datum/team/brother_team/team in pre_brother_teams) - team.pick_meeting_area() - team.forge_brother_objectives() - for(var/datum/mind/M in team.members) - M.add_antag_datum(/datum/antagonist/brother, team) - team.update_name() - brother_teams += pre_brother_teams - return ..() - -/datum/game_mode/traitor/bros/generate_report() - return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." - -/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind) - var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] - brotherhud.join_hud(brother_mind.current) - set_antag_hud(brother_mind.current, "brother") - -/datum/game_mode/proc/update_brother_icons_removed(datum/mind/brother_mind) - var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] - brotherhud.leave_hud(brother_mind.current) - set_antag_hud(brother_mind.current, null) +/datum/game_mode + var/list/datum/mind/brothers = list() + var/list/datum/team/brother_team/brother_teams = list() + +/datum/game_mode/traitor/bros + name = "traitor+brothers" + config_tag = "traitorbro" + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") + + announce_span = "danger" + announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\ + Traitors: Accomplish your objectives.\n\ + Blood Brothers: Accomplish your objectives.\n\ + Crew: Do not let the traitors or brothers succeed!" + + var/list/datum/team/brother_team/pre_brother_teams = list() + var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off + var/const/min_team_size = 2 + traitors_required = FALSE //Only teams are possible + +/datum/game_mode/traitor/bros/pre_setup() + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER) + + var/num_teams = team_amount + var/bsc = CONFIG_GET(number/brother_scaling_coeff) + if(bsc) + num_teams = max(1, round(num_players() / bsc)) + + for(var/j = 1 to num_teams) + if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies) + break + var/datum/team/brother_team/team = new + var/team_size = prob(10) ? min(3, possible_brothers.len) : 2 + for(var/k = 1 to team_size) + var/datum/mind/bro = antag_pick(possible_brothers) + possible_brothers -= bro + antag_candidates -= bro + team.add_member(bro) + bro.special_role = "brother" + bro.restricted_roles = restricted_jobs + log_game("[key_name(bro)] has been selected as a Brother") + pre_brother_teams += team + return ..() + +/datum/game_mode/traitor/bros/post_setup() + for(var/datum/team/brother_team/team in pre_brother_teams) + team.pick_meeting_area() + team.forge_brother_objectives() + for(var/datum/mind/M in team.members) + M.add_antag_datum(/datum/antagonist/brother, team) + team.update_name() + brother_teams += pre_brother_teams + return ..() + +/datum/game_mode/traitor/bros/generate_report() + return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." + +/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind) + var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] + brotherhud.join_hud(brother_mind.current) + set_antag_hud(brother_mind.current, "brother") + +/datum/game_mode/proc/update_brother_icons_removed(datum/mind/brother_mind) + var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] + brotherhud.leave_hud(brother_mind.current) + set_antag_hud(brother_mind.current, null) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index d6131ce58e..14fe960422 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,127 +1,127 @@ -GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")) -GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")) -GLOBAL_LIST_INIT(slot2slot, list("head" = SLOT_HEAD, "wear_mask" = SLOT_WEAR_MASK, "neck" = SLOT_NECK, "back" = SLOT_BACK, "wear_suit" = SLOT_WEAR_SUIT, "w_uniform" = SLOT_W_UNIFORM, "shoes" = SLOT_SHOES, "belt" = SLOT_BELT, "gloves" = SLOT_GLOVES, "glasses" = SLOT_GLASSES, "ears" = SLOT_EARS, "wear_id" = SLOT_WEAR_ID, "s_store" = SLOT_S_STORE)) -GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling)) -GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings - - -/datum/game_mode/changeling - name = "changeling" - config_tag = "changeling" - antag_flag = ROLE_CHANGELING - false_report_weight = 10 - restricted_jobs = list("AI", "Cyborg") - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist - required_players = 15 - required_enemies = 1 - recommended_enemies = 4 - reroll_friendly = 1 - - announce_span = "green" - announce_text = "Alien changelings have infiltrated the crew!\n\ - Changelings: Accomplish the objectives assigned to you.\n\ - Crew: Root out and eliminate the changeling menace." - - var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off - var/list/changelings = list() - -/datum/game_mode/changeling/pre_setup() - - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - - var/num_changelings = 1 - - var/csc = CONFIG_GET(number/changeling_scaling_coeff) - if(csc) - num_changelings = max(1, min(round(num_players() / (csc * 2)) + 2, round(num_players() / csc))) - else - num_changelings = max(1, min(num_players(), changeling_amount)) - - if(antag_candidates.len>0) - for(var/i = 0, i < num_changelings, i++) - if(!antag_candidates.len) - break - var/datum/mind/changeling = antag_pick(antag_candidates) - antag_candidates -= changeling - changelings += changeling - changeling.special_role = ROLE_CHANGELING - changeling.restricted_roles = restricted_jobs - return 1 - else - setup_error = "Not enough changeling candidates" - return 0 - -/datum/game_mode/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - log_game("[key_name(changeling)] has been selected as a changeling") - var/datum/antagonist/changeling/new_antag = new() - new_antag.team_mode = TRUE - changeling.add_antag_datum(new_antag) - ..() - -/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners - var/csc = CONFIG_GET(number/changeling_scaling_coeff) - var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc)) - if(changelings.len >= changelingcap) //Caps number of latejoin antagonists - return - if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2))) - if(ROLE_CHANGELING in character.client.prefs.be_special) - if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - character.mind.make_Changeling() - changelings += character.mind - -/datum/game_mode/changeling/generate_report() - return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \ - codenamed \"Thing\", and it was highly adaptive and extremely dangerous. We have reason to believe that the Thing has allied with the Syndicate, and you should note that likelihood \ - of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \ - as paranoia may spread and inhibit workplace efficiency." - -/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof) - var/datum/dna/chosen_dna = chosen_prof.dna - user.real_name = chosen_prof.name - user.underwear = chosen_prof.underwear - user.undie_color = chosen_prof.undie_color - user.undershirt = chosen_prof.undershirt - user.shirt_color =chosen_prof.shirt_color - user.socks = chosen_prof.socks - user.socks_color =chosen_prof.socks_color - - chosen_dna.transfer_identity(user, 1) - user.updateappearance(mutcolor_update=1) - user.update_body() - user.domutcheck() - - //vars hackery. not pretty, but better than the alternative. - for(var/slot in GLOB.slots) - if(istype(user.vars[slot], GLOB.slot2type[slot]) && !(chosen_prof.exists_list[slot])) //remove unnecessary flesh items - qdel(user.vars[slot]) - continue - - if((user.vars[slot] && !istype(user.vars[slot], GLOB.slot2type[slot])) || !(chosen_prof.exists_list[slot])) - continue - - var/obj/item/C - var/equip = 0 - if(!user.vars[slot]) - var/thetype = GLOB.slot2type[slot] - equip = 1 - C = new thetype(user) - - else if(istype(user.vars[slot], GLOB.slot2type[slot])) - C = user.vars[slot] - - C.appearance = chosen_prof.appearance_list[slot] - C.name = chosen_prof.name_list[slot] - C.flags_cover = chosen_prof.flags_cover_list[slot] - C.item_color = chosen_prof.item_color_list[slot] - C.item_state = chosen_prof.item_state_list[slot] - if(equip) - user.equip_to_slot_or_del(C, GLOB.slot2slot[slot]) - - user.regenerate_icons() +GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")) +GLOBAL_LIST_INIT(slots, list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store")) +GLOBAL_LIST_INIT(slot2slot, list("head" = SLOT_HEAD, "wear_mask" = SLOT_WEAR_MASK, "neck" = SLOT_NECK, "back" = SLOT_BACK, "wear_suit" = SLOT_WEAR_SUIT, "w_uniform" = SLOT_W_UNIFORM, "shoes" = SLOT_SHOES, "belt" = SLOT_BELT, "gloves" = SLOT_GLOVES, "glasses" = SLOT_GLASSES, "ears" = SLOT_EARS, "wear_id" = SLOT_WEAR_ID, "s_store" = SLOT_S_STORE)) +GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "wear_mask" = /obj/item/clothing/mask/changeling, "back" = /obj/item/changeling, "wear_suit" = /obj/item/clothing/suit/changeling, "w_uniform" = /obj/item/clothing/under/changeling, "shoes" = /obj/item/clothing/shoes/changeling, "belt" = /obj/item/changeling, "gloves" = /obj/item/clothing/gloves/changeling, "glasses" = /obj/item/clothing/glasses/changeling, "ears" = /obj/item/changeling, "wear_id" = /obj/item/changeling, "s_store" = /obj/item/changeling)) +GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our this objective to all lings + + +/datum/game_mode/changeling + name = "changeling" + config_tag = "changeling" + antag_flag = ROLE_CHANGELING + false_report_weight = 10 + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist + required_players = 15 + required_enemies = 1 + recommended_enemies = 4 + reroll_friendly = 1 + + announce_span = "green" + announce_text = "Alien changelings have infiltrated the crew!\n\ + Changelings: Accomplish the objectives assigned to you.\n\ + Crew: Root out and eliminate the changeling menace." + + var/const/changeling_amount = 4 //hard limit on changelings if scaling is turned off + var/list/changelings = list() + +/datum/game_mode/changeling/pre_setup() + + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + var/num_changelings = 1 + + var/csc = CONFIG_GET(number/changeling_scaling_coeff) + if(csc) + num_changelings = max(1, min(round(num_players() / (csc * 2)) + 2, round(num_players() / csc))) + else + num_changelings = max(1, min(num_players(), changeling_amount)) + + if(antag_candidates.len>0) + for(var/i = 0, i < num_changelings, i++) + if(!antag_candidates.len) + break + var/datum/mind/changeling = antag_pick(antag_candidates) + antag_candidates -= changeling + changelings += changeling + changeling.special_role = ROLE_CHANGELING + changeling.restricted_roles = restricted_jobs + return 1 + else + setup_error = "Not enough changeling candidates" + return 0 + +/datum/game_mode/changeling/post_setup() + for(var/datum/mind/changeling in changelings) + log_game("[key_name(changeling)] has been selected as a changeling") + var/datum/antagonist/changeling/new_antag = new() + new_antag.team_mode = TRUE + changeling.add_antag_datum(new_antag) + ..() + +/datum/game_mode/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners + var/csc = CONFIG_GET(number/changeling_scaling_coeff) + var/changelingcap = min(round(GLOB.joined_player_list.len / (csc * 2)) + 2, round(GLOB.joined_player_list.len / csc)) + if(changelings.len >= changelingcap) //Caps number of latejoin antagonists + return + if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2))) + if(ROLE_CHANGELING in character.client.prefs.be_special) + if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) + if(age_check(character.client)) + if(!(character.job in restricted_jobs)) + character.mind.make_Changeling() + changelings += character.mind + +/datum/game_mode/changeling/generate_report() + return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \ + codenamed \"Thing\", and it was highly adaptive and extremely dangerous. We have reason to believe that the Thing has allied with the Syndicate, and you should note that likelihood \ + of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \ + as paranoia may spread and inhibit workplace efficiency." + +/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof) + var/datum/dna/chosen_dna = chosen_prof.dna + user.real_name = chosen_prof.name + user.underwear = chosen_prof.underwear + user.undie_color = chosen_prof.undie_color + user.undershirt = chosen_prof.undershirt + user.shirt_color =chosen_prof.shirt_color + user.socks = chosen_prof.socks + user.socks_color =chosen_prof.socks_color + + chosen_dna.transfer_identity(user, 1) + user.updateappearance(mutcolor_update=1) + user.update_body() + user.domutcheck() + + //vars hackery. not pretty, but better than the alternative. + for(var/slot in GLOB.slots) + if(istype(user.vars[slot], GLOB.slot2type[slot]) && !(chosen_prof.exists_list[slot])) //remove unnecessary flesh items + qdel(user.vars[slot]) + continue + + if((user.vars[slot] && !istype(user.vars[slot], GLOB.slot2type[slot])) || !(chosen_prof.exists_list[slot])) + continue + + var/obj/item/C + var/equip = 0 + if(!user.vars[slot]) + var/thetype = GLOB.slot2type[slot] + equip = 1 + C = new thetype(user) + + else if(istype(user.vars[slot], GLOB.slot2type[slot])) + C = user.vars[slot] + + C.appearance = chosen_prof.appearance_list[slot] + C.name = chosen_prof.name_list[slot] + C.flags_cover = chosen_prof.flags_cover_list[slot] + C.item_color = chosen_prof.item_color_list[slot] + C.item_state = chosen_prof.item_state_list[slot] + if(equip) + user.equip_to_slot_or_del(C, GLOB.slot2slot[slot]) + + user.regenerate_icons() diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index 3f5abe531b..b010b08bc3 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -1,84 +1,84 @@ -/datum/game_mode/traitor/changeling - name = "traitor+changeling" - config_tag = "traitorchan" - false_report_weight = 10 - traitors_possible = 3 //hard limit on traitors if scaling is turned off - restricted_jobs = list("AI", "Cyborg") - required_players = 25 - required_enemies = 1 // how many of each type are required - recommended_enemies = 3 - reroll_friendly = 1 - - var/list/possible_changelings = list() - var/list/changelings = list() - var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off - -/datum/game_mode/traitor/changeling/announce() - to_chat(world, "The current game mode is - Traitor+Changeling!") - to_chat(world, "There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!") - -/datum/game_mode/traitor/changeling/can_start() - if(!..()) - return 0 - possible_changelings = get_players_for_role(ROLE_CHANGELING) - if(possible_changelings.len < required_enemies) - return 0 - return 1 - -/datum/game_mode/traitor/changeling/pre_setup() - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - - var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) - - var/num_changelings = 1 - - var/csc = CONFIG_GET(number/changeling_scaling_coeff) - if(csc) - num_changelings = max(1, min(round(num_players() / (csc * 4)) + 2, round(num_players() / (csc * 2)))) - else - num_changelings = max(1, min(num_players(), changeling_amount/2)) - - if(possible_changelings.len>0) - for(var/j = 0, j < num_changelings, j++) - if(!possible_changelings.len) - break - var/datum/mind/changeling = antag_pick(possible_changelings) - antag_candidates -= changeling - possible_changelings -= changeling - changeling.special_role = ROLE_CHANGELING - changelings += changeling - changeling.restricted_roles = restricted_jobs - return ..() - else - return 0 - -/datum/game_mode/traitor/changeling/post_setup() - for(var/datum/mind/changeling in changelings) - changeling.add_antag_datum(/datum/antagonist/changeling) - return ..() - -/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners - var/csc = CONFIG_GET(number/changeling_scaling_coeff) - var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2))) - if(changelings.len >= changelingcap) //Caps number of latejoin antagonists - ..() - return - if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4))) - if(ROLE_CHANGELING in character.client.prefs.be_special) - if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - character.mind.make_Changeling() - changelings += character.mind - if(QDELETED(character)) - return - ..() - -/datum/game_mode/traitor/changeling/generate_report() - return "The Syndicate has started some experimental research regarding humanoid shapeshifting. There are rumors that this technology will be field tested on a Nanotrasen station \ - for infiltration purposes. Be advised that support personel may also be deployed to defend these shapeshifters. Trust nobody - suspect everybody. Do not announce this to the crew, \ - as paranoia may spread and inhibit workplace efficiency." +/datum/game_mode/traitor/changeling + name = "traitor+changeling" + config_tag = "traitorchan" + false_report_weight = 10 + traitors_possible = 3 //hard limit on traitors if scaling is turned off + restricted_jobs = list("AI", "Cyborg") + required_players = 25 + required_enemies = 1 // how many of each type are required + recommended_enemies = 3 + reroll_friendly = 1 + + var/list/possible_changelings = list() + var/list/changelings = list() + var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off + +/datum/game_mode/traitor/changeling/announce() + to_chat(world, "The current game mode is - Traitor+Changeling!") + to_chat(world, "There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!") + +/datum/game_mode/traitor/changeling/can_start() + if(!..()) + return 0 + possible_changelings = get_players_for_role(ROLE_CHANGELING) + if(possible_changelings.len < required_enemies) + return 0 + return 1 + +/datum/game_mode/traitor/changeling/pre_setup() + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) + + var/num_changelings = 1 + + var/csc = CONFIG_GET(number/changeling_scaling_coeff) + if(csc) + num_changelings = max(1, min(round(num_players() / (csc * 4)) + 2, round(num_players() / (csc * 2)))) + else + num_changelings = max(1, min(num_players(), changeling_amount/2)) + + if(possible_changelings.len>0) + for(var/j = 0, j < num_changelings, j++) + if(!possible_changelings.len) + break + var/datum/mind/changeling = antag_pick(possible_changelings) + antag_candidates -= changeling + possible_changelings -= changeling + changeling.special_role = ROLE_CHANGELING + changelings += changeling + changeling.restricted_roles = restricted_jobs + return ..() + else + return 0 + +/datum/game_mode/traitor/changeling/post_setup() + for(var/datum/mind/changeling in changelings) + changeling.add_antag_datum(/datum/antagonist/changeling) + return ..() + +/datum/game_mode/traitor/changeling/make_antag_chance(mob/living/carbon/human/character) //Assigns changeling to latejoiners + var/csc = CONFIG_GET(number/changeling_scaling_coeff) + var/changelingcap = min( round(GLOB.joined_player_list.len / (csc * 4)) + 2, round(GLOB.joined_player_list.len / (csc * 2))) + if(changelings.len >= changelingcap) //Caps number of latejoin antagonists + ..() + return + if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4))) + if(ROLE_CHANGELING in character.client.prefs.be_special) + if(!jobban_isbanned(character, ROLE_CHANGELING) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) + if(age_check(character.client)) + if(!(character.job in restricted_jobs)) + character.mind.make_Changeling() + changelings += character.mind + if(QDELETED(character)) + return + ..() + +/datum/game_mode/traitor/changeling/generate_report() + return "The Syndicate has started some experimental research regarding humanoid shapeshifting. There are rumors that this technology will be field tested on a Nanotrasen station \ + for infiltration purposes. Be advised that support personel may also be deployed to defend these shapeshifters. Trust nobody - suspect everybody. Do not announce this to the crew, \ + as paranoia may spread and inhibit workplace efficiency." diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index 8d3254933a..d010da465e 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -1,82 +1,82 @@ -/proc/power_failure() - priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff") - for(var/obj/machinery/power/smes/S in GLOB.machines) - if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z)) - continue - S.charge = 0 - S.output_level = 0 - S.output_attempt = 0 - S.update_icon() - S.power_change() - - var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai) - - for(var/area/A in world) - if( !A.requires_power || A.always_unpowered ) - continue - - var/skip = 0 - for(var/area_type in skipped_areas) - if(istype(A,area_type)) - skip = 1 - break - if(A.contents) - for(var/atom/AT in A.contents) - if(!is_station_level(AT.z)) //Only check one, it's enough. - skip = 1 - break - if(skip) - continue - A.power_light = FALSE - A.power_equip = FALSE - A.power_environ = FALSE - A.power_change() - - for(var/obj/machinery/power/apc/C in GLOB.apcs_list) - if(C.cell && is_station_level(C.z)) - var/area/A = C.area - - var/skip = 0 - for(var/area_type in skipped_areas) - if(istype(A,area_type)) - skip = 1 - break - if(skip) - continue - - C.cell.charge = 0 - -/proc/power_restore() - - priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", "poweron") - for(var/obj/machinery/power/apc/C in GLOB.machines) - if(C.cell && is_station_level(C.z)) - C.cell.charge = C.cell.maxcharge - C.failure_timer = 0 - for(var/obj/machinery/power/smes/S in GLOB.machines) - if(!is_station_level(S.z)) - continue - S.charge = S.capacity - S.output_level = S.output_level_max - S.output_attempt = 1 - S.update_icon() - S.power_change() - for(var/area/A in world) - if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival)) - A.power_light = TRUE - A.power_equip = TRUE - A.power_environ = TRUE - A.power_change() - -/proc/power_restore_quick() - - priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", "poweron") - for(var/obj/machinery/power/smes/S in GLOB.machines) - if(!is_station_level(S.z)) - continue - S.charge = S.capacity - S.output_level = S.output_level_max - S.output_attempt = 1 - S.update_icon() - S.power_change() - +/proc/power_failure() + priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff") + for(var/obj/machinery/power/smes/S in GLOB.machines) + if(istype(get_area(S), /area/ai_monitored/turret_protected) || !is_station_level(S.z)) + continue + S.charge = 0 + S.output_level = 0 + S.output_attempt = 0 + S.update_icon() + S.power_change() + + var/list/skipped_areas = list(/area/engine/engineering, /area/engine/supermatter, /area/engine/atmospherics_engine, /area/ai_monitored/turret_protected/ai) + + for(var/area/A in world) + if( !A.requires_power || A.always_unpowered ) + continue + + var/skip = 0 + for(var/area_type in skipped_areas) + if(istype(A,area_type)) + skip = 1 + break + if(A.contents) + for(var/atom/AT in A.contents) + if(!is_station_level(AT.z)) //Only check one, it's enough. + skip = 1 + break + if(skip) + continue + A.power_light = FALSE + A.power_equip = FALSE + A.power_environ = FALSE + A.power_change() + + for(var/obj/machinery/power/apc/C in GLOB.apcs_list) + if(C.cell && is_station_level(C.z)) + var/area/A = C.area + + var/skip = 0 + for(var/area_type in skipped_areas) + if(istype(A,area_type)) + skip = 1 + break + if(skip) + continue + + C.cell.charge = 0 + +/proc/power_restore() + + priority_announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", "poweron") + for(var/obj/machinery/power/apc/C in GLOB.machines) + if(C.cell && is_station_level(C.z)) + C.cell.charge = C.cell.maxcharge + C.failure_timer = 0 + for(var/obj/machinery/power/smes/S in GLOB.machines) + if(!is_station_level(S.z)) + continue + S.charge = S.capacity + S.output_level = S.output_level_max + S.output_attempt = 1 + S.update_icon() + S.power_change() + for(var/area/A in world) + if(!istype(A, /area/space) && !istype(A, /area/shuttle) && !istype(A, /area/arrival)) + A.power_light = TRUE + A.power_equip = TRUE + A.power_environ = TRUE + A.power_change() + +/proc/power_restore_quick() + + priority_announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", "poweron") + for(var/obj/machinery/power/smes/S in GLOB.machines) + if(!is_station_level(S.z)) + continue + S.charge = S.capacity + S.output_level = S.output_level_max + S.output_attempt = 1 + S.update_icon() + S.power_change() + diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 1229a9cf8c..976f3e3eca 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,32 +1,32 @@ -/datum/game_mode/extended - name = "secret extended" - config_tag = "secret_extended" - false_report_weight = 5 - required_players = 0 - - announce_span = "notice" - announce_text = "Just have fun and enjoy the game!" - -/datum/game_mode/extended/pre_setup() - return 1 - -/datum/game_mode/extended/generate_report() - return "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift." - -/datum/game_mode/extended/announced - name = "extended" - config_tag = "extended" - false_report_weight = 0 - -/datum/game_mode/extended/announced/generate_station_goals() - if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart - return ..() - for(var/T in subtypesof(/datum/station_goal)) - var/datum/station_goal/G = new T - station_goals += G - G.on_report() - -/datum/game_mode/extended/announced/send_intercept(report = 0) - if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart - return ..() - priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport") +/datum/game_mode/extended + name = "secret extended" + config_tag = "secret_extended" + false_report_weight = 5 + required_players = 0 + + announce_span = "notice" + announce_text = "Just have fun and enjoy the game!" + +/datum/game_mode/extended/pre_setup() + return 1 + +/datum/game_mode/extended/generate_report() + return "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift." + +/datum/game_mode/extended/announced + name = "extended" + config_tag = "extended" + false_report_weight = 0 + +/datum/game_mode/extended/announced/generate_station_goals() + if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart + return ..() + for(var/T in subtypesof(/datum/station_goal)) + var/datum/station_goal/G = new T + station_goals += G + G.on_report() + +/datum/game_mode/extended/announced/send_intercept(report = 0) + if(flipseclevel) //CIT CHANGE - allows the sec level to be flipped roundstart + return ..() + priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 3a258599b7..b98462d4d4 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,606 +1,606 @@ - - -/* - * GAMEMODES (by Rastaf0) - * - * In the new mode system all special roles are fully supported. - * You can have proper wizards/traitors/changelings/cultists during any mode. - * Only two things really depends on gamemode: - * 1. Starting roles, equipment and preparations - * 2. Conditions of finishing the round. - * - */ - - -/datum/game_mode - var/name = "invalid" - var/config_tag = null - var/votable = 1 - var/probability = 0 - var/false_report_weight = 0 //How often will this show up incorrectly in a centcom report? - var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm - var/nuke_off_station = 0 //Used for tracking where the nuke hit - var/round_ends_with_antag_death = 0 //flags the "one verse the station" antags as such - var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here - var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist - var/list/protected_jobs = list() // Jobs that can't be traitors because - var/list/required_jobs = list() // alternative required job groups eg list(list(cap=1),list(hos=1,sec=2)) translates to one captain OR one hos and two secmans - var/required_players = 0 - var/maximum_players = -1 // -1 is no maximum, positive numbers limit the selection of a mode on overstaffed stations - var/required_enemies = 0 - var/recommended_enemies = 0 - var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag - var/mob/living/living_antag_player = null - var/datum/game_mode/replacementmode = null - var/round_converted = 0 //0: round not converted, 1: round going to convert, 2: round converted - var/reroll_friendly //During mode conversion only these are in the running - var/continuous_sanity_checked //Catches some cases where config options could be used to suggest that modes without antagonists should end when all antagonists die - var/enemy_minimum_age = 7 //How many days must players have been playing before they can play this antagonist - - var/announce_span = "warning" //The gamemode's name will be in this span during announcement. - var/announce_text = "This gamemode forgot to set a descriptive text! Uh oh!" //Used to describe a gamemode when it's announced. - - var/const/waittime_l = 600 - var/const/waittime_h = 1800 // started at 1800 - - var/list/datum/station_goal/station_goals = list() - - var/allow_persistence_save = TRUE - - var/gamemode_ready = FALSE //Is the gamemode all set up and ready to start checking for ending conditions. - var/setup_error //What stopepd setting up the mode. - var/flipseclevel = FALSE //CIT CHANGE - adds a 10% chance for the alert level to be the opposite of what the gamemode is supposed to have - -/datum/game_mode/proc/announce() //Shows the gamemode's name and a fast description. - to_chat(world, "The gamemode is: [name]!") - to_chat(world, "[announce_text]") - - -///Checks to see if the game can be setup and ran with the current number of players or whatnot. -/datum/game_mode/proc/can_start() - var/playerC = 0 - for(var/mob/dead/new_player/player in GLOB.player_list) - if((player.client)&&(player.ready == PLAYER_READY_TO_PLAY)) - playerC++ - if(!GLOB.Debug2) - if(playerC < required_players || (maximum_players >= 0 && playerC > maximum_players)) - return 0 - antag_candidates = get_players_for_role(antag_flag) - if(!GLOB.Debug2) - if(antag_candidates.len < required_enemies) - return 0 - return 1 - else - message_admins("DEBUG: GAME STARTING WITHOUT PLAYER NUMBER CHECKS, THIS WILL PROBABLY BREAK SHIT.") - return 1 - - -///Attempts to select players for special roles the mode might have. -/datum/game_mode/proc/pre_setup() - return 1 - -///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things -/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. - //finalize_monster_hunters() Disabled for now - if(!report) - report = !CONFIG_GET(flag/no_intercept_report) - addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME) - - if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is - flipseclevel = TRUE - if(SSdbcore.Connect()) - var/sql - if(SSticker.mode) - sql += "game_mode = '[SSticker.mode]'" - if(GLOB.revdata.originmastercommit) - if(sql) - sql += ", " - sql += "commit_hash = '[GLOB.revdata.originmastercommit]'" - if(sql) - var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]") - query_round_game_mode.Execute() - qdel(query_round_game_mode) - if(report) - addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h)) - generate_station_goals() - gamemode_ready = TRUE - return 1 - - -///Handles late-join antag assignments -/datum/game_mode/proc/make_antag_chance(mob/living/carbon/human/character) - if(replacementmode && round_converted == 2) - replacementmode.make_antag_chance(character) - return - - -///Allows rounds to basically be "rerolled" should the initial premise fall through. Also known as mulligan antags. -/datum/game_mode/proc/convert_roundtype() - set waitfor = FALSE - var/list/living_crew = list() - - for(var/mob/Player in GLOB.mob_list) - if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) && !isbrain(Player) && Player.client) - living_crew += Player - var/malc = CONFIG_GET(number/midround_antag_life_check) - if(living_crew.len / GLOB.joined_player_list.len <= malc) //If a lot of the player base died, we start fresh - message_admins("Convert_roundtype failed due to too many dead people. Limit is [malc * 100]% living crew") - return null - - var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len) - var/list/datum/game_mode/usable_modes = list() - for(var/datum/game_mode/G in runnable_modes) - if(G.reroll_friendly && living_crew.len >= G.required_players) - usable_modes += G - else - qdel(G) - - if(!usable_modes) - message_admins("Convert_roundtype failed due to no valid modes to convert to. Please report this error to the Coders.") - return null - - replacementmode = pickweight(usable_modes) - - switch(SSshuttle.emergency.mode) //Rounds on the verge of ending don't get new antags, they just run out - if(SHUTTLE_STRANDED, SHUTTLE_ESCAPE) - return 1 - if(SHUTTLE_CALL) - if(SSshuttle.emergency.timeLeft(1) < initial(SSshuttle.emergencyCallTime)*0.5) - return 1 - - var/matc = CONFIG_GET(number/midround_antag_time_check) - if(world.time >= (matc * 600)) - message_admins("Convert_roundtype failed due to round length. Limit is [matc] minutes.") - return null - - var/list/antag_candidates = list() - - for(var/mob/living/carbon/human/H in living_crew) - if(H.client && H.client.prefs.allow_midround_antag) - antag_candidates += H - - if(!antag_candidates) - message_admins("Convert_roundtype failed due to no antag candidates.") - return null - - antag_candidates = shuffle(antag_candidates) - - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - replacementmode.restricted_jobs += replacementmode.protected_jobs - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - replacementmode.restricted_jobs += "Assistant" - - message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit stop the creation of antags or end the round now.") - log_game("Roundtype converted to [replacementmode.name]") - - . = 1 - - sleep(rand(600,1800)) - if(!SSticker.IsRoundInProgress()) - message_admins("Roundtype conversion cancelled, the game appears to have finished!") - round_converted = 0 - return - //somewhere between 1 and 3 minutes from now - if(!CONFIG_GET(keyed_list/midround_antag)[SSticker.mode.config_tag]) - round_converted = 0 - return 1 - for(var/mob/living/carbon/human/H in antag_candidates) - if(H.client) - replacementmode.make_antag_chance(H) - replacementmode.gamemode_ready = TRUE //Awful but we're not doing standard setup here. - round_converted = 2 - message_admins("-- IMPORTANT: The roundtype has been converted to [replacementmode.name], antagonists may have been created! --") - - -///Called by the gameSSticker -/datum/game_mode/process() - return 0 - -//For things that do not die easily -/datum/game_mode/proc/are_special_antags_dead() - return TRUE - - -/datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker - if(!SSticker.setup_done || !gamemode_ready) - return FALSE - if(replacementmode && round_converted == 2) - return replacementmode.check_finished() - if(SSshuttle.emergency && (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)) - return TRUE - if(station_was_nuked) - return TRUE - var/list/continuous = CONFIG_GET(keyed_list/continuous) - var/list/midround_antag = CONFIG_GET(keyed_list/midround_antag) - if(!round_converted && (!continuous[config_tag] || (continuous[config_tag] && midround_antag[config_tag]))) //Non-continuous or continous with replacement antags - if(!continuous_sanity_checked) //make sure we have antags to be checking in the first place - for(var/mob/Player in GLOB.mob_list) - if(Player.mind) - if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) - continuous_sanity_checked = 1 - return 0 - if(!continuous_sanity_checked) - message_admins("The roundtype ([config_tag]) has no antagonists, continuous round has been defaulted to on and midround_antag has been defaulted to off.") - continuous[config_tag] = TRUE - midround_antag[config_tag] = FALSE - SSshuttle.clearHostileEnvironment(src) - return 0 - - - if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player) && (living_antag_player.mind.special_role || LAZYLEN(living_antag_player.mind.antag_datums))) - return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark. - - for(var/mob/Player in GLOB.alive_mob_list) - if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) &&!isbrain(Player) && Player.client) - if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) //Someone's still antaging! - living_antag_player = Player - return 0 - - if(!are_special_antags_dead()) - return FALSE - - if(!continuous[config_tag] || force_ending) - return 1 - - else - round_converted = convert_roundtype() - if(!round_converted) - if(round_ends_with_antag_death) - return 1 - else - midround_antag[config_tag] = 0 - return 0 - - return 0 - - -/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. - return 0 - -/datum/game_mode/proc/send_intercept() - if(flipseclevel && !(config_tag == "extended"))//CIT CHANGE - lets the security level be flipped roundstart - priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport") - return - var/intercepttext = "Central Command Status Summary
    " - intercepttext += "Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \ - likely threats to appear in your sector." - var/list/report_weights = config.mode_false_report_weight.Copy() - report_weights[config_tag] = 0 //Prevent the current mode from being falsely selected. - var/list/reports = list() - var/Count = 0 //To compensate for missing correct report - if(prob(65)) // 65% chance the actual mode will appear on the list - reports += config.mode_reports[config_tag] - Count++ - for(var/i in Count to rand(3,5)) //Between three and five wrong entries on the list. - var/false_report_type = pickweightAllowZero(report_weights) - report_weights[false_report_type] = 0 //Make it so the same false report won't be selected twice - reports += config.mode_reports[false_report_type] - - reports = shuffle(reports) //Randomize the order, so the real one is at a random position. - - for(var/report in reports) - intercepttext += "
    " - intercepttext += report - - if(station_goals.len) - intercepttext += "
    Special Orders for [station_name()]:" - for(var/datum/station_goal/G in station_goals) - G.on_report() - intercepttext += G.get_report() - - print_command_report(intercepttext, "Central Command Status Summary", announce=FALSE) - priority_announce("A summary has been copied and printed to all communications consoles.", "Enemy communication intercepted. Security level elevated.", "intercept") - if(GLOB.security_level < SEC_LEVEL_BLUE) - set_security_level(SEC_LEVEL_BLUE) - - -// This is a frequency selection system. You may imagine it like a raffle where each player can have some number of tickets. The more tickets you have the more likely you are to -// "win". The default is 100 tickets. If no players use any extra tickets (earned with the antagonist rep system) calling this function should be equivalent to calling the normal -// pick() function. By default you may use up to 100 extra tickets per roll, meaning at maximum a player may double their chances compared to a player who has no extra tickets. -// -// The odds of being picked are simply (your_tickets / total_tickets). Suppose you have one player using fifty (50) extra tickets, and one who uses no extra: -// Player A: 150 tickets -// Player B: 100 tickets -// Total: 250 tickets -// -// The odds become: -// Player A: 150 / 250 = 0.6 = 60% -// Player B: 100 / 250 = 0.4 = 40% - -//Use return list if you want a list, with the arg being the number you want returned. -//WARNING: THIS PROC DOES NOT TAKE INTO ACCOUNT WHAT SSPersistence ALREADY HAS FOR "ADJUST ANTAG REP". If this is used more than once -//and the person rolls more than once, they will not get even more deduction! -//More efficient if you use return list instead of calling this multiple times -//fail_default_pick makes it use pick() instead of antag rep if it can't find anyone -//allow_zero_if_insufficient allows it to pick people with zero rep if there isn't enough antags -/datum/game_mode/proc/antag_pick(list/datum/mind/candidates, return_list = FALSE, fail_default_pick = TRUE, allow_zero_if_insufficient = TRUE) - if(!CONFIG_GET(flag/use_antag_rep)) // || candidates.len <= 1) - return pick(candidates) - - //whoever named the config entries is a bad person :( - - //Tickets you get for free - var/free_tickets = CONFIG_GET(number/default_antag_tickets) - //Max extra tickets you can use - var/additional_tickets = CONFIG_GET(number/max_tickets_per_roll) - - var/list/ckey_to_mind = list() //this is admittedly shitcode but I'm webediting - var/list/prev_tickets = SSpersistence.antag_rep //cache for hyper-speed in theory. how many tickets someone has stored - var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets - var/list/datum/mind/insufficient = list() //who got cucked out of an antag roll due to not having *any* tickets - for(var/datum/mind/M in candidates) - var/mind_ckey = ckey(M.key) - var/can_spend = min(prev_tickets[mind_ckey], additional_tickets) //they can only spend up to config/max_tickets_per_roll - var/amount = can_spend + free_tickets //but they get config/default_antag_tickets for free - if(amount <= 0) //if they don't have any - insufficient += M //too bad! - continue - curr_tickets[mind_ckey] = amount - ckey_to_mind[mind_ckey] = M //make sure we can look them up after picking - - if(!return_list) //return a single guy - var/ckey - if(length(curr_tickets)) - ckey = pickweight(curr_tickets) - SSpersistence.antag_rep_change[ckey] = -(curr_tickets[ckey] - free_tickets) //deduct what they spent - var/mind = ckey_to_mind[ckey] || (allow_zero_if_insufficient? pick(insufficient) : null) //we want their mind - if(!mind) //no mind - var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]" - message_admins(warning) - log_game(warning) - if(fail_default_pick) - mind = pick(candidates) - return mind - else //the far more efficient and proper use of this, to get a list - var/list/rolled = list() - var/list/spend_tickets = list() - for(var/i in 1 to return_list) - if(!length(curr_tickets)) //ah heck, we're out of candidates.. - break - var/ckey = pickweight(curr_tickets) //pick - rolled += ckey //add - spend_tickets[ckey] = curr_tickets[ckey] - free_tickets - curr_tickets -= ckey //don't roll them again - var/missing = return_list - length(rolled) - var/list/add - if((missing > 0) && allow_zero_if_insufficient) //need more.. - for(var/i in 1 to missing) - if(!length(insufficient)) - break //still not enough - var/datum/mind/M = pick_n_take(insufficient) - add += M - if(!length(rolled) && !length(add)) //if no one could normally roll AND no one can zero roll - var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]" - message_admins(warning) - log_game(warning) - var/list/failed = list() - if(fail_default_pick) - var/list/C = candidates.Copy() - for(var/i in 1 to return_list) - if(!length(C)) - break - failed += pick_n_take(C) - return failed //Wew, no one qualified! - for(var/i in 1 to length(rolled)) - var/ckey = rolled[i] - SSpersistence.antag_rep_change[ckey] = -(spend_tickets[ckey]) //deduct what all of the folks who rolled spent - rolled[i] = ckey_to_mind[ckey] //whoever called us wants minds, not ckeys - if(add) - rolled += add - return rolled - -/datum/game_mode/proc/get_players_for_role(role) - var/list/players = list() - var/list/candidates = list() - var/list/drafted = list() - var/datum/mind/applicant = null - - // Ultimate randomizing code right here - for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.client && player.ready == PLAYER_READY_TO_PLAY && player.check_preferences()) - players += player - - // Shuffling, the players list is now ping-independent!!! - // Goodbye antag dante - players = shuffle(players) - - for(var/mob/dead/new_player/player in players) - if(player.client && player.ready == PLAYER_READY_TO_PLAY) - if(role in player.client.prefs.be_special) - if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player)) //Nodrak/Carn: Antag Job-bans - if(age_check(player.client)) //Must be older than the minimum age - candidates += player.mind // Get a list of all the people who want to be the antagonist for this round - - if(restricted_jobs) - for(var/datum/mind/player in candidates) - for(var/job in restricted_jobs) // Remove people who want to be antagonist but have a job already that precludes it - if(player.assigned_role == job) - candidates -= player - - if(candidates.len < recommended_enemies) - for(var/mob/dead/new_player/player in players) - if(player.client && player.ready == PLAYER_READY_TO_PLAY) - if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one - if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player) ) //Nodrak/Carn: Antag Job-bans - drafted += player.mind - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - drafted.Remove(applicant) - - else // Not enough scrubs, ABORT ABORT ABORT - break - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - drafted.Remove(applicant) - - else // Not enough scrubs, ABORT ABORT ABORT - break - - return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies - // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, - // Less if there are not enough valid players in the game entirely to make recommended_enemies. - - - -/datum/game_mode/proc/num_players() - . = 0 - for(var/mob/dead/new_player/P in GLOB.player_list) - if(P.client && P.ready == PLAYER_READY_TO_PLAY) - . ++ - -////////////////////////// -//Reports player logouts// -////////////////////////// -/proc/display_roundstart_logout_report() - var/list/msg = list("Roundstart logout report\n\n") - for(var/i in GLOB.mob_living_list) - var/mob/living/L = i - var/mob/living/carbon/C = L - if (istype(C) && !C.last_mind) - continue // never had a client - - if(L.ckey && !GLOB.directory[L.ckey]) - msg += "[L.name] ([L.key]), the [L.job] (Disconnected)\n" - - - if(L.ckey && L.client) - var/failed = FALSE - if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) - msg += "[L.name] ([L.key]), the [L.job] (Connected, Inactive)\n" - failed = TRUE //AFK client - if(!failed && L.stat) - if(L.suiciding) //Suicider - msg += "[L.name] ([L.key]), the [L.job] (Suicide)\n" - failed = TRUE //Disconnected client - if(!failed && L.stat == UNCONSCIOUS) - msg += "[L.name] ([L.key]), the [L.job] (Dying)\n" - failed = TRUE //Unconscious - if(!failed && L.stat == DEAD) - msg += "[L.name] ([L.key]), the [L.job] (Dead)\n" - failed = TRUE //Dead - - var/p_ckey = L.client.ckey -// WARNING("AR_DEBUG: [p_ckey]: failed - [failed], antag_rep_change: [SSpersistence.antag_rep_change[p_ckey]]") - - // people who died or left should not gain any reputation - // people who rolled antagonist still lose it - if(failed && SSpersistence.antag_rep_change[p_ckey] > 0) -// WARNING("AR_DEBUG: Zeroed [p_ckey]'s antag_rep_change") - SSpersistence.antag_rep_change[p_ckey] = 0 - - continue //Happy connected client - for(var/mob/dead/observer/D in GLOB.dead_mob_list) - if(D.mind && D.mind.current == L) - if(L.stat == DEAD) - if(L.suiciding) //Suicider - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n" - continue //Disconnected client - else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n" - continue //Dead mob, ghost abandoned - else - if(D.can_reenter_corpse) - continue //Adminghost, or cult/wizard ghost - else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" - continue //Ghosted while alive - - - for (var/C in GLOB.admins) - to_chat(C, msg.Join()) - -//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 -/datum/game_mode/proc/age_check(client/C) - if(get_remaining_days(C) == 0) - return 1 //Available in 0 days = available right now = player is old enough to play. - return 0 - - -/datum/game_mode/proc/get_remaining_days(client/C) - if(!C) - return 0 - if(!CONFIG_GET(flag/use_age_restriction_for_jobs)) - return 0 - if(!isnum(C.player_age)) - return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced - if(!isnum(enemy_minimum_age)) - return 0 - - return max(0, enemy_minimum_age - C.player_age) - -/datum/game_mode/proc/remove_antag_for_borging(datum/mind/newborgie) - SSticker.mode.remove_cultist(newborgie, 0, 0) - var/datum/antagonist/rev/rev = newborgie.has_antag_datum(/datum/antagonist/rev) - if(rev) - rev.remove_revolutionary(TRUE) - -/datum/game_mode/proc/generate_station_goals() - if(flipseclevel && !(config_tag == "extended")) //CIT CHANGE - allows the sec level to be flipped roundstart - for(var/T in subtypesof(/datum/station_goal)) - var/datum/station_goal/G = new T - station_goals += G - G.on_report() - return - var/list/possible = list() - for(var/T in subtypesof(/datum/station_goal)) - var/datum/station_goal/G = T - if(config_tag in initial(G.gamemode_blacklist)) - continue - possible += T - var/goal_weights = 0 - while(possible.len && goal_weights < STATION_GOAL_BUDGET) - var/datum/station_goal/picked = pick_n_take(possible) - goal_weights += initial(picked.weight) - station_goals += new picked - - -/datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report - return "Gamemode report for [name] not set. Contact a coder." - -//By default nuke just ends the round -/datum/game_mode/proc/OnNukeExplosion(off_station) - nuke_off_station = off_station - if(off_station < 2) - station_was_nuked = TRUE //Will end the round on next check. - -//Additional report section in roundend report -/datum/game_mode/proc/special_report() - return - -//Set result and news report here -/datum/game_mode/proc/set_round_result() - SSticker.mode_result = "undefined" - if(station_was_nuked) - SSticker.news_report = STATION_DESTROYED_NUKE - if(EMERGENCY_ESCAPED_OR_ENDGAMED) - SSticker.news_report = STATION_EVACUATED - if(SSshuttle.emergency.is_hijacked()) - SSticker.news_report = SHUTTLE_HIJACK - -/// Mode specific admin panel. -/datum/game_mode/proc/admin_panel() - return + + +/* + * GAMEMODES (by Rastaf0) + * + * In the new mode system all special roles are fully supported. + * You can have proper wizards/traitors/changelings/cultists during any mode. + * Only two things really depends on gamemode: + * 1. Starting roles, equipment and preparations + * 2. Conditions of finishing the round. + * + */ + + +/datum/game_mode + var/name = "invalid" + var/config_tag = null + var/votable = 1 + var/probability = 0 + var/false_report_weight = 0 //How often will this show up incorrectly in a centcom report? + var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm + var/nuke_off_station = 0 //Used for tracking where the nuke hit + var/round_ends_with_antag_death = 0 //flags the "one verse the station" antags as such + var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here + var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist + var/list/protected_jobs = list() // Jobs that can't be traitors because + var/list/required_jobs = list() // alternative required job groups eg list(list(cap=1),list(hos=1,sec=2)) translates to one captain OR one hos and two secmans + var/required_players = 0 + var/maximum_players = -1 // -1 is no maximum, positive numbers limit the selection of a mode on overstaffed stations + var/required_enemies = 0 + var/recommended_enemies = 0 + var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag + var/mob/living/living_antag_player = null + var/datum/game_mode/replacementmode = null + var/round_converted = 0 //0: round not converted, 1: round going to convert, 2: round converted + var/reroll_friendly //During mode conversion only these are in the running + var/continuous_sanity_checked //Catches some cases where config options could be used to suggest that modes without antagonists should end when all antagonists die + var/enemy_minimum_age = 7 //How many days must players have been playing before they can play this antagonist + + var/announce_span = "warning" //The gamemode's name will be in this span during announcement. + var/announce_text = "This gamemode forgot to set a descriptive text! Uh oh!" //Used to describe a gamemode when it's announced. + + var/const/waittime_l = 600 + var/const/waittime_h = 1800 // started at 1800 + + var/list/datum/station_goal/station_goals = list() + + var/allow_persistence_save = TRUE + + var/gamemode_ready = FALSE //Is the gamemode all set up and ready to start checking for ending conditions. + var/setup_error //What stopepd setting up the mode. + var/flipseclevel = FALSE //CIT CHANGE - adds a 10% chance for the alert level to be the opposite of what the gamemode is supposed to have + +/datum/game_mode/proc/announce() //Shows the gamemode's name and a fast description. + to_chat(world, "The gamemode is: [name]!") + to_chat(world, "[announce_text]") + + +///Checks to see if the game can be setup and ran with the current number of players or whatnot. +/datum/game_mode/proc/can_start() + var/playerC = 0 + for(var/mob/dead/new_player/player in GLOB.player_list) + if((player.client)&&(player.ready == PLAYER_READY_TO_PLAY)) + playerC++ + if(!GLOB.Debug2) + if(playerC < required_players || (maximum_players >= 0 && playerC > maximum_players)) + return 0 + antag_candidates = get_players_for_role(antag_flag) + if(!GLOB.Debug2) + if(antag_candidates.len < required_enemies) + return 0 + return 1 + else + message_admins("DEBUG: GAME STARTING WITHOUT PLAYER NUMBER CHECKS, THIS WILL PROBABLY BREAK SHIT.") + return 1 + + +///Attempts to select players for special roles the mode might have. +/datum/game_mode/proc/pre_setup() + return 1 + +///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things +/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. + //finalize_monster_hunters() Disabled for now + if(!report) + report = !CONFIG_GET(flag/no_intercept_report) + addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME) + + if(prob(20)) //CIT CHANGE - adds a 20% chance for the security level to be the opposite of what it normally is + flipseclevel = TRUE + if(SSdbcore.Connect()) + var/sql + if(SSticker.mode) + sql += "game_mode = '[SSticker.mode]'" + if(GLOB.revdata.originmastercommit) + if(sql) + sql += ", " + sql += "commit_hash = '[GLOB.revdata.originmastercommit]'" + if(sql) + var/datum/DBQuery/query_round_game_mode = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET [sql] WHERE id = [GLOB.round_id]") + query_round_game_mode.Execute() + qdel(query_round_game_mode) + if(report) + addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h)) + generate_station_goals() + gamemode_ready = TRUE + return 1 + + +///Handles late-join antag assignments +/datum/game_mode/proc/make_antag_chance(mob/living/carbon/human/character) + if(replacementmode && round_converted == 2) + replacementmode.make_antag_chance(character) + return + + +///Allows rounds to basically be "rerolled" should the initial premise fall through. Also known as mulligan antags. +/datum/game_mode/proc/convert_roundtype() + set waitfor = FALSE + var/list/living_crew = list() + + for(var/mob/Player in GLOB.mob_list) + if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) && !isbrain(Player) && Player.client) + living_crew += Player + var/malc = CONFIG_GET(number/midround_antag_life_check) + if(living_crew.len / GLOB.joined_player_list.len <= malc) //If a lot of the player base died, we start fresh + message_admins("Convert_roundtype failed due to too many dead people. Limit is [malc * 100]% living crew") + return null + + var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len) + var/list/datum/game_mode/usable_modes = list() + for(var/datum/game_mode/G in runnable_modes) + if(G.reroll_friendly && living_crew.len >= G.required_players) + usable_modes += G + else + qdel(G) + + if(!usable_modes) + message_admins("Convert_roundtype failed due to no valid modes to convert to. Please report this error to the Coders.") + return null + + replacementmode = pickweight(usable_modes) + + switch(SSshuttle.emergency.mode) //Rounds on the verge of ending don't get new antags, they just run out + if(SHUTTLE_STRANDED, SHUTTLE_ESCAPE) + return 1 + if(SHUTTLE_CALL) + if(SSshuttle.emergency.timeLeft(1) < initial(SSshuttle.emergencyCallTime)*0.5) + return 1 + + var/matc = CONFIG_GET(number/midround_antag_time_check) + if(world.time >= (matc * 600)) + message_admins("Convert_roundtype failed due to round length. Limit is [matc] minutes.") + return null + + var/list/antag_candidates = list() + + for(var/mob/living/carbon/human/H in living_crew) + if(H.client && H.client.prefs.allow_midround_antag) + antag_candidates += H + + if(!antag_candidates) + message_admins("Convert_roundtype failed due to no antag candidates.") + return null + + antag_candidates = shuffle(antag_candidates) + + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + replacementmode.restricted_jobs += replacementmode.protected_jobs + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + replacementmode.restricted_jobs += "Assistant" + + message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit stop the creation of antags or end the round now.") + log_game("Roundtype converted to [replacementmode.name]") + + . = 1 + + sleep(rand(600,1800)) + if(!SSticker.IsRoundInProgress()) + message_admins("Roundtype conversion cancelled, the game appears to have finished!") + round_converted = 0 + return + //somewhere between 1 and 3 minutes from now + if(!CONFIG_GET(keyed_list/midround_antag)[SSticker.mode.config_tag]) + round_converted = 0 + return 1 + for(var/mob/living/carbon/human/H in antag_candidates) + if(H.client) + replacementmode.make_antag_chance(H) + replacementmode.gamemode_ready = TRUE //Awful but we're not doing standard setup here. + round_converted = 2 + message_admins("-- IMPORTANT: The roundtype has been converted to [replacementmode.name], antagonists may have been created! --") + + +///Called by the gameSSticker +/datum/game_mode/process() + return 0 + +//For things that do not die easily +/datum/game_mode/proc/are_special_antags_dead() + return TRUE + + +/datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker + if(!SSticker.setup_done || !gamemode_ready) + return FALSE + if(replacementmode && round_converted == 2) + return replacementmode.check_finished() + if(SSshuttle.emergency && (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)) + return TRUE + if(station_was_nuked) + return TRUE + var/list/continuous = CONFIG_GET(keyed_list/continuous) + var/list/midround_antag = CONFIG_GET(keyed_list/midround_antag) + if(!round_converted && (!continuous[config_tag] || (continuous[config_tag] && midround_antag[config_tag]))) //Non-continuous or continous with replacement antags + if(!continuous_sanity_checked) //make sure we have antags to be checking in the first place + for(var/mob/Player in GLOB.mob_list) + if(Player.mind) + if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) + continuous_sanity_checked = 1 + return 0 + if(!continuous_sanity_checked) + message_admins("The roundtype ([config_tag]) has no antagonists, continuous round has been defaulted to on and midround_antag has been defaulted to off.") + continuous[config_tag] = TRUE + midround_antag[config_tag] = FALSE + SSshuttle.clearHostileEnvironment(src) + return 0 + + + if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player) && (living_antag_player.mind.special_role || LAZYLEN(living_antag_player.mind.antag_datums))) + return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark. + + for(var/mob/Player in GLOB.alive_mob_list) + if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) &&!isbrain(Player) && Player.client) + if(Player.mind.special_role || LAZYLEN(Player.mind.antag_datums)) //Someone's still antaging! + living_antag_player = Player + return 0 + + if(!are_special_antags_dead()) + return FALSE + + if(!continuous[config_tag] || force_ending) + return 1 + + else + round_converted = convert_roundtype() + if(!round_converted) + if(round_ends_with_antag_death) + return 1 + else + midround_antag[config_tag] = 0 + return 0 + + return 0 + + +/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. + return 0 + +/datum/game_mode/proc/send_intercept() + if(flipseclevel && !(config_tag == "extended"))//CIT CHANGE - lets the security level be flipped roundstart + priority_announce("Thanks to the tireless efforts of our security and intelligence divisions, there are currently no credible threats to [station_name()]. All station construction projects have been authorized. Have a secure shift!", "Security Report", "commandreport") + return + var/intercepttext = "Central Command Status Summary
    " + intercepttext += "Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \ + likely threats to appear in your sector." + var/list/report_weights = config.mode_false_report_weight.Copy() + report_weights[config_tag] = 0 //Prevent the current mode from being falsely selected. + var/list/reports = list() + var/Count = 0 //To compensate for missing correct report + if(prob(65)) // 65% chance the actual mode will appear on the list + reports += config.mode_reports[config_tag] + Count++ + for(var/i in Count to rand(3,5)) //Between three and five wrong entries on the list. + var/false_report_type = pickweightAllowZero(report_weights) + report_weights[false_report_type] = 0 //Make it so the same false report won't be selected twice + reports += config.mode_reports[false_report_type] + + reports = shuffle(reports) //Randomize the order, so the real one is at a random position. + + for(var/report in reports) + intercepttext += "
    " + intercepttext += report + + if(station_goals.len) + intercepttext += "
    Special Orders for [station_name()]:" + for(var/datum/station_goal/G in station_goals) + G.on_report() + intercepttext += G.get_report() + + print_command_report(intercepttext, "Central Command Status Summary", announce=FALSE) + priority_announce("A summary has been copied and printed to all communications consoles.", "Enemy communication intercepted. Security level elevated.", "intercept") + if(GLOB.security_level < SEC_LEVEL_BLUE) + set_security_level(SEC_LEVEL_BLUE) + + +// This is a frequency selection system. You may imagine it like a raffle where each player can have some number of tickets. The more tickets you have the more likely you are to +// "win". The default is 100 tickets. If no players use any extra tickets (earned with the antagonist rep system) calling this function should be equivalent to calling the normal +// pick() function. By default you may use up to 100 extra tickets per roll, meaning at maximum a player may double their chances compared to a player who has no extra tickets. +// +// The odds of being picked are simply (your_tickets / total_tickets). Suppose you have one player using fifty (50) extra tickets, and one who uses no extra: +// Player A: 150 tickets +// Player B: 100 tickets +// Total: 250 tickets +// +// The odds become: +// Player A: 150 / 250 = 0.6 = 60% +// Player B: 100 / 250 = 0.4 = 40% + +//Use return list if you want a list, with the arg being the number you want returned. +//WARNING: THIS PROC DOES NOT TAKE INTO ACCOUNT WHAT SSPersistence ALREADY HAS FOR "ADJUST ANTAG REP". If this is used more than once +//and the person rolls more than once, they will not get even more deduction! +//More efficient if you use return list instead of calling this multiple times +//fail_default_pick makes it use pick() instead of antag rep if it can't find anyone +//allow_zero_if_insufficient allows it to pick people with zero rep if there isn't enough antags +/datum/game_mode/proc/antag_pick(list/datum/mind/candidates, return_list = FALSE, fail_default_pick = TRUE, allow_zero_if_insufficient = TRUE) + if(!CONFIG_GET(flag/use_antag_rep)) // || candidates.len <= 1) + return pick(candidates) + + //whoever named the config entries is a bad person :( + + //Tickets you get for free + var/free_tickets = CONFIG_GET(number/default_antag_tickets) + //Max extra tickets you can use + var/additional_tickets = CONFIG_GET(number/max_tickets_per_roll) + + var/list/ckey_to_mind = list() //this is admittedly shitcode but I'm webediting + var/list/prev_tickets = SSpersistence.antag_rep //cache for hyper-speed in theory. how many tickets someone has stored + var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets + var/list/datum/mind/insufficient = list() //who got cucked out of an antag roll due to not having *any* tickets + for(var/datum/mind/M in candidates) + var/mind_ckey = ckey(M.key) + var/can_spend = min(prev_tickets[mind_ckey], additional_tickets) //they can only spend up to config/max_tickets_per_roll + var/amount = can_spend + free_tickets //but they get config/default_antag_tickets for free + if(amount <= 0) //if they don't have any + insufficient += M //too bad! + continue + curr_tickets[mind_ckey] = amount + ckey_to_mind[mind_ckey] = M //make sure we can look them up after picking + + if(!return_list) //return a single guy + var/ckey + if(length(curr_tickets)) + ckey = pickweight(curr_tickets) + SSpersistence.antag_rep_change[ckey] = -(curr_tickets[ckey] - free_tickets) //deduct what they spent + var/mind = ckey_to_mind[ckey] || (allow_zero_if_insufficient? pick(insufficient) : null) //we want their mind + if(!mind) //no mind + var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]" + message_admins(warning) + log_game(warning) + if(fail_default_pick) + mind = pick(candidates) + return mind + else //the far more efficient and proper use of this, to get a list + var/list/rolled = list() + var/list/spend_tickets = list() + for(var/i in 1 to return_list) + if(!length(curr_tickets)) //ah heck, we're out of candidates.. + break + var/ckey = pickweight(curr_tickets) //pick + rolled += ckey //add + spend_tickets[ckey] = curr_tickets[ckey] - free_tickets + curr_tickets -= ckey //don't roll them again + var/missing = return_list - length(rolled) + var/list/add + if((missing > 0) && allow_zero_if_insufficient) //need more.. + for(var/i in 1 to missing) + if(!length(insufficient)) + break //still not enough + var/datum/mind/M = pick_n_take(insufficient) + add += M + if(!length(rolled) && !length(add)) //if no one could normally roll AND no one can zero roll + var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]" + message_admins(warning) + log_game(warning) + var/list/failed = list() + if(fail_default_pick) + var/list/C = candidates.Copy() + for(var/i in 1 to return_list) + if(!length(C)) + break + failed += pick_n_take(C) + return failed //Wew, no one qualified! + for(var/i in 1 to length(rolled)) + var/ckey = rolled[i] + SSpersistence.antag_rep_change[ckey] = -(spend_tickets[ckey]) //deduct what all of the folks who rolled spent + rolled[i] = ckey_to_mind[ckey] //whoever called us wants minds, not ckeys + if(add) + rolled += add + return rolled + +/datum/game_mode/proc/get_players_for_role(role) + var/list/players = list() + var/list/candidates = list() + var/list/drafted = list() + var/datum/mind/applicant = null + + // Ultimate randomizing code right here + for(var/mob/dead/new_player/player in GLOB.player_list) + if(player.client && player.ready == PLAYER_READY_TO_PLAY && player.check_preferences()) + players += player + + // Shuffling, the players list is now ping-independent!!! + // Goodbye antag dante + players = shuffle(players) + + for(var/mob/dead/new_player/player in players) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) + if(role in player.client.prefs.be_special) + if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player)) //Nodrak/Carn: Antag Job-bans + if(age_check(player.client)) //Must be older than the minimum age + candidates += player.mind // Get a list of all the people who want to be the antagonist for this round + + if(restricted_jobs) + for(var/datum/mind/player in candidates) + for(var/job in restricted_jobs) // Remove people who want to be antagonist but have a job already that precludes it + if(player.assigned_role == job) + candidates -= player + + if(candidates.len < recommended_enemies) + for(var/mob/dead/new_player/player in players) + if(player.client && player.ready == PLAYER_READY_TO_PLAY) + if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one + if(!jobban_isbanned(player, ROLE_SYNDICATE) && !QDELETED(player) && !jobban_isbanned(player, role) && !QDELETED(player) ) //Nodrak/Carn: Antag Job-bans + drafted += player.mind + + if(restricted_jobs) + for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist + for(var/job in restricted_jobs) + if(player.assigned_role == job) + drafted -= player + + drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie + + while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates + if(drafted.len > 0) + applicant = pick(drafted) + if(applicant) + candidates += applicant + drafted.Remove(applicant) + + else // Not enough scrubs, ABORT ABORT ABORT + break + + if(restricted_jobs) + for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist + for(var/job in restricted_jobs) + if(player.assigned_role == job) + drafted -= player + + drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie + + while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates + if(drafted.len > 0) + applicant = pick(drafted) + if(applicant) + candidates += applicant + drafted.Remove(applicant) + + else // Not enough scrubs, ABORT ABORT ABORT + break + + return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies + // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies, + // Less if there are not enough valid players in the game entirely to make recommended_enemies. + + + +/datum/game_mode/proc/num_players() + . = 0 + for(var/mob/dead/new_player/P in GLOB.player_list) + if(P.client && P.ready == PLAYER_READY_TO_PLAY) + . ++ + +////////////////////////// +//Reports player logouts// +////////////////////////// +/proc/display_roundstart_logout_report() + var/list/msg = list("Roundstart logout report\n\n") + for(var/i in GLOB.mob_living_list) + var/mob/living/L = i + var/mob/living/carbon/C = L + if (istype(C) && !C.last_mind) + continue // never had a client + + if(L.ckey && !GLOB.directory[L.ckey]) + msg += "[L.name] ([L.key]), the [L.job] (Disconnected)\n" + + + if(L.ckey && L.client) + var/failed = FALSE + if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something) + msg += "[L.name] ([L.key]), the [L.job] (Connected, Inactive)\n" + failed = TRUE //AFK client + if(!failed && L.stat) + if(L.suiciding) //Suicider + msg += "[L.name] ([L.key]), the [L.job] (Suicide)\n" + failed = TRUE //Disconnected client + if(!failed && L.stat == UNCONSCIOUS) + msg += "[L.name] ([L.key]), the [L.job] (Dying)\n" + failed = TRUE //Unconscious + if(!failed && L.stat == DEAD) + msg += "[L.name] ([L.key]), the [L.job] (Dead)\n" + failed = TRUE //Dead + + var/p_ckey = L.client.ckey +// WARNING("AR_DEBUG: [p_ckey]: failed - [failed], antag_rep_change: [SSpersistence.antag_rep_change[p_ckey]]") + + // people who died or left should not gain any reputation + // people who rolled antagonist still lose it + if(failed && SSpersistence.antag_rep_change[p_ckey] > 0) +// WARNING("AR_DEBUG: Zeroed [p_ckey]'s antag_rep_change") + SSpersistence.antag_rep_change[p_ckey] = 0 + + continue //Happy connected client + for(var/mob/dead/observer/D in GLOB.dead_mob_list) + if(D.mind && D.mind.current == L) + if(L.stat == DEAD) + if(L.suiciding) //Suicider + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n" + continue //Disconnected client + else + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n" + continue //Dead mob, ghost abandoned + else + if(D.can_reenter_corpse) + continue //Adminghost, or cult/wizard ghost + else + msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" + continue //Ghosted while alive + + + for (var/C in GLOB.admins) + to_chat(C, msg.Join()) + +//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 +/datum/game_mode/proc/age_check(client/C) + if(get_remaining_days(C) == 0) + return 1 //Available in 0 days = available right now = player is old enough to play. + return 0 + + +/datum/game_mode/proc/get_remaining_days(client/C) + if(!C) + return 0 + if(!CONFIG_GET(flag/use_age_restriction_for_jobs)) + return 0 + if(!isnum(C.player_age)) + return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced + if(!isnum(enemy_minimum_age)) + return 0 + + return max(0, enemy_minimum_age - C.player_age) + +/datum/game_mode/proc/remove_antag_for_borging(datum/mind/newborgie) + SSticker.mode.remove_cultist(newborgie, 0, 0) + var/datum/antagonist/rev/rev = newborgie.has_antag_datum(/datum/antagonist/rev) + if(rev) + rev.remove_revolutionary(TRUE) + +/datum/game_mode/proc/generate_station_goals() + if(flipseclevel && !(config_tag == "extended")) //CIT CHANGE - allows the sec level to be flipped roundstart + for(var/T in subtypesof(/datum/station_goal)) + var/datum/station_goal/G = new T + station_goals += G + G.on_report() + return + var/list/possible = list() + for(var/T in subtypesof(/datum/station_goal)) + var/datum/station_goal/G = T + if(config_tag in initial(G.gamemode_blacklist)) + continue + possible += T + var/goal_weights = 0 + while(possible.len && goal_weights < STATION_GOAL_BUDGET) + var/datum/station_goal/picked = pick_n_take(possible) + goal_weights += initial(picked.weight) + station_goals += new picked + + +/datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report + return "Gamemode report for [name] not set. Contact a coder." + +//By default nuke just ends the round +/datum/game_mode/proc/OnNukeExplosion(off_station) + nuke_off_station = off_station + if(off_station < 2) + station_was_nuked = TRUE //Will end the round on next check. + +//Additional report section in roundend report +/datum/game_mode/proc/special_report() + return + +//Set result and news report here +/datum/game_mode/proc/set_round_result() + SSticker.mode_result = "undefined" + if(station_was_nuked) + SSticker.news_report = STATION_DESTROYED_NUKE + if(EMERGENCY_ESCAPED_OR_ENDGAMED) + SSticker.news_report = STATION_EVACUATED + if(SSshuttle.emergency.is_hijacked()) + SSticker.news_report = SHUTTLE_HIJACK + +/// Mode specific admin panel. +/datum/game_mode/proc/admin_panel() + return diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index 90e2b85f11..7857eb8253 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -1,59 +1,59 @@ -/datum/game_mode/meteor - name = "meteor" - config_tag = "meteor" - false_report_weight = 1 - var/meteordelay = 2000 - var/nometeors = 0 - var/rampupdelta = 5 - required_players = 0 - - announce_span = "danger" - announce_text = "A major meteor shower is bombarding the station! The crew needs to evacuate or survive the onslaught." - - -/datum/game_mode/meteor/process() - if(nometeors || meteordelay > world.time - SSticker.round_start_time) - return - - var/list/wavetype = GLOB.meteors_normal - var/meteorminutes = (world.time - SSticker.round_start_time - meteordelay) / 10 / 60 - - - if (prob(meteorminutes)) - wavetype = GLOB.meteors_threatening - - if (prob(meteorminutes/2)) - wavetype = GLOB.meteors_catastrophic - - var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10) - - spawn_meteors(ramp_up_final, wavetype) - - -/datum/game_mode/meteor/special_report() - var/survivors = 0 - var/list/survivor_list = list() - - for(var/mob/living/player in GLOB.player_list) - if(player.stat != DEAD) - ++survivors - - if(player.onCentCom()) - survivor_list += "[player.real_name] escaped to the safety of CentCom." - else if(player.onSyndieBase()) - survivor_list += "[player.real_name] escaped to the (relative) safety of Syndicate Space." - else - survivor_list += "[player.real_name] survived but is stranded without any hope of rescue." - - if(survivors) - return "
    The following survived the meteor storm:
    [survivor_list.Join("
    ")]
    " - else - return "
    Nobody survived the meteor storm!
    " - -/datum/game_mode/meteor/set_round_result() - ..() - SSticker.mode_result = "end - evacuation" - -/datum/game_mode/meteor/generate_report() - return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \ - though unlikely. Be prepared for largescale impacts and destruction. Please note that the debris will prevent the escape shuttle from arriving quickly." +/datum/game_mode/meteor + name = "meteor" + config_tag = "meteor" + false_report_weight = 1 + var/meteordelay = 2000 + var/nometeors = 0 + var/rampupdelta = 5 + required_players = 0 + + announce_span = "danger" + announce_text = "A major meteor shower is bombarding the station! The crew needs to evacuate or survive the onslaught." + + +/datum/game_mode/meteor/process() + if(nometeors || meteordelay > world.time - SSticker.round_start_time) + return + + var/list/wavetype = GLOB.meteors_normal + var/meteorminutes = (world.time - SSticker.round_start_time - meteordelay) / 10 / 60 + + + if (prob(meteorminutes)) + wavetype = GLOB.meteors_threatening + + if (prob(meteorminutes/2)) + wavetype = GLOB.meteors_catastrophic + + var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10) + + spawn_meteors(ramp_up_final, wavetype) + + +/datum/game_mode/meteor/special_report() + var/survivors = 0 + var/list/survivor_list = list() + + for(var/mob/living/player in GLOB.player_list) + if(player.stat != DEAD) + ++survivors + + if(player.onCentCom()) + survivor_list += "[player.real_name] escaped to the safety of CentCom." + else if(player.onSyndieBase()) + survivor_list += "[player.real_name] escaped to the (relative) safety of Syndicate Space." + else + survivor_list += "[player.real_name] survived but is stranded without any hope of rescue." + + if(survivors) + return "
    The following survived the meteor storm:
    [survivor_list.Join("
    ")]
    " + else + return "
    Nobody survived the meteor storm!
    " + +/datum/game_mode/meteor/set_round_result() + ..() + SSticker.mode_result = "end - evacuation" + +/datum/game_mode/meteor/generate_report() + return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \ + though unlikely. Be prepared for largescale impacts and destruction. Please note that the debris will prevent the escape shuttle from arriving quickly." diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 176f62ef2d..d84c104a2f 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -1,265 +1,265 @@ -//Contains the target item datums for Steal objectives. - -/datum/objective_item - var/name = "A silly bike horn! Honk!" - var/targetitem = /obj/item/bikehorn //typepath of the objective item - var/difficulty = 9001 //vaguely how hard it is to do this objective - var/list/excludefromjob = list() //If you don't want a job to get a certain objective (no captain stealing his own medal, etcetc) - var/list/altitems = list() //Items which can serve as an alternative to the objective (darn you blueprints) - var/list/special_equipment = list() - -/datum/objective_item/proc/check_special_completion() //for objectives with special checks (is that slime extract unused? does that intellicard have an ai in it? etcetc) - return 1 - -/datum/objective_item/proc/TargetExists() - return TRUE - -/datum/objective_item/steal/New() - ..() - if(TargetExists()) - GLOB.possible_items += src - else - qdel(src) - -/datum/objective_item/steal/Destroy() - GLOB.possible_items -= src - return ..() - -/datum/objective_item/steal/caplaser - name = "the captain's antique laser gun." - targetitem = /obj/item/gun/energy/laser/captain - difficulty = 5 - excludefromjob = list("Captain") - -/datum/objective_item/steal/hoslaser - name = "the head of security's personal laser gun." - targetitem = /obj/item/gun/energy/e_gun/hos - difficulty = 10 - excludefromjob = list("Head Of Security") - -/datum/objective_item/steal/handtele - name = "a hand teleporter." - targetitem = /obj/item/hand_tele - difficulty = 5 - excludefromjob = list("Captain", "Research Director") - -/datum/objective_item/steal/jetpack - name = "the Captain's jetpack." - targetitem = /obj/item/tank/jetpack/oxygen/captain - difficulty = 5 - excludefromjob = list("Captain") - -/datum/objective_item/steal/magboots - name = "the chief engineer's advanced magnetic boots." - targetitem = /obj/item/clothing/shoes/magboots/advance - difficulty = 5 - excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician") - -/datum/objective_item/steal/capmedal - name = "the medal of captaincy." - targetitem = /obj/item/clothing/accessory/medal/gold/captain - difficulty = 5 - excludefromjob = list("Captain") - -/datum/objective_item/steal/hypo - name = "the Chief Medical Officer's MKII hypospray." - targetitem = /obj/item/hypospray/mkii/CMO //CITADEL EDIT, changing theft objective for the Hypo MK II - difficulty = 5 - excludefromjob = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Geneticist") - -/datum/objective_item/steal/nukedisc - name = "the nuclear authentication disk." - targetitem = /obj/item/disk/nuclear - difficulty = 5 - excludefromjob = list("Captain") - -/datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N) - return !N.fake - -/datum/objective_item/steal/reflector - name = "a reflector vest." - targetitem = /obj/item/clothing/suit/armor/laserproof - difficulty = 3 - excludefromjob = list("Head of Security", "Warden") - -/datum/objective_item/steal/reactive - name = "a reactive teleport armor." - targetitem = /obj/item/clothing/suit/armor/reactive - difficulty = 5 - excludefromjob = list("Research Director","Scientist", "Roboticist") - -/datum/objective_item/steal/documents - name = "any set of secret documents of any organization." - targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's - difficulty = 5 - -/datum/objective_item/steal/nuke_core - name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!" - targetitem = /obj/item/nuke_core - difficulty = 15 - -/datum/objective_item/steal/nuke_core/New() - special_equipment += /obj/item/storage/box/syndie_kit/nuke - ..() - -/datum/objective_item/steal/supermatter - name = "a sliver of a supermatter crystal. Be sure to use the proper safety equipment when extracting the sliver!" - targetitem = /obj/item/nuke_core/supermatter_sliver - difficulty = 15 - -/datum/objective_item/steal/supermatter/New() - special_equipment += /obj/item/storage/box/syndie_kit/supermatter - ..() - -/datum/objective_item/steal/supermatter/TargetExists() - return GLOB.main_supermatter_engine != null - -//Items with special checks! -/datum/objective_item/steal/plasma - name = "28 moles of plasma (full tank)." - targetitem = /obj/item/tank - difficulty = 3 - excludefromjob = list("Chief Engineer","Research Director","Station Engineer","Scientist","Atmospheric Technician") - -/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T) - var/target_amount = text2num(name) - var/found_amount = 0 - found_amount += T.air_contents.gases[/datum/gas/plasma] - return found_amount>=target_amount - - -/datum/objective_item/steal/functionalai - name = "a functional AI." - targetitem = /obj/item/aicard - difficulty = 20 //beyond the impossible - -/datum/objective_item/steal/functionalai/check_special_completion(obj/item/aicard/C) - for(var/mob/living/silicon/ai/A in C) - if(isAI(A) && A.stat != DEAD) //See if any AI's are alive inside that card. - return 1 - return 0 - -/datum/objective_item/steal/blueprints - name = "the station blueprints." - targetitem = /obj/item/areaeditor/blueprints - difficulty = 10 - excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician") - altitems = list(/obj/item/photo) - -/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I) - if(istype(I, /obj/item/areaeditor/blueprints)) - return TRUE - if(istype(I, /obj/item/photo)) - var/obj/item/photo/P = I - if(P.picture.has_blueprints) //if the blueprints are in frame - return TRUE - return FALSE - -/datum/objective_item/steal/slime - name = "an unused sample of slime extract." - targetitem = /obj/item/slime_extract - difficulty = 3 - excludefromjob = list("Research Director","Scientist", "Roboticist") - -/datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E) - if(E.Uses > 0) - return 1 - return 0 - -//Unique Objectives -/datum/objective_item/unique/docs_red - name = "the \"Red\" secret documents." - targetitem = /obj/item/documents/syndicate/red - difficulty = 10 - -/datum/objective_item/unique/docs_blue - name = "the \"Blue\" secret documents." - targetitem = /obj/item/documents/syndicate/blue - difficulty = 10 - -/datum/objective_item/special/New() - ..() - if(TargetExists()) - GLOB.possible_items_special += src - else - qdel(src) - -/datum/objective_item/special/Destroy() - GLOB.possible_items_special -= src - return ..() - -//Old ninja objectives. -/datum/objective_item/special/pinpointer/nuke - name = "the captain's pinpointer." - targetitem = /obj/item/pinpointer - difficulty = 10 - -/datum/objective_item/special/aegun - name = "an advanced energy gun." - targetitem = /obj/item/gun/energy/e_gun/nuclear - difficulty = 10 - -/datum/objective_item/special/ddrill - name = "a diamond drill." - targetitem = /obj/item/pickaxe/drill/diamonddrill - difficulty = 10 - -/datum/objective_item/special/boh - name = "a bag of holding." - targetitem = /obj/item/storage/backpack/holding - difficulty = 10 - -/datum/objective_item/special/hypercell - name = "a hyper-capacity power cell." - targetitem = /obj/item/stock_parts/cell/hyper - difficulty = 5 - -/datum/objective_item/special/laserpointer - name = "a laser pointer." - targetitem = /obj/item/laser_pointer - difficulty = 5 - -/datum/objective_item/special/corgimeat - name = "a piece of corgi meat." - targetitem = /obj/item/reagent_containers/food/snacks/meat/slab/corgi - difficulty = 5 - -/datum/objective_item/stack/New() - ..() - if(TargetExists()) - GLOB.possible_items_special += src - else - qdel(src) - -/datum/objective_item/stack/Destroy() - GLOB.possible_items_special -= src - return ..() - -//Stack objectives get their own subtype -/datum/objective_item/stack - name = "5 cardboard." - targetitem = /obj/item/stack/sheet/cardboard - difficulty = 9001 - -/datum/objective_item/stack/check_special_completion(obj/item/stack/S) - var/target_amount = text2num(name) - var/found_amount = 0 - - if(istype(S, targetitem)) - found_amount = S.amount - return found_amount>=target_amount - -/datum/objective_item/stack/diamond - name = "10 diamonds." - targetitem = /obj/item/stack/sheet/mineral/diamond - difficulty = 10 - -/datum/objective_item/stack/gold - name = "50 gold bars." - targetitem = /obj/item/stack/sheet/mineral/gold - difficulty = 15 - -/datum/objective_item/stack/uranium - name = "25 refined uranium bars." - targetitem = /obj/item/stack/sheet/mineral/uranium - difficulty = 10 +//Contains the target item datums for Steal objectives. + +/datum/objective_item + var/name = "A silly bike horn! Honk!" + var/targetitem = /obj/item/bikehorn //typepath of the objective item + var/difficulty = 9001 //vaguely how hard it is to do this objective + var/list/excludefromjob = list() //If you don't want a job to get a certain objective (no captain stealing his own medal, etcetc) + var/list/altitems = list() //Items which can serve as an alternative to the objective (darn you blueprints) + var/list/special_equipment = list() + +/datum/objective_item/proc/check_special_completion() //for objectives with special checks (is that slime extract unused? does that intellicard have an ai in it? etcetc) + return 1 + +/datum/objective_item/proc/TargetExists() + return TRUE + +/datum/objective_item/steal/New() + ..() + if(TargetExists()) + GLOB.possible_items += src + else + qdel(src) + +/datum/objective_item/steal/Destroy() + GLOB.possible_items -= src + return ..() + +/datum/objective_item/steal/caplaser + name = "the captain's antique laser gun." + targetitem = /obj/item/gun/energy/laser/captain + difficulty = 5 + excludefromjob = list("Captain") + +/datum/objective_item/steal/hoslaser + name = "the head of security's personal laser gun." + targetitem = /obj/item/gun/energy/e_gun/hos + difficulty = 10 + excludefromjob = list("Head Of Security") + +/datum/objective_item/steal/handtele + name = "a hand teleporter." + targetitem = /obj/item/hand_tele + difficulty = 5 + excludefromjob = list("Captain", "Research Director") + +/datum/objective_item/steal/jetpack + name = "the Captain's jetpack." + targetitem = /obj/item/tank/jetpack/oxygen/captain + difficulty = 5 + excludefromjob = list("Captain") + +/datum/objective_item/steal/magboots + name = "the chief engineer's advanced magnetic boots." + targetitem = /obj/item/clothing/shoes/magboots/advance + difficulty = 5 + excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician") + +/datum/objective_item/steal/capmedal + name = "the medal of captaincy." + targetitem = /obj/item/clothing/accessory/medal/gold/captain + difficulty = 5 + excludefromjob = list("Captain") + +/datum/objective_item/steal/hypo + name = "the Chief Medical Officer's MKII hypospray." + targetitem = /obj/item/hypospray/mkii/CMO //CITADEL EDIT, changing theft objective for the Hypo MK II + difficulty = 5 + excludefromjob = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Geneticist") + +/datum/objective_item/steal/nukedisc + name = "the nuclear authentication disk." + targetitem = /obj/item/disk/nuclear + difficulty = 5 + excludefromjob = list("Captain") + +/datum/objective_item/steal/nukedisc/check_special_completion(obj/item/disk/nuclear/N) + return !N.fake + +/datum/objective_item/steal/reflector + name = "a reflector vest." + targetitem = /obj/item/clothing/suit/armor/laserproof + difficulty = 3 + excludefromjob = list("Head of Security", "Warden") + +/datum/objective_item/steal/reactive + name = "a reactive teleport armor." + targetitem = /obj/item/clothing/suit/armor/reactive + difficulty = 5 + excludefromjob = list("Research Director","Scientist", "Roboticist") + +/datum/objective_item/steal/documents + name = "any set of secret documents of any organization." + targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's + difficulty = 5 + +/datum/objective_item/steal/nuke_core + name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!" + targetitem = /obj/item/nuke_core + difficulty = 15 + +/datum/objective_item/steal/nuke_core/New() + special_equipment += /obj/item/storage/box/syndie_kit/nuke + ..() + +/datum/objective_item/steal/supermatter + name = "a sliver of a supermatter crystal. Be sure to use the proper safety equipment when extracting the sliver!" + targetitem = /obj/item/nuke_core/supermatter_sliver + difficulty = 15 + +/datum/objective_item/steal/supermatter/New() + special_equipment += /obj/item/storage/box/syndie_kit/supermatter + ..() + +/datum/objective_item/steal/supermatter/TargetExists() + return GLOB.main_supermatter_engine != null + +//Items with special checks! +/datum/objective_item/steal/plasma + name = "28 moles of plasma (full tank)." + targetitem = /obj/item/tank + difficulty = 3 + excludefromjob = list("Chief Engineer","Research Director","Station Engineer","Scientist","Atmospheric Technician") + +/datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T) + var/target_amount = text2num(name) + var/found_amount = 0 + found_amount += T.air_contents.gases[/datum/gas/plasma] + return found_amount>=target_amount + + +/datum/objective_item/steal/functionalai + name = "a functional AI." + targetitem = /obj/item/aicard + difficulty = 20 //beyond the impossible + +/datum/objective_item/steal/functionalai/check_special_completion(obj/item/aicard/C) + for(var/mob/living/silicon/ai/A in C) + if(isAI(A) && A.stat != DEAD) //See if any AI's are alive inside that card. + return 1 + return 0 + +/datum/objective_item/steal/blueprints + name = "the station blueprints." + targetitem = /obj/item/areaeditor/blueprints + difficulty = 10 + excludefromjob = list("Chief Engineer", "Station Engineer", "Atmospheric Technician") + altitems = list(/obj/item/photo) + +/datum/objective_item/steal/blueprints/check_special_completion(obj/item/I) + if(istype(I, /obj/item/areaeditor/blueprints)) + return TRUE + if(istype(I, /obj/item/photo)) + var/obj/item/photo/P = I + if(P.picture.has_blueprints) //if the blueprints are in frame + return TRUE + return FALSE + +/datum/objective_item/steal/slime + name = "an unused sample of slime extract." + targetitem = /obj/item/slime_extract + difficulty = 3 + excludefromjob = list("Research Director","Scientist", "Roboticist") + +/datum/objective_item/steal/slime/check_special_completion(obj/item/slime_extract/E) + if(E.Uses > 0) + return 1 + return 0 + +//Unique Objectives +/datum/objective_item/unique/docs_red + name = "the \"Red\" secret documents." + targetitem = /obj/item/documents/syndicate/red + difficulty = 10 + +/datum/objective_item/unique/docs_blue + name = "the \"Blue\" secret documents." + targetitem = /obj/item/documents/syndicate/blue + difficulty = 10 + +/datum/objective_item/special/New() + ..() + if(TargetExists()) + GLOB.possible_items_special += src + else + qdel(src) + +/datum/objective_item/special/Destroy() + GLOB.possible_items_special -= src + return ..() + +//Old ninja objectives. +/datum/objective_item/special/pinpointer/nuke + name = "the captain's pinpointer." + targetitem = /obj/item/pinpointer + difficulty = 10 + +/datum/objective_item/special/aegun + name = "an advanced energy gun." + targetitem = /obj/item/gun/energy/e_gun/nuclear + difficulty = 10 + +/datum/objective_item/special/ddrill + name = "a diamond drill." + targetitem = /obj/item/pickaxe/drill/diamonddrill + difficulty = 10 + +/datum/objective_item/special/boh + name = "a bag of holding." + targetitem = /obj/item/storage/backpack/holding + difficulty = 10 + +/datum/objective_item/special/hypercell + name = "a hyper-capacity power cell." + targetitem = /obj/item/stock_parts/cell/hyper + difficulty = 5 + +/datum/objective_item/special/laserpointer + name = "a laser pointer." + targetitem = /obj/item/laser_pointer + difficulty = 5 + +/datum/objective_item/special/corgimeat + name = "a piece of corgi meat." + targetitem = /obj/item/reagent_containers/food/snacks/meat/slab/corgi + difficulty = 5 + +/datum/objective_item/stack/New() + ..() + if(TargetExists()) + GLOB.possible_items_special += src + else + qdel(src) + +/datum/objective_item/stack/Destroy() + GLOB.possible_items_special -= src + return ..() + +//Stack objectives get their own subtype +/datum/objective_item/stack + name = "5 cardboard." + targetitem = /obj/item/stack/sheet/cardboard + difficulty = 9001 + +/datum/objective_item/stack/check_special_completion(obj/item/stack/S) + var/target_amount = text2num(name) + var/found_amount = 0 + + if(istype(S, targetitem)) + found_amount = S.amount + return found_amount>=target_amount + +/datum/objective_item/stack/diamond + name = "10 diamonds." + targetitem = /obj/item/stack/sheet/mineral/diamond + difficulty = 10 + +/datum/objective_item/stack/gold + name = "50 gold bars." + targetitem = /obj/item/stack/sheet/mineral/gold + difficulty = 15 + +/datum/objective_item/stack/uranium + name = "25 refined uranium bars." + targetitem = /obj/item/stack/sheet/mineral/uranium + difficulty = 10 diff --git a/code/game/gamemodes/sandbox/airlock_maker.dm b/code/game/gamemodes/sandbox/airlock_maker.dm index 6b988fd077..ddb622ab08 100644 --- a/code/game/gamemodes/sandbox/airlock_maker.dm +++ b/code/game/gamemodes/sandbox/airlock_maker.dm @@ -1,141 +1,141 @@ -/* - This is for the sandbox for now, - maybe useful later for an actual thing? - -Sayu -*/ - -/obj/structure/door_assembly - var/datum/airlock_maker/maker = null - -/obj/structure/door_assembly/attack_hand() - . = ..() - if(.) - return - if(maker) - maker.interact() - -/datum/airlock_maker - var/obj/structure/door_assembly/linked = null - - var/list/access_used = null - var/require_all = 1 - - var/paintjob = "none" - var/glassdoor = 0 - - var/doorname = "airlock" - -/datum/airlock_maker/New(var/atom/target_loc) - linked = new(target_loc) - linked.maker = src - linked.anchored = FALSE - access_used = list() - - interact() - -/datum/airlock_maker/proc/linkpretty(href,desc,active) - if(!desc) - var/static/list/defaults = list("No","Yes") - desc = defaults[active+1] - if(active) - return "[desc]" - return "[desc]" - -/datum/airlock_maker/proc/interact() - var/list/leftcolumn = list() - var/list/rightcolumn = list() - leftcolumn += "Required Access" - for(var/access in get_all_accesses()) - leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used) - leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]" - - rightcolumn += "Paintjob" - for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity")) - rightcolumn += linkpretty("paint=[option]",option,option == paintjob) - rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "

    " - var/length = max(leftcolumn.len,rightcolumn.len) - - var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.

    " - dat += "Door name: \"[doorname]\"" - dat += "" - for(var/i=1; i<=length; i++) - dat += "" - - dat += "
    " - if(i<=leftcolumn.len) - dat += leftcolumn[i] - dat += "" - if(i<=rightcolumn.len) - dat += rightcolumn[i] - dat += "

    Finalize Airlock Construction | Cancel and Destroy Airlock" - usr << browse(dat,"window=airlockmaker") - -/datum/airlock_maker/Topic(var/href,var/list/href_list) - if(!usr) - return - if(!src || !linked || !linked.loc) - usr << browse(null,"window=airlockmaker") - return - - if("rename" in href_list) - var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname) - if(newname) - doorname = newname - if("access" in href_list) - var/value = text2num(href_list["access"]) - access_used ^= value - if("reqall" in href_list) - require_all = !require_all - if("paint" in href_list) - paintjob = href_list["paint"] - if("glass" in href_list) - glassdoor = !glassdoor - - if("cancel" in href_list) - usr << browse(null,"window=airlockmaker") - qdel(linked) - qdel(src) - return - - if("done" in href_list) - usr << browse(null,"window=airlockmaker") - var/turf/t_loc = linked.loc - qdel(linked) - if(!istype(t_loc)) - return - - var/target_type = "/obj/machinery/door/airlock" - if(glassdoor) - if(paintjob != "none") - if(paintjob in list("external","highsecurity","maintenance")) // no glass version - target_type += "/[paintjob]" - else - target_type += "/glass_[paintjob]" - else - target_type += "/glass" - else if(paintjob != "none") - target_type += "/[paintjob]" - var/final = target_type - target_type = text2path(final) - if(!target_type) - to_chat(usr, "Didn't work, contact Sayu with this: [final]") - usr << browse(null,"window=airlockmaker") - return - - var/obj/machinery/door/D = new target_type(t_loc) - - D.name = doorname - - if(access_used.len == 0) - D.req_access = null - D.req_one_access = null - else if(require_all) - D.req_access = access_used.Copy() - D.req_one_access = null - else - D.req_access = null - D.req_one_access = access_used.Copy() - - return - - interact() +/* + This is for the sandbox for now, + maybe useful later for an actual thing? + -Sayu +*/ + +/obj/structure/door_assembly + var/datum/airlock_maker/maker = null + +/obj/structure/door_assembly/attack_hand() + . = ..() + if(.) + return + if(maker) + maker.interact() + +/datum/airlock_maker + var/obj/structure/door_assembly/linked = null + + var/list/access_used = null + var/require_all = 1 + + var/paintjob = "none" + var/glassdoor = 0 + + var/doorname = "airlock" + +/datum/airlock_maker/New(var/atom/target_loc) + linked = new(target_loc) + linked.maker = src + linked.anchored = FALSE + access_used = list() + + interact() + +/datum/airlock_maker/proc/linkpretty(href,desc,active) + if(!desc) + var/static/list/defaults = list("No","Yes") + desc = defaults[active+1] + if(active) + return "[desc]" + return "[desc]" + +/datum/airlock_maker/proc/interact() + var/list/leftcolumn = list() + var/list/rightcolumn = list() + leftcolumn += "Required Access" + for(var/access in get_all_accesses()) + leftcolumn += linkpretty("access=[access]",get_access_desc(access),access in access_used) + leftcolumn += "Require all listed accesses: [linkpretty("reqall",null,require_all)]" + + rightcolumn += "Paintjob" + for(var/option in list("none","engineering","atmos","security","command","medical","research","mining","maintenance","external","highsecurity")) + rightcolumn += linkpretty("paint=[option]",option,option == paintjob) + rightcolumn += "Glass door: " + linkpretty("glass",null,glassdoor) + "

    " + var/length = max(leftcolumn.len,rightcolumn.len) + + var/dat = "You may move the model airlock around. A new airlock will be built in its space when you click done, below.

    " + dat += "Door name: \"[doorname]\"" + dat += "" + for(var/i=1; i<=length; i++) + dat += "" + + dat += "
    " + if(i<=leftcolumn.len) + dat += leftcolumn[i] + dat += "" + if(i<=rightcolumn.len) + dat += rightcolumn[i] + dat += "

    Finalize Airlock Construction | Cancel and Destroy Airlock" + usr << browse(dat,"window=airlockmaker") + +/datum/airlock_maker/Topic(var/href,var/list/href_list) + if(!usr) + return + if(!src || !linked || !linked.loc) + usr << browse(null,"window=airlockmaker") + return + + if("rename" in href_list) + var/newname = stripped_input(usr,"New airlock name:","Name the airlock",doorname) + if(newname) + doorname = newname + if("access" in href_list) + var/value = text2num(href_list["access"]) + access_used ^= value + if("reqall" in href_list) + require_all = !require_all + if("paint" in href_list) + paintjob = href_list["paint"] + if("glass" in href_list) + glassdoor = !glassdoor + + if("cancel" in href_list) + usr << browse(null,"window=airlockmaker") + qdel(linked) + qdel(src) + return + + if("done" in href_list) + usr << browse(null,"window=airlockmaker") + var/turf/t_loc = linked.loc + qdel(linked) + if(!istype(t_loc)) + return + + var/target_type = "/obj/machinery/door/airlock" + if(glassdoor) + if(paintjob != "none") + if(paintjob in list("external","highsecurity","maintenance")) // no glass version + target_type += "/[paintjob]" + else + target_type += "/glass_[paintjob]" + else + target_type += "/glass" + else if(paintjob != "none") + target_type += "/[paintjob]" + var/final = target_type + target_type = text2path(final) + if(!target_type) + to_chat(usr, "Didn't work, contact Sayu with this: [final]") + usr << browse(null,"window=airlockmaker") + return + + var/obj/machinery/door/D = new target_type(t_loc) + + D.name = doorname + + if(access_used.len == 0) + D.req_access = null + D.req_one_access = null + else if(require_all) + D.req_access = access_used.Copy() + D.req_one_access = null + else + D.req_access = null + D.req_one_access = access_used.Copy() + + return + + interact() diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index d54dda5353..e1fbb636c8 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -1,303 +1,303 @@ - - -GLOBAL_VAR_INIT(hsboxspawn, TRUE) - -/mob - var/datum/hSB/sandbox = null -/mob/proc/CanBuild() - sandbox = new/datum/hSB - sandbox.owner = src.ckey - if(src.client.holder) - sandbox.admin = 1 - verbs += new/mob/proc/sandbox_panel -/mob/proc/sandbox_panel() - set name = "Sandbox Panel" - if(sandbox) - sandbox.update() - -/datum/hSB - var/owner = null - var/admin = 0 - - var/static/clothinfo = null - var/static/reaginfo = null - var/static/objinfo = null - var/canisterinfo = null - var/hsbinfo = null - //items that shouldn't spawn on the floor because they would bug or act weird - var/static/list/spawn_forbidden = list( - /obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you - /obj/item/assembly, /obj/item/onetankbomb, /obj/item/pda/ai, - /obj/item/smallDelivery, /obj/item/projectile, - /obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module) - -/datum/hSB/proc/update() - var/static/list/hrefs = list( - "Space Gear", - "Suit Up (Space Travel Gear)" = "hsbsuit", - "Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]", - "Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]", - - "Standard Tools", - "Spawn Flashlight" = "hsbspawn&path=[/obj/item/flashlight]", - "Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]", - "Spawn Light Replacer" = "hsbspawn&path=[/obj/item/lightreplacer]", - "Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]", - "Spawn All-Access ID" = "hsbaaid", - - "Building Supplies", - "Spawn 50 Wood" = "hsbwood", - "Spawn 50 Metal" = "hsbmetal", - "Spawn 50 Plasteel" = "hsbplasteel", - "Spawn 50 Reinforced Glass" = "hsbrglass", - "Spawn 50 Glass" = "hsbglass", - "Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]", - "Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]", - "Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]", - "Spawn Rapid Construction Device" = "hsbrcd", - "Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]", - "Spawn Airlock" = "hsbairlock", - - "Miscellaneous", - "Spawn Air Scrubber" = "hsbscrubber", - "Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]", - "Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]", - - "Bots", - "Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]", - "Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]", - "Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]", - - "Canisters", - "Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]", - "Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]") - - - if(!hsbinfo) - hsbinfo = "
    Sandbox Panel

    " - if(admin) - hsbinfo += "Administration
    " - hsbinfo += "- Toggle Object Spawning
    " - hsbinfo += "- Toggle Item Spawn Panel Auto-close
    " - hsbinfo += "Canister Spawning
    " - hsbinfo += "- Spawn Plasma Canister
    " - hsbinfo += "- Spawn CO2 Canister
    " - hsbinfo += "- Spawn Nitrogen Canister
    " - hsbinfo += "- Spawn N2O Canister
    " - else - hsbinfo += "Some item spawning may be disabled by the administrators.
    " - hsbinfo += "Only administrators may spawn dangerous canisters.
    " - for(var/T in hrefs) - var/href = hrefs[T] - if(href) - hsbinfo += "- [T]
    " - else - hsbinfo += "
    [T]
    " - hsbinfo += "
    " - hsbinfo += "- Spawn Clothing...
    " - hsbinfo += "- Spawn Reagent Container...
    " - hsbinfo += "- Spawn Other Item...

    " - - usr << browse(hsbinfo, "window=hsbpanel") - -/datum/hSB/Topic(href, href_list) - if(!usr || !src || !(src.owner == usr.ckey)) - if(usr) - usr << browse(null,"window=sandbox") - return - - if(href_list["hsb"]) - switch(href_list["hsb"]) - // - // Admin: toggle spawning - // - if("hsbtobj") - if(!admin) return - if(GLOB.hsboxspawn) - to_chat(world, "Sandbox: \black[usr.key] has disabled object spawning!") - GLOB.hsboxspawn = FALSE - return - else - to_chat(world, "Sandbox: \black[usr.key] has enabled object spawning!") - GLOB.hsboxspawn = TRUE - return - // - // Admin: Toggle auto-close - // - if("hsbtac") - if(!admin) return - var/sbac = CONFIG_GET(flag/sandbox_autoclose) - if(sbac) - to_chat(world, "Sandbox: \black [usr.key] has removed the object spawn limiter.") - else - to_chat(world, "Sandbox: \black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.") - CONFIG_SET(flag/sandbox_autoclose, !sbac) - return - // - // Spacesuit with full air jetpack set as internals - // - if("hsbsuit") - var/mob/living/carbon/human/P = usr - if(!istype(P)) return - if(P.wear_suit) - P.wear_suit.forceMove(P.drop_location()) - P.wear_suit.layer = initial(P.wear_suit.layer) - P.wear_suit.plane = initial(P.wear_suit.plane) - P.wear_suit = null - P.wear_suit = new/obj/item/clothing/suit/space(P) - P.wear_suit.layer = ABOVE_HUD_LAYER - P.wear_suit.plane = ABOVE_HUD_PLANE - P.update_inv_wear_suit() - if(P.head) - P.head.forceMove(P.drop_location()) - P.head.layer = initial(P.head.layer) - P.head.plane = initial(P.head.plane) - P.head = null - P.head = new/obj/item/clothing/head/helmet/space(P) - P.head.layer = ABOVE_HUD_LAYER - P.head.plane = ABOVE_HUD_PLANE - P.update_inv_head() - if(P.wear_mask) - P.wear_mask.forceMove(P.drop_location()) - P.wear_mask.layer = initial(P.wear_mask.layer) - P.wear_mask.plane = initial(P.wear_mask.plane) - P.wear_mask = null - P.wear_mask = new/obj/item/clothing/mask/gas(P) - P.wear_mask.layer = ABOVE_HUD_LAYER - P.wear_mask.plane = ABOVE_HUD_PLANE - P.update_inv_wear_mask() - if(P.back) - P.back.forceMove(P.drop_location()) - P.back.layer = initial(P.back.layer) - P.back.plane = initial(P.back.plane) - P.back = null - P.back = new/obj/item/tank/jetpack/oxygen(P) - P.back.layer = ABOVE_HUD_LAYER - P.back.plane = ABOVE_HUD_PLANE - P.update_inv_back() - P.internal = P.back - P.update_internals_hud_icon(1) - - if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it - var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc) - hsb.update_icon() // hackish but it wasn't meant to be spawned I guess? - - // - // Stacked Materials - // - - if("hsbrglass") - new/obj/item/stack/sheet/rglass{amount=50}(usr.loc) - - if("hsbmetal") - new/obj/item/stack/sheet/metal{amount=50}(usr.loc) - - if("hsbplasteel") - new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc) - - if("hsbglass") - new/obj/item/stack/sheet/glass{amount=50}(usr.loc) - - if("hsbwood") - new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc) - - // - // All access ID - // - if("hsbaaid") - var/obj/item/card/id/gold/ID = new(usr.loc) - ID.registered_name = usr.real_name - ID.assignment = "Sandbox" - ID.access = get_all_accesses() - ID.update_label() - - // - // RCD - starts with full clip - // Spawn check due to grief potential (destroying floors, walls, etc) - // - if("hsbrcd") - if(!GLOB.hsboxspawn) return - - new/obj/item/construction/rcd/combat(usr.loc) - - // - // New sandbox airlock maker - // - if("hsbairlock") - new /datum/airlock_maker(usr.loc) - - // - // Object spawn window - // - - // Clothing - if("hsbcloth") - if(!GLOB.hsboxspawn) return - - if(!clothinfo) - clothinfo = "Clothing (Reagent Containers) (Other Items)

    " - var/list/all_items = subtypesof(/obj/item/clothing) - for(var/typekey in spawn_forbidden) - all_items -= typesof(typekey) - for(var/O in reverseRange(all_items)) - clothinfo += "[O]
    " - - usr << browse(clothinfo,"window=sandbox") - - // Reagent containers - if("hsbreag") - if(!GLOB.hsboxspawn) return - - if(!reaginfo) - reaginfo = "Reagent Containers (Clothing) (Other Items)

    " - var/list/all_items = subtypesof(/obj/item/reagent_containers) - for(var/typekey in spawn_forbidden) - all_items -= typesof(typekey) - for(var/O in reverseRange(all_items)) - reaginfo += "[O]
    " - - usr << browse(reaginfo,"window=sandbox") - - // Other items - if("hsbobj") - if(!GLOB.hsboxspawn) return - - if(!objinfo) - objinfo = "Other Items (Clothing) (Reagent Containers)

    " - var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers) - for(var/typekey in spawn_forbidden) - all_items -= typesof(typekey) - - for(var/O in reverseRange(all_items)) - objinfo += "[O]
    " - - usr << browse(objinfo,"window=sandbox") - - // - // Safespawn checks to see if spawning is disabled. - // - if("hsb_safespawn") - if(!GLOB.hsboxspawn) - usr << browse(null,"window=sandbox") - return - - var/typepath = text2path(href_list["path"]) - if(!typepath) - to_chat(usr, "Bad path: \"[href_list["path"]]\"") - return - new typepath(usr.loc) - - if(CONFIG_GET(flag/sandbox_autoclose)) - usr << browse(null,"window=sandbox") - // - // For everything else in the href list - // - if("hsbspawn") - var/typepath = text2path(href_list["path"]) - if(!typepath) - to_chat(usr, "Bad path: \"[href_list["path"]]\"") - return - new typepath(usr.loc) - - if(CONFIG_GET(flag/sandbox_autoclose)) - usr << browse(null,"window=sandbox") + + +GLOBAL_VAR_INIT(hsboxspawn, TRUE) + +/mob + var/datum/hSB/sandbox = null +/mob/proc/CanBuild() + sandbox = new/datum/hSB + sandbox.owner = src.ckey + if(src.client.holder) + sandbox.admin = 1 + verbs += new/mob/proc/sandbox_panel +/mob/proc/sandbox_panel() + set name = "Sandbox Panel" + if(sandbox) + sandbox.update() + +/datum/hSB + var/owner = null + var/admin = 0 + + var/static/clothinfo = null + var/static/reaginfo = null + var/static/objinfo = null + var/canisterinfo = null + var/hsbinfo = null + //items that shouldn't spawn on the floor because they would bug or act weird + var/static/list/spawn_forbidden = list( + /obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you + /obj/item/assembly, /obj/item/onetankbomb, /obj/item/pda/ai, + /obj/item/smallDelivery, /obj/item/projectile, + /obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module) + +/datum/hSB/proc/update() + var/static/list/hrefs = list( + "Space Gear", + "Suit Up (Space Travel Gear)" = "hsbsuit", + "Spawn Gas Mask" = "hsbspawn&path=[/obj/item/clothing/mask/gas]", + "Spawn Emergency Air Tank" = "hsbspawn&path=[/obj/item/tank/internals/emergency_oxygen/double]", + + "Standard Tools", + "Spawn Flashlight" = "hsbspawn&path=[/obj/item/flashlight]", + "Spawn Toolbox" = "hsbspawn&path=[/obj/item/storage/toolbox/mechanical]", + "Spawn Light Replacer" = "hsbspawn&path=[/obj/item/lightreplacer]", + "Spawn Medical Kit" = "hsbspawn&path=[/obj/item/storage/firstaid/regular]", + "Spawn All-Access ID" = "hsbaaid", + + "Building Supplies", + "Spawn 50 Wood" = "hsbwood", + "Spawn 50 Metal" = "hsbmetal", + "Spawn 50 Plasteel" = "hsbplasteel", + "Spawn 50 Reinforced Glass" = "hsbrglass", + "Spawn 50 Glass" = "hsbglass", + "Spawn Full Cable Coil" = "hsbspawn&path=[/obj/item/stack/cable_coil]", + "Spawn Hyper Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/hyper]", + "Spawn Inf. Capacity Power Cell" = "hsbspawn&path=[/obj/item/stock_parts/cell/infinite]", + "Spawn Rapid Construction Device" = "hsbrcd", + "Spawn RCD Ammo" = "hsb_safespawn&path=[/obj/item/rcd_ammo]", + "Spawn Airlock" = "hsbairlock", + + "Miscellaneous", + "Spawn Air Scrubber" = "hsbscrubber", + "Spawn Welding Fuel Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/fueltank]", + "Spawn Water Tank" = "hsbspawn&path=[/obj/structure/reagent_dispensers/watertank]", + + "Bots", + "Spawn Cleanbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/cleanbot]", + "Spawn Floorbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/floorbot]", + "Spawn Medbot" = "hsbspawn&path=[/mob/living/simple_animal/bot/medbot]", + + "Canisters", + "Spawn O2 Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/oxygen]", + "Spawn Air Canister" = "hsbspawn&path=[/obj/machinery/portable_atmospherics/canister/air]") + + + if(!hsbinfo) + hsbinfo = "
    Sandbox Panel

    " + if(admin) + hsbinfo += "Administration
    " + hsbinfo += "- Toggle Object Spawning
    " + hsbinfo += "- Toggle Item Spawn Panel Auto-close
    " + hsbinfo += "Canister Spawning
    " + hsbinfo += "- Spawn Plasma Canister
    " + hsbinfo += "- Spawn CO2 Canister
    " + hsbinfo += "- Spawn Nitrogen Canister
    " + hsbinfo += "- Spawn N2O Canister
    " + else + hsbinfo += "Some item spawning may be disabled by the administrators.
    " + hsbinfo += "Only administrators may spawn dangerous canisters.
    " + for(var/T in hrefs) + var/href = hrefs[T] + if(href) + hsbinfo += "- [T]
    " + else + hsbinfo += "
    [T]
    " + hsbinfo += "
    " + hsbinfo += "- Spawn Clothing...
    " + hsbinfo += "- Spawn Reagent Container...
    " + hsbinfo += "- Spawn Other Item...

    " + + usr << browse(hsbinfo, "window=hsbpanel") + +/datum/hSB/Topic(href, href_list) + if(!usr || !src || !(src.owner == usr.ckey)) + if(usr) + usr << browse(null,"window=sandbox") + return + + if(href_list["hsb"]) + switch(href_list["hsb"]) + // + // Admin: toggle spawning + // + if("hsbtobj") + if(!admin) return + if(GLOB.hsboxspawn) + to_chat(world, "Sandbox: \black[usr.key] has disabled object spawning!") + GLOB.hsboxspawn = FALSE + return + else + to_chat(world, "Sandbox: \black[usr.key] has enabled object spawning!") + GLOB.hsboxspawn = TRUE + return + // + // Admin: Toggle auto-close + // + if("hsbtac") + if(!admin) return + var/sbac = CONFIG_GET(flag/sandbox_autoclose) + if(sbac) + to_chat(world, "Sandbox: \black [usr.key] has removed the object spawn limiter.") + else + to_chat(world, "Sandbox: \black [usr.key] has added a limiter to object spawning. The window will now auto-close after use.") + CONFIG_SET(flag/sandbox_autoclose, !sbac) + return + // + // Spacesuit with full air jetpack set as internals + // + if("hsbsuit") + var/mob/living/carbon/human/P = usr + if(!istype(P)) return + if(P.wear_suit) + P.wear_suit.forceMove(P.drop_location()) + P.wear_suit.layer = initial(P.wear_suit.layer) + P.wear_suit.plane = initial(P.wear_suit.plane) + P.wear_suit = null + P.wear_suit = new/obj/item/clothing/suit/space(P) + P.wear_suit.layer = ABOVE_HUD_LAYER + P.wear_suit.plane = ABOVE_HUD_PLANE + P.update_inv_wear_suit() + if(P.head) + P.head.forceMove(P.drop_location()) + P.head.layer = initial(P.head.layer) + P.head.plane = initial(P.head.plane) + P.head = null + P.head = new/obj/item/clothing/head/helmet/space(P) + P.head.layer = ABOVE_HUD_LAYER + P.head.plane = ABOVE_HUD_PLANE + P.update_inv_head() + if(P.wear_mask) + P.wear_mask.forceMove(P.drop_location()) + P.wear_mask.layer = initial(P.wear_mask.layer) + P.wear_mask.plane = initial(P.wear_mask.plane) + P.wear_mask = null + P.wear_mask = new/obj/item/clothing/mask/gas(P) + P.wear_mask.layer = ABOVE_HUD_LAYER + P.wear_mask.plane = ABOVE_HUD_PLANE + P.update_inv_wear_mask() + if(P.back) + P.back.forceMove(P.drop_location()) + P.back.layer = initial(P.back.layer) + P.back.plane = initial(P.back.plane) + P.back = null + P.back = new/obj/item/tank/jetpack/oxygen(P) + P.back.layer = ABOVE_HUD_LAYER + P.back.plane = ABOVE_HUD_PLANE + P.update_inv_back() + P.internal = P.back + P.update_internals_hud_icon(1) + + if("hsbscrubber") // This is beyond its normal capability but this is sandbox and you spawned one, I assume you need it + var/obj/hsb = new/obj/machinery/portable_atmospherics/scrubber{volume_rate=50*ONE_ATMOSPHERE;on=1}(usr.loc) + hsb.update_icon() // hackish but it wasn't meant to be spawned I guess? + + // + // Stacked Materials + // + + if("hsbrglass") + new/obj/item/stack/sheet/rglass{amount=50}(usr.loc) + + if("hsbmetal") + new/obj/item/stack/sheet/metal{amount=50}(usr.loc) + + if("hsbplasteel") + new/obj/item/stack/sheet/plasteel{amount=50}(usr.loc) + + if("hsbglass") + new/obj/item/stack/sheet/glass{amount=50}(usr.loc) + + if("hsbwood") + new/obj/item/stack/sheet/mineral/wood{amount=50}(usr.loc) + + // + // All access ID + // + if("hsbaaid") + var/obj/item/card/id/gold/ID = new(usr.loc) + ID.registered_name = usr.real_name + ID.assignment = "Sandbox" + ID.access = get_all_accesses() + ID.update_label() + + // + // RCD - starts with full clip + // Spawn check due to grief potential (destroying floors, walls, etc) + // + if("hsbrcd") + if(!GLOB.hsboxspawn) return + + new/obj/item/construction/rcd/combat(usr.loc) + + // + // New sandbox airlock maker + // + if("hsbairlock") + new /datum/airlock_maker(usr.loc) + + // + // Object spawn window + // + + // Clothing + if("hsbcloth") + if(!GLOB.hsboxspawn) return + + if(!clothinfo) + clothinfo = "Clothing (Reagent Containers) (Other Items)

    " + var/list/all_items = subtypesof(/obj/item/clothing) + for(var/typekey in spawn_forbidden) + all_items -= typesof(typekey) + for(var/O in reverseRange(all_items)) + clothinfo += "[O]
    " + + usr << browse(clothinfo,"window=sandbox") + + // Reagent containers + if("hsbreag") + if(!GLOB.hsboxspawn) return + + if(!reaginfo) + reaginfo = "Reagent Containers (Clothing) (Other Items)

    " + var/list/all_items = subtypesof(/obj/item/reagent_containers) + for(var/typekey in spawn_forbidden) + all_items -= typesof(typekey) + for(var/O in reverseRange(all_items)) + reaginfo += "[O]
    " + + usr << browse(reaginfo,"window=sandbox") + + // Other items + if("hsbobj") + if(!GLOB.hsboxspawn) return + + if(!objinfo) + objinfo = "Other Items (Clothing) (Reagent Containers)

    " + var/list/all_items = subtypesof(/obj/item/) - typesof(/obj/item/clothing) - typesof(/obj/item/reagent_containers) + for(var/typekey in spawn_forbidden) + all_items -= typesof(typekey) + + for(var/O in reverseRange(all_items)) + objinfo += "[O]
    " + + usr << browse(objinfo,"window=sandbox") + + // + // Safespawn checks to see if spawning is disabled. + // + if("hsb_safespawn") + if(!GLOB.hsboxspawn) + usr << browse(null,"window=sandbox") + return + + var/typepath = text2path(href_list["path"]) + if(!typepath) + to_chat(usr, "Bad path: \"[href_list["path"]]\"") + return + new typepath(usr.loc) + + if(CONFIG_GET(flag/sandbox_autoclose)) + usr << browse(null,"window=sandbox") + // + // For everything else in the href list + // + if("hsbspawn") + var/typepath = text2path(href_list["path"]) + if(!typepath) + to_chat(usr, "Bad path: \"[href_list["path"]]\"") + return + new typepath(usr.loc) + + if(CONFIG_GET(flag/sandbox_autoclose)) + usr << browse(null,"window=sandbox") diff --git a/code/game/gamemodes/sandbox/sandbox.dm b/code/game/gamemodes/sandbox/sandbox.dm index 21169b8236..9c38bd83e8 100644 --- a/code/game/gamemodes/sandbox/sandbox.dm +++ b/code/game/gamemodes/sandbox/sandbox.dm @@ -1,21 +1,21 @@ -/datum/game_mode/sandbox - name = "sandbox" - config_tag = "sandbox" - required_players = 0 - - announce_span = "info" - announce_text = "Build your own station... or just shoot each other!" - - allow_persistence_save = FALSE - -/datum/game_mode/sandbox/pre_setup() - for(var/mob/M in GLOB.player_list) - M.CanBuild() - return 1 - -/datum/game_mode/sandbox/post_setup() - ..() - SSshuttle.registerHostileEnvironment(src) - -/datum/game_mode/sandbox/generate_report() - return "Sensors indicate that crewmembers have been all given psychic powers from which they can manifest various objects.

    This can only end poorly." +/datum/game_mode/sandbox + name = "sandbox" + config_tag = "sandbox" + required_players = 0 + + announce_span = "info" + announce_text = "Build your own station... or just shoot each other!" + + allow_persistence_save = FALSE + +/datum/game_mode/sandbox/pre_setup() + for(var/mob/M in GLOB.player_list) + M.CanBuild() + return 1 + +/datum/game_mode/sandbox/post_setup() + ..() + SSshuttle.registerHostileEnvironment(src) + +/datum/game_mode/sandbox/generate_report() + return "Sensors indicate that crewmembers have been all given psychic powers from which they can manifest various objects.

    This can only end poorly." diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm index 3811fa9562..fc669d4855 100644 --- a/code/game/gamemodes/traitor/double_agents.dm +++ b/code/game/gamemodes/traitor/double_agents.dm @@ -1,82 +1,82 @@ -/datum/game_mode - var/list/target_list = list() - var/list/late_joining_list = list() - -/datum/game_mode/traitor/internal_affairs - name = "Internal Affairs" - config_tag = "internal_affairs" - false_report_weight = 10 - required_players = 25 - required_enemies = 5 - recommended_enemies = 8 - reroll_friendly = 0 - traitor_name = "Nanotrasen Internal Affairs Agent" - antag_flag = ROLE_INTERNAL_AFFAIRS - - traitors_possible = 10 //hard limit on traitors if scaling is turned off - num_modifier = 4 // Four additional traitors - antag_datum = /datum/antagonist/traitor/internal_affairs - - announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\ - IAA: Eliminate your targets and protect yourself!\n\ - Crew: Stop the IAA agents before they can cause too much mayhem." - - - -/datum/game_mode/traitor/internal_affairs/post_setup() - var/i = 0 - for(var/datum/mind/traitor in pre_traitors) - i++ - if(i + 1 > pre_traitors.len) - i = 0 - target_list[traitor] = pre_traitors[i+1] - ..() - - -/datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character) - - check_potential_agents() - - // As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other. - if(late_joining_list.len >= rand(3, 4)) - // True randomness - shuffle_inplace(late_joining_list) - // Reset the target_list, it'll be used again in force_traitor_objectives - target_list = list() - - // Basically setting the target_list for who is killing who - var/i = 0 - for(var/datum/mind/traitor in late_joining_list) - i++ - if(i + 1 > late_joining_list.len) - i = 0 - target_list[traitor] = late_joining_list[i + 1] - traitor.special_role = traitor_name - - // Now, give them their targets - for(var/datum/mind/traitor in target_list) - ..(traitor) - - late_joining_list = list() - else - late_joining_list += character - return - -/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents() - - for(var/M in late_joining_list) - if(istype(M, /datum/mind)) - var/datum/mind/agent_mind = M - if(ishuman(agent_mind.current)) - var/mob/living/carbon/human/H = agent_mind.current - if(H.stat != DEAD) - if(H.client) - continue // It all checks out. - - // If any check fails, remove them from our list - late_joining_list -= M - - -/datum/game_mode/traitor/internal_affairs/generate_report() - return "Nanotrasen denies any accusations of placing internal affairs agents onboard your station to eliminate inconvenient employees. Any further accusations against CentCom for such \ - actions will be met with a conversation with an official internal affairs agent." +/datum/game_mode + var/list/target_list = list() + var/list/late_joining_list = list() + +/datum/game_mode/traitor/internal_affairs + name = "Internal Affairs" + config_tag = "internal_affairs" + false_report_weight = 10 + required_players = 25 + required_enemies = 5 + recommended_enemies = 8 + reroll_friendly = 0 + traitor_name = "Nanotrasen Internal Affairs Agent" + antag_flag = ROLE_INTERNAL_AFFAIRS + + traitors_possible = 10 //hard limit on traitors if scaling is turned off + num_modifier = 4 // Four additional traitors + antag_datum = /datum/antagonist/traitor/internal_affairs + + announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\ + IAA: Eliminate your targets and protect yourself!\n\ + Crew: Stop the IAA agents before they can cause too much mayhem." + + + +/datum/game_mode/traitor/internal_affairs/post_setup() + var/i = 0 + for(var/datum/mind/traitor in pre_traitors) + i++ + if(i + 1 > pre_traitors.len) + i = 0 + target_list[traitor] = pre_traitors[i+1] + ..() + + +/datum/game_mode/traitor/internal_affairs/add_latejoin_traitor(datum/mind/character) + + check_potential_agents() + + // As soon as we get 3 or 4 extra latejoin traitors, make them traitors and kill each other. + if(late_joining_list.len >= rand(3, 4)) + // True randomness + shuffle_inplace(late_joining_list) + // Reset the target_list, it'll be used again in force_traitor_objectives + target_list = list() + + // Basically setting the target_list for who is killing who + var/i = 0 + for(var/datum/mind/traitor in late_joining_list) + i++ + if(i + 1 > late_joining_list.len) + i = 0 + target_list[traitor] = late_joining_list[i + 1] + traitor.special_role = traitor_name + + // Now, give them their targets + for(var/datum/mind/traitor in target_list) + ..(traitor) + + late_joining_list = list() + else + late_joining_list += character + return + +/datum/game_mode/traitor/internal_affairs/proc/check_potential_agents() + + for(var/M in late_joining_list) + if(istype(M, /datum/mind)) + var/datum/mind/agent_mind = M + if(ishuman(agent_mind.current)) + var/mob/living/carbon/human/H = agent_mind.current + if(H.stat != DEAD) + if(H.client) + continue // It all checks out. + + // If any check fails, remove them from our list + late_joining_list -= M + + +/datum/game_mode/traitor/internal_affairs/generate_report() + return "Nanotrasen denies any accusations of placing internal affairs agents onboard your station to eliminate inconvenient employees. Any further accusations against CentCom for such \ + actions will be met with a conversation with an official internal affairs agent." diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 4a6e72cf67..8b1b18660a 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,99 +1,99 @@ -/datum/game_mode - var/traitor_name = "traitor" - var/list/datum/mind/traitors = list() - - var/datum/mind/exchange_red - var/datum/mind/exchange_blue - -/datum/game_mode/traitor - name = "traitor" - config_tag = "traitor" - antag_flag = ROLE_TRAITOR - false_report_weight = 20 //Reports of traitors are pretty common. - restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances - protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist - required_players = 0 - required_enemies = 1 - recommended_enemies = 4 - reroll_friendly = 1 - enemy_minimum_age = 0 - - announce_span = "danger" - announce_text = "There are Syndicate agents on the station!\n\ - Traitors: Accomplish your objectives.\n\ - Crew: Do not let the traitors succeed!" - - var/list/datum/mind/pre_traitors = list() - var/traitors_possible = 4 //hard limit on traitors if scaling is turned off - var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. - var/antag_datum = /datum/antagonist/traitor //what type of antag to create - var/traitors_required = TRUE //Will allow no traitors - - -/datum/game_mode/traitor/pre_setup() - - if(CONFIG_GET(flag/protect_roles_from_antagonist)) - restricted_jobs += protected_jobs - - if(CONFIG_GET(flag/protect_assistant_from_antagonist)) - restricted_jobs += "Assistant" - - var/num_traitors = 1 - - var/tsc = CONFIG_GET(number/traitor_scaling_coeff) - if(tsc) - num_traitors = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier)) - else - num_traitors = max(1, min(num_players(), traitors_possible)) - - for(var/j = 0, j < num_traitors, j++) - if (!antag_candidates.len) - break - var/datum/mind/traitor = antag_pick(antag_candidates) - pre_traitors += traitor - traitor.special_role = traitor_name - traitor.restricted_roles = restricted_jobs - log_game("[key_name(traitor)] has been selected as a [traitor_name]") - antag_candidates.Remove(traitor) - - var/enough_tators = !traitors_required || pre_traitors.len > 0 - - if(!enough_tators) - setup_error = "Not enough traitor candidates" - return FALSE - else - return TRUE - - -/datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in pre_traitors) - var/datum/antagonist/traitor/new_antag = new antag_datum() - addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100)) - if(!exchange_blue) - exchange_blue = -1 //Block latejoiners from getting exchange objectives - ..() - - //We're not actually ready until all traitors are assigned. - gamemode_ready = FALSE - addtimer(VARSET_CALLBACK(src, gamemode_ready, TRUE), 101) - return TRUE - -/datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners - var/tsc = CONFIG_GET(number/traitor_scaling_coeff) - var/traitorcap = min(round(GLOB.joined_player_list.len / (tsc * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len / tsc) + num_modifier) - if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists - return - if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2))) - if(antag_flag in character.client.prefs.be_special) - if(!jobban_isbanned(character, ROLE_TRAITOR) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - add_latejoin_traitor(character.mind) - -/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character) - var/datum/antagonist/traitor/new_antag = new antag_datum() - character.add_antag_datum(new_antag) - -/datum/game_mode/traitor/generate_report() - return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \ - Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions." +/datum/game_mode + var/traitor_name = "traitor" + var/list/datum/mind/traitors = list() + + var/datum/mind/exchange_red + var/datum/mind/exchange_blue + +/datum/game_mode/traitor + name = "traitor" + config_tag = "traitor" + antag_flag = ROLE_TRAITOR + false_report_weight = 20 //Reports of traitors are pretty common. + restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to ling role blacklist + required_players = 0 + required_enemies = 1 + recommended_enemies = 4 + reroll_friendly = 1 + enemy_minimum_age = 0 + + announce_span = "danger" + announce_text = "There are Syndicate agents on the station!\n\ + Traitors: Accomplish your objectives.\n\ + Crew: Do not let the traitors succeed!" + + var/list/datum/mind/pre_traitors = list() + var/traitors_possible = 4 //hard limit on traitors if scaling is turned off + var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. + var/antag_datum = /datum/antagonist/traitor //what type of antag to create + var/traitors_required = TRUE //Will allow no traitors + + +/datum/game_mode/traitor/pre_setup() + + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + var/num_traitors = 1 + + var/tsc = CONFIG_GET(number/traitor_scaling_coeff) + if(tsc) + num_traitors = max(1, min(round(num_players() / (tsc * 2)) + 2 + num_modifier, round(num_players() / tsc) + num_modifier)) + else + num_traitors = max(1, min(num_players(), traitors_possible)) + + for(var/j = 0, j < num_traitors, j++) + if (!antag_candidates.len) + break + var/datum/mind/traitor = antag_pick(antag_candidates) + pre_traitors += traitor + traitor.special_role = traitor_name + traitor.restricted_roles = restricted_jobs + log_game("[key_name(traitor)] has been selected as a [traitor_name]") + antag_candidates.Remove(traitor) + + var/enough_tators = !traitors_required || pre_traitors.len > 0 + + if(!enough_tators) + setup_error = "Not enough traitor candidates" + return FALSE + else + return TRUE + + +/datum/game_mode/traitor/post_setup() + for(var/datum/mind/traitor in pre_traitors) + var/datum/antagonist/traitor/new_antag = new antag_datum() + addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100)) + if(!exchange_blue) + exchange_blue = -1 //Block latejoiners from getting exchange objectives + ..() + + //We're not actually ready until all traitors are assigned. + gamemode_ready = FALSE + addtimer(VARSET_CALLBACK(src, gamemode_ready, TRUE), 101) + return TRUE + +/datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners + var/tsc = CONFIG_GET(number/traitor_scaling_coeff) + var/traitorcap = min(round(GLOB.joined_player_list.len / (tsc * 2)) + 2 + num_modifier, round(GLOB.joined_player_list.len / tsc) + num_modifier) + if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists + return + if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2))) + if(antag_flag in character.client.prefs.be_special) + if(!jobban_isbanned(character, ROLE_TRAITOR) && !QDELETED(character) && !jobban_isbanned(character, ROLE_SYNDICATE) && !QDELETED(character)) + if(age_check(character.client)) + if(!(character.job in restricted_jobs)) + add_latejoin_traitor(character.mind) + +/datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character) + var/datum/antagonist/traitor/new_antag = new antag_datum() + character.add_antag_datum(new_antag) + +/datum/game_mode/traitor/generate_report() + return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \ + Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions." diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 9ea2694354..2f3645a248 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,73 +1,73 @@ -/datum/game_mode - var/list/datum/mind/wizards = list() - var/list/datum/mind/apprentices = list() - -/datum/game_mode/wizard - name = "wizard" - config_tag = "wizard" - antag_flag = ROLE_WIZARD - false_report_weight = 10 - required_players = 20 - required_enemies = 1 - recommended_enemies = 1 - enemy_minimum_age = 7 - round_ends_with_antag_death = 1 - announce_span = "danger" - announce_text = "There is a space wizard attacking the station!\n\ - Wizard: Accomplish your objectives and cause mayhem on the station.\n\ - Crew: Eliminate the wizard before they can succeed!" - var/finished = 0 - -/datum/game_mode/wizard/pre_setup() - var/datum/mind/wizard = antag_pick(antag_candidates) - wizards += wizard - wizard.assigned_role = ROLE_WIZARD - wizard.special_role = ROLE_WIZARD - log_game("[key_name(wizard)] has been selected as a Wizard") //TODO: Move these to base antag datum - if(GLOB.wizardstart.len == 0) - setup_error = "No wizard starting location found" - return FALSE - for(var/datum/mind/wiz in wizards) - wiz.current.forceMove(pick(GLOB.wizardstart)) - return TRUE - - -/datum/game_mode/wizard/post_setup() - for(var/datum/mind/wizard in wizards) - wizard.add_antag_datum(/datum/antagonist/wizard) - return ..() - -/datum/game_mode/wizard/generate_report() - return "A dangerous Wizards' Federation individual by the name of [pick(GLOB.wizard_first)] [pick(GLOB.wizard_second)] has recently escaped confinement from an unlisted prison facility. This \ - man is a dangerous mutant with the ability to alter himself and the world around him by what he and his leaders believe to be magic. If this man attempts an attack on your station, \ - his execution is highly encouraged, as is the preservation of his body for later study." - - -/datum/game_mode/wizard/are_special_antags_dead() - for(var/datum/mind/wizard in wizards) - if(isliving(wizard.current) && wizard.current.stat!=DEAD) - return FALSE - - for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead() - if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard)) - return FALSE - - if(SSevents.wizardmode) //If summon events was active, turn it off - SSevents.toggleWizardmode() - SSevents.resetFrequency() - - return TRUE - -/datum/game_mode/wizard/set_round_result() - ..() - if(finished) - SSticker.mode_result = "loss - wizard killed" - SSticker.news_report = WIZARD_KILLED - -/datum/game_mode/wizard/special_report() - if(finished) - return "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" - -//returns whether the mob is a wizard (or apprentice) -/proc/iswizard(mob/living/M) - return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE) +/datum/game_mode + var/list/datum/mind/wizards = list() + var/list/datum/mind/apprentices = list() + +/datum/game_mode/wizard + name = "wizard" + config_tag = "wizard" + antag_flag = ROLE_WIZARD + false_report_weight = 10 + required_players = 20 + required_enemies = 1 + recommended_enemies = 1 + enemy_minimum_age = 7 + round_ends_with_antag_death = 1 + announce_span = "danger" + announce_text = "There is a space wizard attacking the station!\n\ + Wizard: Accomplish your objectives and cause mayhem on the station.\n\ + Crew: Eliminate the wizard before they can succeed!" + var/finished = 0 + +/datum/game_mode/wizard/pre_setup() + var/datum/mind/wizard = antag_pick(antag_candidates) + wizards += wizard + wizard.assigned_role = ROLE_WIZARD + wizard.special_role = ROLE_WIZARD + log_game("[key_name(wizard)] has been selected as a Wizard") //TODO: Move these to base antag datum + if(GLOB.wizardstart.len == 0) + setup_error = "No wizard starting location found" + return FALSE + for(var/datum/mind/wiz in wizards) + wiz.current.forceMove(pick(GLOB.wizardstart)) + return TRUE + + +/datum/game_mode/wizard/post_setup() + for(var/datum/mind/wizard in wizards) + wizard.add_antag_datum(/datum/antagonist/wizard) + return ..() + +/datum/game_mode/wizard/generate_report() + return "A dangerous Wizards' Federation individual by the name of [pick(GLOB.wizard_first)] [pick(GLOB.wizard_second)] has recently escaped confinement from an unlisted prison facility. This \ + man is a dangerous mutant with the ability to alter himself and the world around him by what he and his leaders believe to be magic. If this man attempts an attack on your station, \ + his execution is highly encouraged, as is the preservation of his body for later study." + + +/datum/game_mode/wizard/are_special_antags_dead() + for(var/datum/mind/wizard in wizards) + if(isliving(wizard.current) && wizard.current.stat!=DEAD) + return FALSE + + for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead() + if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard)) + return FALSE + + if(SSevents.wizardmode) //If summon events was active, turn it off + SSevents.toggleWizardmode() + SSevents.resetFrequency() + + return TRUE + +/datum/game_mode/wizard/set_round_result() + ..() + if(finished) + SSticker.mode_result = "loss - wizard killed" + SSticker.news_report = WIZARD_KILLED + +/datum/game_mode/wizard/special_report() + if(finished) + return "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" + +//returns whether the mob is a wizard (or apprentice) +/proc/iswizard(mob/living/M) + return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE) diff --git a/code/game/machinery/Beacon.dm b/code/game/machinery/Beacon.dm index c98795c90b..84eda82ef5 100644 --- a/code/game/machinery/Beacon.dm +++ b/code/game/machinery/Beacon.dm @@ -1,48 +1,48 @@ -/obj/machinery/bluespace_beacon - - icon = 'icons/obj/objects.dmi' - icon_state = "floor_beaconf" - name = "bluespace gigabeacon" - desc = "A device that draws power from bluespace and creates a permanent tracking beacon." - level = 1 // underfloor - layer = LOW_OBJ_LAYER - use_power = IDLE_POWER_USE - idle_power_usage = 0 - var/obj/item/beacon/Beacon - -/obj/machinery/bluespace_beacon/Initialize() - . = ..() - var/turf/T = loc - Beacon = new(T) - Beacon.invisibility = INVISIBILITY_MAXIMUM - - hide(T.intact) - -/obj/machinery/bluespace_beacon/Destroy() - QDEL_NULL(Beacon) - return ..() - -// update the invisibility and icon -/obj/machinery/bluespace_beacon/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - update_icon() - -// update the icon_state -/obj/machinery/bluespace_beacon/update_icon() - var/state="floor_beacon" - - if(invisibility) - icon_state = "[state]f" - - else - icon_state = "[state]" - -/obj/machinery/bluespace_beacon/process() - if(!Beacon) - var/turf/T = loc - Beacon = new(T) - Beacon.invisibility = INVISIBILITY_MAXIMUM - else if (Beacon.loc != loc) - Beacon.forceMove(loc) - - update_icon() +/obj/machinery/bluespace_beacon + + icon = 'icons/obj/objects.dmi' + icon_state = "floor_beaconf" + name = "bluespace gigabeacon" + desc = "A device that draws power from bluespace and creates a permanent tracking beacon." + level = 1 // underfloor + layer = LOW_OBJ_LAYER + use_power = IDLE_POWER_USE + idle_power_usage = 0 + var/obj/item/beacon/Beacon + +/obj/machinery/bluespace_beacon/Initialize() + . = ..() + var/turf/T = loc + Beacon = new(T) + Beacon.invisibility = INVISIBILITY_MAXIMUM + + hide(T.intact) + +/obj/machinery/bluespace_beacon/Destroy() + QDEL_NULL(Beacon) + return ..() + +// update the invisibility and icon +/obj/machinery/bluespace_beacon/hide(intact) + invisibility = intact ? INVISIBILITY_MAXIMUM : 0 + update_icon() + +// update the icon_state +/obj/machinery/bluespace_beacon/update_icon() + var/state="floor_beacon" + + if(invisibility) + icon_state = "[state]f" + + else + icon_state = "[state]" + +/obj/machinery/bluespace_beacon/process() + if(!Beacon) + var/turf/T = loc + Beacon = new(T) + Beacon.invisibility = INVISIBILITY_MAXIMUM + else if (Beacon.loc != loc) + Beacon.forceMove(loc) + + update_icon() diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 45a3b59661..20efee9420 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -1,143 +1,143 @@ -/obj/machinery/pdapainter - name = "\improper PDA painter" - desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme." - icon = 'icons/obj/pda.dmi' - icon_state = "pdapainter" - density = TRUE - max_integrity = 200 - var/obj/item/pda/storedpda = null - var/list/colorlist = list() - - -/obj/machinery/pdapainter/update_icon() - cut_overlays() - - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - return - - if(storedpda) - add_overlay("[initial(icon_state)]-closed") - - if(powered()) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]-off" - - return - -/obj/machinery/pdapainter/Initialize() - . = ..() - var/list/blocked = list( - /obj/item/pda/ai/pai, - /obj/item/pda/ai, - /obj/item/pda/heads, - /obj/item/pda/clear, - /obj/item/pda/syndicate, - /obj/item/pda/chameleon, - /obj/item/pda/chameleon/broken, - /obj/item/pda/lieutenant) - - for(var/A in typesof(/obj/item/pda) - blocked) - var/obj/item/pda/P = A - var/PDA_name = initial(P.name) - colorlist += PDA_name - colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons)) - -/obj/machinery/pdapainter/Destroy() - QDEL_NULL(storedpda) - return ..() - -/obj/machinery/pdapainter/on_deconstruction() - if(storedpda) - storedpda.forceMove(loc) - storedpda = null - -/obj/machinery/pdapainter/contents_explosion(severity, target) - if(storedpda) - storedpda.ex_act(severity, target) - -/obj/machinery/pdapainter/handle_atom_del(atom/A) - if(A == storedpda) - storedpda = null - update_icon() - -/obj/machinery/pdapainter/attackby(obj/item/O, mob/user, params) - if(default_unfasten_wrench(user, O)) - power_change() - return - - else if(istype(O, /obj/item/pda)) - if(storedpda) - to_chat(user, "There is already a PDA inside!") - return - else if(!user.transferItemToLoc(O, src)) - return - storedpda = O - O.add_fingerprint(user) - update_icon() - - else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) - if(stat & BROKEN) - if(!O.tool_start_check(user, amount=0)) - return - user.visible_message("[user] is repairing [src].", \ - "You begin repairing [src]...", \ - "You hear welding.") - if(O.use_tool(src, user, 40, volume=50)) - if(!(stat & BROKEN)) - return - to_chat(user, "You repair [src].") - stat &= ~BROKEN - obj_integrity = max_integrity - update_icon() - else - to_chat(user, "[src] does not need repairs.") - else - return ..() - -/obj/machinery/pdapainter/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(!(stat & BROKEN)) - stat |= BROKEN - update_icon() - -/obj/machinery/pdapainter/attack_hand(mob/user) - . = ..() - if(.) - return - - if(!storedpda) - to_chat(user, "[src] is empty.") - return - var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist - if(!choice || !storedpda || !in_range(src, user)) - return - var/list/P = colorlist[choice] - storedpda.icon_state = P[1] - storedpda.desc = P[2] - storedpda.overlays_offsets = P[3] - storedpda.overlays_icons = P[4] - storedpda.set_new_overlays() - storedpda.update_icon() - ejectpda() - -/obj/machinery/pdapainter/verb/ejectpda() - set name = "Eject PDA" - set category = "Object" - set src in oview(1) - - if(usr.stat || usr.restrained()) - return - - if(storedpda) - storedpda.forceMove(drop_location()) - storedpda = null - update_icon() - else - to_chat(usr, "[src] is empty.") - - -/obj/machinery/pdapainter/power_change() - ..() - update_icon() +/obj/machinery/pdapainter + name = "\improper PDA painter" + desc = "A PDA painting machine. To use, simply insert your PDA and choose the desired preset paint scheme." + icon = 'icons/obj/pda.dmi' + icon_state = "pdapainter" + density = TRUE + max_integrity = 200 + var/obj/item/pda/storedpda = null + var/list/colorlist = list() + + +/obj/machinery/pdapainter/update_icon() + cut_overlays() + + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + return + + if(storedpda) + add_overlay("[initial(icon_state)]-closed") + + if(powered()) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]-off" + + return + +/obj/machinery/pdapainter/Initialize() + . = ..() + var/list/blocked = list( + /obj/item/pda/ai/pai, + /obj/item/pda/ai, + /obj/item/pda/heads, + /obj/item/pda/clear, + /obj/item/pda/syndicate, + /obj/item/pda/chameleon, + /obj/item/pda/chameleon/broken, + /obj/item/pda/lieutenant) + + for(var/A in typesof(/obj/item/pda) - blocked) + var/obj/item/pda/P = A + var/PDA_name = initial(P.name) + colorlist += PDA_name + colorlist[PDA_name] = list(initial(P.icon_state), initial(P.desc), initial(P.overlays_offsets), initial(P.overlays_icons)) + +/obj/machinery/pdapainter/Destroy() + QDEL_NULL(storedpda) + return ..() + +/obj/machinery/pdapainter/on_deconstruction() + if(storedpda) + storedpda.forceMove(loc) + storedpda = null + +/obj/machinery/pdapainter/contents_explosion(severity, target) + if(storedpda) + storedpda.ex_act(severity, target) + +/obj/machinery/pdapainter/handle_atom_del(atom/A) + if(A == storedpda) + storedpda = null + update_icon() + +/obj/machinery/pdapainter/attackby(obj/item/O, mob/user, params) + if(default_unfasten_wrench(user, O)) + power_change() + return + + else if(istype(O, /obj/item/pda)) + if(storedpda) + to_chat(user, "There is already a PDA inside!") + return + else if(!user.transferItemToLoc(O, src)) + return + storedpda = O + O.add_fingerprint(user) + update_icon() + + else if(istype(O, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) + if(stat & BROKEN) + if(!O.tool_start_check(user, amount=0)) + return + user.visible_message("[user] is repairing [src].", \ + "You begin repairing [src]...", \ + "You hear welding.") + if(O.use_tool(src, user, 40, volume=50)) + if(!(stat & BROKEN)) + return + to_chat(user, "You repair [src].") + stat &= ~BROKEN + obj_integrity = max_integrity + update_icon() + else + to_chat(user, "[src] does not need repairs.") + else + return ..() + +/obj/machinery/pdapainter/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(!(stat & BROKEN)) + stat |= BROKEN + update_icon() + +/obj/machinery/pdapainter/attack_hand(mob/user) + . = ..() + if(.) + return + + if(!storedpda) + to_chat(user, "[src] is empty.") + return + var/choice = input(user, "Select the new skin!", "PDA Painting") as null|anything in colorlist + if(!choice || !storedpda || !in_range(src, user)) + return + var/list/P = colorlist[choice] + storedpda.icon_state = P[1] + storedpda.desc = P[2] + storedpda.overlays_offsets = P[3] + storedpda.overlays_icons = P[4] + storedpda.set_new_overlays() + storedpda.update_icon() + ejectpda() + +/obj/machinery/pdapainter/verb/ejectpda() + set name = "Eject PDA" + set category = "Object" + set src in oview(1) + + if(usr.stat || usr.restrained()) + return + + if(storedpda) + storedpda.forceMove(drop_location()) + storedpda = null + update_icon() + else + to_chat(usr, "[src] is empty.") + + +/obj/machinery/pdapainter/power_change() + ..() + update_icon() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 88b0e804b7..b6dc09eb59 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -1,412 +1,412 @@ -/obj/machinery/sleep_console - name = "sleeper console" - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "console" - density = FALSE - -/obj/machinery/sleeper - name = "sleeper" - desc = "An enclosed machine used to stabilize and heal patients." - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "sleeper" - density = FALSE - state_open = TRUE - circuit = /obj/item/circuitboard/machine/sleeper - req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines - var/efficiency = 1 - var/min_health = 30 - var/list/available_chems - var/controls_inside = FALSE - var/list/possible_chems = list( - list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/morphine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane), - list(/datum/reagent/medicine/oculine,/datum/reagent/medicine/inacusiate), - list(/datum/reagent/medicine/antitoxin, /datum/reagent/medicine/mutadone, /datum/reagent/medicine/mannitol, /datum/reagent/medicine/pen_acid), - list(/datum/reagent/medicine/omnizine) - ) - var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine - var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning - var/enter_message = "You feel cool air surround you. You go numb as your senses turn inward." - -/obj/machinery/sleeper/Initialize() - . = ..() - create_reagents(500, NO_REACT) - occupant_typecache = GLOB.typecache_living - update_icon() - reset_chem_buttons() - RefreshParts() - add_inital_chems() - -/obj/machinery/sleeper/on_deconstruction() - var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc) - buffer.volume = reagents.maximum_volume - buffer.reagents.maximum_volume = reagents.maximum_volume - reagents.trans_to(buffer.reagents, reagents.total_volume) - -/obj/machinery/sleeper/proc/add_inital_chems() - for(var/i in available_chems) - var/datum/reagent/R = reagents.has_reagent(i) - if(!R) - reagents.add_reagent(i, (20)) - continue - if(R.volume < 20) - reagents.add_reagent(i, (20 - R.volume)) - -/obj/machinery/sleeper/RefreshParts() - var/E - for(var/obj/item/stock_parts/matter_bin/B in component_parts) - E += B.rating - var/I - for(var/obj/item/stock_parts/manipulator/M in component_parts) - I += M.rating - - efficiency = initial(efficiency)* E - min_health = initial(min_health) - (10*(E-1)) // CIT CHANGE - changes min health equation to be min_health - (matterbin rating * 10) - available_chems = list() - for(var/i in 1 to I) - available_chems |= possible_chems[i] - reset_chem_buttons() - - //Total container size 500 - 2000u - if(reagents) - reagents.maximum_volume = (500*E) - - -/obj/machinery/sleeper/update_icon() - icon_state = initial(icon_state) - if(state_open) - icon_state += "-open" - -/obj/machinery/sleeper/container_resist(mob/living/user) - visible_message("[occupant] emerges from [src]!", - "You climb out of [src]!") - open_machine() - -/obj/machinery/sleeper/Exited(atom/movable/user) - if (!state_open && user == occupant) - container_resist(user) - -/obj/machinery/sleeper/relaymove(mob/user) - if (!state_open) - container_resist(user) - -/obj/machinery/sleeper/open_machine() - if(!state_open && !panel_open) - ..() - -/obj/machinery/sleeper/close_machine(mob/user) - if((isnull(user) || istype(user)) && state_open && !panel_open) - ..(user) - var/mob/living/mob_occupant = occupant - if(mob_occupant && mob_occupant.stat != DEAD) - to_chat(occupant, "[enter_message]") - -/obj/machinery/sleeper/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(is_operational() && occupant) - var/datum/reagent/R = pick(reagents.reagent_list) - inject_chem(R.type, occupant) - open_machine() - //Is this too much? - if(severity == EMP_HEAVY) - var/chem = pick(available_chems) - available_chems -= chem - available_chems += get_random_reagent_id() - reset_chem_buttons() - -/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/reagent_containers/sleeper_buffer)) - var/obj/item/reagent_containers/sleeper_buffer/SB = I - if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume) - SB.reagents.trans_to(reagents, SB.reagents.total_volume) - visible_message("[user] places the [SB] into the [src].") - qdel(SB) - return - else - SB.reagents.trans_to(reagents, SB.reagents.total_volume) - visible_message("[user] adds as much as they can to the [src] from the [SB].") - return - if(istype(I, /obj/item/reagent_containers)) - var/obj/item/reagent_containers/RC = I - if(RC.reagents.total_volume == 0) - to_chat(user, "The [I] is empty!") - for(var/datum/reagent/R in RC.reagents.reagent_list) - if((obj_flags & EMAGGED) || (allowed(usr))) - break - if(!istype(R, /datum/reagent/medicine)) - visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"") - return - RC.reagents.trans_to(reagents, 1000) - visible_message("[user] adds as much as they can to the [src] from the [I].") - return - - -/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) - return - close_machine(target) - -/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I) - . = TRUE - if(..()) - return - if(occupant) - to_chat(user, "[src] is currently occupied!") - return - if(state_open) - to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!") - return - if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I)) - return - return FALSE - -/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I) - . = ..() - if(default_change_direction_wrench(user, I)) - return TRUE - -/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I) - . = ..() - if(default_pry_open(I)) - return TRUE - if(default_deconstruction_crowbar(I)) - return TRUE - -/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew - . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR - if(.) - I.play_tool_sound(src, 50) - visible_message("[usr] pries open [src].", "You pry open [src].") - open_machine() - -/obj/machinery/sleeper/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, !issilicon(user))) - return - if(state_open) - close_machine() - else - open_machine() - return TRUE - -/obj/machinery/sleeper/examine(mob/user) - . = ..() - . += "Alt-click [src] to [state_open ? "close" : "open"] it." - -/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) - - if(controls_inside && state == GLOB.notcontained_state) - state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it. - - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state) - ui.open() - -/obj/machinery/sleeper/ui_data() - var/list/data = list() - data["occupied"] = occupant ? 1 : 0 - data["open"] = state_open - data["efficiency"] = efficiency - data["current_vol"] = reagents.total_volume - data["tot_capacity"] = reagents.maximum_volume - - data["chems"] = list() - for(var/chem in available_chems) - var/datum/reagent/R = reagents.has_reagent(chem) - R = GLOB.chemical_reagents_list[chem] - data["synthchems"] += list(list("name" = R.name, "id" = R.type, "synth_allowed" = synth_allowed(chem))) - for(var/datum/reagent/R in reagents.reagent_list) - data["chems"] += list(list("name" = R.name, "id" = R.type, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.type))) - - data["occupant"] = list() - var/mob/living/mob_occupant = occupant - if(mob_occupant) - data["occupant"]["name"] = mob_occupant.name - switch(mob_occupant.stat) - if(CONSCIOUS) - data["occupant"]["stat"] = "Conscious" - data["occupant"]["statstate"] = "good" - if(SOFT_CRIT) - data["occupant"]["stat"] = "Conscious" - data["occupant"]["statstate"] = "average" - if(UNCONSCIOUS) - data["occupant"]["stat"] = "Unconscious" - data["occupant"]["statstate"] = "average" - if(DEAD) - data["occupant"]["stat"] = "Dead" - data["occupant"]["statstate"] = "bad" - data["occupant"]["health"] = mob_occupant.health - data["occupant"]["maxHealth"] = mob_occupant.maxHealth - data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD - data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss() - data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss() - data["occupant"]["toxLoss"] = mob_occupant.getToxLoss() - data["occupant"]["fireLoss"] = mob_occupant.getFireLoss() - data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss() - data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN) - data["occupant"]["reagents"] = list() - if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len) - for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) - data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume)) - data["occupant"]["failing_organs"] = list() - var/mob/living/carbon/C = mob_occupant - if(C) - for(var/obj/item/organ/Or in C.getFailingOrgans()) - if(istype(Or, /obj/item/organ/brain)) - continue - data["occupant"]["failing_organs"] += list(list("name" = Or.name)) - - if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner. - var/blood_id = C.get_blood_id() - if(blood_id) - data["occupant"]["blood"] = list() // We can start populating this list. - var/blood_type = C.dna.blood_type - if(blood_id != "blood") // special blood substance - var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] - if(R) - blood_type = R.name - else - blood_type = blood_id - data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio) - data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume - data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE - data["occupant"]["blood"]["bloodType"] = blood_type - return data - -/obj/machinery/sleeper/ui_act(action, params) - if(..()) - return - var/mob/living/mob_occupant = occupant - - switch(action) - if("door") - if(state_open) - close_machine() - else - open_machine() - . = TRUE - if("inject") - var/chem = text2path(params["chem"]) - var/amount = text2num(params["volume"]) - if(!is_operational() || !mob_occupant || isnull(chem)) - return - if(mob_occupant.health < min_health && chem != /datum/reagent/medicine/epinephrine) - return - if(inject_chem(chem, usr, amount)) - . = TRUE - if(scrambled_chems && prob(5)) - to_chat(usr, "Chemical system re-route detected, results may not be as expected!") - if("synth") - var/chem = text2path(params["chem"]) - if(!is_operational()) - return - reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in - if("purge") - var/chem = text2path(params["chem"]) - if(allowed(usr)) - if(!is_operational()) - return - reagents.remove_reagent(chem, 10) - return - if(chem in available_chems) - if(!is_operational()) - return - /*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in - if(R.purity < 0.8)*/ - reagents.remove_reagent(chem, 10) - else - visible_message("Access Denied.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - -/obj/machinery/sleeper/emag_act(mob/user) - . = ..() - obj_flags |= EMAGGED - scramble_chem_buttons() - to_chat(user, "You scramble the sleeper's user interface!") - return TRUE - -//trans to -/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10) - if(chem_allowed(chem)) - reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU - if(user) - log_combat(user, occupant, "injected [chem] into", addition = "via [src]") - return TRUE - -/obj/machinery/sleeper/proc/chem_allowed(chem) - var/mob/living/mob_occupant = occupant - if(!mob_occupant || !mob_occupant.reagents) - return - var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency - var/occ_health = mob_occupant.health > min_health || chem == /datum/reagent/medicine/epinephrine - return amount && occ_health - -/obj/machinery/sleeper/proc/synth_allowed(chem) - var/datum/reagent/R = reagents.has_reagent(chem) - if(!R) - return TRUE - if(R.volume < 50) - return TRUE - return FALSE - -/obj/machinery/sleeper/proc/reset_chem_buttons() - scrambled_chems = FALSE - LAZYINITLIST(chem_buttons) - for(var/chem in available_chems) - chem_buttons[chem] = chem - -/obj/machinery/sleeper/proc/scramble_chem_buttons() - scrambled_chems = TRUE - var/list/av_chem = available_chems.Copy() - for(var/chem in av_chem) - chem_buttons[chem] = pick_n_take(av_chem) //no dupes, allow for random buttons to still be correct - - -/obj/machinery/sleeper/syndie - icon_state = "sleeper_s" - controls_inside = TRUE - -/obj/machinery/sleeper/syndie/Initialize() - . = ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null) - component_parts += new /obj/item/stock_parts/matter_bin/super(null) - component_parts += new /obj/item/stock_parts/manipulator/pico(null) - component_parts += new /obj/item/stack/sheet/glass(null) - component_parts += new /obj/item/stack/sheet/glass(null) - component_parts += new /obj/item/stack/cable_coil(null) - RefreshParts() - -/obj/machinery/sleeper/syndie/fullupgrade/Initialize() - . = ..() - component_parts = list() - component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null) - component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null) - component_parts += new /obj/item/stock_parts/manipulator/femto(null) - component_parts += new /obj/item/stack/sheet/glass(null) - component_parts += new /obj/item/stack/sheet/glass(null) - component_parts += new /obj/item/stack/cable_coil(null) - RefreshParts() - -/obj/machinery/sleeper/clockwork - name = "soothing sleeper" - desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch." - icon_state = "sleeper_clockwork" - enter_message = "You hear the gentle hum and click of machinery, and are lulled into a sense of peace." - possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol")) - -/obj/machinery/sleeper/clockwork/process() - if(occupant && isliving(occupant)) - var/mob/living/L = occupant - if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing - GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1) - L.adjustBruteLoss(-1) - L.adjustFireLoss(-1) - L.adjustOxyLoss(-5) - -/obj/machinery/sleeper/old - icon_state = "oldpod" +/obj/machinery/sleep_console + name = "sleeper console" + icon = 'icons/obj/machines/sleeper.dmi' + icon_state = "console" + density = FALSE + +/obj/machinery/sleeper + name = "sleeper" + desc = "An enclosed machine used to stabilize and heal patients." + icon = 'icons/obj/machines/sleeper.dmi' + icon_state = "sleeper" + density = FALSE + state_open = TRUE + circuit = /obj/item/circuitboard/machine/sleeper + req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines + var/efficiency = 1 + var/min_health = 30 + var/list/available_chems + var/controls_inside = FALSE + var/list/possible_chems = list( + list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/morphine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane), + list(/datum/reagent/medicine/oculine,/datum/reagent/medicine/inacusiate), + list(/datum/reagent/medicine/antitoxin, /datum/reagent/medicine/mutadone, /datum/reagent/medicine/mannitol, /datum/reagent/medicine/pen_acid), + list(/datum/reagent/medicine/omnizine) + ) + var/list/chem_buttons //Used when emagged to scramble which chem is used, eg: antitoxin -> morphine + var/scrambled_chems = FALSE //Are chem buttons scrambled? used as a warning + var/enter_message = "You feel cool air surround you. You go numb as your senses turn inward." + +/obj/machinery/sleeper/Initialize() + . = ..() + create_reagents(500, NO_REACT) + occupant_typecache = GLOB.typecache_living + update_icon() + reset_chem_buttons() + RefreshParts() + add_inital_chems() + +/obj/machinery/sleeper/on_deconstruction() + var/obj/item/reagent_containers/sleeper_buffer/buffer = new (loc) + buffer.volume = reagents.maximum_volume + buffer.reagents.maximum_volume = reagents.maximum_volume + reagents.trans_to(buffer.reagents, reagents.total_volume) + +/obj/machinery/sleeper/proc/add_inital_chems() + for(var/i in available_chems) + var/datum/reagent/R = reagents.has_reagent(i) + if(!R) + reagents.add_reagent(i, (20)) + continue + if(R.volume < 20) + reagents.add_reagent(i, (20 - R.volume)) + +/obj/machinery/sleeper/RefreshParts() + var/E + for(var/obj/item/stock_parts/matter_bin/B in component_parts) + E += B.rating + var/I + for(var/obj/item/stock_parts/manipulator/M in component_parts) + I += M.rating + + efficiency = initial(efficiency)* E + min_health = initial(min_health) - (10*(E-1)) // CIT CHANGE - changes min health equation to be min_health - (matterbin rating * 10) + available_chems = list() + for(var/i in 1 to I) + available_chems |= possible_chems[i] + reset_chem_buttons() + + //Total container size 500 - 2000u + if(reagents) + reagents.maximum_volume = (500*E) + + +/obj/machinery/sleeper/update_icon() + icon_state = initial(icon_state) + if(state_open) + icon_state += "-open" + +/obj/machinery/sleeper/container_resist(mob/living/user) + visible_message("[occupant] emerges from [src]!", + "You climb out of [src]!") + open_machine() + +/obj/machinery/sleeper/Exited(atom/movable/user) + if (!state_open && user == occupant) + container_resist(user) + +/obj/machinery/sleeper/relaymove(mob/user) + if (!state_open) + container_resist(user) + +/obj/machinery/sleeper/open_machine() + if(!state_open && !panel_open) + ..() + +/obj/machinery/sleeper/close_machine(mob/user) + if((isnull(user) || istype(user)) && state_open && !panel_open) + ..(user) + var/mob/living/mob_occupant = occupant + if(mob_occupant && mob_occupant.stat != DEAD) + to_chat(occupant, "[enter_message]") + +/obj/machinery/sleeper/emp_act(severity) + . = ..() + if (. & EMP_PROTECT_SELF) + return + if(is_operational() && occupant) + var/datum/reagent/R = pick(reagents.reagent_list) + inject_chem(R.type, occupant) + open_machine() + //Is this too much? + if(severity == EMP_HEAVY) + var/chem = pick(available_chems) + available_chems -= chem + available_chems += get_random_reagent_id() + reset_chem_buttons() + +/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/reagent_containers/sleeper_buffer)) + var/obj/item/reagent_containers/sleeper_buffer/SB = I + if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume) + SB.reagents.trans_to(reagents, SB.reagents.total_volume) + visible_message("[user] places the [SB] into the [src].") + qdel(SB) + return + else + SB.reagents.trans_to(reagents, SB.reagents.total_volume) + visible_message("[user] adds as much as they can to the [src] from the [SB].") + return + if(istype(I, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/RC = I + if(RC.reagents.total_volume == 0) + to_chat(user, "The [I] is empty!") + for(var/datum/reagent/R in RC.reagents.reagent_list) + if((obj_flags & EMAGGED) || (allowed(usr))) + break + if(!istype(R, /datum/reagent/medicine)) + visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"") + return + RC.reagents.trans_to(reagents, 1000) + visible_message("[user] adds as much as they can to the [src] from the [I].") + return + + +/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) + if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) + return + close_machine(target) + +/obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I) + . = TRUE + if(..()) + return + if(occupant) + to_chat(user, "[src] is currently occupied!") + return + if(state_open) + to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!") + return + if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I)) + return + return FALSE + +/obj/machinery/sleeper/wrench_act(mob/living/user, obj/item/I) + . = ..() + if(default_change_direction_wrench(user, I)) + return TRUE + +/obj/machinery/sleeper/crowbar_act(mob/living/user, obj/item/I) + . = ..() + if(default_pry_open(I)) + return TRUE + if(default_deconstruction_crowbar(I)) + return TRUE + +/obj/machinery/sleeper/default_pry_open(obj/item/I) //wew + . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR + if(.) + I.play_tool_sound(src, 50) + visible_message("[usr] pries open [src].", "You pry open [src].") + open_machine() + +/obj/machinery/sleeper/AltClick(mob/user) + . = ..() + if(!user.canUseTopic(src, !issilicon(user))) + return + if(state_open) + close_machine() + else + open_machine() + return TRUE + +/obj/machinery/sleeper/examine(mob/user) + . = ..() + . += "Alt-click [src] to [state_open ? "close" : "open"] it." + +/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) + + if(controls_inside && state == GLOB.notcontained_state) + state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it. + + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state) + ui.open() + +/obj/machinery/sleeper/ui_data() + var/list/data = list() + data["occupied"] = occupant ? 1 : 0 + data["open"] = state_open + data["efficiency"] = efficiency + data["current_vol"] = reagents.total_volume + data["tot_capacity"] = reagents.maximum_volume + + data["chems"] = list() + for(var/chem in available_chems) + var/datum/reagent/R = reagents.has_reagent(chem) + R = GLOB.chemical_reagents_list[chem] + data["synthchems"] += list(list("name" = R.name, "id" = R.type, "synth_allowed" = synth_allowed(chem))) + for(var/datum/reagent/R in reagents.reagent_list) + data["chems"] += list(list("name" = R.name, "id" = R.type, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.type))) + + data["occupant"] = list() + var/mob/living/mob_occupant = occupant + if(mob_occupant) + data["occupant"]["name"] = mob_occupant.name + switch(mob_occupant.stat) + if(CONSCIOUS) + data["occupant"]["stat"] = "Conscious" + data["occupant"]["statstate"] = "good" + if(SOFT_CRIT) + data["occupant"]["stat"] = "Conscious" + data["occupant"]["statstate"] = "average" + if(UNCONSCIOUS) + data["occupant"]["stat"] = "Unconscious" + data["occupant"]["statstate"] = "average" + if(DEAD) + data["occupant"]["stat"] = "Dead" + data["occupant"]["statstate"] = "bad" + data["occupant"]["health"] = mob_occupant.health + data["occupant"]["maxHealth"] = mob_occupant.maxHealth + data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD + data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss() + data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss() + data["occupant"]["toxLoss"] = mob_occupant.getToxLoss() + data["occupant"]["fireLoss"] = mob_occupant.getFireLoss() + data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss() + data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN) + data["occupant"]["reagents"] = list() + if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len) + for(var/datum/reagent/R in mob_occupant.reagents.reagent_list) + data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume)) + data["occupant"]["failing_organs"] = list() + var/mob/living/carbon/C = mob_occupant + if(C) + for(var/obj/item/organ/Or in C.getFailingOrgans()) + if(istype(Or, /obj/item/organ/brain)) + continue + data["occupant"]["failing_organs"] += list(list("name" = Or.name)) + + if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner. + var/blood_id = C.get_blood_id() + if(blood_id) + data["occupant"]["blood"] = list() // We can start populating this list. + var/blood_type = C.dna.blood_type + if(blood_id != "blood") // special blood substance + var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] + if(R) + blood_type = R.name + else + blood_type = blood_id + data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio) + data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume + data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE + data["occupant"]["blood"]["bloodType"] = blood_type + return data + +/obj/machinery/sleeper/ui_act(action, params) + if(..()) + return + var/mob/living/mob_occupant = occupant + + switch(action) + if("door") + if(state_open) + close_machine() + else + open_machine() + . = TRUE + if("inject") + var/chem = text2path(params["chem"]) + var/amount = text2num(params["volume"]) + if(!is_operational() || !mob_occupant || isnull(chem)) + return + if(mob_occupant.health < min_health && chem != /datum/reagent/medicine/epinephrine) + return + if(inject_chem(chem, usr, amount)) + . = TRUE + if(scrambled_chems && prob(5)) + to_chat(usr, "Chemical system re-route detected, results may not be as expected!") + if("synth") + var/chem = text2path(params["chem"]) + if(!is_operational()) + return + reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in + if("purge") + var/chem = text2path(params["chem"]) + if(allowed(usr)) + if(!is_operational()) + return + reagents.remove_reagent(chem, 10) + return + if(chem in available_chems) + if(!is_operational()) + return + /*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in + if(R.purity < 0.8)*/ + reagents.remove_reagent(chem, 10) + else + visible_message("Access Denied.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + +/obj/machinery/sleeper/emag_act(mob/user) + . = ..() + obj_flags |= EMAGGED + scramble_chem_buttons() + to_chat(user, "You scramble the sleeper's user interface!") + return TRUE + +//trans to +/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10) + if(chem_allowed(chem)) + reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU + if(user) + log_combat(user, occupant, "injected [chem] into", addition = "via [src]") + return TRUE + +/obj/machinery/sleeper/proc/chem_allowed(chem) + var/mob/living/mob_occupant = occupant + if(!mob_occupant || !mob_occupant.reagents) + return + var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency + var/occ_health = mob_occupant.health > min_health || chem == /datum/reagent/medicine/epinephrine + return amount && occ_health + +/obj/machinery/sleeper/proc/synth_allowed(chem) + var/datum/reagent/R = reagents.has_reagent(chem) + if(!R) + return TRUE + if(R.volume < 50) + return TRUE + return FALSE + +/obj/machinery/sleeper/proc/reset_chem_buttons() + scrambled_chems = FALSE + LAZYINITLIST(chem_buttons) + for(var/chem in available_chems) + chem_buttons[chem] = chem + +/obj/machinery/sleeper/proc/scramble_chem_buttons() + scrambled_chems = TRUE + var/list/av_chem = available_chems.Copy() + for(var/chem in av_chem) + chem_buttons[chem] = pick_n_take(av_chem) //no dupes, allow for random buttons to still be correct + + +/obj/machinery/sleeper/syndie + icon_state = "sleeper_s" + controls_inside = TRUE + +/obj/machinery/sleeper/syndie/Initialize() + . = ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null) + component_parts += new /obj/item/stock_parts/matter_bin/super(null) + component_parts += new /obj/item/stock_parts/manipulator/pico(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/cable_coil(null) + RefreshParts() + +/obj/machinery/sleeper/syndie/fullupgrade/Initialize() + . = ..() + component_parts = list() + component_parts += new /obj/item/circuitboard/machine/sleeper/syndie(null) + component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null) + component_parts += new /obj/item/stock_parts/manipulator/femto(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/sheet/glass(null) + component_parts += new /obj/item/stack/cable_coil(null) + RefreshParts() + +/obj/machinery/sleeper/clockwork + name = "soothing sleeper" + desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch." + icon_state = "sleeper_clockwork" + enter_message = "You hear the gentle hum and click of machinery, and are lulled into a sense of peace." + possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol")) + +/obj/machinery/sleeper/clockwork/process() + if(occupant && isliving(occupant)) + var/mob/living/L = occupant + if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing + GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1) + L.adjustBruteLoss(-1) + L.adjustFireLoss(-1) + L.adjustOxyLoss(-5) + +/obj/machinery/sleeper/old + icon_state = "oldpod" diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index 1703ce57d1..4935c9d4d3 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -1,48 +1,48 @@ -/obj/machinery/ai_slipper - name = "foam dispenser" - desc = "A remotely-activatable dispenser for crowd-controlling foam." - icon = 'icons/obj/device.dmi' - icon_state = "ai-slipper0" - layer = PROJECTILE_HIT_THRESHHOLD_LAYER - plane = FLOOR_PLANE - max_integrity = 200 - armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) - - var/uses = 20 - var/cooldown = 0 - var/cooldown_time = 100 - req_access = list(ACCESS_AI_UPLOAD) - -/obj/machinery/ai_slipper/examine(mob/user) - . = ..() - . += "It has [uses] uses of foam remaining." - -/obj/machinery/ai_slipper/power_change() - if(stat & BROKEN) - return - else - if(powered()) - stat &= ~NOPOWER - else - stat |= NOPOWER - if((stat & (NOPOWER|BROKEN)) || cooldown_time > world.time || !uses) - icon_state = "ai-slipper0" - else - icon_state = "ai-slipper1" - -/obj/machinery/ai_slipper/interact(mob/user) - if(!allowed(user)) - to_chat(user, "Access denied.") - return - if(!uses) - to_chat(user, "[src] is out of foam and cannot be activated.") - return - if(cooldown_time > world.time) - to_chat(user, "[src] cannot be activated for [DisplayTimeText(world.time - cooldown_time)].") - return - new /obj/effect/particle_effect/foam(loc) - uses-- - to_chat(user, "You activate [src]. It now has [uses] uses of foam remaining.") - cooldown = world.time + cooldown_time - power_change() - addtimer(CALLBACK(src, .proc/power_change), cooldown_time) +/obj/machinery/ai_slipper + name = "foam dispenser" + desc = "A remotely-activatable dispenser for crowd-controlling foam." + icon = 'icons/obj/device.dmi' + icon_state = "ai-slipper0" + layer = PROJECTILE_HIT_THRESHHOLD_LAYER + plane = FLOOR_PLANE + max_integrity = 200 + armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + + var/uses = 20 + var/cooldown = 0 + var/cooldown_time = 100 + req_access = list(ACCESS_AI_UPLOAD) + +/obj/machinery/ai_slipper/examine(mob/user) + . = ..() + . += "It has [uses] uses of foam remaining." + +/obj/machinery/ai_slipper/power_change() + if(stat & BROKEN) + return + else + if(powered()) + stat &= ~NOPOWER + else + stat |= NOPOWER + if((stat & (NOPOWER|BROKEN)) || cooldown_time > world.time || !uses) + icon_state = "ai-slipper0" + else + icon_state = "ai-slipper1" + +/obj/machinery/ai_slipper/interact(mob/user) + if(!allowed(user)) + to_chat(user, "Access denied.") + return + if(!uses) + to_chat(user, "[src] is out of foam and cannot be activated.") + return + if(cooldown_time > world.time) + to_chat(user, "[src] cannot be activated for [DisplayTimeText(world.time - cooldown_time)].") + return + new /obj/effect/particle_effect/foam(loc) + uses-- + to_chat(user, "You activate [src]. It now has [uses] uses of foam remaining.") + cooldown = world.time + cooldown_time + power_change() + addtimer(CALLBACK(src, .proc/power_change), cooldown_time) diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 14dc7d05c2..69dbdcd50c 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -1,164 +1,164 @@ -#define AIRLOCK_CONTROL_RANGE 5 - -// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access) -/obj/machinery/door/airlock - var/id_tag - var/frequency - var/datum/radio_frequency/radio_connection - - -/obj/machinery/door/airlock/receive_signal(datum/signal/signal) - if(!signal) - return - - if(id_tag != signal.data["tag"] || !signal.data["command"]) - return - - switch(signal.data["command"]) - if("open") - open(1) - - if("close") - close(1) - - if("unlock") - locked = FALSE - update_icon() - - if("lock") - locked = TRUE - update_icon() - - if("secure_open") - locked = FALSE - update_icon() - - sleep(2) - open(1) - - locked = TRUE - update_icon() - - if("secure_close") - locked = FALSE - close(1) - - locked = TRUE - sleep(2) - update_icon() - - send_status() - - -/obj/machinery/door/airlock/proc/send_status() - if(radio_connection) - var/datum/signal/signal = new(list( - "tag" = id_tag, - "timestamp" = world.time, - "door_status" = density ? "closed" : "open", - "lock_status" = locked ? "locked" : "unlocked" - )) - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - - -/obj/machinery/door/airlock/open(surpress_send) - . = ..() - if(!surpress_send) - send_status() - - -/obj/machinery/door/airlock/close(surpress_send) - . = ..() - if(!surpress_send) - send_status() - - -/obj/machinery/door/airlock/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - if(new_frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) - -/obj/machinery/door/airlock/Destroy() - if(frequency) - SSradio.remove_object(src,frequency) - return ..() - -/obj/machinery/airlock_sensor - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_sensor_off" - name = "airlock sensor" - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - - power_channel = ENVIRON - - var/id_tag - var/master_tag - var/frequency = FREQ_AIRLOCK_CONTROL - - var/datum/radio_frequency/radio_connection - - var/on = TRUE - var/alert = FALSE - -/obj/machinery/airlock_sensor/incinerator_toxmix - id_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR - master_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER - -/obj/machinery/airlock_sensor/incinerator_atmos - id_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR - master_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER - -/obj/machinery/airlock_sensor/incinerator_syndicatelava - id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR - master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER - -/obj/machinery/airlock_sensor/update_icon() - if(on) - if(alert) - icon_state = "airlock_sensor_alert" - else - icon_state = "airlock_sensor_standby" - else - icon_state = "airlock_sensor_off" - -/obj/machinery/airlock_sensor/attack_hand(mob/user) - . = ..() - if(.) - return - var/datum/signal/signal = new(list( - "tag" = master_tag, - "command" = "cycle" - )) - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - flick("airlock_sensor_cycle", src) - -/obj/machinery/airlock_sensor/process() - if(on) - var/datum/gas_mixture/air_sample = return_air() - var/pressure = round(air_sample.return_pressure(),0.1) - alert = (pressure < ONE_ATMOSPHERE*0.8) - - var/datum/signal/signal = new(list( - "tag" = id_tag, - "timestamp" = world.time, - "pressure" = num2text(pressure) - )) - - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) - - update_icon() - -/obj/machinery/airlock_sensor/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) - -/obj/machinery/airlock_sensor/Initialize() - . = ..() - set_frequency(frequency) - -/obj/machinery/airlock_sensor/Destroy() - SSradio.remove_object(src,frequency) +#define AIRLOCK_CONTROL_RANGE 5 + +// This code allows for airlocks to be controlled externally by setting an id_tag and comm frequency (disables ID access) +/obj/machinery/door/airlock + var/id_tag + var/frequency + var/datum/radio_frequency/radio_connection + + +/obj/machinery/door/airlock/receive_signal(datum/signal/signal) + if(!signal) + return + + if(id_tag != signal.data["tag"] || !signal.data["command"]) + return + + switch(signal.data["command"]) + if("open") + open(1) + + if("close") + close(1) + + if("unlock") + locked = FALSE + update_icon() + + if("lock") + locked = TRUE + update_icon() + + if("secure_open") + locked = FALSE + update_icon() + + sleep(2) + open(1) + + locked = TRUE + update_icon() + + if("secure_close") + locked = FALSE + close(1) + + locked = TRUE + sleep(2) + update_icon() + + send_status() + + +/obj/machinery/door/airlock/proc/send_status() + if(radio_connection) + var/datum/signal/signal = new(list( + "tag" = id_tag, + "timestamp" = world.time, + "door_status" = density ? "closed" : "open", + "lock_status" = locked ? "locked" : "unlocked" + )) + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + + +/obj/machinery/door/airlock/open(surpress_send) + . = ..() + if(!surpress_send) + send_status() + + +/obj/machinery/door/airlock/close(surpress_send) + . = ..() + if(!surpress_send) + send_status() + + +/obj/machinery/door/airlock/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + if(new_frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) + +/obj/machinery/door/airlock/Destroy() + if(frequency) + SSradio.remove_object(src,frequency) + return ..() + +/obj/machinery/airlock_sensor + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_sensor_off" + name = "airlock sensor" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + + power_channel = ENVIRON + + var/id_tag + var/master_tag + var/frequency = FREQ_AIRLOCK_CONTROL + + var/datum/radio_frequency/radio_connection + + var/on = TRUE + var/alert = FALSE + +/obj/machinery/airlock_sensor/incinerator_toxmix + id_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR + master_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER + +/obj/machinery/airlock_sensor/incinerator_atmos + id_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR + master_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER + +/obj/machinery/airlock_sensor/incinerator_syndicatelava + id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR + master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER + +/obj/machinery/airlock_sensor/update_icon() + if(on) + if(alert) + icon_state = "airlock_sensor_alert" + else + icon_state = "airlock_sensor_standby" + else + icon_state = "airlock_sensor_off" + +/obj/machinery/airlock_sensor/attack_hand(mob/user) + . = ..() + if(.) + return + var/datum/signal/signal = new(list( + "tag" = master_tag, + "command" = "cycle" + )) + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + flick("airlock_sensor_cycle", src) + +/obj/machinery/airlock_sensor/process() + if(on) + var/datum/gas_mixture/air_sample = return_air() + var/pressure = round(air_sample.return_pressure(),0.1) + alert = (pressure < ONE_ATMOSPHERE*0.8) + + var/datum/signal/signal = new(list( + "tag" = id_tag, + "timestamp" = world.time, + "pressure" = num2text(pressure) + )) + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + + update_icon() + +/obj/machinery/airlock_sensor/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) + +/obj/machinery/airlock_sensor/Initialize() + . = ..() + set_frequency(frequency) + +/obj/machinery/airlock_sensor/Destroy() + SSradio.remove_object(src,frequency) return ..() \ No newline at end of file diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index bdb90c4c97..016f226399 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -1,383 +1,383 @@ -#define AUTOLATHE_MAIN_MENU 1 -#define AUTOLATHE_CATEGORY_MENU 2 -#define AUTOLATHE_SEARCH_MENU 3 - -/obj/machinery/autolathe - name = "autolathe" - desc = "It produces items using metal and glass." - icon_state = "autolathe" - density = TRUE - use_power = IDLE_POWER_USE - idle_power_usage = 10 - active_power_usage = 100 - circuit = /obj/item/circuitboard/machine/autolathe - layer = BELOW_OBJ_LAYER - - var/operating = FALSE - var/list/L = list() - var/list/LL = list() - var/hacked = FALSE - var/disabled = 0 - var/shocked = FALSE - var/hack_wire - var/disable_wire - var/shock_wire - - var/busy = FALSE - var/prod_coeff = 1 - - var/datum/design/being_built - var/datum/techweb/stored_research - var/list/datum/design/matching_designs - var/selected_category - var/screen = 1 - - var/list/categories = list( - "Tools", - "Electronics", - "Construction", - "T-Comm", - "Security", - "Machinery", - "Medical", - "Misc", - "Dinnerware", - "Imported" - ) - -/obj/machinery/autolathe/Initialize() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) - . = ..() - - wires = new /datum/wires/autolathe(src) - stored_research = new /datum/techweb/specialized/autounlocking/autolathe - matching_designs = list() - -/obj/machinery/autolathe/Destroy() - QDEL_NULL(wires) - return ..() - -/obj/machinery/autolathe/ui_interact(mob/user) - . = ..() - if(!is_operational()) - return - - if(shocked && !(stat & NOPOWER)) - shock(user,50) - - var/dat - - switch(screen) - if(AUTOLATHE_MAIN_MENU) - dat = main_win(user) - if(AUTOLATHE_CATEGORY_MENU) - dat = category_win(user,selected_category) - if(AUTOLATHE_SEARCH_MENU) - dat = search_win(user) - - var/datum/browser/popup = new(user, "autolathe", name, 400, 500) - popup.set_content(dat) - popup.open() - -/obj/machinery/autolathe/on_deconstruction() - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.retrieve_all() - -/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params) - if (busy) - to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") - return TRUE - - if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O)) - updateUsrDialog() - return TRUE - - if(default_deconstruction_crowbar(O)) - return TRUE - - if(panel_open && is_wire_tool(O)) - wires.interact(user) - return TRUE - - if(user.a_intent == INTENT_HARM) //so we can hit the machine - return ..() - - if(stat) - return TRUE - - if(istype(O, /obj/item/disk/design_disk)) - user.visible_message("[user] begins to load \the [O] in \the [src]...", - "You begin to load a design from \the [O]...", - "You hear the chatter of a floppy drive.") - busy = TRUE - var/obj/item/disk/design_disk/D = O - if(do_after(user, 14.4, target = src)) - for(var/B in D.blueprints) - if(B) - stored_research.add_design(B) - busy = FALSE - return TRUE - - return ..() - -/obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted) - if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal)) - use_power(MINERAL_MATERIAL_AMOUNT / 10) - else - switch(id_inserted) - if (MAT_METAL) - flick("autolathe_o",src)//plays metal insertion animation - if (MAT_GLASS) - flick("autolathe_r",src)//plays glass insertion animation - use_power(min(1000, amount_inserted / 100)) - updateUsrDialog() - -/obj/machinery/autolathe/Topic(href, href_list) - if(..()) - return - if (!busy) - if(href_list["menu"]) - screen = text2num(href_list["menu"]) - updateUsrDialog() - - if(href_list["category"]) - selected_category = href_list["category"] - updateUsrDialog() - - if(href_list["make"]) - - ///////////////// - //href protection - being_built = stored_research.isDesignResearchedID(href_list["make"]) - if(!being_built) - return - - var/multiplier = text2num(href_list["multiplier"]) - var/is_stack = ispath(being_built.build_path, /obj/item/stack) - multiplier = CLAMP(multiplier,1,50) - - ///////////////// - - var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient - var/metal_cost = being_built.materials[MAT_METAL] - var/glass_cost = being_built.materials[MAT_GLASS] - - var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) - - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff)) - busy = TRUE - use_power(power) - icon_state = "autolathe_n" - var/time = is_stack ? 32 : 32*coeff*multiplier - addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time) - - if(href_list["search"]) - matching_designs.Cut() - - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(findtext(D.name,href_list["to_search"])) - matching_designs.Add(D) - updateUsrDialog() - else - to_chat(usr, "The autolathe is busy. Please wait for completion of previous operation.") - - updateUsrDialog() - - return - -/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/atom/A = drop_location() - use_power(power) - var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier) - materials.use_amount(materials_used) - - if(is_stack) - var/obj/item/stack/N = new being_built.build_path(A, multiplier) - N.update_icon() - N.autolathe_crafted(src) - else - for(var/i=1, i<=multiplier, i++) - var/obj/item/new_item = new being_built.build_path(A) - new_item.materials = new_item.materials.Copy() - for(var/mat in materials_used) - new_item.materials[mat] = materials_used[mat] / multiplier - new_item.autolathe_crafted(src) - icon_state = "autolathe" - busy = FALSE - updateDialog() - -/obj/machinery/autolathe/RefreshParts() - var/T = 0 - for(var/obj/item/stock_parts/matter_bin/MB in component_parts) - T += MB.rating*75000 - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.max_amount = T - T=1.2 - for(var/obj/item/stock_parts/manipulator/M in component_parts) - T -= M.rating*0.2 - prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4 - -/obj/machinery/autolathe/proc/main_win(mob/user) - var/dat = "

    Autolathe Menu:


    " - dat += materials_printout() - - dat += "
    \ - \ - \ - \ - \ - \ -

    " - - var/line_length = 1 - dat += "" - - for(var/C in categories) - if(line_length > 2) - dat += "" - line_length = 1 - - dat += "" - line_length++ - - dat += "
    [C]
    " - return dat - -/obj/machinery/autolathe/proc/category_win(mob/user,selected_category) - var/dat = "Return to main menu" - dat += "

    Browsing [selected_category]:


    " - dat += materials_printout() - - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(!(selected_category in D.category)) - continue - - if(disabled || !can_build(D)) - dat += "[D.name]" - else - dat += "[D.name]" - - if(ispath(D.build_path, /obj/item/stack)) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) - if (max_multiplier>10 && !disabled) - dat += " x10" - if (max_multiplier>25 && !disabled) - dat += " x25" - if(max_multiplier > 0 && !disabled) - dat += " x[max_multiplier]" - else - if(!disabled && can_build(D, 5)) - dat += " x5" - if(!disabled && can_build(D, 10)) - dat += " x10" - - dat += "[get_design_cost(D)]
    " - - dat += "
    " - return dat - -/obj/machinery/autolathe/proc/search_win(mob/user) - var/dat = "Return to main menu" - dat += "

    Search results:


    " - dat += materials_printout() - - for(var/v in matching_designs) - var/datum/design/D = v - if(disabled || !can_build(D)) - dat += "[D.name]" - else - dat += "[D.name]" - - if(ispath(D.build_path, /obj/item/stack)) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) - if (max_multiplier>10 && !disabled) - dat += " x10" - if (max_multiplier>25 && !disabled) - dat += " x25" - if(max_multiplier > 0 && !disabled) - dat += " x[max_multiplier]" - - dat += "[get_design_cost(D)]
    " - - dat += "
    " - return dat - -/obj/machinery/autolathe/proc/materials_printout() - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
    " - for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - dat += "[M.name] amount: [M.amount] cm3
    " - return dat - -/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1) - if(D.make_reagents.len) - return FALSE - - var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) - - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount))) - return FALSE - if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount))) - return FALSE - return TRUE - -/obj/machinery/autolathe/proc/get_design_cost(datum/design/D) - var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) - var/dat - if(D.materials[MAT_METAL]) - dat += "[D.materials[MAT_METAL] * coeff] metal " - if(D.materials[MAT_GLASS]) - dat += "[D.materials[MAT_GLASS] * coeff] glass" - return dat - -/obj/machinery/autolathe/proc/reset(wire) - switch(wire) - if(WIRE_HACK) - if(!wires.is_cut(wire)) - adjust_hacked(FALSE) - if(WIRE_SHOCK) - if(!wires.is_cut(wire)) - shocked = FALSE - if(WIRE_DISABLE) - if(!wires.is_cut(wire)) - disabled = FALSE - -/obj/machinery/autolathe/proc/shock(mob/user, prb) - if(stat & (BROKEN|NOPOWER)) // unpowered, no shock - return FALSE - if(!prob(prb)) - return FALSE - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(5, 1, src) - s.start() - if (electrocute_mob(user, get_area(src), src, 0.7, TRUE)) - return TRUE - else - return FALSE - -/obj/machinery/autolathe/proc/adjust_hacked(state) - hacked = state - for(var/id in SSresearch.techweb_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(id) - if((D.build_type & AUTOLATHE) && ("hacked" in D.category)) - if(hacked) - stored_research.add_design(D) - else - stored_research.remove_design(D) - -/obj/machinery/autolathe/hacked/Initialize() - . = ..() - adjust_hacked(TRUE) - -//Called when the object is constructed by an autolathe -//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes -/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A) +#define AUTOLATHE_MAIN_MENU 1 +#define AUTOLATHE_CATEGORY_MENU 2 +#define AUTOLATHE_SEARCH_MENU 3 + +/obj/machinery/autolathe + name = "autolathe" + desc = "It produces items using metal and glass." + icon_state = "autolathe" + density = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 10 + active_power_usage = 100 + circuit = /obj/item/circuitboard/machine/autolathe + layer = BELOW_OBJ_LAYER + + var/operating = FALSE + var/list/L = list() + var/list/LL = list() + var/hacked = FALSE + var/disabled = 0 + var/shocked = FALSE + var/hack_wire + var/disable_wire + var/shock_wire + + var/busy = FALSE + var/prod_coeff = 1 + + var/datum/design/being_built + var/datum/techweb/stored_research + var/list/datum/design/matching_designs + var/selected_category + var/screen = 1 + + var/list/categories = list( + "Tools", + "Electronics", + "Construction", + "T-Comm", + "Security", + "Machinery", + "Medical", + "Misc", + "Dinnerware", + "Imported" + ) + +/obj/machinery/autolathe/Initialize() + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) + . = ..() + + wires = new /datum/wires/autolathe(src) + stored_research = new /datum/techweb/specialized/autounlocking/autolathe + matching_designs = list() + +/obj/machinery/autolathe/Destroy() + QDEL_NULL(wires) + return ..() + +/obj/machinery/autolathe/ui_interact(mob/user) + . = ..() + if(!is_operational()) + return + + if(shocked && !(stat & NOPOWER)) + shock(user,50) + + var/dat + + switch(screen) + if(AUTOLATHE_MAIN_MENU) + dat = main_win(user) + if(AUTOLATHE_CATEGORY_MENU) + dat = category_win(user,selected_category) + if(AUTOLATHE_SEARCH_MENU) + dat = search_win(user) + + var/datum/browser/popup = new(user, "autolathe", name, 400, 500) + popup.set_content(dat) + popup.open() + +/obj/machinery/autolathe/on_deconstruction() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.retrieve_all() + +/obj/machinery/autolathe/attackby(obj/item/O, mob/user, params) + if (busy) + to_chat(user, "The autolathe is busy. Please wait for completion of previous operation.") + return TRUE + + if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O)) + updateUsrDialog() + return TRUE + + if(default_deconstruction_crowbar(O)) + return TRUE + + if(panel_open && is_wire_tool(O)) + wires.interact(user) + return TRUE + + if(user.a_intent == INTENT_HARM) //so we can hit the machine + return ..() + + if(stat) + return TRUE + + if(istype(O, /obj/item/disk/design_disk)) + user.visible_message("[user] begins to load \the [O] in \the [src]...", + "You begin to load a design from \the [O]...", + "You hear the chatter of a floppy drive.") + busy = TRUE + var/obj/item/disk/design_disk/D = O + if(do_after(user, 14.4, target = src)) + for(var/B in D.blueprints) + if(B) + stored_research.add_design(B) + busy = FALSE + return TRUE + + return ..() + +/obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted) + if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal)) + use_power(MINERAL_MATERIAL_AMOUNT / 10) + else + switch(id_inserted) + if (MAT_METAL) + flick("autolathe_o",src)//plays metal insertion animation + if (MAT_GLASS) + flick("autolathe_r",src)//plays glass insertion animation + use_power(min(1000, amount_inserted / 100)) + updateUsrDialog() + +/obj/machinery/autolathe/Topic(href, href_list) + if(..()) + return + if (!busy) + if(href_list["menu"]) + screen = text2num(href_list["menu"]) + updateUsrDialog() + + if(href_list["category"]) + selected_category = href_list["category"] + updateUsrDialog() + + if(href_list["make"]) + + ///////////////// + //href protection + being_built = stored_research.isDesignResearchedID(href_list["make"]) + if(!being_built) + return + + var/multiplier = text2num(href_list["multiplier"]) + var/is_stack = ispath(being_built.build_path, /obj/item/stack) + multiplier = CLAMP(multiplier,1,50) + + ///////////////// + + var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient + var/metal_cost = being_built.materials[MAT_METAL] + var/glass_cost = being_built.materials[MAT_GLASS] + + var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff)) + busy = TRUE + use_power(power) + icon_state = "autolathe_n" + var/time = is_stack ? 32 : 32*coeff*multiplier + addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time) + + if(href_list["search"]) + matching_designs.Cut() + + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(findtext(D.name,href_list["to_search"])) + matching_designs.Add(D) + updateUsrDialog() + else + to_chat(usr, "The autolathe is busy. Please wait for completion of previous operation.") + + updateUsrDialog() + + return + +/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/atom/A = drop_location() + use_power(power) + var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier) + materials.use_amount(materials_used) + + if(is_stack) + var/obj/item/stack/N = new being_built.build_path(A, multiplier) + N.update_icon() + N.autolathe_crafted(src) + else + for(var/i=1, i<=multiplier, i++) + var/obj/item/new_item = new being_built.build_path(A) + new_item.materials = new_item.materials.Copy() + for(var/mat in materials_used) + new_item.materials[mat] = materials_used[mat] / multiplier + new_item.autolathe_crafted(src) + icon_state = "autolathe" + busy = FALSE + updateDialog() + +/obj/machinery/autolathe/RefreshParts() + var/T = 0 + for(var/obj/item/stock_parts/matter_bin/MB in component_parts) + T += MB.rating*75000 + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.max_amount = T + T=1.2 + for(var/obj/item/stock_parts/manipulator/M in component_parts) + T -= M.rating*0.2 + prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4 + +/obj/machinery/autolathe/proc/main_win(mob/user) + var/dat = "

    Autolathe Menu:


    " + dat += materials_printout() + + dat += "
    \ + \ + \ + \ + \ + \ +

    " + + var/line_length = 1 + dat += "" + + for(var/C in categories) + if(line_length > 2) + dat += "" + line_length = 1 + + dat += "" + line_length++ + + dat += "
    [C]
    " + return dat + +/obj/machinery/autolathe/proc/category_win(mob/user,selected_category) + var/dat = "Return to main menu" + dat += "

    Browsing [selected_category]:


    " + dat += materials_printout() + + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(!(selected_category in D.category)) + continue + + if(disabled || !can_build(D)) + dat += "[D.name]" + else + dat += "[D.name]" + + if(ispath(D.build_path, /obj/item/stack)) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) + if (max_multiplier>10 && !disabled) + dat += " x10" + if (max_multiplier>25 && !disabled) + dat += " x25" + if(max_multiplier > 0 && !disabled) + dat += " x[max_multiplier]" + else + if(!disabled && can_build(D, 5)) + dat += " x5" + if(!disabled && can_build(D, 10)) + dat += " x10" + + dat += "[get_design_cost(D)]
    " + + dat += "
    " + return dat + +/obj/machinery/autolathe/proc/search_win(mob/user) + var/dat = "Return to main menu" + dat += "

    Search results:


    " + dat += materials_printout() + + for(var/v in matching_designs) + var/datum/design/D = v + if(disabled || !can_build(D)) + dat += "[D.name]" + else + dat += "[D.name]" + + if(ispath(D.build_path, /obj/item/stack)) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) + if (max_multiplier>10 && !disabled) + dat += " x10" + if (max_multiplier>25 && !disabled) + dat += " x25" + if(max_multiplier > 0 && !disabled) + dat += " x[max_multiplier]" + + dat += "[get_design_cost(D)]
    " + + dat += "
    " + return dat + +/obj/machinery/autolathe/proc/materials_printout() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
    " + for(var/mat_id in materials.materials) + var/datum/material/M = materials.materials[mat_id] + dat += "[M.name] amount: [M.amount] cm3
    " + return dat + +/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1) + if(D.make_reagents.len) + return FALSE + + var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount))) + return FALSE + if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount))) + return FALSE + return TRUE + +/obj/machinery/autolathe/proc/get_design_cost(datum/design/D) + var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + var/dat + if(D.materials[MAT_METAL]) + dat += "[D.materials[MAT_METAL] * coeff] metal " + if(D.materials[MAT_GLASS]) + dat += "[D.materials[MAT_GLASS] * coeff] glass" + return dat + +/obj/machinery/autolathe/proc/reset(wire) + switch(wire) + if(WIRE_HACK) + if(!wires.is_cut(wire)) + adjust_hacked(FALSE) + if(WIRE_SHOCK) + if(!wires.is_cut(wire)) + shocked = FALSE + if(WIRE_DISABLE) + if(!wires.is_cut(wire)) + disabled = FALSE + +/obj/machinery/autolathe/proc/shock(mob/user, prb) + if(stat & (BROKEN|NOPOWER)) // unpowered, no shock + return FALSE + if(!prob(prb)) + return FALSE + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(5, 1, src) + s.start() + if (electrocute_mob(user, get_area(src), src, 0.7, TRUE)) + return TRUE + else + return FALSE + +/obj/machinery/autolathe/proc/adjust_hacked(state) + hacked = state + for(var/id in SSresearch.techweb_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(id) + if((D.build_type & AUTOLATHE) && ("hacked" in D.category)) + if(hacked) + stored_research.add_design(D) + else + stored_research.remove_design(D) + +/obj/machinery/autolathe/hacked/Initialize() + . = ..() + adjust_hacked(TRUE) + +//Called when the object is constructed by an autolathe +//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes +/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A) return \ No newline at end of file diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 24c9e32969..3a9b560bd6 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -1,268 +1,268 @@ -/obj/machinery/button - name = "button" - desc = "A remote control switch." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "doorctrl" - var/skin = "doorctrl" - power_channel = ENVIRON - var/obj/item/assembly/device - var/obj/item/electronics/airlock/board - var/device_type = null - var/id = null - var/initialized_button = 0 - armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 70) - use_power = IDLE_POWER_USE - idle_power_usage = 2 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - -/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0) - . = ..() - if(built) - setDir(ndir) - pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) - pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 - panel_open = TRUE - update_icon() - - - if(!built && !device && device_type) - device = new device_type(src) - - src.check_access(null) - - if(req_access.len || req_one_access.len) - board = new(src) - if(req_access.len) - board.accesses = req_access - else - board.one_access = 1 - board.accesses = req_one_access - -/obj/machinery/button/update_icon_state() - if(panel_open) - icon_state = "button-open" - else if(stat & (NOPOWER|BROKEN)) - icon_state = "[skin]-p" - else - icon_state = skin - -/obj/machinery/button/update_overlays() - . = ..() - if(!panel_open) - return - if(device) - . += "button-device" - if(board) - . += "button-board" - -/obj/machinery/button/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/screwdriver)) - if(panel_open || allowed(user)) - default_deconstruction_screwdriver(user, "button-open", "[skin]",W) - update_icon() - else - to_chat(user, "Maintenance Access Denied") - flick("[skin]-denied", src) - return - - if(panel_open) - if(!device && istype(W, /obj/item/assembly)) - if(!user.transferItemToLoc(W, src)) - to_chat(user, "\The [W] is stuck to you!") - return - device = W - to_chat(user, "You add [W] to the button.") - - if(!board && istype(W, /obj/item/electronics/airlock)) - if(!user.transferItemToLoc(W, src)) - to_chat(user, "\The [W] is stuck to you!") - return - board = W - if(board.one_access) - req_one_access = board.accesses - else - req_access = board.accesses - to_chat(user, "You add [W] to the button.") - - if(!device && !board && istype(W, /obj/item/wrench)) - to_chat(user, "You start unsecuring the button frame...") - W.play_tool_sound(src) - if(W.use_tool(src, user, 40)) - to_chat(user, "You unsecure the button frame.") - transfer_fingerprints_to(new /obj/item/wallframe/button(get_turf(src))) - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - qdel(src) - - update_icon() - return - - if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON)) - return attack_hand(user) - else - return ..() - -/obj/machinery/button/emag_act(mob/user) - . = ..() - if(obj_flags & EMAGGED) - return - req_access = list() - req_one_access = list() - playsound(src, "sparks", 100, 1) - obj_flags |= EMAGGED - return TRUE - -/obj/machinery/button/attack_ai(mob/user) - if(!panel_open) - return attack_hand(user) - -/obj/machinery/button/attack_robot(mob/user) - return attack_ai(user) - -/obj/machinery/button/proc/setup_device() - if(id && istype(device, /obj/item/assembly/control)) - var/obj/item/assembly/control/A = device - A.id = id - initialized_button = 1 - -/obj/machinery/button/attack_hand(mob/user) - . = ..() - if(.) - return - if(!initialized_button) - setup_device() - add_fingerprint(user) - if(panel_open) - if(device || board) - if(device) - device.forceMove(drop_location()) - device = null - if(board) - board.forceMove(drop_location()) - req_access = list() - req_one_access = list() - board = null - update_icon() - to_chat(user, "You remove electronics from the button frame.") - - else - if(skin == "doorctrl") - skin = "launcher" - else - skin = "doorctrl" - to_chat(user, "You change the button frame's front panel.") - return - - if((stat & (NOPOWER|BROKEN))) - return - - if(device && device.next_activate > world.time) - return - - if(!allowed(user)) - to_chat(user, "Access Denied") - flick("[skin]-denied", src) - return - - use_power(5) - icon_state = "[skin]1" - - if(device) - device.pulsed() - - addtimer(CALLBACK(src, /atom/.proc/update_icon), 15) - -/obj/machinery/button/power_change() - ..() - update_icon() - - -/obj/machinery/button/door - name = "door button" - desc = "A door remote control switch." - var/normaldoorcontrol = FALSE - var/specialfunctions = OPEN // Bitflag, see assembly file - -/obj/machinery/button/door/setup_device() - if(!device) - if(normaldoorcontrol) - var/obj/item/assembly/control/airlock/A = new(src) - device = A - A.specialfunctions = specialfunctions - else - device = new /obj/item/assembly/control(src) - ..() - -/obj/machinery/button/door/incinerator_vent_toxmix - name = "combustion chamber vent control" - id = INCINERATOR_TOXMIX_VENT - req_access = list(ACCESS_TOX) - -/obj/machinery/button/door/incinerator_vent_atmos_main - name = "turbine vent control" - id = INCINERATOR_ATMOS_MAINVENT - req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS) - -/obj/machinery/button/door/incinerator_vent_atmos_aux - name = "combustion chamber vent control" - id = INCINERATOR_ATMOS_AUXVENT - req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS) - -/obj/machinery/button/door/incinerator_vent_syndicatelava_main - name = "turbine vent control" - id = INCINERATOR_SYNDICATELAVA_MAINVENT - req_access = list(ACCESS_SYNDICATE) - -/obj/machinery/button/door/incinerator_vent_syndicatelava_aux - name = "combustion chamber vent control" - id = INCINERATOR_SYNDICATELAVA_AUXVENT - req_access = list(ACCESS_SYNDICATE) - -/obj/machinery/button/massdriver - name = "mass driver button" - desc = "A remote control switch for a mass driver." - icon_state = "launcher" - skin = "launcher" - device_type = /obj/item/assembly/control/massdriver - -/obj/machinery/button/ignition - name = "ignition switch" - desc = "A remote control switch for a mounted igniter." - icon_state = "launcher" - skin = "launcher" - device_type = /obj/item/assembly/control/igniter - -/obj/machinery/button/ignition/incinerator - name = "combustion chamber ignition switch" - desc = "A remote control switch for the combustion chamber's igniter." - -/obj/machinery/button/ignition/incinerator/toxmix - id = INCINERATOR_TOXMIX_IGNITER - -/obj/machinery/button/ignition/incinerator/atmos - id = INCINERATOR_ATMOS_IGNITER - -/obj/machinery/button/ignition/incinerator/syndicatelava - id = INCINERATOR_SYNDICATELAVA_IGNITER - -/obj/machinery/button/flasher - name = "flasher button" - desc = "A remote control switch for a mounted flasher." - icon_state = "launcher" - skin = "launcher" - device_type = /obj/item/assembly/control/flasher - -/obj/machinery/button/crematorium - name = "crematorium igniter" - desc = "Burn baby burn!" - icon_state = "launcher" - skin = "launcher" - device_type = /obj/item/assembly/control/crematorium - req_access = list() - id = 1 - -/obj/item/wallframe/button - name = "button frame" - desc = "Used for building buttons." - icon_state = "button" - result_path = /obj/machinery/button - materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT) +/obj/machinery/button + name = "button" + desc = "A remote control switch." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "doorctrl" + var/skin = "doorctrl" + power_channel = ENVIRON + var/obj/item/assembly/device + var/obj/item/electronics/airlock/board + var/device_type = null + var/id = null + var/initialized_button = 0 + armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 70) + use_power = IDLE_POWER_USE + idle_power_usage = 2 + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + +/obj/machinery/button/Initialize(mapload, ndir = 0, built = 0) + . = ..() + if(built) + setDir(ndir) + pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) + pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 + panel_open = TRUE + update_icon() + + + if(!built && !device && device_type) + device = new device_type(src) + + src.check_access(null) + + if(req_access.len || req_one_access.len) + board = new(src) + if(req_access.len) + board.accesses = req_access + else + board.one_access = 1 + board.accesses = req_one_access + +/obj/machinery/button/update_icon_state() + if(panel_open) + icon_state = "button-open" + else if(stat & (NOPOWER|BROKEN)) + icon_state = "[skin]-p" + else + icon_state = skin + +/obj/machinery/button/update_overlays() + . = ..() + if(!panel_open) + return + if(device) + . += "button-device" + if(board) + . += "button-board" + +/obj/machinery/button/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/screwdriver)) + if(panel_open || allowed(user)) + default_deconstruction_screwdriver(user, "button-open", "[skin]",W) + update_icon() + else + to_chat(user, "Maintenance Access Denied") + flick("[skin]-denied", src) + return + + if(panel_open) + if(!device && istype(W, /obj/item/assembly)) + if(!user.transferItemToLoc(W, src)) + to_chat(user, "\The [W] is stuck to you!") + return + device = W + to_chat(user, "You add [W] to the button.") + + if(!board && istype(W, /obj/item/electronics/airlock)) + if(!user.transferItemToLoc(W, src)) + to_chat(user, "\The [W] is stuck to you!") + return + board = W + if(board.one_access) + req_one_access = board.accesses + else + req_access = board.accesses + to_chat(user, "You add [W] to the button.") + + if(!device && !board && istype(W, /obj/item/wrench)) + to_chat(user, "You start unsecuring the button frame...") + W.play_tool_sound(src) + if(W.use_tool(src, user, 40)) + to_chat(user, "You unsecure the button frame.") + transfer_fingerprints_to(new /obj/item/wallframe/button(get_turf(src))) + playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) + qdel(src) + + update_icon() + return + + if(user.a_intent != INTENT_HARM && !(W.item_flags & NOBLUDGEON)) + return attack_hand(user) + else + return ..() + +/obj/machinery/button/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + return + req_access = list() + req_one_access = list() + playsound(src, "sparks", 100, 1) + obj_flags |= EMAGGED + return TRUE + +/obj/machinery/button/attack_ai(mob/user) + if(!panel_open) + return attack_hand(user) + +/obj/machinery/button/attack_robot(mob/user) + return attack_ai(user) + +/obj/machinery/button/proc/setup_device() + if(id && istype(device, /obj/item/assembly/control)) + var/obj/item/assembly/control/A = device + A.id = id + initialized_button = 1 + +/obj/machinery/button/attack_hand(mob/user) + . = ..() + if(.) + return + if(!initialized_button) + setup_device() + add_fingerprint(user) + if(panel_open) + if(device || board) + if(device) + device.forceMove(drop_location()) + device = null + if(board) + board.forceMove(drop_location()) + req_access = list() + req_one_access = list() + board = null + update_icon() + to_chat(user, "You remove electronics from the button frame.") + + else + if(skin == "doorctrl") + skin = "launcher" + else + skin = "doorctrl" + to_chat(user, "You change the button frame's front panel.") + return + + if((stat & (NOPOWER|BROKEN))) + return + + if(device && device.next_activate > world.time) + return + + if(!allowed(user)) + to_chat(user, "Access Denied") + flick("[skin]-denied", src) + return + + use_power(5) + icon_state = "[skin]1" + + if(device) + device.pulsed() + + addtimer(CALLBACK(src, /atom/.proc/update_icon), 15) + +/obj/machinery/button/power_change() + ..() + update_icon() + + +/obj/machinery/button/door + name = "door button" + desc = "A door remote control switch." + var/normaldoorcontrol = FALSE + var/specialfunctions = OPEN // Bitflag, see assembly file + +/obj/machinery/button/door/setup_device() + if(!device) + if(normaldoorcontrol) + var/obj/item/assembly/control/airlock/A = new(src) + device = A + A.specialfunctions = specialfunctions + else + device = new /obj/item/assembly/control(src) + ..() + +/obj/machinery/button/door/incinerator_vent_toxmix + name = "combustion chamber vent control" + id = INCINERATOR_TOXMIX_VENT + req_access = list(ACCESS_TOX) + +/obj/machinery/button/door/incinerator_vent_atmos_main + name = "turbine vent control" + id = INCINERATOR_ATMOS_MAINVENT + req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS) + +/obj/machinery/button/door/incinerator_vent_atmos_aux + name = "combustion chamber vent control" + id = INCINERATOR_ATMOS_AUXVENT + req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS) + +/obj/machinery/button/door/incinerator_vent_syndicatelava_main + name = "turbine vent control" + id = INCINERATOR_SYNDICATELAVA_MAINVENT + req_access = list(ACCESS_SYNDICATE) + +/obj/machinery/button/door/incinerator_vent_syndicatelava_aux + name = "combustion chamber vent control" + id = INCINERATOR_SYNDICATELAVA_AUXVENT + req_access = list(ACCESS_SYNDICATE) + +/obj/machinery/button/massdriver + name = "mass driver button" + desc = "A remote control switch for a mass driver." + icon_state = "launcher" + skin = "launcher" + device_type = /obj/item/assembly/control/massdriver + +/obj/machinery/button/ignition + name = "ignition switch" + desc = "A remote control switch for a mounted igniter." + icon_state = "launcher" + skin = "launcher" + device_type = /obj/item/assembly/control/igniter + +/obj/machinery/button/ignition/incinerator + name = "combustion chamber ignition switch" + desc = "A remote control switch for the combustion chamber's igniter." + +/obj/machinery/button/ignition/incinerator/toxmix + id = INCINERATOR_TOXMIX_IGNITER + +/obj/machinery/button/ignition/incinerator/atmos + id = INCINERATOR_ATMOS_IGNITER + +/obj/machinery/button/ignition/incinerator/syndicatelava + id = INCINERATOR_SYNDICATELAVA_IGNITER + +/obj/machinery/button/flasher + name = "flasher button" + desc = "A remote control switch for a mounted flasher." + icon_state = "launcher" + skin = "launcher" + device_type = /obj/item/assembly/control/flasher + +/obj/machinery/button/crematorium + name = "crematorium igniter" + desc = "Burn baby burn!" + icon_state = "launcher" + skin = "launcher" + device_type = /obj/item/assembly/control/crematorium + req_access = list() + id = 1 + +/obj/item/wallframe/button + name = "button frame" + desc = "Used for building buttons." + icon_state = "button" + result_path = /obj/machinery/button + materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index b120720992..66e302bab6 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -1,148 +1,148 @@ -/obj/item/wallframe/camera - name = "camera assembly" - desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." - icon = 'icons/obj/machines/camera.dmi' - icon_state = "cameracase" - materials = list(MAT_METAL=400, MAT_GLASS=250) - result_path = /obj/structure/camera_assembly - - -/obj/structure/camera_assembly - name = "camera assembly" - desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." - icon = 'icons/obj/machines/camera.dmi' - icon_state = "camera1" - max_integrity = 150 - // Motion, EMP-Proof, X-ray - var/static/list/possible_upgrades = typecacheof(list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer)) - var/list/upgrades - var/state = 1 - - /* - 1 = Wrenched in place - 2 = Welded in place - 3 = Wires attached to it (you can now attach/dettach upgrades) - 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades) - */ - -/obj/structure/camera_assembly/Initialize(mapload, ndir, building) - . = ..() - if(building) - setDir(ndir) - upgrades = list() - -/obj/structure/camera_assembly/Destroy() - QDEL_LIST(upgrades) - return ..() - -/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params) - switch(state) - if(1) - // State 1 - if(istype(W, /obj/item/weldingtool)) - if(weld(W, user)) - to_chat(user, "You weld the assembly securely into place.") - setAnchored(TRUE) - state = 2 - return - if(2) - // State 2 - if(istype(W, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/C = W - if(C.use(2)) - to_chat(user, "You add wires to the assembly.") - state = 3 - else - to_chat(user, "You need two lengths of cable to wire a camera!") - return - return - - else if(istype(W, /obj/item/weldingtool)) - - if(weld(W, user)) - to_chat(user, "You unweld the assembly from its place.") - state = 1 - setAnchored(TRUE) - return - - // Upgrades! - if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. - if(!user.transferItemToLoc(W, src)) - return - to_chat(user, "You attach \the [W] into the assembly inner circuits.") - upgrades += W - return - - return ..() - -/obj/structure/camera_assembly/crowbar_act(mob/user, obj/item/tool) - if(!upgrades.len) - return FALSE - var/obj/U = locate(/obj) in upgrades - if(U) - to_chat(user, "You detach an upgrade from the assembly.") - tool.play_tool_sound(src) - U.forceMove(drop_location()) - upgrades -= U - return TRUE - -/obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool) - . = ..() - if(.) - return TRUE - if(state != 3) - return FALSE - - tool.play_tool_sound(src) - var/input = stripped_input(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13") - if(!input) - to_chat(user, "No input found, please hang up and try your call again!") - return - var/list/tempnetwork = splittext(input, ",") - if(tempnetwork.len < 1) - to_chat(user, "No network found, please hang up and try your call again!") - return - for(var/i in tempnetwork) - tempnetwork -= i - tempnetwork += lowertext(i) - state = 4 - var/obj/machinery/camera/C = new(loc, src) - forceMove(C) - C.setDir(src.dir) - - C.network = tempnetwork - var/area/A = get_area(src) - C.c_tag = "[A.name] ([rand(1, 999)])" - return TRUE - -/obj/structure/camera_assembly/wirecutter_act(mob/user, obj/item/I) - if(state != 3) - return FALSE - - new /obj/item/stack/cable_coil(drop_location(), 2) - I.play_tool_sound(src) - to_chat(user, "You cut the wires from the circuits.") - state = 2 - return TRUE - -/obj/structure/camera_assembly/wrench_act(mob/user, obj/item/I) - if(state != 1) - return FALSE - I.play_tool_sound(src) - to_chat(user, "You detach the assembly from its place.") - new /obj/item/wallframe/camera(drop_location()) - qdel(src) - return TRUE - -/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user) - if(!W.tool_start_check(user, amount=0)) - return FALSE - to_chat(user, "You start to weld \the [src]...") - if(W.use_tool(src, user, 20, volume=50)) - return TRUE - return FALSE - -/obj/structure/camera_assembly/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - new /obj/item/stack/sheet/metal(loc) - qdel(src) +/obj/item/wallframe/camera + name = "camera assembly" + desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." + icon = 'icons/obj/machines/camera.dmi' + icon_state = "cameracase" + materials = list(MAT_METAL=400, MAT_GLASS=250) + result_path = /obj/structure/camera_assembly + + +/obj/structure/camera_assembly + name = "camera assembly" + desc = "The basic construction for Nanotrasen-Always-Watching-You cameras." + icon = 'icons/obj/machines/camera.dmi' + icon_state = "camera1" + max_integrity = 150 + // Motion, EMP-Proof, X-ray + var/static/list/possible_upgrades = typecacheof(list(/obj/item/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/analyzer)) + var/list/upgrades + var/state = 1 + + /* + 1 = Wrenched in place + 2 = Welded in place + 3 = Wires attached to it (you can now attach/dettach upgrades) + 4 = Screwdriver panel closed and is fully built (you cannot attach upgrades) + */ + +/obj/structure/camera_assembly/Initialize(mapload, ndir, building) + . = ..() + if(building) + setDir(ndir) + upgrades = list() + +/obj/structure/camera_assembly/Destroy() + QDEL_LIST(upgrades) + return ..() + +/obj/structure/camera_assembly/attackby(obj/item/W, mob/living/user, params) + switch(state) + if(1) + // State 1 + if(istype(W, /obj/item/weldingtool)) + if(weld(W, user)) + to_chat(user, "You weld the assembly securely into place.") + setAnchored(TRUE) + state = 2 + return + if(2) + // State 2 + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + if(C.use(2)) + to_chat(user, "You add wires to the assembly.") + state = 3 + else + to_chat(user, "You need two lengths of cable to wire a camera!") + return + return + + else if(istype(W, /obj/item/weldingtool)) + + if(weld(W, user)) + to_chat(user, "You unweld the assembly from its place.") + state = 1 + setAnchored(TRUE) + return + + // Upgrades! + if(is_type_in_typecache(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. + if(!user.transferItemToLoc(W, src)) + return + to_chat(user, "You attach \the [W] into the assembly inner circuits.") + upgrades += W + return + + return ..() + +/obj/structure/camera_assembly/crowbar_act(mob/user, obj/item/tool) + if(!upgrades.len) + return FALSE + var/obj/U = locate(/obj) in upgrades + if(U) + to_chat(user, "You detach an upgrade from the assembly.") + tool.play_tool_sound(src) + U.forceMove(drop_location()) + upgrades -= U + return TRUE + +/obj/structure/camera_assembly/screwdriver_act(mob/user, obj/item/tool) + . = ..() + if(.) + return TRUE + if(state != 3) + return FALSE + + tool.play_tool_sound(src) + var/input = stripped_input(user, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13") + if(!input) + to_chat(user, "No input found, please hang up and try your call again!") + return + var/list/tempnetwork = splittext(input, ",") + if(tempnetwork.len < 1) + to_chat(user, "No network found, please hang up and try your call again!") + return + for(var/i in tempnetwork) + tempnetwork -= i + tempnetwork += lowertext(i) + state = 4 + var/obj/machinery/camera/C = new(loc, src) + forceMove(C) + C.setDir(src.dir) + + C.network = tempnetwork + var/area/A = get_area(src) + C.c_tag = "[A.name] ([rand(1, 999)])" + return TRUE + +/obj/structure/camera_assembly/wirecutter_act(mob/user, obj/item/I) + if(state != 3) + return FALSE + + new /obj/item/stack/cable_coil(drop_location(), 2) + I.play_tool_sound(src) + to_chat(user, "You cut the wires from the circuits.") + state = 2 + return TRUE + +/obj/structure/camera_assembly/wrench_act(mob/user, obj/item/I) + if(state != 1) + return FALSE + I.play_tool_sound(src) + to_chat(user, "You detach the assembly from its place.") + new /obj/item/wallframe/camera(drop_location()) + qdel(src) + return TRUE + +/obj/structure/camera_assembly/proc/weld(obj/item/weldingtool/W, mob/living/user) + if(!W.tool_start_check(user, amount=0)) + return FALSE + to_chat(user, "You start to weld \the [src]...") + if(W.use_tool(src, user, 20, volume=50)) + return TRUE + return FALSE + +/obj/structure/camera_assembly/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + new /obj/item/stack/sheet/metal(loc) + qdel(src) diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm index 6c134417bb..d103e2a856 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -1,77 +1,77 @@ -/obj/machinery/camera - - var/list/datum/weakref/localMotionTargets = list() - var/detectTime = 0 - var/area/ai_monitored/area_motion = null - var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm() - -/obj/machinery/camera/process() - // motion camera event loop - if(!isMotion()) - . = PROCESS_KILL - return - if(stat & EMPED) - return - if (detectTime > 0) - var/elapsed = world.time - detectTime - if (elapsed > alarm_delay) - triggerAlarm() - else if (detectTime == -1) - for (var/datum/weakref/targetref in getTargetList()) - var/mob/target = targetref.resolve() - if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target))) - //If not part of a monitored area and the camera is not in range or the target is dead - lostTargetRef(targetref) - -/obj/machinery/camera/proc/getTargetList() - if(area_motion) - return area_motion.motionTargets - return localMotionTargets - -/obj/machinery/camera/proc/newTarget(mob/target) - if(isAI(target)) - return FALSE - if (detectTime == 0) - detectTime = world.time // start the clock - var/list/targets = getTargetList() - targets |= WEAKREF(target) - return TRUE - -/obj/machinery/camera/Destroy() - var/area/ai_monitored/A = get_area(src) - localMotionTargets = null - if(istype(A)) - A.motioncameras -= src - cancelAlarm() - return ..() - -/obj/machinery/camera/proc/lostTargetRef(datum/weakref/R) - var/list/targets = getTargetList() - targets -= R - if (targets.len == 0) - cancelAlarm() - -/obj/machinery/camera/proc/cancelAlarm() - if (detectTime == -1) - for (var/i in GLOB.silicon_mobs) - var/mob/living/silicon/aiPlayer = i - if (status) - aiPlayer.cancelAlarm("Motion", get_area(src), src) - detectTime = 0 - return TRUE - -/obj/machinery/camera/proc/triggerAlarm() - if (!detectTime) - return FALSE - for (var/mob/living/silicon/aiPlayer in GLOB.player_list) - if (status) - aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) - visible_message("A red light flashes on the [src]!") - detectTime = -1 - return TRUE - -/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj) - // Motion cameras outside of an "ai monitored" area will use this to detect stuff. - if (!area_motion) - if(isliving(AM)) - newTarget(AM) +/obj/machinery/camera + + var/list/datum/weakref/localMotionTargets = list() + var/detectTime = 0 + var/area/ai_monitored/area_motion = null + var/alarm_delay = 30 // Don't forget, there's another 3 seconds in queueAlarm() + +/obj/machinery/camera/process() + // motion camera event loop + if(!isMotion()) + . = PROCESS_KILL + return + if(stat & EMPED) + return + if (detectTime > 0) + var/elapsed = world.time - detectTime + if (elapsed > alarm_delay) + triggerAlarm() + else if (detectTime == -1) + for (var/datum/weakref/targetref in getTargetList()) + var/mob/target = targetref.resolve() + if(QDELETED(target) || target.stat == DEAD || (!area_motion && !in_range(src, target))) + //If not part of a monitored area and the camera is not in range or the target is dead + lostTargetRef(targetref) + +/obj/machinery/camera/proc/getTargetList() + if(area_motion) + return area_motion.motionTargets + return localMotionTargets + +/obj/machinery/camera/proc/newTarget(mob/target) + if(isAI(target)) + return FALSE + if (detectTime == 0) + detectTime = world.time // start the clock + var/list/targets = getTargetList() + targets |= WEAKREF(target) + return TRUE + +/obj/machinery/camera/Destroy() + var/area/ai_monitored/A = get_area(src) + localMotionTargets = null + if(istype(A)) + A.motioncameras -= src + cancelAlarm() + return ..() + +/obj/machinery/camera/proc/lostTargetRef(datum/weakref/R) + var/list/targets = getTargetList() + targets -= R + if (targets.len == 0) + cancelAlarm() + +/obj/machinery/camera/proc/cancelAlarm() + if (detectTime == -1) + for (var/i in GLOB.silicon_mobs) + var/mob/living/silicon/aiPlayer = i + if (status) + aiPlayer.cancelAlarm("Motion", get_area(src), src) + detectTime = 0 + return TRUE + +/obj/machinery/camera/proc/triggerAlarm() + if (!detectTime) + return FALSE + for (var/mob/living/silicon/aiPlayer in GLOB.player_list) + if (status) + aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) + visible_message("A red light flashes on the [src]!") + detectTime = -1 + return TRUE + +/obj/machinery/camera/HasProximity(atom/movable/AM as mob|obj) + // Motion cameras outside of an "ai monitored" area will use this to detect stuff. + if (!area_motion) + if(isliving(AM)) + newTarget(AM) diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index afcc1fee7c..021232f435 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -1,89 +1,89 @@ -// PRESETS - -// EMP -/obj/machinery/camera/emp_proof - start_active = TRUE - -/obj/machinery/camera/emp_proof/Initialize() - . = ..() - upgradeEmpProof() - -// X-ray - -/obj/machinery/camera/xray - start_active = TRUE - icon_state = "xraycam" // Thanks to Krutchen for the icons. - -/obj/machinery/camera/xray/Initialize() - . = ..() - upgradeXRay() - -// MOTION -/obj/machinery/camera/motion - start_active = TRUE - name = "motion-sensitive security camera" - -/obj/machinery/camera/motion/Initialize() - . = ..() - upgradeMotion() - -// ALL UPGRADES -/obj/machinery/camera/all - start_active = TRUE - -/obj/machinery/camera/all/Initialize() - . = ..() - upgradeEmpProof() - upgradeXRay() - upgradeMotion() - -// AUTONAME - -/obj/machinery/camera/autoname - var/number = 0 //camera number in area - -//This camera type automatically sets it's name to whatever the area that it's in is called. -/obj/machinery/camera/autoname/Initialize() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/camera/autoname/LateInitialize() - . = ..() - number = 1 - var/area/A = get_area(src) - if(A) - 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) - if(C.number) - number = max(number, C.number+1) - c_tag = "[A.name] #[number]" - -// CHECKS - -/obj/machinery/camera/proc/isEmpProof() - return upgrades & CAMERA_UPGRADE_EMP_PROOF - -/obj/machinery/camera/proc/isXRay() - return upgrades & CAMERA_UPGRADE_XRAY - -/obj/machinery/camera/proc/isMotion() - return upgrades & CAMERA_UPGRADE_MOTION - -// UPGRADE PROCS - -/obj/machinery/camera/proc/upgradeEmpProof() - AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) - assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) - upgrades |= CAMERA_UPGRADE_EMP_PROOF - -/obj/machinery/camera/proc/upgradeXRay() - assembly.upgrades.Add(new /obj/item/analyzer(assembly)) - upgrades |= CAMERA_UPGRADE_XRAY - -// If you are upgrading Motion, and it isn't in the camera's Initialize(), add it to the machines list. -/obj/machinery/camera/proc/upgradeMotion() - assembly.upgrades.Add(new /obj/item/assembly/prox_sensor(assembly)) - upgrades |= CAMERA_UPGRADE_MOTION +// PRESETS + +// EMP +/obj/machinery/camera/emp_proof + start_active = TRUE + +/obj/machinery/camera/emp_proof/Initialize() + . = ..() + upgradeEmpProof() + +// X-ray + +/obj/machinery/camera/xray + start_active = TRUE + icon_state = "xraycam" // Thanks to Krutchen for the icons. + +/obj/machinery/camera/xray/Initialize() + . = ..() + upgradeXRay() + +// MOTION +/obj/machinery/camera/motion + start_active = TRUE + name = "motion-sensitive security camera" + +/obj/machinery/camera/motion/Initialize() + . = ..() + upgradeMotion() + +// ALL UPGRADES +/obj/machinery/camera/all + start_active = TRUE + +/obj/machinery/camera/all/Initialize() + . = ..() + upgradeEmpProof() + upgradeXRay() + upgradeMotion() + +// AUTONAME + +/obj/machinery/camera/autoname + var/number = 0 //camera number in area + +//This camera type automatically sets it's name to whatever the area that it's in is called. +/obj/machinery/camera/autoname/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/camera/autoname/LateInitialize() + . = ..() + number = 1 + var/area/A = get_area(src) + if(A) + 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) + if(C.number) + number = max(number, C.number+1) + c_tag = "[A.name] #[number]" + +// CHECKS + +/obj/machinery/camera/proc/isEmpProof() + return upgrades & CAMERA_UPGRADE_EMP_PROOF + +/obj/machinery/camera/proc/isXRay() + return upgrades & CAMERA_UPGRADE_XRAY + +/obj/machinery/camera/proc/isMotion() + return upgrades & CAMERA_UPGRADE_MOTION + +// UPGRADE PROCS + +/obj/machinery/camera/proc/upgradeEmpProof() + AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES | EMP_PROTECT_CONTENTS) + assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) + upgrades |= CAMERA_UPGRADE_EMP_PROOF + +/obj/machinery/camera/proc/upgradeXRay() + assembly.upgrades.Add(new /obj/item/analyzer(assembly)) + upgrades |= CAMERA_UPGRADE_XRAY + +// If you are upgrading Motion, and it isn't in the camera's Initialize(), add it to the machines list. +/obj/machinery/camera/proc/upgradeMotion() + assembly.upgrades.Add(new /obj/item/assembly/prox_sensor(assembly)) + upgrades |= CAMERA_UPGRADE_MOTION diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 1dbfe9d055..bf1b84fe5d 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,151 +1,151 @@ -/mob/living/silicon/ai/proc/get_camera_list() - var/list/L = list() - for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) - L.Add(C) - - camera_sort(L) - - var/list/T = list() - - for (var/obj/machinery/camera/C in L) - var/list/tempnetwork = C.network&src.network - if (tempnetwork.len) - T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C - - return T - -/mob/living/silicon/ai/proc/show_camera_list() - var/list/cameras = get_camera_list() - var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras - switchCamera(cameras[camera]) - -/datum/trackable - var/initialized = FALSE - var/list/names = list() - var/list/namecounts = list() - var/list/humans = list() - var/list/others = list() - -/mob/living/silicon/ai/proc/trackable_mobs() - track.initialized = TRUE - track.names.Cut() - track.namecounts.Cut() - track.humans.Cut() - track.others.Cut() - - if(usr.stat == DEAD) - return list() - - for(var/i in GLOB.mob_living_list) - var/mob/living/L = i - if(!L.can_track(usr)) - continue - - var/name = L.name - while(name in track.names) - track.namecounts[name]++ - name = text("[] ([])", name, track.namecounts[name]) - track.names.Add(name) - track.namecounts[name] = 1 - - if(ishuman(L)) - track.humans[name] = L - else - track.others[name] = L - - var/list/targets = sortList(track.humans) + sortList(track.others) - - return targets - -/mob/living/silicon/ai/verb/ai_camera_track(target_name in trackable_mobs()) - set name = "track" - set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass - - if(!target_name) - return - - if(!track.initialized) - trackable_mobs() - - var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) - - ai_actual_track(target) - -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) - if(!istype(target)) - return - var/mob/living/silicon/ai/U = usr - - U.cameraFollow = target - U.tracking = 1 - - if(!target || !target.can_track(usr)) - to_chat(U, "Target is not near any active cameras.") - U.cameraFollow = null - return - - to_chat(U, "Now tracking [target.get_visible_name()] on camera.") - - var/cameraticks = 0 - spawn(0) - while(U.cameraFollow == target) - if(U.cameraFollow == null) - return - - if(!target.can_track(usr)) - U.tracking = 1 - if(!cameraticks) - to_chat(U, "Target is not near any active cameras. Attempting to reacquire...") - cameraticks++ - if(cameraticks > 9) - U.cameraFollow = null - to_chat(U, "Unable to reacquire, cancelling track...") - tracking = 0 - return - else - sleep(10) - continue - - else - cameraticks = 0 - U.tracking = 0 - - if(U.eyeobj) - U.eyeobj.setLoc(get_turf(target)) - - else - view_core() - U.cameraFollow = null - return - - sleep(10) - -/proc/near_camera(mob/living/M) - if (!isturf(M.loc)) - return FALSE - if(issilicon(M)) - var/mob/living/silicon/S = M - if((QDELETED(S.builtInCamera) || !S.builtInCamera.can_use()) && !GLOB.cameranet.checkCameraVis(M)) - return FALSE - else if(!GLOB.cameranet.checkCameraVis(M)) - return FALSE - return TRUE - -/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user) - if (!istype(user)) - return - if (!can_use()) - return - user.switchCamera(src) - -/proc/camera_sort(list/L) - var/obj/machinery/camera/a - var/obj/machinery/camera/b - - for (var/i = L.len, i > 0, i--) - for (var/j = 1 to i - 1) - a = L[j] - b = L[j + 1] - if (sorttext(a.c_tag, b.c_tag) < 0) - L.Swap(j, j + 1) - return L +/mob/living/silicon/ai/proc/get_camera_list() + var/list/L = list() + for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) + L.Add(C) + + camera_sort(L) + + var/list/T = list() + + for (var/obj/machinery/camera/C in L) + var/list/tempnetwork = C.network&src.network + if (tempnetwork.len) + T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C + + return T + +/mob/living/silicon/ai/proc/show_camera_list() + var/list/cameras = get_camera_list() + var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras + switchCamera(cameras[camera]) + +/datum/trackable + var/initialized = FALSE + var/list/names = list() + var/list/namecounts = list() + var/list/humans = list() + var/list/others = list() + +/mob/living/silicon/ai/proc/trackable_mobs() + track.initialized = TRUE + track.names.Cut() + track.namecounts.Cut() + track.humans.Cut() + track.others.Cut() + + if(usr.stat == DEAD) + return list() + + for(var/i in GLOB.mob_living_list) + var/mob/living/L = i + if(!L.can_track(usr)) + continue + + var/name = L.name + while(name in track.names) + track.namecounts[name]++ + name = text("[] ([])", name, track.namecounts[name]) + track.names.Add(name) + track.namecounts[name] = 1 + + if(ishuman(L)) + track.humans[name] = L + else + track.others[name] = L + + var/list/targets = sortList(track.humans) + sortList(track.others) + + return targets + +/mob/living/silicon/ai/verb/ai_camera_track(target_name in trackable_mobs()) + set name = "track" + set hidden = 1 //Don't display it on the verb lists. This verb exists purely so you can type "track Oldman Robustin" and follow his ass + + if(!target_name) + return + + if(!track.initialized) + trackable_mobs() + + var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) + + ai_actual_track(target) + +/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) + if(!istype(target)) + return + var/mob/living/silicon/ai/U = usr + + U.cameraFollow = target + U.tracking = 1 + + if(!target || !target.can_track(usr)) + to_chat(U, "Target is not near any active cameras.") + U.cameraFollow = null + return + + to_chat(U, "Now tracking [target.get_visible_name()] on camera.") + + var/cameraticks = 0 + spawn(0) + while(U.cameraFollow == target) + if(U.cameraFollow == null) + return + + if(!target.can_track(usr)) + U.tracking = 1 + if(!cameraticks) + to_chat(U, "Target is not near any active cameras. Attempting to reacquire...") + cameraticks++ + if(cameraticks > 9) + U.cameraFollow = null + to_chat(U, "Unable to reacquire, cancelling track...") + tracking = 0 + return + else + sleep(10) + continue + + else + cameraticks = 0 + U.tracking = 0 + + if(U.eyeobj) + U.eyeobj.setLoc(get_turf(target)) + + else + view_core() + U.cameraFollow = null + return + + sleep(10) + +/proc/near_camera(mob/living/M) + if (!isturf(M.loc)) + return FALSE + if(issilicon(M)) + var/mob/living/silicon/S = M + if((QDELETED(S.builtInCamera) || !S.builtInCamera.can_use()) && !GLOB.cameranet.checkCameraVis(M)) + return FALSE + else if(!GLOB.cameranet.checkCameraVis(M)) + return FALSE + return TRUE + +/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user) + if (!istype(user)) + return + if (!can_use()) + return + user.switchCamera(src) + +/proc/camera_sort(list/L) + var/obj/machinery/camera/a + var/obj/machinery/camera/b + + for (var/i = L.len, i > 0, i--) + for (var/j = 1 to i - 1) + a = L[j] + b = L[j + 1] + if (sorttext(a.c_tag, b.c_tag) < 0) + L.Swap(j, j + 1) + return L diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 1c0635fd3d..a982411692 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -1,130 +1,130 @@ -/obj/machinery/cell_charger - name = "cell charger" - desc = "It charges power cells." - icon = 'icons/obj/power.dmi' - icon_state = "ccharger" - use_power = IDLE_POWER_USE - idle_power_usage = 5 - active_power_usage = 60 - power_channel = EQUIP - circuit = /obj/item/circuitboard/machine/cell_charger - pass_flags = PASSTABLE - var/obj/item/stock_parts/cell/charging = null - var/chargelevel = -1 - var/charge_rate = 500 - -/obj/machinery/cell_charger/update_icon() - cut_overlays() - if(charging) - add_overlay(image(charging.icon, charging.icon_state)) - add_overlay("ccharger-on") - if(!(stat & (BROKEN|NOPOWER))) - var/newlevel = round(charging.percent() * 4 / 100) - chargelevel = newlevel - add_overlay("ccharger-o[newlevel]") - -/obj/machinery/cell_charger/examine(mob/user) - . = ..() - . += "There's [charging ? "a" : "no"] cell in the charger." - if(charging) - . += "Current charge: [round(charging.percent(), 1)]%." - -/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/stock_parts/cell) && !panel_open) - if(stat & BROKEN) - to_chat(user, "[src] is broken!") - return - if(!anchored) - to_chat(user, "[src] isn't attached to the ground!") - return - if(charging) - to_chat(user, "There is already a cell in the charger!") - return - else - var/area/a = loc.loc // Gets our locations location, like a dream within a dream - if(!isarea(a)) - return - if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! - to_chat(user, "[src] blinks red as you try to insert the cell!") - return - if(!user.transferItemToLoc(W,src)) - return - - charging = W - user.visible_message("[user] inserts a cell into [src].", "You insert a cell into [src].") - chargelevel = -1 - update_icon() - else - if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W)) - return - if(default_deconstruction_crowbar(W)) - return - if(!charging && default_unfasten_wrench(user, W)) - return - return ..() - -/obj/machinery/cell_charger/deconstruct() - if(charging) - charging.forceMove(drop_location()) - return ..() - -/obj/machinery/cell_charger/Destroy() - QDEL_NULL(charging) - return ..() - -/obj/machinery/cell_charger/proc/removecell() - charging.update_icon() - charging = null - chargelevel = -1 - update_icon() - -/obj/machinery/cell_charger/attack_hand(mob/user) - . = ..() - if(.) - return - if(!charging) - return - - user.put_in_hands(charging) - charging.add_fingerprint(user) - - user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") - - removecell() - -/obj/machinery/cell_charger/attack_tk(mob/user) - if(!charging) - return - - charging.forceMove(loc) - to_chat(user, "You telekinetically remove [charging] from [src].") - - removecell() - -/obj/machinery/cell_charger/attack_ai(mob/user) - return - -/obj/machinery/cell_charger/emp_act(severity) - . = ..() - - if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS) - return - - if(charging) - charging.emp_act(severity) - -/obj/machinery/cell_charger/RefreshParts() - charge_rate = 500 - for(var/obj/item/stock_parts/capacitor/C in component_parts) - charge_rate *= C.rating - -/obj/machinery/cell_charger/process() - if(!charging || !anchored || (stat & (BROKEN|NOPOWER))) - return - - if(charging.percent() >= 100) - return - use_power(charge_rate) - charging.give(charge_rate) //this is 2558, efficient batteries exist - - update_icon() +/obj/machinery/cell_charger + name = "cell charger" + desc = "It charges power cells." + icon = 'icons/obj/power.dmi' + icon_state = "ccharger" + use_power = IDLE_POWER_USE + idle_power_usage = 5 + active_power_usage = 60 + power_channel = EQUIP + circuit = /obj/item/circuitboard/machine/cell_charger + pass_flags = PASSTABLE + var/obj/item/stock_parts/cell/charging = null + var/chargelevel = -1 + var/charge_rate = 500 + +/obj/machinery/cell_charger/update_icon() + cut_overlays() + if(charging) + add_overlay(image(charging.icon, charging.icon_state)) + add_overlay("ccharger-on") + if(!(stat & (BROKEN|NOPOWER))) + var/newlevel = round(charging.percent() * 4 / 100) + chargelevel = newlevel + add_overlay("ccharger-o[newlevel]") + +/obj/machinery/cell_charger/examine(mob/user) + . = ..() + . += "There's [charging ? "a" : "no"] cell in the charger." + if(charging) + . += "Current charge: [round(charging.percent(), 1)]%." + +/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/stock_parts/cell) && !panel_open) + if(stat & BROKEN) + to_chat(user, "[src] is broken!") + return + if(!anchored) + to_chat(user, "[src] isn't attached to the ground!") + return + if(charging) + to_chat(user, "There is already a cell in the charger!") + return + else + var/area/a = loc.loc // Gets our locations location, like a dream within a dream + if(!isarea(a)) + return + if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! + to_chat(user, "[src] blinks red as you try to insert the cell!") + return + if(!user.transferItemToLoc(W,src)) + return + + charging = W + user.visible_message("[user] inserts a cell into [src].", "You insert a cell into [src].") + chargelevel = -1 + update_icon() + else + if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W)) + return + if(default_deconstruction_crowbar(W)) + return + if(!charging && default_unfasten_wrench(user, W)) + return + return ..() + +/obj/machinery/cell_charger/deconstruct() + if(charging) + charging.forceMove(drop_location()) + return ..() + +/obj/machinery/cell_charger/Destroy() + QDEL_NULL(charging) + return ..() + +/obj/machinery/cell_charger/proc/removecell() + charging.update_icon() + charging = null + chargelevel = -1 + update_icon() + +/obj/machinery/cell_charger/attack_hand(mob/user) + . = ..() + if(.) + return + if(!charging) + return + + user.put_in_hands(charging) + charging.add_fingerprint(user) + + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") + + removecell() + +/obj/machinery/cell_charger/attack_tk(mob/user) + if(!charging) + return + + charging.forceMove(loc) + to_chat(user, "You telekinetically remove [charging] from [src].") + + removecell() + +/obj/machinery/cell_charger/attack_ai(mob/user) + return + +/obj/machinery/cell_charger/emp_act(severity) + . = ..() + + if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_CONTENTS) + return + + if(charging) + charging.emp_act(severity) + +/obj/machinery/cell_charger/RefreshParts() + charge_rate = 500 + for(var/obj/item/stock_parts/capacitor/C in component_parts) + charge_rate *= C.rating + +/obj/machinery/cell_charger/process() + if(!charging || !anchored || (stat & (BROKEN|NOPOWER))) + return + + if(charging.percent() >= 100) + return + use_power(charge_rate) + charging.give(charge_rate) //this is 2558, efficient batteries exist + + update_icon() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 97b260f3bf..413621d8b9 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -1,556 +1,556 @@ -//Cloning revival method. -//The pod handles the actual cloning while the computer manages the clone profiles - -//Potential replacement for genetics revives or something I dunno (?) - -#define CLONE_INITIAL_DAMAGE 150 //Clones in clonepods start with 150 cloneloss damage and 150 brainloss damage, thats just logical -#define MINIMUM_HEAL_LEVEL 40 - -#define SPEAK(message) radio.talk_into(src, message, radio_channel) - -/obj/machinery/clonepod - name = "cloning pod" - desc = "An electronically-lockable pod for growing organic tissue." - density = TRUE - icon = 'icons/obj/machines/cloning.dmi' - icon_state = "pod_0" - req_access = list(ACCESS_CLONING) //FOR PREMATURE UNLOCKING. - verb_say = "states" - circuit = /obj/item/circuitboard/machine/clonepod - - 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. - var/mess = FALSE //Need to clean out it if it's full of exploded clone. - var/attempting = FALSE //One clone attempt at a time thanks - var/speed_coeff - var/efficiency - - var/datum/mind/clonemind - var/grab_ghost_when = CLONER_MATURE_CLONE - - var/internal_radio = TRUE - var/obj/item/radio/radio - var/radio_key = /obj/item/encryptionkey/headset_med - var/radio_channel = RADIO_CHANNEL_MEDICAL - - var/obj/effect/countdown/clonepod/countdown - - var/list/unattached_flesh - var/flesh_number = 0 - -/obj/machinery/clonepod/Initialize() - . = ..() - - countdown = new(src) - - if(internal_radio) - radio = new(src) - radio.keyslot = new radio_key - radio.subspace_transmission = TRUE - radio.canhear_range = 0 - radio.recalculateChannels() - - update_icon() - -/obj/machinery/clonepod/Destroy() - go_out() - QDEL_NULL(radio) - QDEL_NULL(countdown) - if(connected) - connected.DetachCloner(src) - QDEL_LIST(unattached_flesh) - . = ..() - -/obj/machinery/clonepod/RefreshParts() - speed_coeff = 0 - efficiency = 0 - for(var/obj/item/stock_parts/scanning_module/S in component_parts) - efficiency += S.rating - for(var/obj/item/stock_parts/manipulator/P in component_parts) - speed_coeff += P.rating - heal_level = (efficiency * 15) + 10 - if(heal_level < MINIMUM_HEAL_LEVEL) - heal_level = MINIMUM_HEAL_LEVEL - if(heal_level > 100) - heal_level = 100 - -//The return of data disks?? Just for transferring between genetics machine/cloning machine. -//TO-DO: Make the genetics machine accept them. -/obj/item/disk/data - name = "cloning data disk" - icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. - var/list/fields = list() - var/read_only = 0 //Well,it's still a floppy disk - -//Disk stuff. -/obj/item/disk/data/Initialize() - . = ..() - icon_state = "datadisk[rand(0,6)]" - add_overlay("datadisk_gene") - -/obj/item/disk/data/attack_self(mob/user) - read_only = !read_only - to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].") - -/obj/item/disk/data/examine(mob/user) - . = ..() - . += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]." - - -//Clonepod - -/obj/machinery/clonepod/examine(mob/user) - . = ..() - var/mob/living/mob_occupant = occupant - if(mess) - . += "It's filled with blood and viscera. You swear you can see it moving..." - if(is_operational() && mob_occupant) - if(mob_occupant.stat != DEAD) - . += "Current clone cycle is [round(get_completion())]% complete." - -/obj/machinery/clonepod/return_air() - // We want to simulate the clone not being in contact with - // the atmosphere, so we'll put them in a constant pressure - // nitrogen. They don't need to breathe while cloning anyway. - var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods - if(!GM) - GM = new - return GM - -/obj/machinery/clonepod/proc/get_completion() - . = FALSE - var/mob/living/mob_occupant = occupant - if(mob_occupant) - . = (100 * ((mob_occupant.health + 100) / (heal_level + 100))) - -/obj/machinery/clonepod/attack_ai(mob/user) - return examine(user) - -//Start growing a human clone in the pod! -/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks) - if(panel_open) - return FALSE - if(mess || attempting) - return FALSE - clonemind = locate(mindref) in SSticker.minds - if(!istype(clonemind)) //not a mind - return FALSE - if(!QDELETED(clonemind.current)) - if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body - return FALSE - if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. - return FALSE - if(clonemind.active) //somebody is using that mind - if( ckey(clonemind.key)!=ckey ) - return FALSE - else - // get_ghost() will fail if they're unable to reenter their body - var/mob/dead/observer/G = clonemind.get_ghost() - if(!G) - return FALSE - if(G.suiciding) // The ghost came from a body that is suiciding. - return FALSE - if(clonemind.damnation_type) //Can't clone the damned. - INVOKE_ASYNC(src, .proc/horrifyingsound) - mess = TRUE - update_icon() - return FALSE - if(isvamp(clonemind)) //If the mind is a bloodsucker - return FALSE - - attempting = TRUE //One at a time!! - countdown.start() - - var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) - - H.hardset_dna(ui, se, H.real_name, null, mrace, features) - - if(prob(50 - efficiency*10)) //Chance to give a bad mutation. - H.randmutb() //100% bad mutation. Can be cured with mutadone. - - H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment. - occupant = H - - if(!clonename) //to prevent null names - clonename = "clone ([rand(1,999)])" - H.real_name = clonename - - //Get the clone body ready - maim_clone(H) - ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT) - ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT) - ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) - ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT) - ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT) - ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) - H.Unconscious(80) - - clonemind.transfer_to(H) - - if(grab_ghost_when == CLONER_FRESH_CLONE) - H.grab_ghost() - to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
    So this is what cloning feels like?
    ") - - if(grab_ghost_when == CLONER_MATURE_CLONE) - H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost - to_chat(H.get_ghost(TRUE), "Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.") - - if(H) - H.faction |= factions - - for(var/V in quirks) - var/datum/quirk/Q = new V(H) - Q.on_clone(quirks[V]) - - H.set_cloned_appearance() - H.give_genitals(TRUE) - - H.suiciding = FALSE - attempting = FALSE - return TRUE - -//Grow clones to maturity then kick them out. FREELOADERS -/obj/machinery/clonepod/process() - var/mob/living/mob_occupant = occupant - - if(!is_operational()) //Autoeject if power is lost - if(mob_occupant) - go_out() - mob_occupant.apply_vore_prefs() - connected_message("Clone Ejected: Loss of power.") - - else if(mob_occupant && (mob_occupant.loc == src)) - if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. - connected_message("Clone Rejected: Deceased.") - if(internal_radio) - SPEAK("The cloning has been \ - aborted due to unrecoverable tissue failure.") - go_out() - mob_occupant.apply_vore_prefs() - - else if(mob_occupant.cloneloss > (100 - heal_level)) - mob_occupant.Unconscious(80) - var/dmg_mult = CONFIG_GET(number/damage_multiplier) - //Slowly get that clone healed and finished. - mob_occupant.adjustCloneLoss(-((speed_coeff / 2) * dmg_mult)) - var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss() - // To avoid the default cloner making incomplete clones - progress += (100 - MINIMUM_HEAL_LEVEL) - var/milestone = CLONE_INITIAL_DAMAGE / flesh_number - var/installed = flesh_number - unattached_flesh.len - - if((progress / milestone) >= installed) - // attach some flesh - var/obj/item/I = pick_n_take(unattached_flesh) - if(isorgan(I)) - var/obj/item/organ/O = I - O.organ_flags &= ~ORGAN_FROZEN - O.Insert(mob_occupant) - else if(isbodypart(I)) - var/obj/item/bodypart/BP = I - BP.attach_limb(mob_occupant) - - //Premature clones may have brain damage. - mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult)) - - use_power(7500) //This might need tweaking. - - else if((mob_occupant.cloneloss <= (100 - heal_level))) - connected_message("Cloning Process Complete.") - if(internal_radio) - SPEAK("The cloning cycle is complete.") - - // If the cloner is upgraded to debugging high levels, sometimes - // organs and limbs can be missing. - for(var/i in unattached_flesh) - if(isorgan(i)) - var/obj/item/organ/O = i - O.organ_flags &= ~ORGAN_FROZEN - O.Insert(mob_occupant) - else if(isbodypart(i)) - var/obj/item/bodypart/BP = i - BP.attach_limb(mob_occupant) - - go_out() - mob_occupant.apply_vore_prefs() - - else if (!mob_occupant || mob_occupant.loc != src) - occupant = null - use_power(200) - - update_icon() - -//Let's unlock this early I guess. Might be too early, needs tweaking. -/obj/machinery/clonepod/attackby(obj/item/W, mob/user, params) - if(!(occupant || mess)) - if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W)) - return - - if(default_deconstruction_crowbar(W)) - return - - if(istype(W, /obj/item/multitool)) - var/obj/item/multitool/P = W - - if(istype(P.buffer, /obj/machinery/computer/cloning)) - if(get_area(P.buffer) != get_area(src)) - to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") - P.buffer = null - return - to_chat(user, "-% Successfully linked [P.buffer] with [src] %-") - var/obj/machinery/computer/cloning/comp = P.buffer - if(connected) - connected.DetachCloner(src) - comp.AttachCloner(src) - else - P.buffer = src - to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-") - return - - var/mob/living/mob_occupant = occupant - if(W.GetID()) - if(!check_access(W)) - to_chat(user, "Access Denied.") - return - if(!(mob_occupant || mess)) - to_chat(user, "Error: Pod has no occupant.") - return - else - connected_message("Emergency Ejection") - SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.") - to_chat(user, "You force an emergency ejection. ") - go_out() - mob_occupant.apply_vore_prefs() - else - return ..() - -/obj/machinery/clonepod/emag_act(mob/user) - . = ..() - if(!occupant) - return - to_chat(user, "You corrupt the genetic compiler.") - malfunction() - return TRUE - -//Put messages in the connected computer's temp var for display. -/obj/machinery/clonepod/proc/connected_message(message) - if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning))) - return FALSE - if (!message) - return FALSE - - connected.temp = message - connected.updateUsrDialog() - return TRUE - -/obj/machinery/clonepod/proc/go_out() - countdown.stop() - var/mob/living/mob_occupant = occupant - var/turf/T = get_turf(src) - - if(mess) //Clean that mess and dump those gibs! - for(var/obj/fl in unattached_flesh) - fl.forceMove(T) - if(istype(fl, /obj/item/organ)) - var/obj/item/organ/O = fl - O.organ_flags &= ~ORGAN_FROZEN - unattached_flesh.Cut() - mess = FALSE - if(mob_occupant) - mob_occupant.spawn_gibs() - audible_message("You hear a splat.") - update_icon() - return - - if(!mob_occupant) - return - - REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT) - REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT) - REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) - REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, CLONING_POD_TRAIT) - REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) - REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, CLONING_POD_TRAIT) - - if(grab_ghost_when == CLONER_MATURE_CLONE) - mob_occupant.grab_ghost() - to_chat(occupant, "There is a bright flash!
    You feel like a new being.
    ") - mob_occupant.flash_act() - - occupant.forceMove(T) - update_icon() - mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest. - for(var/fl in unattached_flesh) - qdel(fl) - unattached_flesh.Cut() - - occupant = null - -/obj/machinery/clonepod/proc/malfunction() - var/mob/living/mob_occupant = occupant - if(mob_occupant) - connected_message("Critical Error!") - SPEAK("Critical error! Please contact a Thinktronic Systems \ - technician, as your warranty may be affected.") - mess = TRUE - maim_clone(mob_occupant) //Remove every bit that's grown back so far to drop later, also destroys bits that haven't grown yet - update_icon() - if(mob_occupant.mind != clonemind) - clonemind.transfer_to(mob_occupant) - mob_occupant.grab_ghost() // We really just want to make you suffer. - flash_color(mob_occupant, flash_color="#960000", flash_time=100) - to_chat(mob_occupant, "Agony blazes across your consciousness as your body is torn apart.
    Is this what dying is like? Yes it is.
    ") - playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0) - SEND_SOUND(mob_occupant, sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)) - QDEL_IN(mob_occupant, 40) - -/obj/machinery/clonepod/relaymove(mob/user) - container_resist(user) - -/obj/machinery/clonepod/container_resist(mob/living/user) - if(user.stat == CONSCIOUS) - go_out() - -/obj/machinery/clonepod/emp_act(severity) - . = ..() - if (!(. & EMP_PROTECT_SELF)) - var/mob/living/mob_occupant = occupant - if(mob_occupant && prob(100/(severity*efficiency))) - connected_message(Gibberish("EMP-caused Accidental Ejection", 0)) - SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0)) - mob_occupant.apply_vore_prefs() - go_out() - -/obj/machinery/clonepod/ex_act(severity, target) - ..() - if(!QDELETED(src)) - go_out() - -/obj/machinery/clonepod/handle_atom_del(atom/A) - if(A == occupant) - occupant = null - countdown.stop() - -/obj/machinery/clonepod/proc/horrifyingsound() - for(var/i in 1 to 5) - playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05)) - sleep(1) - sleep(10) - playsound(loc,'sound/hallucinations/wail.ogg',100,1) - -/obj/machinery/clonepod/deconstruct(disassembled = TRUE) - if(occupant) - go_out() - ..() - -/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H) - if(!unattached_flesh) - unattached_flesh = list() - else - for(var/fl in unattached_flesh) - qdel(fl) - unattached_flesh.Cut() - - H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health - //H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE) - // In addition to being cellularly damaged and having barely any - - // brain function, they also have no limbs or internal organs. - - if(!HAS_TRAIT(H, TRAIT_NODISMEMBER)) - var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) - for(var/zone in zones) - var/obj/item/bodypart/BP = H.get_bodypart(zone) - if(BP) - BP.drop_limb() - BP.forceMove(src) - unattached_flesh += BP - - for(var/o in H.internal_organs) - var/obj/item/organ/organ = o - if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL)) - continue - organ.organ_flags |= ORGAN_FROZEN - organ.Remove(H, special=TRUE) - organ.forceMove(src) - unattached_flesh += organ - - flesh_number = unattached_flesh.len - -/obj/machinery/clonepod/update_icon() - cut_overlays() - - if(mess) - icon_state = "pod_g" - var/image/gib1 = image(CRYOMOBS, "gibup") - var/image/gib2 = image(CRYOMOBS, "gibdown") - gib1.pixel_y = 27 + round(sin(world.time) * 3) - gib1.pixel_x = round(sin(world.time * 3)) - gib2.pixel_y = 27 + round(cos(world.time) * 3) - gib2.pixel_x = round(cos(world.time * 3)) - add_overlay(gib2) - add_overlay(gib1) - add_overlay("cover-on") - - else if(occupant) - icon_state = "pod_1" - - var/image/occupant_overlay - var/completion = (flesh_number - unattached_flesh.len) / flesh_number - - if(unattached_flesh.len <= 0) - occupant_overlay = image(occupant.icon, occupant.icon_state) - occupant_overlay.copy_overlays(occupant) - else - occupant_overlay = image(CRYOMOBS, "clone_meat") - var/matrix/tform = matrix() - tform.Scale(completion) - tform.Turn(cos(world.time * 2) * 3) - occupant_overlay.transform = tform - occupant_overlay.appearance_flags = 0 - - occupant_overlay.dir = SOUTH - occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3) - occupant_overlay.pixel_x = round(sin(world.time * 3)) - - add_overlay(occupant_overlay) - add_overlay("cover-on") - else - icon_state = "pod_0" - - if(panel_open) - icon_state = "pod_0_maintenance" - - add_overlay("panel") - -/* - * Manual -- A big ol' manual. - */ - -/obj/item/paper/guides/jobs/medical/cloning - name = "paper - 'H-87 Cloning Apparatus Manual" - info = {"

    Getting Started

    - Congratulations, your station has purchased the H-87 industrial cloning device!
    - Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
    - That's all there is to it!
    - Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
    -

    Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile. - Profile Deletion has been restricted to \[Station Head\] level access.

    -

    Cloning from a profile

    - Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
    - Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
    -
    -

    The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds. - The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.


    - Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
    -

    Profile Management

    -

    The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES. - These diskettes are used to transfer genetic information between machines and profiles. - A load/save dialog will become available in each profile if a disk is inserted.


    - A good diskette is a great way to counter aforementioned genetic drift!
    -
    - This technology produced under license from Thinktronic Systems, LTD."} - -#undef CLONE_INITIAL_DAMAGE -#undef SPEAK -#undef MINIMUM_HEAL_LEVEL +//Cloning revival method. +//The pod handles the actual cloning while the computer manages the clone profiles + +//Potential replacement for genetics revives or something I dunno (?) + +#define CLONE_INITIAL_DAMAGE 150 //Clones in clonepods start with 150 cloneloss damage and 150 brainloss damage, thats just logical +#define MINIMUM_HEAL_LEVEL 40 + +#define SPEAK(message) radio.talk_into(src, message, radio_channel) + +/obj/machinery/clonepod + name = "cloning pod" + desc = "An electronically-lockable pod for growing organic tissue." + density = TRUE + icon = 'icons/obj/machines/cloning.dmi' + icon_state = "pod_0" + req_access = list(ACCESS_CLONING) //FOR PREMATURE UNLOCKING. + verb_say = "states" + circuit = /obj/item/circuitboard/machine/clonepod + + 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. + var/mess = FALSE //Need to clean out it if it's full of exploded clone. + var/attempting = FALSE //One clone attempt at a time thanks + var/speed_coeff + var/efficiency + + var/datum/mind/clonemind + var/grab_ghost_when = CLONER_MATURE_CLONE + + var/internal_radio = TRUE + var/obj/item/radio/radio + var/radio_key = /obj/item/encryptionkey/headset_med + var/radio_channel = RADIO_CHANNEL_MEDICAL + + var/obj/effect/countdown/clonepod/countdown + + var/list/unattached_flesh + var/flesh_number = 0 + +/obj/machinery/clonepod/Initialize() + . = ..() + + countdown = new(src) + + if(internal_radio) + radio = new(src) + radio.keyslot = new radio_key + radio.subspace_transmission = TRUE + radio.canhear_range = 0 + radio.recalculateChannels() + + update_icon() + +/obj/machinery/clonepod/Destroy() + go_out() + QDEL_NULL(radio) + QDEL_NULL(countdown) + if(connected) + connected.DetachCloner(src) + QDEL_LIST(unattached_flesh) + . = ..() + +/obj/machinery/clonepod/RefreshParts() + speed_coeff = 0 + efficiency = 0 + for(var/obj/item/stock_parts/scanning_module/S in component_parts) + efficiency += S.rating + for(var/obj/item/stock_parts/manipulator/P in component_parts) + speed_coeff += P.rating + heal_level = (efficiency * 15) + 10 + if(heal_level < MINIMUM_HEAL_LEVEL) + heal_level = MINIMUM_HEAL_LEVEL + if(heal_level > 100) + heal_level = 100 + +//The return of data disks?? Just for transferring between genetics machine/cloning machine. +//TO-DO: Make the genetics machine accept them. +/obj/item/disk/data + name = "cloning data disk" + icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. + var/list/fields = list() + var/read_only = 0 //Well,it's still a floppy disk + +//Disk stuff. +/obj/item/disk/data/Initialize() + . = ..() + icon_state = "datadisk[rand(0,6)]" + add_overlay("datadisk_gene") + +/obj/item/disk/data/attack_self(mob/user) + read_only = !read_only + to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].") + +/obj/item/disk/data/examine(mob/user) + . = ..() + . += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]." + + +//Clonepod + +/obj/machinery/clonepod/examine(mob/user) + . = ..() + var/mob/living/mob_occupant = occupant + if(mess) + . += "It's filled with blood and viscera. You swear you can see it moving..." + if(is_operational() && mob_occupant) + if(mob_occupant.stat != DEAD) + . += "Current clone cycle is [round(get_completion())]% complete." + +/obj/machinery/clonepod/return_air() + // We want to simulate the clone not being in contact with + // the atmosphere, so we'll put them in a constant pressure + // nitrogen. They don't need to breathe while cloning anyway. + var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods + if(!GM) + GM = new + return GM + +/obj/machinery/clonepod/proc/get_completion() + . = FALSE + var/mob/living/mob_occupant = occupant + if(mob_occupant) + . = (100 * ((mob_occupant.health + 100) / (heal_level + 100))) + +/obj/machinery/clonepod/attack_ai(mob/user) + return examine(user) + +//Start growing a human clone in the pod! +/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks) + if(panel_open) + return FALSE + if(mess || attempting) + return FALSE + clonemind = locate(mindref) in SSticker.minds + if(!istype(clonemind)) //not a mind + return FALSE + if(!QDELETED(clonemind.current)) + if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body + return FALSE + if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. + return FALSE + if(clonemind.active) //somebody is using that mind + if( ckey(clonemind.key)!=ckey ) + return FALSE + else + // get_ghost() will fail if they're unable to reenter their body + var/mob/dead/observer/G = clonemind.get_ghost() + if(!G) + return FALSE + if(G.suiciding) // The ghost came from a body that is suiciding. + return FALSE + if(clonemind.damnation_type) //Can't clone the damned. + INVOKE_ASYNC(src, .proc/horrifyingsound) + mess = TRUE + update_icon() + return FALSE + if(isvamp(clonemind)) //If the mind is a bloodsucker + return FALSE + + attempting = TRUE //One at a time!! + countdown.start() + + var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) + + H.hardset_dna(ui, se, H.real_name, null, mrace, features) + + if(prob(50 - efficiency*10)) //Chance to give a bad mutation. + H.randmutb() //100% bad mutation. Can be cured with mutadone. + + H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment. + occupant = H + + if(!clonename) //to prevent null names + clonename = "clone ([rand(1,999)])" + H.real_name = clonename + + //Get the clone body ready + maim_clone(H) + ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT) + ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) + H.Unconscious(80) + + clonemind.transfer_to(H) + + if(grab_ghost_when == CLONER_FRESH_CLONE) + H.grab_ghost() + to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
    So this is what cloning feels like?
    ") + + if(grab_ghost_when == CLONER_MATURE_CLONE) + H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost + to_chat(H.get_ghost(TRUE), "Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.") + + if(H) + H.faction |= factions + + for(var/V in quirks) + var/datum/quirk/Q = new V(H) + Q.on_clone(quirks[V]) + + H.set_cloned_appearance() + H.give_genitals(TRUE) + + H.suiciding = FALSE + attempting = FALSE + return TRUE + +//Grow clones to maturity then kick them out. FREELOADERS +/obj/machinery/clonepod/process() + var/mob/living/mob_occupant = occupant + + if(!is_operational()) //Autoeject if power is lost + if(mob_occupant) + go_out() + mob_occupant.apply_vore_prefs() + connected_message("Clone Ejected: Loss of power.") + + else if(mob_occupant && (mob_occupant.loc == src)) + if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes. + connected_message("Clone Rejected: Deceased.") + if(internal_radio) + SPEAK("The cloning has been \ + aborted due to unrecoverable tissue failure.") + go_out() + mob_occupant.apply_vore_prefs() + + else if(mob_occupant.cloneloss > (100 - heal_level)) + mob_occupant.Unconscious(80) + var/dmg_mult = CONFIG_GET(number/damage_multiplier) + //Slowly get that clone healed and finished. + mob_occupant.adjustCloneLoss(-((speed_coeff / 2) * dmg_mult)) + var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss() + // To avoid the default cloner making incomplete clones + progress += (100 - MINIMUM_HEAL_LEVEL) + var/milestone = CLONE_INITIAL_DAMAGE / flesh_number + var/installed = flesh_number - unattached_flesh.len + + if((progress / milestone) >= installed) + // attach some flesh + var/obj/item/I = pick_n_take(unattached_flesh) + if(isorgan(I)) + var/obj/item/organ/O = I + O.organ_flags &= ~ORGAN_FROZEN + O.Insert(mob_occupant) + else if(isbodypart(I)) + var/obj/item/bodypart/BP = I + BP.attach_limb(mob_occupant) + + //Premature clones may have brain damage. + mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult)) + + use_power(7500) //This might need tweaking. + + else if((mob_occupant.cloneloss <= (100 - heal_level))) + connected_message("Cloning Process Complete.") + if(internal_radio) + SPEAK("The cloning cycle is complete.") + + // If the cloner is upgraded to debugging high levels, sometimes + // organs and limbs can be missing. + for(var/i in unattached_flesh) + if(isorgan(i)) + var/obj/item/organ/O = i + O.organ_flags &= ~ORGAN_FROZEN + O.Insert(mob_occupant) + else if(isbodypart(i)) + var/obj/item/bodypart/BP = i + BP.attach_limb(mob_occupant) + + go_out() + mob_occupant.apply_vore_prefs() + + else if (!mob_occupant || mob_occupant.loc != src) + occupant = null + use_power(200) + + update_icon() + +//Let's unlock this early I guess. Might be too early, needs tweaking. +/obj/machinery/clonepod/attackby(obj/item/W, mob/user, params) + if(!(occupant || mess)) + if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W)) + return + + if(default_deconstruction_crowbar(W)) + return + + if(istype(W, /obj/item/multitool)) + var/obj/item/multitool/P = W + + if(istype(P.buffer, /obj/machinery/computer/cloning)) + if(get_area(P.buffer) != get_area(src)) + to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") + P.buffer = null + return + to_chat(user, "-% Successfully linked [P.buffer] with [src] %-") + var/obj/machinery/computer/cloning/comp = P.buffer + if(connected) + connected.DetachCloner(src) + comp.AttachCloner(src) + else + P.buffer = src + to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-") + return + + var/mob/living/mob_occupant = occupant + if(W.GetID()) + if(!check_access(W)) + to_chat(user, "Access Denied.") + return + if(!(mob_occupant || mess)) + to_chat(user, "Error: Pod has no occupant.") + return + else + connected_message("Emergency Ejection") + SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.") + to_chat(user, "You force an emergency ejection. ") + go_out() + mob_occupant.apply_vore_prefs() + else + return ..() + +/obj/machinery/clonepod/emag_act(mob/user) + . = ..() + if(!occupant) + return + to_chat(user, "You corrupt the genetic compiler.") + malfunction() + return TRUE + +//Put messages in the connected computer's temp var for display. +/obj/machinery/clonepod/proc/connected_message(message) + if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning))) + return FALSE + if (!message) + return FALSE + + connected.temp = message + connected.updateUsrDialog() + return TRUE + +/obj/machinery/clonepod/proc/go_out() + countdown.stop() + var/mob/living/mob_occupant = occupant + var/turf/T = get_turf(src) + + if(mess) //Clean that mess and dump those gibs! + for(var/obj/fl in unattached_flesh) + fl.forceMove(T) + if(istype(fl, /obj/item/organ)) + var/obj/item/organ/O = fl + O.organ_flags &= ~ORGAN_FROZEN + unattached_flesh.Cut() + mess = FALSE + if(mob_occupant) + mob_occupant.spawn_gibs() + audible_message("You hear a splat.") + update_icon() + return + + if(!mob_occupant) + return + + REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_STABLELIVER, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) + REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, CLONING_POD_TRAIT) + + if(grab_ghost_when == CLONER_MATURE_CLONE) + mob_occupant.grab_ghost() + to_chat(occupant, "There is a bright flash!
    You feel like a new being.
    ") + mob_occupant.flash_act() + + occupant.forceMove(T) + update_icon() + mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest. + for(var/fl in unattached_flesh) + qdel(fl) + unattached_flesh.Cut() + + occupant = null + +/obj/machinery/clonepod/proc/malfunction() + var/mob/living/mob_occupant = occupant + if(mob_occupant) + connected_message("Critical Error!") + SPEAK("Critical error! Please contact a Thinktronic Systems \ + technician, as your warranty may be affected.") + mess = TRUE + maim_clone(mob_occupant) //Remove every bit that's grown back so far to drop later, also destroys bits that haven't grown yet + update_icon() + if(mob_occupant.mind != clonemind) + clonemind.transfer_to(mob_occupant) + mob_occupant.grab_ghost() // We really just want to make you suffer. + flash_color(mob_occupant, flash_color="#960000", flash_time=100) + to_chat(mob_occupant, "Agony blazes across your consciousness as your body is torn apart.
    Is this what dying is like? Yes it is.
    ") + playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0) + SEND_SOUND(mob_occupant, sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)) + QDEL_IN(mob_occupant, 40) + +/obj/machinery/clonepod/relaymove(mob/user) + container_resist(user) + +/obj/machinery/clonepod/container_resist(mob/living/user) + if(user.stat == CONSCIOUS) + go_out() + +/obj/machinery/clonepod/emp_act(severity) + . = ..() + if (!(. & EMP_PROTECT_SELF)) + var/mob/living/mob_occupant = occupant + if(mob_occupant && prob(100/(severity*efficiency))) + connected_message(Gibberish("EMP-caused Accidental Ejection", 0)) + SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0)) + mob_occupant.apply_vore_prefs() + go_out() + +/obj/machinery/clonepod/ex_act(severity, target) + ..() + if(!QDELETED(src)) + go_out() + +/obj/machinery/clonepod/handle_atom_del(atom/A) + if(A == occupant) + occupant = null + countdown.stop() + +/obj/machinery/clonepod/proc/horrifyingsound() + for(var/i in 1 to 5) + playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05)) + sleep(1) + sleep(10) + playsound(loc,'sound/hallucinations/wail.ogg',100,1) + +/obj/machinery/clonepod/deconstruct(disassembled = TRUE) + if(occupant) + go_out() + ..() + +/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H) + if(!unattached_flesh) + unattached_flesh = list() + else + for(var/fl in unattached_flesh) + qdel(fl) + unattached_flesh.Cut() + + H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health + //H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE) + // In addition to being cellularly damaged and having barely any + + // brain function, they also have no limbs or internal organs. + + if(!HAS_TRAIT(H, TRAIT_NODISMEMBER)) + var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + for(var/zone in zones) + var/obj/item/bodypart/BP = H.get_bodypart(zone) + if(BP) + BP.drop_limb() + BP.forceMove(src) + unattached_flesh += BP + + for(var/o in H.internal_organs) + var/obj/item/organ/organ = o + if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL)) + continue + organ.organ_flags |= ORGAN_FROZEN + organ.Remove(H, special=TRUE) + organ.forceMove(src) + unattached_flesh += organ + + flesh_number = unattached_flesh.len + +/obj/machinery/clonepod/update_icon() + cut_overlays() + + if(mess) + icon_state = "pod_g" + var/image/gib1 = image(CRYOMOBS, "gibup") + var/image/gib2 = image(CRYOMOBS, "gibdown") + gib1.pixel_y = 27 + round(sin(world.time) * 3) + gib1.pixel_x = round(sin(world.time * 3)) + gib2.pixel_y = 27 + round(cos(world.time) * 3) + gib2.pixel_x = round(cos(world.time * 3)) + add_overlay(gib2) + add_overlay(gib1) + add_overlay("cover-on") + + else if(occupant) + icon_state = "pod_1" + + var/image/occupant_overlay + var/completion = (flesh_number - unattached_flesh.len) / flesh_number + + if(unattached_flesh.len <= 0) + occupant_overlay = image(occupant.icon, occupant.icon_state) + occupant_overlay.copy_overlays(occupant) + else + occupant_overlay = image(CRYOMOBS, "clone_meat") + var/matrix/tform = matrix() + tform.Scale(completion) + tform.Turn(cos(world.time * 2) * 3) + occupant_overlay.transform = tform + occupant_overlay.appearance_flags = 0 + + occupant_overlay.dir = SOUTH + occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3) + occupant_overlay.pixel_x = round(sin(world.time * 3)) + + add_overlay(occupant_overlay) + add_overlay("cover-on") + else + icon_state = "pod_0" + + if(panel_open) + icon_state = "pod_0_maintenance" + + add_overlay("panel") + +/* + * Manual -- A big ol' manual. + */ + +/obj/item/paper/guides/jobs/medical/cloning + name = "paper - 'H-87 Cloning Apparatus Manual" + info = {"

    Getting Started

    + Congratulations, your station has purchased the H-87 industrial cloning device!
    + Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!
    + That's all there is to it!
    + Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.
    +

    Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile. + Profile Deletion has been restricted to \[Station Head\] level access.

    +

    Cloning from a profile

    + Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.
    + Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.
    +
    +

    The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds. + The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.


    + Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.
    +

    Profile Management

    +

    The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES. + These diskettes are used to transfer genetic information between machines and profiles. + A load/save dialog will become available in each profile if a disk is inserted.


    + A good diskette is a great way to counter aforementioned genetic drift!
    +
    + This technology produced under license from Thinktronic Systems, LTD."} + +#undef CLONE_INITIAL_DAMAGE +#undef SPEAK +#undef MINIMUM_HEAL_LEVEL diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 858a0a995b..3c021d0bd1 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -1,128 +1,128 @@ -#define MENU_OPERATION 1 -#define MENU_SURGERIES 2 - -/obj/machinery/computer/operating - name = "operating computer" - desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures." - icon_screen = "crew" - icon_keyboard = "med_key" - circuit = /obj/item/circuitboard/computer/operating - var/mob/living/carbon/human/patient - var/obj/structure/table/optable/table - var/list/advanced_surgeries = list() - var/datum/techweb/linked_techweb - var/menu = MENU_OPERATION - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/operating/Initialize() - . = ..() - linked_techweb = SSresearch.science_tech - find_table() - -/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/disk/surgery)) - user.visible_message("[user] begins to load \the [O] in \the [src]...", - "You begin to load a surgery protocol from \the [O]...", - "You hear the chatter of a floppy drive.") - var/obj/item/disk/surgery/D = O - if(do_after(user, 10, target = src)) - advanced_surgeries |= D.surgeries - return TRUE - return ..() - -/obj/machinery/computer/operating/proc/sync_surgeries() - for(var/i in linked_techweb.researched_designs) - var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i) - if(!istype(D)) - continue - advanced_surgeries |= D.surgery - -/obj/machinery/computer/operating/proc/find_table() - for(var/direction in GLOB.cardinals) - table = locate(/obj/structure/table/optable, get_step(src, direction)) - if(table) - table.computer = src - break - -/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state) - ui.open() - -/obj/machinery/computer/operating/ui_data(mob/user) - var/list/data = list() - data["table"] = table - if(table) - data["menu"] = menu - - var/list/surgeries = list() - for(var/X in advanced_surgeries) - var/datum/surgery/S = X - var/list/surgery = list() - surgery["name"] = initial(S.name) - surgery["desc"] = initial(S.desc) - surgeries += list(surgery) - data["surgeries"] = surgeries - - data["patient"] = list() - if(table.check_patient()) - patient = table.patient - switch(patient.stat) - if(CONSCIOUS) - data["patient"]["stat"] = "Conscious" - data["patient"]["statstate"] = "good" - if(SOFT_CRIT) - data["patient"]["stat"] = "Conscious" - data["patient"]["statstate"] = "average" - if(UNCONSCIOUS) - data["patient"]["stat"] = "Unconscious" - data["patient"]["statstate"] = "average" - if(DEAD) - data["patient"]["stat"] = "Dead" - data["patient"]["statstate"] = "bad" - data["patient"]["health"] = patient.health - data["patient"]["blood_type"] = patient.dna.blood_type - data["patient"]["maxHealth"] = patient.maxHealth - data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD - data["patient"]["bruteLoss"] = patient.getBruteLoss() - data["patient"]["fireLoss"] = patient.getFireLoss() - data["patient"]["toxLoss"] = patient.getToxLoss() - data["patient"]["oxyLoss"] = patient.getOxyLoss() - if(patient.surgeries.len) - data["procedures"] = list() - for(var/datum/surgery/procedure in patient.surgeries) - var/datum/surgery_step/surgery_step = procedure.get_surgery_step() - var/chems_needed = surgery_step.get_chem_list() - var/alternative_step - var/alt_chems_needed = "" - if(surgery_step.repeatable) - var/datum/surgery_step/next_step = procedure.get_surgery_next_step() - if(next_step) - alternative_step = capitalize(next_step.name) - alt_chems_needed = next_step.get_chem_list() - else - alternative_step = "Finish operation" - data["procedures"] += list(list( - "name" = capitalize(procedure.name), - "next_step" = capitalize(surgery_step.name), - "chems_needed" = chems_needed, - "alternative_step" = alternative_step, - "alt_chems_needed" = alt_chems_needed - )) - return data - -/obj/machinery/computer/operating/ui_act(action, params) - if(..()) - return - switch(action) - if("change_menu") - menu = text2num(params["menu"]) - . = TRUE - if("sync") - sync_surgeries() - . = TRUE - . = TRUE - -#undef MENU_OPERATION -#undef MENU_SURGERIES +#define MENU_OPERATION 1 +#define MENU_SURGERIES 2 + +/obj/machinery/computer/operating + name = "operating computer" + desc = "Monitors patient vitals and displays surgery steps. Can be loaded with surgery disks to perform experimental procedures." + icon_screen = "crew" + icon_keyboard = "med_key" + circuit = /obj/item/circuitboard/computer/operating + var/mob/living/carbon/human/patient + var/obj/structure/table/optable/table + var/list/advanced_surgeries = list() + var/datum/techweb/linked_techweb + var/menu = MENU_OPERATION + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/operating/Initialize() + . = ..() + linked_techweb = SSresearch.science_tech + find_table() + +/obj/machinery/computer/operating/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/disk/surgery)) + user.visible_message("[user] begins to load \the [O] in \the [src]...", + "You begin to load a surgery protocol from \the [O]...", + "You hear the chatter of a floppy drive.") + var/obj/item/disk/surgery/D = O + if(do_after(user, 10, target = src)) + advanced_surgeries |= D.surgeries + return TRUE + return ..() + +/obj/machinery/computer/operating/proc/sync_surgeries() + for(var/i in linked_techweb.researched_designs) + var/datum/design/surgery/D = SSresearch.techweb_design_by_id(i) + if(!istype(D)) + continue + advanced_surgeries |= D.surgery + +/obj/machinery/computer/operating/proc/find_table() + for(var/direction in GLOB.cardinals) + table = locate(/obj/structure/table/optable, get_step(src, direction)) + if(table) + table.computer = src + break + +/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state) + ui.open() + +/obj/machinery/computer/operating/ui_data(mob/user) + var/list/data = list() + data["table"] = table + if(table) + data["menu"] = menu + + var/list/surgeries = list() + for(var/X in advanced_surgeries) + var/datum/surgery/S = X + var/list/surgery = list() + surgery["name"] = initial(S.name) + surgery["desc"] = initial(S.desc) + surgeries += list(surgery) + data["surgeries"] = surgeries + + data["patient"] = list() + if(table.check_patient()) + patient = table.patient + switch(patient.stat) + if(CONSCIOUS) + data["patient"]["stat"] = "Conscious" + data["patient"]["statstate"] = "good" + if(SOFT_CRIT) + data["patient"]["stat"] = "Conscious" + data["patient"]["statstate"] = "average" + if(UNCONSCIOUS) + data["patient"]["stat"] = "Unconscious" + data["patient"]["statstate"] = "average" + if(DEAD) + data["patient"]["stat"] = "Dead" + data["patient"]["statstate"] = "bad" + data["patient"]["health"] = patient.health + data["patient"]["blood_type"] = patient.dna.blood_type + data["patient"]["maxHealth"] = patient.maxHealth + data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD + data["patient"]["bruteLoss"] = patient.getBruteLoss() + data["patient"]["fireLoss"] = patient.getFireLoss() + data["patient"]["toxLoss"] = patient.getToxLoss() + data["patient"]["oxyLoss"] = patient.getOxyLoss() + if(patient.surgeries.len) + data["procedures"] = list() + for(var/datum/surgery/procedure in patient.surgeries) + var/datum/surgery_step/surgery_step = procedure.get_surgery_step() + var/chems_needed = surgery_step.get_chem_list() + var/alternative_step + var/alt_chems_needed = "" + if(surgery_step.repeatable) + var/datum/surgery_step/next_step = procedure.get_surgery_next_step() + if(next_step) + alternative_step = capitalize(next_step.name) + alt_chems_needed = next_step.get_chem_list() + else + alternative_step = "Finish operation" + data["procedures"] += list(list( + "name" = capitalize(procedure.name), + "next_step" = capitalize(surgery_step.name), + "chems_needed" = chems_needed, + "alternative_step" = alternative_step, + "alt_chems_needed" = alt_chems_needed + )) + return data + +/obj/machinery/computer/operating/ui_act(action, params) + if(..()) + return + switch(action) + if("change_menu") + menu = text2num(params["menu"]) + . = TRUE + if("sync") + sync_surgeries() + . = TRUE + . = TRUE + +#undef MENU_OPERATION +#undef MENU_SURGERIES diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 5d6c92a97d..8bb0894cdb 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -1,150 +1,150 @@ -/obj/machinery/computer/aifixer - name = "\improper AI system integrity restorer" - desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order." - req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS) - var/mob/living/silicon/ai/occupier = null - var/active = 0 - circuit = /obj/item/circuitboard/computer/aifixer - icon_keyboard = "tech_key" - icon_screen = "ai-fixer" - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params) - if(occupier && istype(I, /obj/item/screwdriver)) - if(stat & (NOPOWER|BROKEN)) - to_chat(user, "The screws on [name]'s screen won't budge.") - else - to_chat(user, "The screws on [name]'s screen won't budge and it emits a warning beep.") - else - return ..() - -/obj/machinery/computer/aifixer/ui_interact(mob/user) - . = ..() - - var/dat = "" - - if (src.occupier) - var/laws - dat += "

    Stored AI: [src.occupier.name]

    " - dat += "System integrity: [(src.occupier.health+100)/2]%
    " - - if (src.occupier.laws.zeroth) - laws += "0: [src.occupier.laws.zeroth]
    " - - for (var/index = 1, index <= src.occupier.laws.hacked.len, index++) - var/law = src.occupier.laws.hacked[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]: [law]
    " - - for (var/index = 1, index <= src.occupier.laws.ion.len, index++) - var/law = src.occupier.laws.ion[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]: [law]
    " - - var/number = 1 - for (var/index = 1, index <= src.occupier.laws.inherent.len, index++) - var/law = src.occupier.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - for (var/index = 1, index <= src.occupier.laws.supplied.len, index++) - var/law = src.occupier.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - dat += "Laws:
    [laws]
    " - - if (src.occupier.stat == DEAD) - dat += "AI non-functional" - else - dat += "AI functional" - if (!src.active) - dat += {"

    Begin Reconstruction"} - else - dat += "

    Reconstruction in process, please wait.
    " - dat += {"
    Close"} - var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/machinery/computer/aifixer/proc/Fix() - use_power(1000) - occupier.adjustOxyLoss(-1, 0) - occupier.adjustFireLoss(-1, 0) - occupier.adjustToxLoss(-1, 0) - occupier.adjustBruteLoss(-1, 0) - occupier.updatehealth() - if(occupier.health >= 0 && occupier.stat == DEAD) - occupier.revive() - return occupier.health < 100 - -/obj/machinery/computer/aifixer/process() - if(..()) - if(active) - var/oldstat = occupier.stat - active = Fix() - if(oldstat != occupier.stat) - update_icon() - updateDialog() - -/obj/machinery/computer/aifixer/Topic(href, href_list) - if(..()) - return - if(href_list["fix"]) - to_chat(usr, "Reconstruction in progress. This will take several minutes.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) - active = TRUE - add_fingerprint(usr) - updateUsrDialog() - -/obj/machinery/computer/aifixer/update_icon() - ..() - if(stat & (NOPOWER|BROKEN)) - return - else - if(active) - add_overlay("ai-fixer-on") - if (occupier) - switch (occupier.stat) - if (0) - add_overlay("ai-fixer-full") - if (2) - add_overlay("ai-fixer-404") - else - add_overlay("ai-fixer-empty") - -/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card) - if(!..()) - return - //Downloading AI from card to terminal. - if(interaction == AI_TRANS_FROM_CARD) - if(stat & (NOPOWER|BROKEN)) - to_chat(user, "[src] is offline and cannot take an AI at this time!") - return - AI.forceMove(src) - occupier = AI - AI.control_disabled = 1 - AI.radio_enabled = 0 - to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.") - to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.") - card.AI = null - update_icon() - - else //Uploading AI from terminal to card - if(occupier && !active) - to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.") - to_chat(user, "Transfer successful: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.") - occupier.forceMove(card) - card.AI = occupier - occupier = null - update_icon() - else if (active) - to_chat(user, "ERROR: Reconstruction in progress.") - else if (!occupier) - to_chat(user, "ERROR: Unable to locate artificial intelligence.") +/obj/machinery/computer/aifixer + name = "\improper AI system integrity restorer" + desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order." + req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS) + var/mob/living/silicon/ai/occupier = null + var/active = 0 + circuit = /obj/item/circuitboard/computer/aifixer + icon_keyboard = "tech_key" + icon_screen = "ai-fixer" + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params) + if(occupier && istype(I, /obj/item/screwdriver)) + if(stat & (NOPOWER|BROKEN)) + to_chat(user, "The screws on [name]'s screen won't budge.") + else + to_chat(user, "The screws on [name]'s screen won't budge and it emits a warning beep.") + else + return ..() + +/obj/machinery/computer/aifixer/ui_interact(mob/user) + . = ..() + + var/dat = "" + + if (src.occupier) + var/laws + dat += "

    Stored AI: [src.occupier.name]

    " + dat += "System integrity: [(src.occupier.health+100)/2]%
    " + + if (src.occupier.laws.zeroth) + laws += "0: [src.occupier.laws.zeroth]
    " + + for (var/index = 1, index <= src.occupier.laws.hacked.len, index++) + var/law = src.occupier.laws.hacked[index] + if (length(law) > 0) + var/num = ionnum() + laws += "[num]: [law]
    " + + for (var/index = 1, index <= src.occupier.laws.ion.len, index++) + var/law = src.occupier.laws.ion[index] + if (length(law) > 0) + var/num = ionnum() + laws += "[num]: [law]
    " + + var/number = 1 + for (var/index = 1, index <= src.occupier.laws.inherent.len, index++) + var/law = src.occupier.laws.inherent[index] + if (length(law) > 0) + laws += "[number]: [law]
    " + number++ + + for (var/index = 1, index <= src.occupier.laws.supplied.len, index++) + var/law = src.occupier.laws.supplied[index] + if (length(law) > 0) + laws += "[number]: [law]
    " + number++ + + dat += "Laws:
    [laws]
    " + + if (src.occupier.stat == DEAD) + dat += "AI non-functional" + else + dat += "AI functional" + if (!src.active) + dat += {"

    Begin Reconstruction"} + else + dat += "

    Reconstruction in process, please wait.
    " + dat += {"
    Close"} + var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + return + +/obj/machinery/computer/aifixer/proc/Fix() + use_power(1000) + occupier.adjustOxyLoss(-1, 0) + occupier.adjustFireLoss(-1, 0) + occupier.adjustToxLoss(-1, 0) + occupier.adjustBruteLoss(-1, 0) + occupier.updatehealth() + if(occupier.health >= 0 && occupier.stat == DEAD) + occupier.revive() + return occupier.health < 100 + +/obj/machinery/computer/aifixer/process() + if(..()) + if(active) + var/oldstat = occupier.stat + active = Fix() + if(oldstat != occupier.stat) + update_icon() + updateDialog() + +/obj/machinery/computer/aifixer/Topic(href, href_list) + if(..()) + return + if(href_list["fix"]) + to_chat(usr, "Reconstruction in progress. This will take several minutes.") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) + active = TRUE + add_fingerprint(usr) + updateUsrDialog() + +/obj/machinery/computer/aifixer/update_icon() + ..() + if(stat & (NOPOWER|BROKEN)) + return + else + if(active) + add_overlay("ai-fixer-on") + if (occupier) + switch (occupier.stat) + if (0) + add_overlay("ai-fixer-full") + if (2) + add_overlay("ai-fixer-404") + else + add_overlay("ai-fixer-empty") + +/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card) + if(!..()) + return + //Downloading AI from card to terminal. + if(interaction == AI_TRANS_FROM_CARD) + if(stat & (NOPOWER|BROKEN)) + to_chat(user, "[src] is offline and cannot take an AI at this time!") + return + AI.forceMove(src) + occupier = AI + AI.control_disabled = 1 + AI.radio_enabled = 0 + to_chat(AI, "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here.") + to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.") + card.AI = null + update_icon() + + else //Uploading AI from terminal to card + if(occupier && !active) + to_chat(occupier, "You have been downloaded to a mobile storage device. Still no remote access.") + to_chat(user, "Transfer successful: [occupier.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory.") + occupier.forceMove(card) + card.AI = occupier + occupier = null + update_icon() + else if (active) + to_chat(user, "ERROR: Reconstruction in progress.") + else if (!occupier) + to_chat(user, "ERROR: Unable to locate artificial intelligence.") diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index cb3cbf2aa6..4c9e9aed19 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -1,100 +1,100 @@ -/obj/machinery/computer/atmos_alert - name = "atmospheric alert console" - desc = "Used to monitor the station's air alarms." - circuit = /obj/item/circuitboard/computer/atmos_alert - icon_screen = "alert:0" - icon_keyboard = "atmos_key" - var/list/priority_alarms = list() - var/list/minor_alarms = list() - var/receive_frequency = FREQ_ATMOS_ALARMS - var/datum/radio_frequency/radio_connection - - light_color = LIGHT_COLOR_CYAN - -/obj/machinery/computer/atmos_alert/Initialize() - . = ..() - set_frequency(receive_frequency) - -/obj/machinery/computer/atmos_alert/Destroy() - SSradio.remove_object(src, receive_frequency) - return ..() - -/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state) - ui.open() - -/obj/machinery/computer/atmos_alert/ui_data(mob/user) - var/list/data = list() - - data["priority"] = list() - for(var/zone in priority_alarms) - data["priority"] += zone - data["minor"] = list() - for(var/zone in minor_alarms) - data["minor"] += zone - - return data - -/obj/machinery/computer/atmos_alert/ui_act(action, params) - if(..()) - return - switch(action) - if("clear") - var/zone = params["zone"] - if(zone in priority_alarms) - to_chat(usr, "Priority alarm for [zone] cleared.") - priority_alarms -= zone - . = TRUE - if(zone in minor_alarms) - to_chat(usr, "Minor alarm for [zone] cleared.") - minor_alarms -= zone - . = TRUE - update_icon() - -/obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency) - SSradio.remove_object(src, receive_frequency) - receive_frequency = new_frequency - radio_connection = SSradio.add_object(src, receive_frequency, RADIO_ATMOSIA) - -/obj/machinery/computer/atmos_alert/receive_signal(datum/signal/signal) - if(!signal) - return - - var/zone = signal.data["zone"] - var/severity = signal.data["alert"] - - if(!zone || !severity) - return - - minor_alarms -= zone - priority_alarms -= zone - if(severity == "severe") - priority_alarms += zone - else if (severity == "minor") - minor_alarms += zone - update_icon() - return - -/obj/machinery/computer/atmos_alert/update_icon() - ..() - cut_overlays() - SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - var/overlay_state = icon_screen - if(stat & (NOPOWER|BROKEN)) - add_overlay("[icon_keyboard]_off") - return - add_overlay(icon_keyboard) - if(priority_alarms.len) - overlay_state = "alert:2" - add_overlay("alert:2") - else if(minor_alarms.len) - overlay_state = "alert:1" - add_overlay("alert:1") - else - overlay_state = "alert:0" - add_overlay("alert:0") - SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) - SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) +/obj/machinery/computer/atmos_alert + name = "atmospheric alert console" + desc = "Used to monitor the station's air alarms." + circuit = /obj/item/circuitboard/computer/atmos_alert + icon_screen = "alert:0" + icon_keyboard = "atmos_key" + var/list/priority_alarms = list() + var/list/minor_alarms = list() + var/receive_frequency = FREQ_ATMOS_ALARMS + var/datum/radio_frequency/radio_connection + + light_color = LIGHT_COLOR_CYAN + +/obj/machinery/computer/atmos_alert/Initialize() + . = ..() + set_frequency(receive_frequency) + +/obj/machinery/computer/atmos_alert/Destroy() + SSradio.remove_object(src, receive_frequency) + return ..() + +/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state) + ui.open() + +/obj/machinery/computer/atmos_alert/ui_data(mob/user) + var/list/data = list() + + data["priority"] = list() + for(var/zone in priority_alarms) + data["priority"] += zone + data["minor"] = list() + for(var/zone in minor_alarms) + data["minor"] += zone + + return data + +/obj/machinery/computer/atmos_alert/ui_act(action, params) + if(..()) + return + switch(action) + if("clear") + var/zone = params["zone"] + if(zone in priority_alarms) + to_chat(usr, "Priority alarm for [zone] cleared.") + priority_alarms -= zone + . = TRUE + if(zone in minor_alarms) + to_chat(usr, "Minor alarm for [zone] cleared.") + minor_alarms -= zone + . = TRUE + update_icon() + +/obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency) + SSradio.remove_object(src, receive_frequency) + receive_frequency = new_frequency + radio_connection = SSradio.add_object(src, receive_frequency, RADIO_ATMOSIA) + +/obj/machinery/computer/atmos_alert/receive_signal(datum/signal/signal) + if(!signal) + return + + var/zone = signal.data["zone"] + var/severity = signal.data["alert"] + + if(!zone || !severity) + return + + minor_alarms -= zone + priority_alarms -= zone + if(severity == "severe") + priority_alarms += zone + else if (severity == "minor") + minor_alarms += zone + update_icon() + return + +/obj/machinery/computer/atmos_alert/update_icon() + ..() + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + var/overlay_state = icon_screen + if(stat & (NOPOWER|BROKEN)) + add_overlay("[icon_keyboard]_off") + return + add_overlay(icon_keyboard) + if(priority_alarms.len) + overlay_state = "alert:2" + add_overlay("alert:2") + else if(minor_alarms.len) + overlay_state = "alert:1" + add_overlay("alert:1") + else + overlay_state = "alert:0" + add_overlay("alert:0") + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 6576f51e46..f9d2a3c103 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -1,305 +1,305 @@ -///////////////////////////////////////////////////////////// -// AIR SENSOR (found in gas tanks) -///////////////////////////////////////////////////////////// - -/obj/machinery/air_sensor - name = "gas sensor" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "gsensor1" - - var/on = TRUE - - var/id_tag - var/frequency = FREQ_ATMOS_STORAGE - var/datum/radio_frequency/radio_connection - -/obj/machinery/air_sensor/atmos/toxin_tank - name = "plasma tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_TOX -/obj/machinery/air_sensor/atmos/toxins_mixing_tank - name = "toxins mixing gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB -/obj/machinery/air_sensor/atmos/oxygen_tank - name = "oxygen tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_O2 -/obj/machinery/air_sensor/atmos/nitrogen_tank - name = "nitrogen tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_N2 -/obj/machinery/air_sensor/atmos/mix_tank - name = "mix tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX -/obj/machinery/air_sensor/atmos/nitrous_tank - name = "nitrous oxide tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O -/obj/machinery/air_sensor/atmos/air_tank - name = "air mix tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR -/obj/machinery/air_sensor/atmos/carbon_tank - name = "carbon dioxide tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2 -/obj/machinery/air_sensor/atmos/incinerator_tank - name = "incinerator chamber gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR - -/obj/machinery/air_sensor/update_icon() - icon_state = "gsensor[on]" - -/obj/machinery/air_sensor/process_atmos() - if(on) - var/datum/gas_mixture/air_sample = return_air() - - var/datum/signal/signal = new(list( - "sigtype" = "status", - "id_tag" = id_tag, - "timestamp" = world.time, - "pressure" = air_sample.return_pressure(), - "temperature" = air_sample.temperature, - "gases" = list() - )) - var/total_moles = air_sample.total_moles() - if(total_moles) - for(var/gas_id in air_sample.gases) - var/gas_name = GLOB.meta_gas_names[gas_id] - signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100 - - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - - -/obj/machinery/air_sensor/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) - -/obj/machinery/air_sensor/Initialize() - . = ..() - SSair.atmos_machinery += src - set_frequency(frequency) - -/obj/machinery/air_sensor/Destroy() - SSair.atmos_machinery -= src - SSradio.remove_object(src, frequency) - return ..() - -///////////////////////////////////////////////////////////// -// GENERAL AIR CONTROL (a.k.a atmos computer) -///////////////////////////////////////////////////////////// -GLOBAL_LIST_EMPTY(atmos_air_controllers) - -/obj/machinery/computer/atmos_control - name = "atmospherics monitoring" - desc = "Used to monitor the station's atmospherics sensors." - icon_screen = "tank" - icon_keyboard = "atmos_key" - circuit = /obj/item/circuitboard/computer/atmos_control - - var/frequency = FREQ_ATMOS_STORAGE - var/list/sensors = list( - ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank", - ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank", - ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank", - ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank", - ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank", - ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank", - ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank", - ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop", - ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop", - ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber", - ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber" - ) - var/list/sensor_information = list() - var/datum/radio_frequency/radio_connection - - light_color = LIGHT_COLOR_CYAN - -/obj/machinery/computer/atmos_control/Initialize() - . = ..() - GLOB.atmos_air_controllers += src - set_frequency(frequency) - -/obj/machinery/computer/atmos_control/Destroy() - GLOB.atmos_air_controllers -= src - SSradio.remove_object(src, frequency) - return ..() - -/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_control", name, 400, 925, master_ui, state) - ui.open() - -/obj/machinery/computer/atmos_control/ui_data(mob/user) - var/data = list() - - data["sensors"] = list() - for(var/id_tag in sensors) - var/long_name = sensors[id_tag] - var/list/info = sensor_information[id_tag] - if(!info) - continue - data["sensors"] += list(list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "pressure" = info["pressure"], - "temperature" = info["temperature"], - "gases" = info["gases"] - )) - return data - -/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal) - if(!signal) - return - - var/id_tag = signal.data["id_tag"] - if(!id_tag || !sensors.Find(id_tag)) - return - - sensor_information[id_tag] = signal.data - -/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) - -///////////////////////////////////////////////////////////// -// LARGE TANK CONTROL -///////////////////////////////////////////////////////////// - -/obj/machinery/computer/atmos_control/tank - var/input_tag - var/output_tag - frequency = FREQ_ATMOS_STORAGE - circuit = /obj/item/circuitboard/computer/atmos_control/tank - - var/list/input_info - var/list/output_info - -/obj/machinery/computer/atmos_control/tank/oxygen_tank - name = "Oxygen Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_O2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank") - -/obj/machinery/computer/atmos_control/tank/toxin_tank - name = "Plasma Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_TOX - output_tag = ATMOS_GAS_MONITOR_OUTPUT_TOX - sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank") - -/obj/machinery/computer/atmos_control/tank/air_tank - name = "Mixed Air Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_AIR - output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR - sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank") - -/obj/machinery/computer/atmos_control/tank/mix_tank - name = "Gas Mix Tank Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_MIX - output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX - sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank") - -/obj/machinery/computer/atmos_control/tank/nitrous_tank - name = "Nitrous Oxide Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_N2O - output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O - sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank") - -/obj/machinery/computer/atmos_control/tank/nitrogen_tank - name = "Nitrogen Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_N2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank") - -/obj/machinery/computer/atmos_control/tank/carbon_tank - name = "Carbon Dioxide Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_CO2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank") - -/obj/machinery/computer/atmos_control/tank/incinerator - name = "Incinerator Air Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_INCINERATOR - output_tag = ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR - sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber") - -// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this -/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) - var/list/IO = list() - var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE) - var/list/devices = freq.devices["_default"] - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) - var/list/text = splittext(U.id_tag, "_") - IO |= text[1] - for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) - var/list/text = splittext(U.id, "_") - IO |= text[1] - if(!IO.len) - to_chat(user, "No machinery detected.") - var/S = input("Select the device set: ", "Selection", IO[1]) as anything in IO - if(src) - src.input_tag = "[S]_in" - src.output_tag = "[S]_out" - name = "[uppertext(S)] Supply Control" - var/list/new_devices = freq.devices["4"] - for(var/obj/machinery/air_sensor/U in new_devices) - var/list/text = splittext(U.id_tag, "_") - if(text[1] == S) - sensors = list("[S]_sensor" = "Tank") - break - - for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) - U.broadcast_status() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) - U.broadcast_status() - -/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_control", name, 500, 305, master_ui, state) - ui.open() - -/obj/machinery/computer/atmos_control/tank/ui_data(mob/user) - var/list/data = ..() - data["tank"] = TRUE - data["inputting"] = input_info ? input_info["power"] : FALSE - data["inputRate"] = input_info ? input_info["volume_rate"] : 0 - data["outputting"] = output_info ? output_info["power"] : FALSE - data["outputPressure"] = output_info ? output_info["internal"] : 0 - - return data - -/obj/machinery/computer/atmos_control/tank/ui_act(action, params) - if(..() || !radio_connection) - return - var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr)) - switch(action) - if("reconnect") - reconnect(usr) - . = TRUE - if("input") - signal.data += list("tag" = input_tag, "power_toggle" = TRUE) - . = TRUE - if("output") - signal.data += list("tag" = output_tag, "power_toggle" = TRUE) - . = TRUE - if("pressure") - var/target = input("New target pressure:", name, output_info ? output_info["internal"] : 0) as num|null - if(!isnull(target) && !..()) - target = CLAMP(target, 0, 50 * ONE_ATMOSPHERE) - signal.data += list("tag" = output_tag, "set_internal_pressure" = target) - . = TRUE - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - -/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal) - if(!signal) - return - - var/id_tag = signal.data["tag"] - - if(input_tag == id_tag) - input_info = signal.data - else if(output_tag == id_tag) - output_info = signal.data - else - ..(signal) +///////////////////////////////////////////////////////////// +// AIR SENSOR (found in gas tanks) +///////////////////////////////////////////////////////////// + +/obj/machinery/air_sensor + name = "gas sensor" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "gsensor1" + + var/on = TRUE + + var/id_tag + var/frequency = FREQ_ATMOS_STORAGE + var/datum/radio_frequency/radio_connection + +/obj/machinery/air_sensor/atmos/toxin_tank + name = "plasma tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_TOX +/obj/machinery/air_sensor/atmos/toxins_mixing_tank + name = "toxins mixing gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB +/obj/machinery/air_sensor/atmos/oxygen_tank + name = "oxygen tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_O2 +/obj/machinery/air_sensor/atmos/nitrogen_tank + name = "nitrogen tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_N2 +/obj/machinery/air_sensor/atmos/mix_tank + name = "mix tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX +/obj/machinery/air_sensor/atmos/nitrous_tank + name = "nitrous oxide tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O +/obj/machinery/air_sensor/atmos/air_tank + name = "air mix tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR +/obj/machinery/air_sensor/atmos/carbon_tank + name = "carbon dioxide tank gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2 +/obj/machinery/air_sensor/atmos/incinerator_tank + name = "incinerator chamber gas sensor" + id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR + +/obj/machinery/air_sensor/update_icon() + icon_state = "gsensor[on]" + +/obj/machinery/air_sensor/process_atmos() + if(on) + var/datum/gas_mixture/air_sample = return_air() + + var/datum/signal/signal = new(list( + "sigtype" = "status", + "id_tag" = id_tag, + "timestamp" = world.time, + "pressure" = air_sample.return_pressure(), + "temperature" = air_sample.temperature, + "gases" = list() + )) + var/total_moles = air_sample.total_moles() + if(total_moles) + for(var/gas_id in air_sample.gases) + var/gas_name = GLOB.meta_gas_names[gas_id] + signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100 + + radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + + +/obj/machinery/air_sensor/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) + +/obj/machinery/air_sensor/Initialize() + . = ..() + SSair.atmos_machinery += src + set_frequency(frequency) + +/obj/machinery/air_sensor/Destroy() + SSair.atmos_machinery -= src + SSradio.remove_object(src, frequency) + return ..() + +///////////////////////////////////////////////////////////// +// GENERAL AIR CONTROL (a.k.a atmos computer) +///////////////////////////////////////////////////////////// +GLOBAL_LIST_EMPTY(atmos_air_controllers) + +/obj/machinery/computer/atmos_control + name = "atmospherics monitoring" + desc = "Used to monitor the station's atmospherics sensors." + icon_screen = "tank" + icon_keyboard = "atmos_key" + circuit = /obj/item/circuitboard/computer/atmos_control + + var/frequency = FREQ_ATMOS_STORAGE + var/list/sensors = list( + ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank", + ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank", + ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank", + ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank", + ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank", + ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank", + ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank", + ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop", + ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop", + ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber", + ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber" + ) + var/list/sensor_information = list() + var/datum/radio_frequency/radio_connection + + light_color = LIGHT_COLOR_CYAN + +/obj/machinery/computer/atmos_control/Initialize() + . = ..() + GLOB.atmos_air_controllers += src + set_frequency(frequency) + +/obj/machinery/computer/atmos_control/Destroy() + GLOB.atmos_air_controllers -= src + SSradio.remove_object(src, frequency) + return ..() + +/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "atmos_control", name, 400, 925, master_ui, state) + ui.open() + +/obj/machinery/computer/atmos_control/ui_data(mob/user) + var/data = list() + + data["sensors"] = list() + for(var/id_tag in sensors) + var/long_name = sensors[id_tag] + var/list/info = sensor_information[id_tag] + if(!info) + continue + data["sensors"] += list(list( + "id_tag" = id_tag, + "long_name" = sanitize(long_name), + "pressure" = info["pressure"], + "temperature" = info["temperature"], + "gases" = info["gases"] + )) + return data + +/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal) + if(!signal) + return + + var/id_tag = signal.data["id_tag"] + if(!id_tag || !sensors.Find(id_tag)) + return + + sensor_information[id_tag] = signal.data + +/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) + +///////////////////////////////////////////////////////////// +// LARGE TANK CONTROL +///////////////////////////////////////////////////////////// + +/obj/machinery/computer/atmos_control/tank + var/input_tag + var/output_tag + frequency = FREQ_ATMOS_STORAGE + circuit = /obj/item/circuitboard/computer/atmos_control/tank + + var/list/input_info + var/list/output_info + +/obj/machinery/computer/atmos_control/tank/oxygen_tank + name = "Oxygen Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_O2 + output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2 + sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank") + +/obj/machinery/computer/atmos_control/tank/toxin_tank + name = "Plasma Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_TOX + output_tag = ATMOS_GAS_MONITOR_OUTPUT_TOX + sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOX = "Plasma Tank") + +/obj/machinery/computer/atmos_control/tank/air_tank + name = "Mixed Air Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_AIR + output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR + sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank") + +/obj/machinery/computer/atmos_control/tank/mix_tank + name = "Gas Mix Tank Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_MIX + output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX + sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank") + +/obj/machinery/computer/atmos_control/tank/nitrous_tank + name = "Nitrous Oxide Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_N2O + output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O + sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank") + +/obj/machinery/computer/atmos_control/tank/nitrogen_tank + name = "Nitrogen Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_N2 + output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2 + sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank") + +/obj/machinery/computer/atmos_control/tank/carbon_tank + name = "Carbon Dioxide Supply Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_CO2 + output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2 + sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank") + +/obj/machinery/computer/atmos_control/tank/incinerator + name = "Incinerator Air Control" + input_tag = ATMOS_GAS_MONITOR_INPUT_INCINERATOR + output_tag = ATMOS_GAS_MONITOR_OUTPUT_INCINERATOR + sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber") + +// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this +/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) + var/list/IO = list() + var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE) + var/list/devices = freq.devices["_default"] + for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) + var/list/text = splittext(U.id_tag, "_") + IO |= text[1] + for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) + var/list/text = splittext(U.id, "_") + IO |= text[1] + if(!IO.len) + to_chat(user, "No machinery detected.") + var/S = input("Select the device set: ", "Selection", IO[1]) as anything in IO + if(src) + src.input_tag = "[S]_in" + src.output_tag = "[S]_out" + name = "[uppertext(S)] Supply Control" + var/list/new_devices = freq.devices["4"] + for(var/obj/machinery/air_sensor/U in new_devices) + var/list/text = splittext(U.id_tag, "_") + if(text[1] == S) + sensors = list("[S]_sensor" = "Tank") + break + + for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) + U.broadcast_status() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) + U.broadcast_status() + +/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "atmos_control", name, 500, 305, master_ui, state) + ui.open() + +/obj/machinery/computer/atmos_control/tank/ui_data(mob/user) + var/list/data = ..() + data["tank"] = TRUE + data["inputting"] = input_info ? input_info["power"] : FALSE + data["inputRate"] = input_info ? input_info["volume_rate"] : 0 + data["outputting"] = output_info ? output_info["power"] : FALSE + data["outputPressure"] = output_info ? output_info["internal"] : 0 + + return data + +/obj/machinery/computer/atmos_control/tank/ui_act(action, params) + if(..() || !radio_connection) + return + var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr)) + switch(action) + if("reconnect") + reconnect(usr) + . = TRUE + if("input") + signal.data += list("tag" = input_tag, "power_toggle" = TRUE) + . = TRUE + if("output") + signal.data += list("tag" = output_tag, "power_toggle" = TRUE) + . = TRUE + if("pressure") + var/target = input("New target pressure:", name, output_info ? output_info["internal"] : 0) as num|null + if(!isnull(target) && !..()) + target = CLAMP(target, 0, 50 * ONE_ATMOSPHERE) + signal.data += list("tag" = output_tag, "set_internal_pressure" = target) + . = TRUE + radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + +/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal) + if(!signal) + return + + var/id_tag = signal.data["tag"] + + if(input_tag == id_tag) + input_info = signal.data + else if(output_tag == id_tag) + output_info = signal.data + else + ..(signal) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index e8e15ff586..a21ebbeccf 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -1,145 +1,145 @@ -/obj/structure/frame/computer - name = "computer frame" - icon_state = "0" - state = 0 - -/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params) - add_fingerprint(user) - switch(state) - if(0) - if(istype(P, /obj/item/wrench)) - to_chat(user, "You start wrenching the frame into place...") - if(P.use_tool(src, user, 20, volume=50)) - to_chat(user, "You wrench the frame into place.") - setAnchored(TRUE) - state = 1 - return - if(istype(P, /obj/item/weldingtool)) - if(!P.tool_start_check(user, amount=0)) - return - - to_chat(user, "You start deconstructing the frame...") - if(P.use_tool(src, user, 20, volume=50) && state == 0) - to_chat(user, "You deconstruct the frame.") - var/obj/item/stack/sheet/metal/M = new (drop_location(), 5) - M.add_fingerprint(user) - qdel(src) - return - if(1) - if(istype(P, /obj/item/wrench)) - to_chat(user, "You start to unfasten the frame...") - if(P.use_tool(src, user, 20, volume=50) && state == 1) - to_chat(user, "You unfasten the frame.") - setAnchored(FALSE) - state = 0 - return - if(istype(P, /obj/item/circuitboard/computer) && !circuit) - if(!user.transferItemToLoc(P, src)) - return - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You place [P] inside the frame.") - icon_state = "1" - circuit = P - circuit.add_fingerprint(user) - return - - else if(istype(P, /obj/item/circuitboard) && !circuit) - to_chat(user, "This frame does not accept circuit boards of this type!") - return - if(istype(P, /obj/item/screwdriver) && circuit) - P.play_tool_sound(src) - to_chat(user, "You screw [circuit] into place.") - state = 2 - icon_state = "2" - return - if(istype(P, /obj/item/crowbar) && circuit) - P.play_tool_sound(src) - to_chat(user, "You remove [circuit].") - state = 1 - icon_state = "0" - circuit.forceMove(drop_location()) - circuit.add_fingerprint(user) - circuit = null - return - if(2) - if(istype(P, /obj/item/screwdriver) && circuit) - P.play_tool_sound(src) - to_chat(user, "You unfasten the circuit board.") - state = 1 - icon_state = "1" - return - if(istype(P, /obj/item/stack/cable_coil)) - if(!P.tool_start_check(user, amount=5)) - return - to_chat(user, "You start adding cables to the frame...") - if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2))) - to_chat(user, "You add cables to the frame.") - state = 3 - icon_state = "3" - return - if(3) - if(istype(P, /obj/item/wirecutters)) - P.play_tool_sound(src) - to_chat(user, "You remove the cables.") - state = 2 - icon_state = "2" - var/obj/item/stack/cable_coil/A = new (drop_location(), 5) - A.add_fingerprint(user) - return - - if(istype(P, /obj/item/stack/sheet/glass)) - if(!P.tool_start_check(user, amount=2)) - return - playsound(src, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You start to put in the glass panel...") - if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3))) - to_chat(user, "You put in the glass panel.") - state = 4 - src.icon_state = "4" - return - if(4) - if(istype(P, /obj/item/crowbar)) - P.play_tool_sound(src) - to_chat(user, "You remove the glass panel.") - state = 3 - icon_state = "3" - var/obj/item/stack/sheet/glass/G = new(drop_location(), 2) - G.add_fingerprint(user) - return - if(istype(P, /obj/item/screwdriver)) - P.play_tool_sound(src) - to_chat(user, "You connect the monitor.") - var/obj/B = new circuit.build_path (loc, circuit) - B.setDir(dir) - transfer_fingerprints_to(B) - qdel(src) - return - if(user.a_intent == INTENT_HARM) - return ..() - -//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking. -/obj/structure/frame/computer/proc/check_state(target_state) - if(state == target_state) - return TRUE - return FALSE - -/obj/structure/frame/computer/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(state == 4) - new /obj/item/shard(drop_location()) - new /obj/item/shard(drop_location()) - if(state >= 3) - new /obj/item/stack/cable_coil(drop_location(), 5) - ..() - -/obj/structure/frame/computer/AltClick(mob/user) - . = ..() - if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) - return - - if(anchored) - to_chat(usr, "You must unwrench [src] before rotating it!") - return TRUE - - setDir(turn(dir, -90)) - return TRUE +/obj/structure/frame/computer + name = "computer frame" + icon_state = "0" + state = 0 + +/obj/structure/frame/computer/attackby(obj/item/P, mob/user, params) + add_fingerprint(user) + switch(state) + if(0) + if(istype(P, /obj/item/wrench)) + to_chat(user, "You start wrenching the frame into place...") + if(P.use_tool(src, user, 20, volume=50)) + to_chat(user, "You wrench the frame into place.") + setAnchored(TRUE) + state = 1 + return + if(istype(P, /obj/item/weldingtool)) + if(!P.tool_start_check(user, amount=0)) + return + + to_chat(user, "You start deconstructing the frame...") + if(P.use_tool(src, user, 20, volume=50) && state == 0) + to_chat(user, "You deconstruct the frame.") + var/obj/item/stack/sheet/metal/M = new (drop_location(), 5) + M.add_fingerprint(user) + qdel(src) + return + if(1) + if(istype(P, /obj/item/wrench)) + to_chat(user, "You start to unfasten the frame...") + if(P.use_tool(src, user, 20, volume=50) && state == 1) + to_chat(user, "You unfasten the frame.") + setAnchored(FALSE) + state = 0 + return + if(istype(P, /obj/item/circuitboard/computer) && !circuit) + if(!user.transferItemToLoc(P, src)) + return + playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You place [P] inside the frame.") + icon_state = "1" + circuit = P + circuit.add_fingerprint(user) + return + + else if(istype(P, /obj/item/circuitboard) && !circuit) + to_chat(user, "This frame does not accept circuit boards of this type!") + return + if(istype(P, /obj/item/screwdriver) && circuit) + P.play_tool_sound(src) + to_chat(user, "You screw [circuit] into place.") + state = 2 + icon_state = "2" + return + if(istype(P, /obj/item/crowbar) && circuit) + P.play_tool_sound(src) + to_chat(user, "You remove [circuit].") + state = 1 + icon_state = "0" + circuit.forceMove(drop_location()) + circuit.add_fingerprint(user) + circuit = null + return + if(2) + if(istype(P, /obj/item/screwdriver) && circuit) + P.play_tool_sound(src) + to_chat(user, "You unfasten the circuit board.") + state = 1 + icon_state = "1" + return + if(istype(P, /obj/item/stack/cable_coil)) + if(!P.tool_start_check(user, amount=5)) + return + to_chat(user, "You start adding cables to the frame...") + if(P.use_tool(src, user, 20, 5, 50, CALLBACK(src, .proc/check_state, 2))) + to_chat(user, "You add cables to the frame.") + state = 3 + icon_state = "3" + return + if(3) + if(istype(P, /obj/item/wirecutters)) + P.play_tool_sound(src) + to_chat(user, "You remove the cables.") + state = 2 + icon_state = "2" + var/obj/item/stack/cable_coil/A = new (drop_location(), 5) + A.add_fingerprint(user) + return + + if(istype(P, /obj/item/stack/sheet/glass)) + if(!P.tool_start_check(user, amount=2)) + return + playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You start to put in the glass panel...") + if(P.use_tool(src, user, 20, 2, 0, CALLBACK(src, .proc/check_state, 3))) + to_chat(user, "You put in the glass panel.") + state = 4 + src.icon_state = "4" + return + if(4) + if(istype(P, /obj/item/crowbar)) + P.play_tool_sound(src) + to_chat(user, "You remove the glass panel.") + state = 3 + icon_state = "3" + var/obj/item/stack/sheet/glass/G = new(drop_location(), 2) + G.add_fingerprint(user) + return + if(istype(P, /obj/item/screwdriver)) + P.play_tool_sound(src) + to_chat(user, "You connect the monitor.") + var/obj/B = new circuit.build_path (loc, circuit) + B.setDir(dir) + transfer_fingerprints_to(B) + qdel(src) + return + if(user.a_intent == INTENT_HARM) + return ..() + +//callback proc used on stacks use_tool to stop unnecessary amounts being wasted from spam clicking. +/obj/structure/frame/computer/proc/check_state(target_state) + if(state == target_state) + return TRUE + return FALSE + +/obj/structure/frame/computer/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(state == 4) + new /obj/item/shard(drop_location()) + new /obj/item/shard(drop_location()) + if(state >= 3) + new /obj/item/stack/cable_coil(drop_location(), 5) + ..() + +/obj/structure/frame/computer/AltClick(mob/user) + . = ..() + if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + + if(anchored) + to_chat(usr, "You must unwrench [src] before rotating it!") + return TRUE + + setDir(turn(dir, -90)) + return TRUE diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1bafa73aaa..1d54e8f772 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -1,254 +1,254 @@ -/obj/machinery/computer/security - name = "security camera console" - desc = "Used to access the various cameras on the station." - icon_screen = "cameras" - icon_keyboard = "security_key" - circuit = /obj/item/circuitboard/computer/security - var/last_pic = 1 - var/list/network = list("ss13") - var/list/watchers = list() //who's using the console, associated with the camera they're on. - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/security/Initialize() - . = ..() - for(var/i in network) - network -= i - network += lowertext(i) - -/obj/machinery/computer/security/check_eye(mob/user) - if(!can_interact(user) || !(user in watchers) || !watchers[user]) - user.unset_machine() - return - var/obj/machinery/camera/C = watchers[user] - if(!C.can_use()) - user.unset_machine() - return - -/obj/machinery/computer/security/on_unset_machine(mob/user) - watchers.Remove(user) - user.reset_perspective(null) - -/obj/machinery/computer/security/Destroy() - if(watchers.len) - for(var/mob/M in watchers) - M.unset_machine() //to properly reset the view of the users if the console is deleted. - return ..() - -/obj/machinery/computer/security/can_interact(mob/user) - if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src)) - return FALSE - return ..() - -/obj/machinery/computer/security/interact(mob/user, special_state) - . = ..() - if (ismob(user) && !isliving(user)) // ghosts don't need cameras - return - if (!network) - CRASH("No camera network") - user.unset_machine() - return FALSE - if (!(islist(network))) - CRASH("Camera network is not a list") - user.unset_machine() - return FALSE - - var/list/camera_list = get_available_cameras() - if(!(user in watchers)) - for(var/Num in camera_list) - var/obj/machinery/camera/CAM = camera_list[Num] - if(istype(CAM) && CAM.can_use()) - watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants. - break - if(!(user in watchers)) - user.unset_machine() // no usable camera on the network, we disconnect the user from the computer. - return FALSE - playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0) - use_camera_console(user) - -/obj/machinery/computer/security/proc/use_camera_console(mob/user) - var/list/camera_list = get_available_cameras() - var/t = input(user, "Which camera should you change to?") as null|anything in camera_list - if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine. - return - if(!t || t == "Cancel") - user.unset_machine() - playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) - return - - var/obj/machinery/camera/C = camera_list[t] - - if(!C || !C.can_use() || !can_interact(user)) - user.unset_machine() - return FALSE - - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) - if(isAI(user)) - var/mob/living/silicon/ai/A = user - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - else - user.reset_perspective(C) - user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static) - user.clear_fullscreen("flash", 5) - watchers[user] = C - use_power(50) - addtimer(CALLBACK(src, .proc/use_camera_console, user), 5) - -//returns the list of cameras accessible from this computer -/obj/machinery/computer/security/proc/get_available_cameras() - var/list/L = list() - for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) - if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras - continue - L.Add(C) - - camera_sort(L) - - var/list/D = list() - D["Cancel"] = "Cancel" - for(var/obj/machinery/camera/C in L) - if(!C.network) - stack_trace("Camera in a cameranet has no camera network") - continue - if(!(islist(C.network))) - stack_trace("Camera in a cameranet has a non-list camera network") - continue - var/list/tempnetwork = C.network&network - if(tempnetwork.len) - D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C - return D - -// SECURITY MONITORS - -/obj/machinery/computer/security/wooden_tv - name = "security camera monitor" - desc = "An old TV hooked into the station's camera network." - icon_state = "television" - icon_keyboard = null - icon_screen = "detective_tv" - clockwork = TRUE //it'd look weird - pass_flags = PASSTABLE - -/obj/machinery/computer/security/mining - name = "outpost camera console" - desc = "Used to access the various cameras on the outpost." - icon_screen = "mining" - icon_keyboard = "mining_key" - network = list("mine", "auxbase") - circuit = /obj/item/circuitboard/computer/mining - -/obj/machinery/computer/security/research - name = "research camera console" - desc = "Used to access the various cameras in science." - network = list("rd") - circuit = /obj/item/circuitboard/computer/research - -/obj/machinery/computer/security/hos - name = "Head of Security's camera console" - desc = "A custom security console with added access to the labor camp network." - network = list("ss13", "labor") - circuit = null - -/obj/machinery/computer/security/labor - name = "labor camp monitoring" - desc = "Used to access the various cameras on the labor camp." - network = list("labor") - circuit = null - -/obj/machinery/computer/security/qm - name = "Quartermaster's camera console" - desc = "A console with access to the mining, auxillary base and vault camera networks." - network = list("mine", "auxbase", "vault") - circuit = null - -// TELESCREENS - -/obj/machinery/computer/security/telescreen - name = "\improper Telescreen" - desc = "Used for watching an empty arena." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "telescreen" - network = list("thunder") - density = FALSE - circuit = null - clockwork = TRUE //it'd look very weird - light_power = 0 - -/obj/machinery/computer/security/telescreen/update_icon() - icon_state = initial(icon_state) - if(stat & BROKEN) - icon_state += "b" - return - -/obj/machinery/computer/security/telescreen/entertainment - name = "entertainment monitor" - desc = "Damn, they better have the /tg/ channel on these things." - icon = 'icons/obj/status_display.dmi' - icon_state = "entertainment" - network = list("thunder") - -/obj/machinery/computer/security/telescreen/rd - name = "Research Director's telescreen" - desc = "Used for watching the AI and the RD's goons from the safety of his office." - network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test") - -/obj/machinery/computer/security/telescreen/circuitry - name = "circuitry telescreen" - desc = "Used for watching the other eggheads from the safety of the circuitry lab." - network = list("rd") - -/obj/machinery/computer/security/telescreen/ce - name = "Chief Engineer's telescreen" - desc = "Used for watching the engine, telecommunications and the minisat." - network = list("engine", "singularity", "tcomms", "minisat") - -/obj/machinery/computer/security/telescreen/cmo - name = "Chief Medical Officer's telescreen" - desc = "A telescreen with access to the medbay's camera network." - network = list("medbay") - -/obj/machinery/computer/security/telescreen/vault - name = "Vault monitor" - desc = "A telescreen that connects to the vault's camera network." - network = list("vault") - -/obj/machinery/computer/security/telescreen/toxins - name = "Bomb test site monitor" - desc = "A telescreen that connects to the bomb test site's camera." - network = list("toxin") - -/obj/machinery/computer/security/telescreen/engine - name = "engine monitor" - desc = "A telescreen that connects to the engine's camera network." - network = list("engine") - -/obj/machinery/computer/security/telescreen/turbine - name = "turbine monitor" - desc = "A telescreen that connects to the turbine's camera." - network = list("turbine") - -/obj/machinery/computer/security/telescreen/interrogation - name = "interrogation room monitor" - desc = "A telescreen that connects to the interrogation room's camera." - network = list("interrogation") - -/obj/machinery/computer/security/telescreen/prison - name = "prison monitor" - desc = "A telescreen that connects to the permabrig's camera network." - network = list("prison") - -/obj/machinery/computer/security/telescreen/auxbase - name = "auxillary base monitor" - desc = "A telescreen that connects to the auxillary base's camera." - network = list("auxbase") - -/obj/machinery/computer/security/telescreen/minisat - name = "minisat monitor" - desc = "A telescreen that connects to the minisat's camera network." - network = list("minisat") - -/obj/machinery/computer/security/telescreen/aiupload - name = "AI upload monitor" - desc = "A telescreen that connects to the AI upload's camera network." - network = list("aiupload") +/obj/machinery/computer/security + name = "security camera console" + desc = "Used to access the various cameras on the station." + icon_screen = "cameras" + icon_keyboard = "security_key" + circuit = /obj/item/circuitboard/computer/security + var/last_pic = 1 + var/list/network = list("ss13") + var/list/watchers = list() //who's using the console, associated with the camera they're on. + + light_color = LIGHT_COLOR_RED + +/obj/machinery/computer/security/Initialize() + . = ..() + for(var/i in network) + network -= i + network += lowertext(i) + +/obj/machinery/computer/security/check_eye(mob/user) + if(!can_interact(user) || !(user in watchers) || !watchers[user]) + user.unset_machine() + return + var/obj/machinery/camera/C = watchers[user] + if(!C.can_use()) + user.unset_machine() + return + +/obj/machinery/computer/security/on_unset_machine(mob/user) + watchers.Remove(user) + user.reset_perspective(null) + +/obj/machinery/computer/security/Destroy() + if(watchers.len) + for(var/mob/M in watchers) + M.unset_machine() //to properly reset the view of the users if the console is deleted. + return ..() + +/obj/machinery/computer/security/can_interact(mob/user) + if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src)) + return FALSE + return ..() + +/obj/machinery/computer/security/interact(mob/user, special_state) + . = ..() + if (ismob(user) && !isliving(user)) // ghosts don't need cameras + return + if (!network) + CRASH("No camera network") + user.unset_machine() + return FALSE + if (!(islist(network))) + CRASH("Camera network is not a list") + user.unset_machine() + return FALSE + + var/list/camera_list = get_available_cameras() + if(!(user in watchers)) + for(var/Num in camera_list) + var/obj/machinery/camera/CAM = camera_list[Num] + if(istype(CAM) && CAM.can_use()) + watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants. + break + if(!(user in watchers)) + user.unset_machine() // no usable camera on the network, we disconnect the user from the computer. + return FALSE + playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0) + use_camera_console(user) + +/obj/machinery/computer/security/proc/use_camera_console(mob/user) + var/list/camera_list = get_available_cameras() + var/t = input(user, "Which camera should you change to?") as null|anything in camera_list + if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine. + return + if(!t || t == "Cancel") + user.unset_machine() + playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) + return + + var/obj/machinery/camera/C = camera_list[t] + + if(!C || !C.can_use() || !can_interact(user)) + user.unset_machine() + return FALSE + + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) + if(isAI(user)) + var/mob/living/silicon/ai/A = user + A.eyeobj.setLoc(get_turf(C)) + A.client.eye = A.eyeobj + else + user.reset_perspective(C) + user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static) + user.clear_fullscreen("flash", 5) + watchers[user] = C + use_power(50) + addtimer(CALLBACK(src, .proc/use_camera_console, user), 5) + +//returns the list of cameras accessible from this computer +/obj/machinery/computer/security/proc/get_available_cameras() + var/list/L = list() + for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) + if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras + continue + L.Add(C) + + camera_sort(L) + + var/list/D = list() + D["Cancel"] = "Cancel" + for(var/obj/machinery/camera/C in L) + if(!C.network) + stack_trace("Camera in a cameranet has no camera network") + continue + if(!(islist(C.network))) + stack_trace("Camera in a cameranet has a non-list camera network") + continue + var/list/tempnetwork = C.network&network + if(tempnetwork.len) + D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C + return D + +// SECURITY MONITORS + +/obj/machinery/computer/security/wooden_tv + name = "security camera monitor" + desc = "An old TV hooked into the station's camera network." + icon_state = "television" + icon_keyboard = null + icon_screen = "detective_tv" + clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE + +/obj/machinery/computer/security/mining + name = "outpost camera console" + desc = "Used to access the various cameras on the outpost." + icon_screen = "mining" + icon_keyboard = "mining_key" + network = list("mine", "auxbase") + circuit = /obj/item/circuitboard/computer/mining + +/obj/machinery/computer/security/research + name = "research camera console" + desc = "Used to access the various cameras in science." + network = list("rd") + circuit = /obj/item/circuitboard/computer/research + +/obj/machinery/computer/security/hos + name = "Head of Security's camera console" + desc = "A custom security console with added access to the labor camp network." + network = list("ss13", "labor") + circuit = null + +/obj/machinery/computer/security/labor + name = "labor camp monitoring" + desc = "Used to access the various cameras on the labor camp." + network = list("labor") + circuit = null + +/obj/machinery/computer/security/qm + name = "Quartermaster's camera console" + desc = "A console with access to the mining, auxillary base and vault camera networks." + network = list("mine", "auxbase", "vault") + circuit = null + +// TELESCREENS + +/obj/machinery/computer/security/telescreen + name = "\improper Telescreen" + desc = "Used for watching an empty arena." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "telescreen" + network = list("thunder") + density = FALSE + circuit = null + clockwork = TRUE //it'd look very weird + light_power = 0 + +/obj/machinery/computer/security/telescreen/update_icon() + icon_state = initial(icon_state) + if(stat & BROKEN) + icon_state += "b" + return + +/obj/machinery/computer/security/telescreen/entertainment + name = "entertainment monitor" + desc = "Damn, they better have the /tg/ channel on these things." + icon = 'icons/obj/status_display.dmi' + icon_state = "entertainment" + network = list("thunder") + +/obj/machinery/computer/security/telescreen/rd + name = "Research Director's telescreen" + desc = "Used for watching the AI and the RD's goons from the safety of his office." + network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test") + +/obj/machinery/computer/security/telescreen/circuitry + name = "circuitry telescreen" + desc = "Used for watching the other eggheads from the safety of the circuitry lab." + network = list("rd") + +/obj/machinery/computer/security/telescreen/ce + name = "Chief Engineer's telescreen" + desc = "Used for watching the engine, telecommunications and the minisat." + network = list("engine", "singularity", "tcomms", "minisat") + +/obj/machinery/computer/security/telescreen/cmo + name = "Chief Medical Officer's telescreen" + desc = "A telescreen with access to the medbay's camera network." + network = list("medbay") + +/obj/machinery/computer/security/telescreen/vault + name = "Vault monitor" + desc = "A telescreen that connects to the vault's camera network." + network = list("vault") + +/obj/machinery/computer/security/telescreen/toxins + name = "Bomb test site monitor" + desc = "A telescreen that connects to the bomb test site's camera." + network = list("toxin") + +/obj/machinery/computer/security/telescreen/engine + name = "engine monitor" + desc = "A telescreen that connects to the engine's camera network." + network = list("engine") + +/obj/machinery/computer/security/telescreen/turbine + name = "turbine monitor" + desc = "A telescreen that connects to the turbine's camera." + network = list("turbine") + +/obj/machinery/computer/security/telescreen/interrogation + name = "interrogation room monitor" + desc = "A telescreen that connects to the interrogation room's camera." + network = list("interrogation") + +/obj/machinery/computer/security/telescreen/prison + name = "prison monitor" + desc = "A telescreen that connects to the permabrig's camera network." + network = list("prison") + +/obj/machinery/computer/security/telescreen/auxbase + name = "auxillary base monitor" + desc = "A telescreen that connects to the auxillary base's camera." + network = list("auxbase") + +/obj/machinery/computer/security/telescreen/minisat + name = "minisat monitor" + desc = "A telescreen that connects to the minisat's camera network." + network = list("minisat") + +/obj/machinery/computer/security/telescreen/aiupload + name = "AI upload monitor" + desc = "A telescreen that connects to the AI upload's camera network." + network = list("aiupload") diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 3bdb635d39..6703bae525 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -1,630 +1,630 @@ - - -//Keeps track of the time for the ID console. Having it as a global variable prevents people from dismantling/reassembling it to -//increase the slots of many jobs. -GLOBAL_VAR_INIT(time_last_changed_position, 0) - -#define JOB_ALLOWED 1 -#define JOB_COOLDOWN -2 -#define JOB_MAX_POSITIONS -1 // Trying to reduce the number of slots below that of current holders of that job, or trying to open more slots than allowed -#define JOB_DENIED 0 - -/obj/machinery/computer/card - name = "identification console" - desc = "You can use this to manage jobs and ID access." - icon_screen = "id" - icon_keyboard = "id_key" - req_one_access = list(ACCESS_HEADS, ACCESS_CHANGE_IDS) - circuit = /obj/item/circuitboard/computer/card - var/mode = 0 - var/printing = null - var/target_dept = 0 //Which department this computer has access to. 0=all departments - - //Cooldown for closing positions in seconds - //if set to -1: No cooldown... probably a bad idea - //if set to 0: Not able to close "original" positions. You can only close positions that you have opened before - var/change_position_cooldown = 30 - //Jobs you cannot open new positions for - var/list/blacklisted = list( - "AI", - "Assistant", - "Cyborg", - "Captain", - "Head of Personnel", - "Head of Security", - "Chief Engineer", - "Research Director", - "Chief Medical Officer", - "Quartermaster") - - //The scaling factor of max total positions in relation to the total amount of people on board the station in % - var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players - - //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/obj/item/card/id/inserted_scan_id - var/obj/item/card/id/inserted_modify_id - var/list/region_access = null - var/list/head_subordinates = null - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/card/proc/get_jobs() - return get_all_jobs() - -/obj/machinery/computer/card/centcom/get_jobs() - return get_all_centcom_jobs() - -/obj/machinery/computer/card/Initialize() - . = ..() - change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) - -/obj/machinery/computer/card/examine(mob/user) - . = ..() - if(inserted_scan_id || inserted_modify_id) - . += "Alt-click to eject the ID card." - -/obj/machinery/computer/card/attackby(obj/I, mob/user, params) - if(isidcard(I)) - if(check_access(I) && !inserted_scan_id) - if(id_insert(user, I, inserted_scan_id)) - inserted_scan_id = I - updateUsrDialog() - else if(id_insert(user, I, inserted_modify_id)) - inserted_modify_id = I - updateUsrDialog() - else - return ..() - -/obj/machinery/computer/card/Destroy() - if(inserted_scan_id) - qdel(inserted_scan_id) - inserted_scan_id = null - if(inserted_modify_id) - qdel(inserted_modify_id) - inserted_modify_id = null - return ..() - -/obj/machinery/computer/card/handle_atom_del(atom/A) - ..() - if(A == inserted_scan_id) - inserted_scan_id = null - updateUsrDialog() - if(A == inserted_modify_id) - inserted_modify_id = null - updateUsrDialog() - -/obj/machinery/computer/card/on_deconstruction() - if(inserted_scan_id) - inserted_scan_id.forceMove(drop_location()) - inserted_scan_id = null - if(inserted_modify_id) - inserted_modify_id.forceMove(drop_location()) - inserted_modify_id = null - -//Check if you can't open a new position for a certain job -/obj/machinery/computer/card/proc/job_blacklisted(jobtitle) - return (jobtitle in blacklisted) - -//Logic check for Topic() if you can open the job -/obj/machinery/computer/card/proc/can_open_job(datum/job/job) - if(job) - if(!job_blacklisted(job.title)) - if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) - var/delta = (world.time / 10) - GLOB.time_last_changed_position - if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) - return JOB_ALLOWED - return JOB_COOLDOWN - return JOB_MAX_POSITIONS - return JOB_DENIED - -//Logic check for Topic() if you can close the job -/obj/machinery/computer/card/proc/can_close_job(datum/job/job) - if(job) - if(!job_blacklisted(job.title)) - if(job.total_positions > job.current_positions) - var/delta = (world.time / 10) - GLOB.time_last_changed_position - if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) - return JOB_ALLOWED - return JOB_COOLDOWN - return JOB_MAX_POSITIONS - return JOB_DENIED - - -/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/inserting_item, obj/item/target) - var/obj/item/card/id/card_to_insert = inserting_item - var/holder_item = FALSE - - if(!isidcard(card_to_insert)) - card_to_insert = inserting_item.RemoveID() - holder_item = TRUE - - if(!card_to_insert || !user.transferItemToLoc(card_to_insert, src)) - return FALSE - - if(target) - if(holder_item && inserting_item.InsertID(target)) - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - else - id_eject(user, target) - - user.visible_message("[user] inserts \the [card_to_insert] into \the [src].", - "You insert \the [card_to_insert] into \the [src].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - return TRUE - -/obj/machinery/computer/card/proc/id_eject(mob/user, obj/target) - if(!target) - to_chat(user, "That slot is empty!") - return FALSE - else - target.forceMove(drop_location()) - if(!issilicon(user) && Adjacent(user)) - user.put_in_hands(target) - user.visible_message("[user] gets \the [target] from \the [src].", \ - "You get \the [target] from \the [src].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - updateUsrDialog() - return TRUE - -/obj/machinery/computer/card/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) - return - if(inserted_modify_id) - if(id_eject(user, inserted_modify_id)) - inserted_modify_id = null - updateUsrDialog() - return TRUE - if(inserted_scan_id) - if(id_eject(user, inserted_scan_id)) - inserted_scan_id = null - updateUsrDialog() - return TRUE - -/obj/machinery/computer/card/ui_interact(mob/user) - . = ..() - var/list/dat = list() - if (mode == 1) // accessing crew manifest - dat += "Crew Manifest:
    Please use security record computer to modify entries.

    " - for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) - dat += {"[t.fields["name"]] - [t.fields["rank"]]
    "} - dat += "Print

    Access ID modification console.
    " - - else if(mode == 2) - // JOB MANAGEMENT - dat += {"Return - - "} - for(var/datum/job/job in SSjob.occupations) - dat += "" - if(job.title in blacklisted) - continue - dat += {" - - " - dat += "
    JobSlotsOpen jobClose jobPrioritize
    [job.title][job.current_positions]/[job.total_positions]"} - switch(can_open_job(job)) - if(JOB_ALLOWED) - if(authenticated == 2) - dat += "Open Position
    " - else - dat += "Open Position" - if(JOB_COOLDOWN) - var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) - var/mins = round(time_to_wait / 60) - var/seconds = time_to_wait - (60*mins) - dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" - else - dat += "Denied" - dat += "
    " - switch(can_close_job(job)) - if(JOB_ALLOWED) - if(authenticated == 2) - dat += "Close Position" - else - dat += "Close Position" - if(JOB_COOLDOWN) - var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) - var/mins = round(time_to_wait / 60) - var/seconds = time_to_wait - (60*mins) - dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" - else - dat += "Denied" - dat += "" - switch(job.total_positions) - if(0) - dat += "Denied" - else - if(authenticated == 2) - if(job in SSjob.prioritized_jobs) - dat += "Deprioritize" - else - if(SSjob.prioritized_jobs.len < 5) - dat += "Prioritize" - else - dat += "Denied" - else - dat += "Prioritize" - - dat += "
    " - else - var/list/header = list() - - var/scan_name = inserted_scan_id ? html_encode(inserted_scan_id.name) : "--------" - var/target_name = inserted_modify_id ? html_encode(inserted_modify_id.name) : "--------" - var/target_owner = (inserted_modify_id && inserted_modify_id.registered_name) ? html_encode(inserted_modify_id.registered_name) : "--------" - var/target_rank = (inserted_modify_id && inserted_modify_id.assignment) ? html_encode(inserted_modify_id.assignment) : "Unassigned" - - if(!authenticated) - header += {"
    Please insert the cards into the slots
    - Target: [target_name]
    - Confirm Identity: [scan_name]
    "} - else - header += {"

    - Target: Remove [target_name] || - Confirm Identity: Remove [scan_name]
    - Access Crew Manifest
    - [!target_dept ? "Job Management
    " : ""] - Log Out
    "} - - header += "
    " - - var/body - - if (authenticated && inserted_modify_id) - var/list/carddesc = list() - var/list/jobs = list() - if (authenticated == 2) - var/list/jobs_all = list() - for(var/job in (list("Unassigned") + get_jobs() + "Custom")) - jobs_all += "[replacetext(job, " ", " ")] " //make sure there isn't a line break in the middle of a job - carddesc += {""} - carddesc += {"
    - - - registered name: - -
    - Assignment: "} - - jobs += "[target_rank]" //CHECK THIS - - else - carddesc += "registered_name: [target_owner]
    " - jobs += "Assignment: [target_rank] (Demote)
    " - - var/list/accesses = list() - if(istype(src, /obj/machinery/computer/card/centcom)) // REE - accesses += "
    Central Command:
    " - for(var/A in get_all_centcom_access()) - if(A in inserted_modify_id.access) - accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " - else - accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " - else - accesses += {"
    Access
    - - "} - for(var/i = 1; i <= 7; i++) - if(authenticated == 1 && !(i in region_access)) - continue - accesses += "" - accesses += "" - for(var/i = 1; i <= 7; i++) - if(authenticated == 1 && !(i in region_access)) - continue - accesses += "" - accesses += "
    [get_region_accesses_name(i)]:
    " - for(var/A in get_region_accesses(i)) - if(A in inserted_modify_id.access) - accesses += "[replacetext(get_access_desc(A), " ", " ")] " - else - accesses += "[replacetext(get_access_desc(A), " ", " ")] " - accesses += "
    " - accesses += "
    " - body = "[carddesc.Join()]
    [jobs.Join()]

    [accesses.Join()]
    " //CHECK THIS - - else if (!authenticated) - body = {"Log In

    - Access Crew Manifest

    "} - if(!target_dept) - body += "Job Management
    " - - dat = list("", header.Join(), body, "
    ") - var/datum/browser/popup = new(user, "id_com", src.name, 900, 620) - popup.set_content(dat.Join()) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/card/Topic(href, href_list) - if(..()) - return - - if(!usr.canUseTopic(src, !issilicon(usr)) || !is_operational()) - usr.unset_machine() - usr << browse(null, "window=id_com") - return - - usr.set_machine(src) - switch(href_list["choice"]) - if ("inserted_modify_id") - if(inserted_modify_id && !usr.get_active_held_item()) - if(id_eject(usr, inserted_modify_id)) - inserted_modify_id = null - updateUsrDialog() - return - if(usr.get_id_in_hand()) - var/obj/item/held_item = usr.get_active_held_item() - var/obj/item/card/id/id_to_insert = held_item.GetID() - if(id_insert(usr, held_item, inserted_modify_id)) - inserted_modify_id = id_to_insert - updateUsrDialog() - if ("inserted_scan_id") - if(inserted_scan_id && !usr.get_active_held_item()) - if(id_eject(usr, inserted_scan_id)) - inserted_scan_id = null - updateUsrDialog() - return - if(usr.get_id_in_hand()) - var/obj/item/held_item = usr.get_active_held_item() - var/obj/item/card/id/id_to_insert = held_item.GetID() - if(id_insert(usr, held_item, inserted_scan_id)) - inserted_scan_id = id_to_insert - updateUsrDialog() - if ("auth") - if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode)) - if (check_access(inserted_scan_id)) - region_access = list() - head_subordinates = list() - if(ACCESS_CHANGE_IDS in inserted_scan_id.access) - if(target_dept) - head_subordinates = get_all_jobs() - region_access |= target_dept - authenticated = 1 - else - authenticated = 2 - playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) - - else - if((ACCESS_HOP in inserted_scan_id.access) && ((target_dept==1) || !target_dept)) - region_access |= 1 - get_subordinates("Head of Personnel") - if((ACCESS_HOS in inserted_scan_id.access) && ((target_dept==2) || !target_dept)) - region_access |= 2 - get_subordinates("Head of Security") - if((ACCESS_CMO in inserted_scan_id.access) && ((target_dept==3) || !target_dept)) - region_access |= 3 - get_subordinates("Chief Medical Officer") - if((ACCESS_RD in inserted_scan_id.access) && ((target_dept==4) || !target_dept)) - region_access |= 4 - get_subordinates("Research Director") - if((ACCESS_CE in inserted_scan_id.access) && ((target_dept==5) || !target_dept)) - region_access |= 5 - get_subordinates("Chief Engineer") - if((ACCESS_QM in inserted_scan_id.access) && ((target_dept==6) || !target_dept)) - region_access |= 6 - get_subordinates("Quartermaster") - if(region_access) - authenticated = 1 - else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id)) - to_chat(usr, "You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.") - if ("logout") - region_access = null - head_subordinates = null - authenticated = 0 - playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) - - if("access") - if(href_list["allowed"]) - if(authenticated) - var/access_type = text2num(href_list["access_target"]) - var/access_allowed = text2num(href_list["allowed"]) - if(access_type in (istype(src, /obj/machinery/computer/card/centcom)?get_all_centcom_access() : get_all_accesses())) - inserted_modify_id.access -= access_type - if(access_allowed == 1) - inserted_modify_id.access += access_type - playsound(src, "terminal_type", 50, FALSE) - if ("assign") - if (authenticated == 2) - var/t1 = href_list["assign_target"] - if(t1 == "Custom") - var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", inserted_modify_id ? inserted_modify_id.assignment : "Unassigned"), MAX_NAME_LEN) - if(newJob) - t1 = newJob - - else if(t1 == "Unassigned") - inserted_modify_id.access -= get_all_accesses() - - else - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype - if(ckey(J.title) == ckey(t1)) - jobdatum = J - updateUsrDialog() - break - if(!jobdatum) - to_chat(usr, "No log exists for this job.") - updateUsrDialog() - return - - inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() ) - if (inserted_modify_id) - inserted_modify_id.assignment = t1 - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - if ("demote") - if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant") - inserted_modify_id.assignment = "Unassigned" - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - else - to_chat(usr, "You are not authorized to demote this position.") - if ("reg") - if (authenticated) - var/t2 = inserted_modify_id - if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc))) - var/newName = reject_bad_name(href_list["reg"]) - if(newName) - inserted_modify_id.registered_name = newName - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - else - to_chat(usr, "Invalid name entered.") - updateUsrDialog() - return - if ("mode") - mode = text2num(href_list["mode_target"]) - - if("return") - //DISPLAY MAIN MENU - mode = 3; - playsound(src, "terminal_type", 25, FALSE) - - if("make_job_available") - // MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS - if(authenticated && !target_dept) - var/edit_job_target = href_list["job"] - var/datum/job/j = SSjob.GetJob(edit_job_target) - if(!j) - updateUsrDialog() - return 0 - if(can_open_job(j) != 1) - updateUsrDialog() - return 0 - if(opened_positions[edit_job_target] >= 0) - GLOB.time_last_changed_position = world.time / 10 - j.total_positions++ - opened_positions[edit_job_target]++ - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - - if("make_job_unavailable") - // MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS - if(authenticated && !target_dept) - var/edit_job_target = href_list["job"] - var/datum/job/j = SSjob.GetJob(edit_job_target) - if(!j) - updateUsrDialog() - return 0 - if(can_close_job(j) != 1) - updateUsrDialog() - return 0 - //Allow instant closing without cooldown if a position has been opened before - if(opened_positions[edit_job_target] <= 0) - GLOB.time_last_changed_position = world.time / 10 - j.total_positions-- - opened_positions[edit_job_target]-- - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) - - if ("prioritize_job") - // TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY - if(authenticated && !target_dept) - var/priority_target = href_list["job"] - var/datum/job/j = SSjob.GetJob(priority_target) - if(!j) - updateUsrDialog() - return 0 - var/priority = TRUE - if(j in SSjob.prioritized_jobs) - SSjob.prioritized_jobs -= j - priority = FALSE - else if(j.total_positions <= j.current_positions) - to_chat(usr, "[j.title] has had all positions filled. Open up more slots before prioritizing it.") - updateUsrDialog() - return - else - SSjob.prioritized_jobs += j - to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - - if ("print") - if (!( printing )) - printing = 1 - sleep(50) - var/obj/item/paper/P = new /obj/item/paper( loc ) - var/t1 = "Crew Manifest:
    " - for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) - t1 += t.fields["name"] + " - " + t.fields["rank"] + "
    " - P.info = t1 - P.name = "paper- 'Crew Manifest'" - printing = null - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - if (inserted_modify_id) - inserted_modify_id.update_label() - updateUsrDialog() - -/obj/machinery/computer/card/proc/get_subordinates(rank) - for(var/datum/job/job in SSjob.occupations) - if(rank in job.department_head) - head_subordinates += job.title - -/obj/machinery/computer/card/centcom - name = "\improper CentCom identification console" - circuit = /obj/item/circuitboard/computer/card/centcom - req_access = list(ACCESS_CENT_CAPTAIN) - -/obj/machinery/computer/card/minor - name = "department management console" - desc = "You can use this to change ID's for specific departments." - icon_screen = "idminor" - circuit = /obj/item/circuitboard/computer/card/minor - -/obj/machinery/computer/card/minor/Initialize() - . = ..() - var/obj/item/circuitboard/computer/card/minor/typed_circuit = circuit - if(target_dept) - typed_circuit.target_dept = target_dept - else - target_dept = typed_circuit.target_dept - var/list/dept_list = list("civilian","security","medical","science","engineering","cargo") - name = "[dept_list[target_dept]] department console" - -/obj/machinery/computer/card/minor/hos - target_dept = 2 - icon_screen = "idhos" - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/card/minor/cmo - target_dept = 3 - icon_screen = "idcmo" - -/obj/machinery/computer/card/minor/rd - target_dept = 4 - icon_screen = "idrd" - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/card/minor/ce - target_dept = 5 - icon_screen = "idce" - - light_color = LIGHT_COLOR_YELLOW - -/obj/machinery/computer/card/minor/qm - target_dept = 6 - icon_screen = "idqm" - - light_color = LIGHT_COLOR_ORANGE - -#undef JOB_ALLOWED -#undef JOB_COOLDOWN -#undef JOB_MAX_POSITIONS -#undef JOB_DENIED + + +//Keeps track of the time for the ID console. Having it as a global variable prevents people from dismantling/reassembling it to +//increase the slots of many jobs. +GLOBAL_VAR_INIT(time_last_changed_position, 0) + +#define JOB_ALLOWED 1 +#define JOB_COOLDOWN -2 +#define JOB_MAX_POSITIONS -1 // Trying to reduce the number of slots below that of current holders of that job, or trying to open more slots than allowed +#define JOB_DENIED 0 + +/obj/machinery/computer/card + name = "identification console" + desc = "You can use this to manage jobs and ID access." + icon_screen = "id" + icon_keyboard = "id_key" + req_one_access = list(ACCESS_HEADS, ACCESS_CHANGE_IDS) + circuit = /obj/item/circuitboard/computer/card + var/mode = 0 + var/printing = null + var/target_dept = 0 //Which department this computer has access to. 0=all departments + + //Cooldown for closing positions in seconds + //if set to -1: No cooldown... probably a bad idea + //if set to 0: Not able to close "original" positions. You can only close positions that you have opened before + var/change_position_cooldown = 30 + //Jobs you cannot open new positions for + var/list/blacklisted = list( + "AI", + "Assistant", + "Cyborg", + "Captain", + "Head of Personnel", + "Head of Security", + "Chief Engineer", + "Research Director", + "Chief Medical Officer", + "Quartermaster") + + //The scaling factor of max total positions in relation to the total amount of people on board the station in % + var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players + + //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/obj/item/card/id/inserted_scan_id + var/obj/item/card/id/inserted_modify_id + var/list/region_access = null + var/list/head_subordinates = null + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/card/proc/get_jobs() + return get_all_jobs() + +/obj/machinery/computer/card/centcom/get_jobs() + return get_all_centcom_jobs() + +/obj/machinery/computer/card/Initialize() + . = ..() + change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) + +/obj/machinery/computer/card/examine(mob/user) + . = ..() + if(inserted_scan_id || inserted_modify_id) + . += "Alt-click to eject the ID card." + +/obj/machinery/computer/card/attackby(obj/I, mob/user, params) + if(isidcard(I)) + if(check_access(I) && !inserted_scan_id) + if(id_insert(user, I, inserted_scan_id)) + inserted_scan_id = I + updateUsrDialog() + else if(id_insert(user, I, inserted_modify_id)) + inserted_modify_id = I + updateUsrDialog() + else + return ..() + +/obj/machinery/computer/card/Destroy() + if(inserted_scan_id) + qdel(inserted_scan_id) + inserted_scan_id = null + if(inserted_modify_id) + qdel(inserted_modify_id) + inserted_modify_id = null + return ..() + +/obj/machinery/computer/card/handle_atom_del(atom/A) + ..() + if(A == inserted_scan_id) + inserted_scan_id = null + updateUsrDialog() + if(A == inserted_modify_id) + inserted_modify_id = null + updateUsrDialog() + +/obj/machinery/computer/card/on_deconstruction() + if(inserted_scan_id) + inserted_scan_id.forceMove(drop_location()) + inserted_scan_id = null + if(inserted_modify_id) + inserted_modify_id.forceMove(drop_location()) + inserted_modify_id = null + +//Check if you can't open a new position for a certain job +/obj/machinery/computer/card/proc/job_blacklisted(jobtitle) + return (jobtitle in blacklisted) + +//Logic check for Topic() if you can open the job +/obj/machinery/computer/card/proc/can_open_job(datum/job/job) + if(job) + if(!job_blacklisted(job.title)) + if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) + var/delta = (world.time / 10) - GLOB.time_last_changed_position + if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) + return JOB_ALLOWED + return JOB_COOLDOWN + return JOB_MAX_POSITIONS + return JOB_DENIED + +//Logic check for Topic() if you can close the job +/obj/machinery/computer/card/proc/can_close_job(datum/job/job) + if(job) + if(!job_blacklisted(job.title)) + if(job.total_positions > job.current_positions) + var/delta = (world.time / 10) - GLOB.time_last_changed_position + if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) + return JOB_ALLOWED + return JOB_COOLDOWN + return JOB_MAX_POSITIONS + return JOB_DENIED + + +/obj/machinery/computer/card/proc/id_insert(mob/user, obj/item/inserting_item, obj/item/target) + var/obj/item/card/id/card_to_insert = inserting_item + var/holder_item = FALSE + + if(!isidcard(card_to_insert)) + card_to_insert = inserting_item.RemoveID() + holder_item = TRUE + + if(!card_to_insert || !user.transferItemToLoc(card_to_insert, src)) + return FALSE + + if(target) + if(holder_item && inserting_item.InsertID(target)) + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + else + id_eject(user, target) + + user.visible_message("[user] inserts \the [card_to_insert] into \the [src].", + "You insert \the [card_to_insert] into \the [src].") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + updateUsrDialog() + return TRUE + +/obj/machinery/computer/card/proc/id_eject(mob/user, obj/target) + if(!target) + to_chat(user, "That slot is empty!") + return FALSE + else + target.forceMove(drop_location()) + if(!issilicon(user) && Adjacent(user)) + user.put_in_hands(target) + user.visible_message("[user] gets \the [target] from \the [src].", \ + "You get \the [target] from \the [src].") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + updateUsrDialog() + return TRUE + +/obj/machinery/computer/card/AltClick(mob/user) + . = ..() + if(!user.canUseTopic(src, !issilicon(user)) || !is_operational()) + return + if(inserted_modify_id) + if(id_eject(user, inserted_modify_id)) + inserted_modify_id = null + updateUsrDialog() + return TRUE + if(inserted_scan_id) + if(id_eject(user, inserted_scan_id)) + inserted_scan_id = null + updateUsrDialog() + return TRUE + +/obj/machinery/computer/card/ui_interact(mob/user) + . = ..() + var/list/dat = list() + if (mode == 1) // accessing crew manifest + dat += "Crew Manifest:
    Please use security record computer to modify entries.

    " + for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) + dat += {"[t.fields["name"]] - [t.fields["rank"]]
    "} + dat += "Print

    Access ID modification console.
    " + + else if(mode == 2) + // JOB MANAGEMENT + dat += {"Return + + "} + for(var/datum/job/job in SSjob.occupations) + dat += "" + if(job.title in blacklisted) + continue + dat += {" + + " + dat += "
    JobSlotsOpen jobClose jobPrioritize
    [job.title][job.current_positions]/[job.total_positions]"} + switch(can_open_job(job)) + if(JOB_ALLOWED) + if(authenticated == 2) + dat += "Open Position
    " + else + dat += "Open Position" + if(JOB_COOLDOWN) + var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) + var/mins = round(time_to_wait / 60) + var/seconds = time_to_wait - (60*mins) + dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" + else + dat += "Denied" + dat += "
    " + switch(can_close_job(job)) + if(JOB_ALLOWED) + if(authenticated == 2) + dat += "Close Position" + else + dat += "Close Position" + if(JOB_COOLDOWN) + var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) + var/mins = round(time_to_wait / 60) + var/seconds = time_to_wait - (60*mins) + dat += "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" + else + dat += "Denied" + dat += "" + switch(job.total_positions) + if(0) + dat += "Denied" + else + if(authenticated == 2) + if(job in SSjob.prioritized_jobs) + dat += "Deprioritize" + else + if(SSjob.prioritized_jobs.len < 5) + dat += "Prioritize" + else + dat += "Denied" + else + dat += "Prioritize" + + dat += "
    " + else + var/list/header = list() + + var/scan_name = inserted_scan_id ? html_encode(inserted_scan_id.name) : "--------" + var/target_name = inserted_modify_id ? html_encode(inserted_modify_id.name) : "--------" + var/target_owner = (inserted_modify_id && inserted_modify_id.registered_name) ? html_encode(inserted_modify_id.registered_name) : "--------" + var/target_rank = (inserted_modify_id && inserted_modify_id.assignment) ? html_encode(inserted_modify_id.assignment) : "Unassigned" + + if(!authenticated) + header += {"
    Please insert the cards into the slots
    + Target: [target_name]
    + Confirm Identity: [scan_name]
    "} + else + header += {"

    + Target: Remove [target_name] || + Confirm Identity: Remove [scan_name]
    + Access Crew Manifest
    + [!target_dept ? "Job Management
    " : ""] + Log Out
    "} + + header += "
    " + + var/body + + if (authenticated && inserted_modify_id) + var/list/carddesc = list() + var/list/jobs = list() + if (authenticated == 2) + var/list/jobs_all = list() + for(var/job in (list("Unassigned") + get_jobs() + "Custom")) + jobs_all += "[replacetext(job, " ", " ")] " //make sure there isn't a line break in the middle of a job + carddesc += {""} + carddesc += {"
    + + + registered name: + +
    + Assignment: "} + + jobs += "[target_rank]" //CHECK THIS + + else + carddesc += "registered_name: [target_owner]
    " + jobs += "Assignment: [target_rank] (Demote)
    " + + var/list/accesses = list() + if(istype(src, /obj/machinery/computer/card/centcom)) // REE + accesses += "
    Central Command:
    " + for(var/A in get_all_centcom_access()) + if(A in inserted_modify_id.access) + accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " + else + accesses += "[replacetext(get_centcom_access_desc(A), " ", " ")] " + else + accesses += {"
    Access
    + + "} + for(var/i = 1; i <= 7; i++) + if(authenticated == 1 && !(i in region_access)) + continue + accesses += "" + accesses += "" + for(var/i = 1; i <= 7; i++) + if(authenticated == 1 && !(i in region_access)) + continue + accesses += "" + accesses += "
    [get_region_accesses_name(i)]:
    " + for(var/A in get_region_accesses(i)) + if(A in inserted_modify_id.access) + accesses += "[replacetext(get_access_desc(A), " ", " ")] " + else + accesses += "[replacetext(get_access_desc(A), " ", " ")] " + accesses += "
    " + accesses += "
    " + body = "[carddesc.Join()]
    [jobs.Join()]

    [accesses.Join()]
    " //CHECK THIS + + else if (!authenticated) + body = {"Log In

    + Access Crew Manifest

    "} + if(!target_dept) + body += "Job Management
    " + + dat = list("", header.Join(), body, "
    ") + var/datum/browser/popup = new(user, "id_com", src.name, 900, 620) + popup.set_content(dat.Join()) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/card/Topic(href, href_list) + if(..()) + return + + if(!usr.canUseTopic(src, !issilicon(usr)) || !is_operational()) + usr.unset_machine() + usr << browse(null, "window=id_com") + return + + usr.set_machine(src) + switch(href_list["choice"]) + if ("inserted_modify_id") + if(inserted_modify_id && !usr.get_active_held_item()) + if(id_eject(usr, inserted_modify_id)) + inserted_modify_id = null + updateUsrDialog() + return + if(usr.get_id_in_hand()) + var/obj/item/held_item = usr.get_active_held_item() + var/obj/item/card/id/id_to_insert = held_item.GetID() + if(id_insert(usr, held_item, inserted_modify_id)) + inserted_modify_id = id_to_insert + updateUsrDialog() + if ("inserted_scan_id") + if(inserted_scan_id && !usr.get_active_held_item()) + if(id_eject(usr, inserted_scan_id)) + inserted_scan_id = null + updateUsrDialog() + return + if(usr.get_id_in_hand()) + var/obj/item/held_item = usr.get_active_held_item() + var/obj/item/card/id/id_to_insert = held_item.GetID() + if(id_insert(usr, held_item, inserted_scan_id)) + inserted_scan_id = id_to_insert + updateUsrDialog() + if ("auth") + if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode)) + if (check_access(inserted_scan_id)) + region_access = list() + head_subordinates = list() + if(ACCESS_CHANGE_IDS in inserted_scan_id.access) + if(target_dept) + head_subordinates = get_all_jobs() + region_access |= target_dept + authenticated = 1 + else + authenticated = 2 + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) + + else + if((ACCESS_HOP in inserted_scan_id.access) && ((target_dept==1) || !target_dept)) + region_access |= 1 + get_subordinates("Head of Personnel") + if((ACCESS_HOS in inserted_scan_id.access) && ((target_dept==2) || !target_dept)) + region_access |= 2 + get_subordinates("Head of Security") + if((ACCESS_CMO in inserted_scan_id.access) && ((target_dept==3) || !target_dept)) + region_access |= 3 + get_subordinates("Chief Medical Officer") + if((ACCESS_RD in inserted_scan_id.access) && ((target_dept==4) || !target_dept)) + region_access |= 4 + get_subordinates("Research Director") + if((ACCESS_CE in inserted_scan_id.access) && ((target_dept==5) || !target_dept)) + region_access |= 5 + get_subordinates("Chief Engineer") + if((ACCESS_QM in inserted_scan_id.access) && ((target_dept==6) || !target_dept)) + region_access |= 6 + get_subordinates("Quartermaster") + if(region_access) + authenticated = 1 + else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id)) + to_chat(usr, "You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.") + if ("logout") + region_access = null + head_subordinates = null + authenticated = 0 + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) + + if("access") + if(href_list["allowed"]) + if(authenticated) + var/access_type = text2num(href_list["access_target"]) + var/access_allowed = text2num(href_list["allowed"]) + if(access_type in (istype(src, /obj/machinery/computer/card/centcom)?get_all_centcom_access() : get_all_accesses())) + inserted_modify_id.access -= access_type + if(access_allowed == 1) + inserted_modify_id.access += access_type + playsound(src, "terminal_type", 50, FALSE) + if ("assign") + if (authenticated == 2) + var/t1 = href_list["assign_target"] + if(t1 == "Custom") + var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", inserted_modify_id ? inserted_modify_id.assignment : "Unassigned"), MAX_NAME_LEN) + if(newJob) + t1 = newJob + + else if(t1 == "Unassigned") + inserted_modify_id.access -= get_all_accesses() + + else + var/datum/job/jobdatum + for(var/jobtype in typesof(/datum/job)) + var/datum/job/J = new jobtype + if(ckey(J.title) == ckey(t1)) + jobdatum = J + updateUsrDialog() + break + if(!jobdatum) + to_chat(usr, "No log exists for this job.") + updateUsrDialog() + return + + inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() ) + if (inserted_modify_id) + inserted_modify_id.assignment = t1 + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + if ("demote") + if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant") + inserted_modify_id.assignment = "Unassigned" + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + else + to_chat(usr, "You are not authorized to demote this position.") + if ("reg") + if (authenticated) + var/t2 = inserted_modify_id + if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc))) + var/newName = reject_bad_name(href_list["reg"]) + if(newName) + inserted_modify_id.registered_name = newName + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + else + to_chat(usr, "Invalid name entered.") + updateUsrDialog() + return + if ("mode") + mode = text2num(href_list["mode_target"]) + + if("return") + //DISPLAY MAIN MENU + mode = 3; + playsound(src, "terminal_type", 25, FALSE) + + if("make_job_available") + // MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS + if(authenticated && !target_dept) + var/edit_job_target = href_list["job"] + var/datum/job/j = SSjob.GetJob(edit_job_target) + if(!j) + updateUsrDialog() + return 0 + if(can_open_job(j) != 1) + updateUsrDialog() + return 0 + if(opened_positions[edit_job_target] >= 0) + GLOB.time_last_changed_position = world.time / 10 + j.total_positions++ + opened_positions[edit_job_target]++ + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + + if("make_job_unavailable") + // MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS + if(authenticated && !target_dept) + var/edit_job_target = href_list["job"] + var/datum/job/j = SSjob.GetJob(edit_job_target) + if(!j) + updateUsrDialog() + return 0 + if(can_close_job(j) != 1) + updateUsrDialog() + return 0 + //Allow instant closing without cooldown if a position has been opened before + if(opened_positions[edit_job_target] <= 0) + GLOB.time_last_changed_position = world.time / 10 + j.total_positions-- + opened_positions[edit_job_target]-- + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) + + if ("prioritize_job") + // TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY + if(authenticated && !target_dept) + var/priority_target = href_list["job"] + var/datum/job/j = SSjob.GetJob(priority_target) + if(!j) + updateUsrDialog() + return 0 + var/priority = TRUE + if(j in SSjob.prioritized_jobs) + SSjob.prioritized_jobs -= j + priority = FALSE + else if(j.total_positions <= j.current_positions) + to_chat(usr, "[j.title] has had all positions filled. Open up more slots before prioritizing it.") + updateUsrDialog() + return + else + SSjob.prioritized_jobs += j + to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + + if ("print") + if (!( printing )) + printing = 1 + sleep(50) + var/obj/item/paper/P = new /obj/item/paper( loc ) + var/t1 = "Crew Manifest:
    " + for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) + t1 += t.fields["name"] + " - " + t.fields["rank"] + "
    " + P.info = t1 + P.name = "paper- 'Crew Manifest'" + printing = null + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if (inserted_modify_id) + inserted_modify_id.update_label() + updateUsrDialog() + +/obj/machinery/computer/card/proc/get_subordinates(rank) + for(var/datum/job/job in SSjob.occupations) + if(rank in job.department_head) + head_subordinates += job.title + +/obj/machinery/computer/card/centcom + name = "\improper CentCom identification console" + circuit = /obj/item/circuitboard/computer/card/centcom + req_access = list(ACCESS_CENT_CAPTAIN) + +/obj/machinery/computer/card/minor + name = "department management console" + desc = "You can use this to change ID's for specific departments." + icon_screen = "idminor" + circuit = /obj/item/circuitboard/computer/card/minor + +/obj/machinery/computer/card/minor/Initialize() + . = ..() + var/obj/item/circuitboard/computer/card/minor/typed_circuit = circuit + if(target_dept) + typed_circuit.target_dept = target_dept + else + target_dept = typed_circuit.target_dept + var/list/dept_list = list("civilian","security","medical","science","engineering","cargo") + name = "[dept_list[target_dept]] department console" + +/obj/machinery/computer/card/minor/hos + target_dept = 2 + icon_screen = "idhos" + + light_color = LIGHT_COLOR_RED + +/obj/machinery/computer/card/minor/cmo + target_dept = 3 + icon_screen = "idcmo" + +/obj/machinery/computer/card/minor/rd + target_dept = 4 + icon_screen = "idrd" + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/card/minor/ce + target_dept = 5 + icon_screen = "idce" + + light_color = LIGHT_COLOR_YELLOW + +/obj/machinery/computer/card/minor/qm + target_dept = 6 + icon_screen = "idqm" + + light_color = LIGHT_COLOR_ORANGE + +#undef JOB_ALLOWED +#undef JOB_COOLDOWN +#undef JOB_MAX_POSITIONS +#undef JOB_DENIED diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 43cfbdb33b..90969bf4a1 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -1,514 +1,514 @@ -#define AUTOCLONING_MINIMAL_LEVEL 4 - -/obj/machinery/computer/cloning - name = "cloning console" - desc = "Used to clone people and manage DNA." - icon_screen = "dna" - icon_keyboard = "med_key" - circuit = /obj/item/circuitboard/computer/cloning - req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW. - var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. - var/list/pods //Linked cloning pods - var/temp = "Inactive" - var/scantemp_ckey - var/scantemp = "Ready to Scan" - var/menu = 1 //Which menu screen to display - var/datum/data/record/active_record = null - var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything. - var/loading = 0 // Nice loading text - var/autoprocess = 0 - var/list/records = list() - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/cloning/Initialize() - . = ..() - updatemodules(TRUE) - var/obj/item/circuitboard/computer/cloning/board = circuit - records = board.records - - -/obj/machinery/computer/cloning/Destroy() - if(pods) - for(var/P in pods) - DetachCloner(P) - pods = null - return ..() - -/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null) - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.occupant && pod.clonemind == mind) - return null - if(pod.is_operational() && !(pod.occupant || pod.mess)) - return pod - -/obj/machinery/computer/cloning/proc/HasEfficientPod() - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.is_operational() && pod.efficiency > 5) - return TRUE - -/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null) - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.occupant && pod.clonemind == mind) - return pod - else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5) - . = pod - -/obj/machinery/computer/cloning/process() - if(!(scanner && LAZYLEN(pods) && autoprocess)) - return - - for(var/datum/data/record/R in records) - var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mind"]) - - if(!pod) - return - - if(pod.occupant) - continue //how though? - - if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"])) - temp = "[R.fields["name"]] => Cloning cycle in progress..." - records -= R - -/obj/machinery/computer/cloning/proc/updatemodules(findfirstcloner) - src.scanner = findscanner() - if(findfirstcloner && !LAZYLEN(pods)) - findcloner() - if(!autoprocess) - STOP_PROCESSING(SSmachines, src) - else - START_PROCESSING(SSmachines, src) - -/obj/machinery/computer/cloning/proc/findscanner() - var/obj/machinery/dna_scannernew/scannerf = null - - // Loop through every direction - for(var/direction in GLOB.cardinals) - - // Try to find a scanner in that direction - scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction)) - - // If found and operational, return the scanner - if (!isnull(scannerf) && scannerf.is_operational()) - return scannerf - - // If no scanner was found, it will return null - return null - -/obj/machinery/computer/cloning/proc/findcloner() - var/obj/machinery/clonepod/podf = null - - for(var/direction in GLOB.cardinals) - - podf = locate(/obj/machinery/clonepod, get_step(src, direction)) - if (!isnull(podf) && podf.is_operational()) - AttachCloner(podf) - -/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod) - if(!pod.connected) - pod.connected = src - LAZYADD(pods, pod) - -/obj/machinery/computer/cloning/proc/DetachCloner(obj/machinery/clonepod/pod) - pod.connected = null - LAZYREMOVE(pods, pod) - -/obj/machinery/computer/cloning/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/disk/data)) //INSERT SOME DISKETTES - if (!src.diskette) - if (!user.transferItemToLoc(W,src)) - return - src.diskette = W - to_chat(user, "You insert [W].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - src.updateUsrDialog() - else if(istype(W, /obj/item/multitool)) - var/obj/item/multitool/P = W - - if(istype(P.buffer, /obj/machinery/clonepod)) - if(get_area(P.buffer) != get_area(src)) - to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") - P.buffer = null - return - to_chat(user, "-% Successfully linked [P.buffer] with [src] %-") - var/obj/machinery/clonepod/pod = P.buffer - if(pod.connected) - pod.connected.DetachCloner(pod) - AttachCloner(pod) - else - P.buffer = src - to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-") - return - else - return ..() - -/obj/machinery/computer/cloning/ui_interact(mob/user) - . = ..() - - updatemodules(TRUE) - - var/dat = "" - dat += "Refresh" - - if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) - if(!autoprocess) - dat += "Autoclone" - else - dat += "Stop autoclone" - else - dat += "Autoclone" - dat += "

    Cloning Pod Status

    " - dat += "
    [temp] 
    " - - switch(src.menu) - if(1) - // Modules - if (isnull(src.scanner) || !LAZYLEN(pods)) - dat += "

    Modules

    " - //dat += "Reload Modules" - if (isnull(src.scanner)) - dat += "ERROR: No Scanner detected!
    " - if (!LAZYLEN(pods)) - dat += "ERROR: No Pod detected
    " - - // Scanner - if (!isnull(src.scanner)) - var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant) - - dat += "

    Scanner Functions

    " - - dat += "
    " - if(!scanner_occupant) - dat += "Scanner Unoccupied" - else if(loading) - dat += "[scanner_occupant] => Scanning..." - else - if(scanner_occupant.ckey != scantemp_ckey) - scantemp = "Ready to Scan" - scantemp_ckey = scanner_occupant.ckey - dat += "[scanner_occupant] => [scantemp]" - dat += "
    " - - if(scanner_occupant) - dat += "Start Scan" - dat += "
    [src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" - else - dat += "Start Scan" - - // Database - dat += "

    Database Functions

    " - if (src.records.len && src.records.len > 0) - dat += "View Records ([src.records.len])
    " - else - dat += "View Records (0)
    " - if (src.diskette) - dat += "Eject Disk
    " - - - - if(2) - dat += "

    Current records

    " - dat += "<< Back

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

    [R.fields["name"]]

    Scan ID [R.fields["id"]] View Record" - if(3) - dat += "

    Selected Record

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

    [src.active_record.fields["name"]]

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

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

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

    Inserted Disk

    " - dat += "Contents: " - var/list/L = list() - if(diskette.fields["UI"]) - L += "Unique Identifier" - if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"]) - L += "Unique Enzymes" - if(diskette.fields["SE"]) - L += "Structural Enzymes" - dat += english_list(L, "Empty", " + ", " + ") - dat += "
    Load from Disk" - - dat += "
    Save to Disk" - dat += "
    " - - dat += "Delete Record" - - if(4) - if (!src.active_record) - src.menu = 2 - dat = "[src.temp]
    " - dat += "

    Confirm Record Deletion

    " - - dat += "Scan card to confirm.
    " - dat += "Cancel" - - - var/datum/browser/popup = new(user, "cloning", "Cloning System Control") - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/cloning/Topic(href, href_list) - if(..()) - return - - if(loading) - return - - if(href_list["task"]) - switch(href_list["task"]) - if("autoprocess") - if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) - autoprocess = TRUE - START_PROCESSING(SSmachines, src) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - if("stopautoprocess") - autoprocess = FALSE - STOP_PROCESSING(SSmachines, src) - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational()) - scantemp = "" - - loading = 1 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - say("Initiating scan...") - var/prev_locked = scanner.locked - scanner.locked = TRUE - spawn(20) - src.scan_occupant(scanner.occupant) - - loading = 0 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - scanner.locked = prev_locked - - - //No locking an open scanner. - else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational()) - if ((!scanner.locked) && (scanner.occupant)) - scanner.locked = TRUE - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else - scanner.locked = FALSE - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - else if(href_list["view_rec"]) - playsound(src, "terminal_type", 25, 0) - src.active_record = find_record("id", href_list["view_rec"], records) - if(active_record) - if(!active_record.fields["ckey"]) - records -= active_record - active_record = null - src.temp = "Record Corrupt" - else - src.menu = 3 - else - src.temp = "Record missing." - - else if (href_list["del_rec"]) - if ((!src.active_record) || (src.menu < 3)) - return - if (src.menu == 3) //If we are viewing a record, confirm deletion - src.temp = "Delete record?" - src.menu = 4 - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - - else if (src.menu == 4) - var/obj/item/card/id/C = usr.get_active_held_item() - if (istype(C)||istype(C, /obj/item/pda)) - if(src.check_access(C)) - src.temp = "[src.active_record.fields["name"]] => Record deleted." - src.records.Remove(active_record) - active_record = null - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - src.menu = 2 - var/obj/item/circuitboard/computer/cloning/board = circuit - board.records = records - else - src.temp = "Access Denied." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - else if (href_list["disk"]) //Load or eject. - switch(href_list["disk"]) - if("load") - if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields) - src.temp = "Load error." - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if (!src.active_record) - src.temp = "Record error." - src.menu = 1 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - - for(var/key in diskette.fields) - src.active_record.fields[key] = diskette.fields[key] - src.temp = "Load successful." - var/obj/item/circuitboard/computer/cloning/board = circuit - board.records = records - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - if("eject") - if(src.diskette) - src.diskette.forceMove(drop_location()) - src.diskette = null - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) - if("save") - if(!diskette || diskette.read_only || !active_record || !active_record.fields) - src.temp = "Save error." - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - - diskette.fields = active_record.fields.Copy() - diskette.name = "data disk - '[src.diskette.fields["name"]]'" - src.temp = "Save successful." - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - else if (href_list["refresh"]) - src.updateUsrDialog() - playsound(src, "terminal_type", 25, 0) - - else if (href_list["clone"]) - var/datum/data/record/C = find_record("id", href_list["clone"], records) - //Look for that player! They better be dead! - if(C) - var/obj/machinery/clonepod/pod = GetAvailablePod() - //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. - if(!LAZYLEN(pods)) - temp = "No Clonepods detected." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(!pod) - temp = "No Clonepods available." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(!CONFIG_GET(flag/revival_cloning)) - temp = "Unable to initiate cloning cycle." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(pod.occupant) - temp = "Cloning cycle already in progress." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"])) - temp = "[C.fields["name"]] => Cloning cycle in progress..." - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - records.Remove(C) - if(active_record == C) - active_record = null - menu = 1 - else - temp = "[C.fields["name"]] => Initialisation failure." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - else - temp = "Data corruption." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - else if (href_list["menu"]) - src.menu = text2num(href_list["menu"]) - playsound(src, "terminal_type", 25, 0) - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/cloning/proc/scan_occupant(occupant) - var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) - var/datum/dna/dna - if(ishuman(mob_occupant)) - var/mob/living/carbon/C = mob_occupant - dna = C.has_dna() - if(isbrain(mob_occupant)) - var/mob/living/brain/B = mob_occupant - dna = B.stored_dna - - if(!istype(dna)) - scantemp = "Unable to locate valid genetic data." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if(mob_occupant.suiciding || mob_occupant.hellbound) - scantemp = "Subject's brain is not responding to scanning stimuli." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) - scantemp = "Subject no longer contains the fundamental materials required to create a living clone." - playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) - return - if ((!mob_occupant.ckey) || (!mob_occupant.client)) - scantemp = "Mental interface failure." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if (find_record("ckey", mob_occupant.ckey, records)) - scantemp = "Subject already in database." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - - var/datum/data/record/R = new() - if(dna.species) - // We store the instance rather than the path, because some - // species (abductors, slimepeople) store state in their - // species datums - dna.delete_species = FALSE - R.fields["mrace"] = dna.species - else - var/datum/species/rando_race = pick(GLOB.roundstart_races) - R.fields["mrace"] = rando_race.type - - R.fields["ckey"] = mob_occupant.ckey - R.fields["name"] = mob_occupant.real_name - R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6) - R.fields["UE"] = dna.unique_enzymes - R.fields["UI"] = dna.uni_identity - R.fields["SE"] = dna.struc_enzymes - R.fields["blood_type"] = dna.blood_type - R.fields["features"] = dna.features - R.fields["factions"] = mob_occupant.faction - R.fields["quirks"] = list() - for(var/V in mob_occupant.roundstart_quirks) - var/datum/quirk/T = V - R.fields["quirks"][T.type] = T.clone_data() - - if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning. - R.fields["mind"] = "[REF(mob_occupant.mind)]" - - //Add an implant if needed - var/obj/item/implant/health/imp - for(var/obj/item/implant/health/HI in mob_occupant.implants) - imp = HI - break - if(!imp) - imp = new /obj/item/implant/health(mob_occupant) - imp.implant(mob_occupant) - R.fields["imp"] = "[REF(imp)]" - - src.records += R - var/obj/item/circuitboard/computer/cloning/board = circuit - board.records = records - scantemp = "Subject successfully scanned." - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) +#define AUTOCLONING_MINIMAL_LEVEL 4 + +/obj/machinery/computer/cloning + name = "cloning console" + desc = "Used to clone people and manage DNA." + icon_screen = "dna" + icon_keyboard = "med_key" + circuit = /obj/item/circuitboard/computer/cloning + req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW. + var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. + var/list/pods //Linked cloning pods + var/temp = "Inactive" + var/scantemp_ckey + var/scantemp = "Ready to Scan" + var/menu = 1 //Which menu screen to display + var/datum/data/record/active_record = null + var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything. + var/loading = 0 // Nice loading text + var/autoprocess = 0 + var/list/records = list() + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/cloning/Initialize() + . = ..() + updatemodules(TRUE) + var/obj/item/circuitboard/computer/cloning/board = circuit + records = board.records + + +/obj/machinery/computer/cloning/Destroy() + if(pods) + for(var/P in pods) + DetachCloner(P) + pods = null + return ..() + +/obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null) + if(pods) + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.occupant && pod.clonemind == mind) + return null + if(pod.is_operational() && !(pod.occupant || pod.mess)) + return pod + +/obj/machinery/computer/cloning/proc/HasEfficientPod() + if(pods) + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.is_operational() && pod.efficiency > 5) + return TRUE + +/obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null) + if(pods) + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.occupant && pod.clonemind == mind) + return pod + else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5) + . = pod + +/obj/machinery/computer/cloning/process() + if(!(scanner && LAZYLEN(pods) && autoprocess)) + return + + for(var/datum/data/record/R in records) + var/obj/machinery/clonepod/pod = GetAvailableEfficientPod(R.fields["mind"]) + + if(!pod) + return + + if(pod.occupant) + continue //how though? + + if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"])) + temp = "[R.fields["name"]] => Cloning cycle in progress..." + records -= R + +/obj/machinery/computer/cloning/proc/updatemodules(findfirstcloner) + src.scanner = findscanner() + if(findfirstcloner && !LAZYLEN(pods)) + findcloner() + if(!autoprocess) + STOP_PROCESSING(SSmachines, src) + else + START_PROCESSING(SSmachines, src) + +/obj/machinery/computer/cloning/proc/findscanner() + var/obj/machinery/dna_scannernew/scannerf = null + + // Loop through every direction + for(var/direction in GLOB.cardinals) + + // Try to find a scanner in that direction + scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction)) + + // If found and operational, return the scanner + if (!isnull(scannerf) && scannerf.is_operational()) + return scannerf + + // If no scanner was found, it will return null + return null + +/obj/machinery/computer/cloning/proc/findcloner() + var/obj/machinery/clonepod/podf = null + + for(var/direction in GLOB.cardinals) + + podf = locate(/obj/machinery/clonepod, get_step(src, direction)) + if (!isnull(podf) && podf.is_operational()) + AttachCloner(podf) + +/obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod) + if(!pod.connected) + pod.connected = src + LAZYADD(pods, pod) + +/obj/machinery/computer/cloning/proc/DetachCloner(obj/machinery/clonepod/pod) + pod.connected = null + LAZYREMOVE(pods, pod) + +/obj/machinery/computer/cloning/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/disk/data)) //INSERT SOME DISKETTES + if (!src.diskette) + if (!user.transferItemToLoc(W,src)) + return + src.diskette = W + to_chat(user, "You insert [W].") + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) + src.updateUsrDialog() + else if(istype(W, /obj/item/multitool)) + var/obj/item/multitool/P = W + + if(istype(P.buffer, /obj/machinery/clonepod)) + if(get_area(P.buffer) != get_area(src)) + to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") + P.buffer = null + return + to_chat(user, "-% Successfully linked [P.buffer] with [src] %-") + var/obj/machinery/clonepod/pod = P.buffer + if(pod.connected) + pod.connected.DetachCloner(pod) + AttachCloner(pod) + else + P.buffer = src + to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-") + return + else + return ..() + +/obj/machinery/computer/cloning/ui_interact(mob/user) + . = ..() + + updatemodules(TRUE) + + var/dat = "" + dat += "Refresh" + + if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) + if(!autoprocess) + dat += "Autoclone" + else + dat += "Stop autoclone" + else + dat += "Autoclone" + dat += "

    Cloning Pod Status

    " + dat += "
    [temp] 
    " + + switch(src.menu) + if(1) + // Modules + if (isnull(src.scanner) || !LAZYLEN(pods)) + dat += "

    Modules

    " + //dat += "Reload Modules" + if (isnull(src.scanner)) + dat += "ERROR: No Scanner detected!
    " + if (!LAZYLEN(pods)) + dat += "ERROR: No Pod detected
    " + + // Scanner + if (!isnull(src.scanner)) + var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant) + + dat += "

    Scanner Functions

    " + + dat += "
    " + if(!scanner_occupant) + dat += "Scanner Unoccupied" + else if(loading) + dat += "[scanner_occupant] => Scanning..." + else + if(scanner_occupant.ckey != scantemp_ckey) + scantemp = "Ready to Scan" + scantemp_ckey = scanner_occupant.ckey + dat += "[scanner_occupant] => [scantemp]" + dat += "
    " + + if(scanner_occupant) + dat += "Start Scan" + dat += "
    [src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" + else + dat += "Start Scan" + + // Database + dat += "

    Database Functions

    " + if (src.records.len && src.records.len > 0) + dat += "View Records ([src.records.len])
    " + else + dat += "View Records (0)
    " + if (src.diskette) + dat += "Eject Disk
    " + + + + if(2) + dat += "

    Current records

    " + dat += "<< Back

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

    [R.fields["name"]]

    Scan ID [R.fields["id"]] View Record" + if(3) + dat += "

    Selected Record

    " + dat += "<< Back
    " + + if (!src.active_record) + dat += "Record not found." + else + dat += "

    [src.active_record.fields["name"]]

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

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

    " + + dat += "Unique Identifier:
    [src.active_record.fields["UI"]]
    " + dat += "Structural Enzymes:
    [src.active_record.fields["SE"]]
    " + + if(diskette && diskette.fields) + dat += "
    " + dat += "

    Inserted Disk

    " + dat += "Contents: " + var/list/L = list() + if(diskette.fields["UI"]) + L += "Unique Identifier" + if(diskette.fields["UE"] && diskette.fields["name"] && diskette.fields["blood_type"]) + L += "Unique Enzymes" + if(diskette.fields["SE"]) + L += "Structural Enzymes" + dat += english_list(L, "Empty", " + ", " + ") + dat += "
    Load from Disk" + + dat += "
    Save to Disk" + dat += "
    " + + dat += "Delete Record" + + if(4) + if (!src.active_record) + src.menu = 2 + dat = "[src.temp]
    " + dat += "

    Confirm Record Deletion

    " + + dat += "Scan card to confirm.
    " + dat += "Cancel" + + + var/datum/browser/popup = new(user, "cloning", "Cloning System Control") + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/cloning/Topic(href, href_list) + if(..()) + return + + if(loading) + return + + if(href_list["task"]) + switch(href_list["task"]) + if("autoprocess") + if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) + autoprocess = TRUE + START_PROCESSING(SSmachines, src) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + if("stopautoprocess") + autoprocess = FALSE + STOP_PROCESSING(SSmachines, src) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational()) + scantemp = "" + + loading = 1 + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + say("Initiating scan...") + var/prev_locked = scanner.locked + scanner.locked = TRUE + spawn(20) + src.scan_occupant(scanner.occupant) + + loading = 0 + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + scanner.locked = prev_locked + + + //No locking an open scanner. + else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational()) + if ((!scanner.locked) && (scanner.occupant)) + scanner.locked = TRUE + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else + scanner.locked = FALSE + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + + else if(href_list["view_rec"]) + playsound(src, "terminal_type", 25, 0) + src.active_record = find_record("id", href_list["view_rec"], records) + if(active_record) + if(!active_record.fields["ckey"]) + records -= active_record + active_record = null + src.temp = "Record Corrupt" + else + src.menu = 3 + else + src.temp = "Record missing." + + else if (href_list["del_rec"]) + if ((!src.active_record) || (src.menu < 3)) + return + if (src.menu == 3) //If we are viewing a record, confirm deletion + src.temp = "Delete record?" + src.menu = 4 + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + + else if (src.menu == 4) + var/obj/item/card/id/C = usr.get_active_held_item() + if (istype(C)||istype(C, /obj/item/pda)) + if(src.check_access(C)) + src.temp = "[src.active_record.fields["name"]] => Record deleted." + src.records.Remove(active_record) + active_record = null + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + src.menu = 2 + var/obj/item/circuitboard/computer/cloning/board = circuit + board.records = records + else + src.temp = "Access Denied." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + else if (href_list["disk"]) //Load or eject. + switch(href_list["disk"]) + if("load") + if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields) + src.temp = "Load error." + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if (!src.active_record) + src.temp = "Record error." + src.menu = 1 + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + + for(var/key in diskette.fields) + src.active_record.fields[key] = diskette.fields[key] + src.temp = "Load successful." + var/obj/item/circuitboard/computer/cloning/board = circuit + board.records = records + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + + if("eject") + if(src.diskette) + src.diskette.forceMove(drop_location()) + src.diskette = null + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) + if("save") + if(!diskette || diskette.read_only || !active_record || !active_record.fields) + src.temp = "Save error." + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + + diskette.fields = active_record.fields.Copy() + diskette.name = "data disk - '[src.diskette.fields["name"]]'" + src.temp = "Save successful." + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + + else if (href_list["refresh"]) + src.updateUsrDialog() + playsound(src, "terminal_type", 25, 0) + + else if (href_list["clone"]) + var/datum/data/record/C = find_record("id", href_list["clone"], records) + //Look for that player! They better be dead! + if(C) + var/obj/machinery/clonepod/pod = GetAvailablePod() + //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. + if(!LAZYLEN(pods)) + temp = "No Clonepods detected." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(!pod) + temp = "No Clonepods available." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(!CONFIG_GET(flag/revival_cloning)) + temp = "Unable to initiate cloning cycle." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(pod.occupant) + temp = "Cloning cycle already in progress." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"])) + temp = "[C.fields["name"]] => Cloning cycle in progress..." + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + records.Remove(C) + if(active_record == C) + active_record = null + menu = 1 + else + temp = "[C.fields["name"]] => Initialisation failure." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + else + temp = "Data corruption." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + else if (href_list["menu"]) + src.menu = text2num(href_list["menu"]) + playsound(src, "terminal_type", 25, 0) + + src.add_fingerprint(usr) + src.updateUsrDialog() + return + +/obj/machinery/computer/cloning/proc/scan_occupant(occupant) + var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) + var/datum/dna/dna + if(ishuman(mob_occupant)) + var/mob/living/carbon/C = mob_occupant + dna = C.has_dna() + if(isbrain(mob_occupant)) + var/mob/living/brain/B = mob_occupant + dna = B.stored_dna + + if(!istype(dna)) + scantemp = "Unable to locate valid genetic data." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if(mob_occupant.suiciding || mob_occupant.hellbound) + scantemp = "Subject's brain is not responding to scanning stimuli." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) + scantemp = "Subject no longer contains the fundamental materials required to create a living clone." + playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + return + if ((!mob_occupant.ckey) || (!mob_occupant.client)) + scantemp = "Mental interface failure." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if (find_record("ckey", mob_occupant.ckey, records)) + scantemp = "Subject already in database." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + + var/datum/data/record/R = new() + if(dna.species) + // We store the instance rather than the path, because some + // species (abductors, slimepeople) store state in their + // species datums + dna.delete_species = FALSE + R.fields["mrace"] = dna.species + else + var/datum/species/rando_race = pick(GLOB.roundstart_races) + R.fields["mrace"] = rando_race.type + + R.fields["ckey"] = mob_occupant.ckey + R.fields["name"] = mob_occupant.real_name + R.fields["id"] = copytext(md5(mob_occupant.real_name), 2, 6) + R.fields["UE"] = dna.unique_enzymes + R.fields["UI"] = dna.uni_identity + R.fields["SE"] = dna.struc_enzymes + R.fields["blood_type"] = dna.blood_type + R.fields["features"] = dna.features + R.fields["factions"] = mob_occupant.faction + R.fields["quirks"] = list() + for(var/V in mob_occupant.roundstart_quirks) + var/datum/quirk/T = V + R.fields["quirks"][T.type] = T.clone_data() + + if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning. + R.fields["mind"] = "[REF(mob_occupant.mind)]" + + //Add an implant if needed + var/obj/item/implant/health/imp + for(var/obj/item/implant/health/HI in mob_occupant.implants) + imp = HI + break + if(!imp) + imp = new /obj/item/implant/health(mob_occupant) + imp.implant(mob_occupant) + R.fields["imp"] = "[REF(imp)]" + + src.records += R + var/obj/item/circuitboard/computer/cloning/board = circuit + board.records = records + scantemp = "Subject successfully scanned." + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 22a523c58b..1bc8a82147 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -1,759 +1,759 @@ -// The communications computer -/obj/machinery/computer/communications - name = "communications console" - desc = "A console used for high-priority announcements and emergencies." - icon_screen = "comm" - icon_keyboard = "tech_key" - req_access = list(ACCESS_HEADS) - circuit = /obj/item/circuitboard/computer/communications - var/auth_id = "Unknown" //Who is currently logged in? - var/list/datum/comm_message/messages = list() - var/datum/comm_message/currmsg - var/datum/comm_message/aicurrmsg - var/state = STATE_DEFAULT - var/aistate = STATE_DEFAULT - var/message_cooldown = 0 - var/ai_message_cooldown = 0 - var/tmp_alertlevel = 0 - var/const/STATE_DEFAULT = 1 - var/const/STATE_CALLSHUTTLE = 2 - var/const/STATE_CANCELSHUTTLE = 3 - var/const/STATE_MESSAGELIST = 4 - var/const/STATE_VIEWMESSAGE = 5 - var/const/STATE_DELMESSAGE = 6 - var/const/STATE_STATUSDISPLAY = 7 - var/const/STATE_ALERT_LEVEL = 8 - var/const/STATE_CONFIRM_LEVEL = 9 - var/const/STATE_TOGGLE_EMERGENCY = 10 - var/const/STATE_PURCHASE = 11 - - var/stat_msg1 - var/stat_msg2 - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/communications/proc/checkCCcooldown() - var/obj/item/circuitboard/computer/communications/CM = circuit - if(CM.lastTimeUsed + 600 > world.time) - return FALSE - return TRUE - -/obj/machinery/computer/communications/Initialize() - . = ..() - GLOB.shuttle_caller_list += src - -/obj/machinery/computer/communications/Topic(href, href_list) - if(..()) - return - if(!usr.canUseTopic(src)) - return - if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 - to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") - return - usr.set_machine(src) - - - if(!href_list["operation"]) - return - var/obj/item/circuitboard/computer/communications/CM = circuit - switch(href_list["operation"]) - // main interface - if("main") - state = STATE_DEFAULT - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - if("login") - var/mob/M = usr - - var/obj/item/card/id/I = M.get_idcard(TRUE) - - if(I && istype(I)) - if(check_access(I)) - authenticated = 1 - auth_id = "[I.registered_name] ([I.assignment])" - if((ACCESS_CAPTAIN in I.access)) - authenticated = 2 - playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) - if(obj_flags & EMAGGED) - authenticated = 2 - auth_id = "Unknown" - to_chat(M, "[src] lets out a quiet alarm as its login is overridden.") - playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) - playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0) - if(prob(25)) - for(var/mob/living/silicon/ai/AI in active_ais()) - SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons - if("logout") - authenticated = 0 - playsound(src, 'sound/machines/terminal_off.ogg', 50, 0) - - if("swipeidseclevel") - var/mob/M = usr - var/obj/item/card/id/I = M.get_active_held_item() - if (istype(I, /obj/item/pda)) - var/obj/item/pda/pda = I - I = pda.id - if (I && istype(I)) - if(ACCESS_CAPTAIN in I.access) - var/old_level = GLOB.security_level - if(!tmp_alertlevel) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel < SEC_LEVEL_GREEN) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel == SEC_LEVEL_BLUE) - tmp_alertlevel = SEC_LEVEL_BLUE - if(tmp_alertlevel > SEC_LEVEL_AMBER) - tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this - set_security_level(tmp_alertlevel) - if(GLOB.security_level != old_level) - to_chat(usr, "Authorization confirmed. Modifying security level.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - //Only notify people if an actual change happened - var/security_level = get_security_level() - log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].") - message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].") - deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] with [src] at [get_area_name(usr, TRUE)].", usr) - tmp_alertlevel = 0 - else - to_chat(usr, "You are not authorized to do this!") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - tmp_alertlevel = 0 - state = STATE_DEFAULT - else - to_chat(usr, "You need to swipe your ID!") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - - if("announce") - if(authenticated==2) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - make_announcement(usr) - - if("crossserver") - if(authenticated==2) - if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "") - if(!input || !(usr in view(1,src)) || !checkCCcooldown()) - return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - send2otherserver("[station_name()]", input,"Comms_Console") - minor_announce(input, title = "Outgoing message to allied station") - usr.log_talk(input, LOG_SAY, tag="message to the other server") - message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.") - deadchat_broadcast("[usr.real_name] has sent an outgoing message to the other station(s).", usr) - CM.lastTimeUsed = world.time - - if("purchase_menu") - state = STATE_PURCHASE - - if("buyshuttle") - if(authenticated==2) - var/list/shuttles = flatten_list(SSmapping.shuttle_templates) - var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles - if(S && istype(S)) - if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE) - to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?") - return - if(SSshuttle.shuttle_purchased) - to_chat(usr, "A replacement shuttle has already been purchased.") - else if(!S.prerequisites_met()) - to_chat(usr, "You have not met the requirements for purchasing this shuttle.") - else - if(SSshuttle.points >= S.credit_cost) - var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines - if(M) - SSshuttle.shuttle_purchased = TRUE - SSshuttle.points -= S.credit_cost - minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase") - message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].") - SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]") - M.unload_preview() - M.load_template(S) - M.existing_shuttle = SSshuttle.emergency - M.action_load(S) - message_admins("[S.name] loaded, purchased by [usr]") - else - to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.") - else - to_chat(usr, "Not enough credits.") - - if("callshuttle") - state = STATE_DEFAULT - if(authenticated) - state = STATE_CALLSHUTTLE - if("callshuttle2") - if(authenticated) - SSshuttle.requestEvac(usr, href_list["call"]) - if(SSshuttle.emergency.timer) - post_status("shuttle") - state = STATE_DEFAULT - if("cancelshuttle") - state = STATE_DEFAULT - if(authenticated) - state = STATE_CANCELSHUTTLE - if("cancelshuttle2") - if(authenticated) - if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) //Citadel Edit Removing auto_call caused recall. - say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.") - else - SSshuttle.cancelEvac(usr) - state = STATE_DEFAULT - if("messagelist") - currmsg = 0 - state = STATE_MESSAGELIST - if("viewmessage") - state = STATE_VIEWMESSAGE - if (!currmsg) - if(href_list["message-num"]) - var/msgnum = text2num(href_list["message-num"]) - currmsg = messages[msgnum] - else - state = STATE_MESSAGELIST - if("delmessage") - state = currmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST - if("delmessage2") - if(authenticated) - if(currmsg) - if(aicurrmsg == currmsg) - aicurrmsg = null - messages -= currmsg - currmsg = null - state = STATE_MESSAGELIST - else - state = STATE_VIEWMESSAGE - if("respond") - var/answer = text2num(href_list["answer"]) - if(!currmsg || !answer || currmsg.possible_answers.len < answer) - state = STATE_MESSAGELIST - else - if(!currmsg.answered) - currmsg.answered = answer - log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]") - if(currmsg) - currmsg.answer_callback.InvokeAsync() - state = STATE_VIEWMESSAGE - updateDialog() - if("status") - state = STATE_STATUSDISPLAY - if("securitylevel") - tmp_alertlevel = text2num( href_list["newalertlevel"] ) - if(!tmp_alertlevel) - tmp_alertlevel = 0 - state = STATE_CONFIRM_LEVEL - if("changeseclevel") - state = STATE_ALERT_LEVEL - - if("emergencyaccess") - state = STATE_TOGGLE_EMERGENCY - if("enableemergency") - make_maint_all_access() - log_game("[key_name(usr)] enabled emergency maintenance access.") - message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.") - deadchat_broadcast("[usr.real_name] enabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr) - state = STATE_DEFAULT - if("disableemergency") - revoke_maint_all_access() - log_game("[key_name(usr)] disabled emergency maintenance access.") - message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.") - deadchat_broadcast("[usr.real_name] disabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr) - state = STATE_DEFAULT - - // Status display stuff - if("setstat") - playsound(src, "terminal_type", 50, 0) - switch(href_list["statdisp"]) - if("message") - post_status("message", stat_msg1, stat_msg2) - if("alert") - post_status("alert", href_list["alert"]) - else - post_status(href_list["statdisp"]) - - if("setmsg1") - stat_msg1 = reject_bad_text(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40) - updateDialog() - if("setmsg2") - stat_msg2 = reject_bad_text(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40) - updateDialog() - - // OMG CENTCOM LETTERHEAD - if("MessageCentCom") - if(authenticated) - if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - return - var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "") - if(!input || !(usr in view(1,src)) || !checkCCcooldown()) - return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - CentCom_announce(input, usr) - to_chat(usr, "Message transmitted to Central Command.") - usr.log_talk(input, LOG_SAY, tag="CentCom announcement") - deadchat_broadcast("[usr.real_name] has messaged CentCom, \"[input]\" at [get_area_name(usr, TRUE)].", usr) - CM.lastTimeUsed = world.time - - // OMG SYNDICATE ...LETTERHEAD - if("MessageSyndicate") - if((authenticated==2) && (obj_flags & EMAGGED)) - if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to /??????/.", "") - if(!input || !(usr in view(1,src)) || !checkCCcooldown()) - return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - Syndicate_announce(input, usr) - to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.") - usr.log_talk(input, LOG_SAY, tag="Syndicate announcement") - deadchat_broadcast("[usr.real_name] has messaged the Syndicate, \"[input]\" at [get_area_name(usr, TRUE)].", usr) - CM.lastTimeUsed = world.time - - if("RestoreBackup") - to_chat(usr, "Backup routing data restored!") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - obj_flags &= ~EMAGGED - updateDialog() - - if("nukerequest") //When there's no other way - if(authenticated==2) - if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - return - var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") - if(!input || !(usr in view(1,src)) || !checkCCcooldown()) - return - Nuke_request(input, usr) - to_chat(usr, "Request sent.") - usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) - priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport") - CM.lastTimeUsed = world.time - - - // AI interface - if("ai-main") - aicurrmsg = null - aistate = STATE_DEFAULT - if("ai-callshuttle") - aistate = STATE_CALLSHUTTLE - if("ai-callshuttle2") - SSshuttle.requestEvac(usr, href_list["call"]) - aistate = STATE_DEFAULT - if("ai-messagelist") - aicurrmsg = null - aistate = STATE_MESSAGELIST - if("ai-viewmessage") - aistate = STATE_VIEWMESSAGE - if (!aicurrmsg) - if(href_list["message-num"]) - var/msgnum = text2num(href_list["message-num"]) - aicurrmsg = messages[msgnum] - else - aistate = STATE_MESSAGELIST - if("ai-delmessage") - aistate = aicurrmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST - if("ai-delmessage2") - if(aicurrmsg) - if(currmsg == aicurrmsg) - currmsg = null - messages -= aicurrmsg - aicurrmsg = null - aistate = STATE_MESSAGELIST - if("ai-respond") - var/answer = text2num(href_list["answer"]) - if(!aicurrmsg || !answer || aicurrmsg.possible_answers.len < answer) - aistate = STATE_MESSAGELIST - else - if(!aicurrmsg.answered) - aicurrmsg.answered = answer - log_game("[key_name(usr)] answered [aicurrmsg.title] comm message. Answer : [aicurrmsg.answered]") - if(aicurrmsg.answer_callback) - aicurrmsg.answer_callback.InvokeAsync() - aistate = STATE_VIEWMESSAGE - if("ai-status") - aistate = STATE_STATUSDISPLAY - if("ai-announce") - make_announcement(usr, 1) - if("ai-securitylevel") - tmp_alertlevel = text2num( href_list["newalertlevel"] ) - if(!tmp_alertlevel) - tmp_alertlevel = 0 - var/old_level = GLOB.security_level - if(!tmp_alertlevel) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel < SEC_LEVEL_GREEN) - tmp_alertlevel = SEC_LEVEL_GREEN - if(tmp_alertlevel == SEC_LEVEL_BLUE) - tmp_alertlevel = SEC_LEVEL_BLUE - if(tmp_alertlevel > SEC_LEVEL_AMBER) - tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this - set_security_level(tmp_alertlevel) - if(GLOB.security_level != old_level) - //Only notify people if an actual change happened - var/security_level = get_security_level() - log_game("[key_name(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].") - message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].") - deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] from [src] at [get_area_name(usr, TRUE)].", usr) - tmp_alertlevel = 0 - aistate = STATE_DEFAULT - if("ai-changeseclevel") - aistate = STATE_ALERT_LEVEL - if("ai-emergencyaccess") - aistate = STATE_TOGGLE_EMERGENCY - if("ai-enableemergency") - make_maint_all_access() - log_game("[key_name(usr)] enabled emergency maintenance access.") - message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.") - deadchat_broadcast("[usr.real_name] enabled emergency maintenance access.", usr) - aistate = STATE_DEFAULT - if("ai-disableemergency") - revoke_maint_all_access() - log_game("[key_name(usr)] disabled emergency maintenance access.") - message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.") - deadchat_broadcast("[usr.real_name] disabled emergency maintenance access.", usr) - aistate = STATE_DEFAULT - - updateUsrDialog() - -/obj/machinery/computer/communications/attackby(obj/I, mob/user, params) - if(istype(I, /obj/item/card/id)) - attack_hand(user) - else - return ..() - -/obj/machinery/computer/communications/emag_act(mob/user) - . = ..() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - SSshuttle.shuttle_purchase_requirements_met |= "emagged" - if(authenticated == 1) - authenticated = 2 - to_chat(user, "You scramble the communication routing circuits!") - playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) - return TRUE - -/obj/machinery/computer/communications/ui_interact(mob/user) - . = ..() - if (z > 6) - to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") - return - - var/dat = "" - if(SSshuttle.emergency.mode == SHUTTLE_CALL) - var/timeleft = SSshuttle.emergency.timeLeft() - dat += "Emergency shuttle\n
    \nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" - - - var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - - if(issilicon(user)) - var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access - if(dat2) - dat += dat2 - popup.set_content(dat) - popup.open() - return - - switch(state) - if(STATE_DEFAULT) - if (authenticated) - if(SSshuttle.emergencyCallAmount) - if(SSshuttle.emergencyLastCallLoc) - dat += "Most recent shuttle call/recall traced to: [format_text(SSshuttle.emergencyLastCallLoc.name)]
    " - else - dat += "Unable to trace most recent shuttle call/recall signal.
    " - dat += "Logged in as: [auth_id]" - dat += "
    " - dat += "
    \[ Log Out \]
    " - dat += "
    General Functions" - dat += "
    \[ Message List \]" - switch(SSshuttle.emergency.mode) - if(SHUTTLE_IDLE, SHUTTLE_RECALL) - dat += "
    \[ Call Emergency Shuttle \]" - else - dat += "
    \[ Cancel Shuttle Call \]" - - dat += "
    \[ Set Status Display \]" - if (authenticated==2) - dat += "

    Captain Functions" - dat += "
    \[ Make a Captain's Announcement \]" - var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server)) - if(cross_servers_count) - dat += "
    \[ Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""] \]" - if(SSmapping.config.allow_custom_shuttles) - dat += "
    \[ Purchase Shuttle \]" - dat += "
    \[ Change Alert Level \]" - dat += "
    \[ Emergency Maintenance Access \]" - dat += "
    \[ Request Nuclear Authentication Codes \]" - if(!(obj_flags & EMAGGED)) - dat += "
    \[ Send Message to CentCom \]" - else - dat += "
    \[ Send Message to \[UNKNOWN\] \]" - dat += "
    \[ Restore Backup Routing Data \]" - else - dat += "
    \[ Log In \]" - if(STATE_CALLSHUTTLE) - dat += get_call_shuttle_form() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - if(STATE_CANCELSHUTTLE) - dat += get_cancel_shuttle_form() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - if(STATE_MESSAGELIST) - dat += "Messages:" - for(var/i in 1 to messages.len) - var/datum/comm_message/M = messages[i] - dat += "
    [M.title]" - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - if(STATE_VIEWMESSAGE) - if (currmsg) - dat += "[currmsg.title]

    [currmsg.content]" - if(!currmsg.answered && currmsg.possible_answers.len) - for(var/i in 1 to currmsg.possible_answers.len) - var/answer = currmsg.possible_answers[i] - dat += "
    \[ Answer : [answer] \]" - else if(currmsg.answered) - var/answered = currmsg.possible_answers[currmsg.answered] - dat += "
    Archived Answer : [answered]" - dat += "

    \[ Delete \]" - else - aistate = STATE_MESSAGELIST - attack_hand(user) - return - if(STATE_DELMESSAGE) - if (currmsg) - dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" - else - state = STATE_MESSAGELIST - attack_hand(user) - return - if(STATE_STATUSDISPLAY) - dat += "Set Status Displays
    " - dat += "\[ Clear \]
    " - dat += "\[ Shuttle ETA \]
    " - dat += "\[ Message \]" - dat += "
    " - dat += "\[ Alert: None |" - dat += " Red Alert |" - dat += " Lockdown |" - dat += " Biohazard \]

    " - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - if(STATE_ALERT_LEVEL) - dat += "Current alert level: [get_security_level()]
    " - if(GLOB.security_level == SEC_LEVEL_DELTA) - dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." - else - dat += "Amber
    " - dat += "Blue
    " - dat += "Green" - if(STATE_CONFIRM_LEVEL) - dat += "Current alert level: [get_security_level()]
    " - dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]
    " - dat += "Swipe ID to confirm change.
    " - if(STATE_TOGGLE_EMERGENCY) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - if(GLOB.emergency_access == 1) - dat += "Emergency Maintenance Access is currently ENABLED" - dat += "
    Restore maintenance access restrictions?
    \[ OK | Cancel \]" - else - dat += "Emergency Maintenance Access is currently DISABLED" - dat += "
    Lift access restrictions on maintenance and external airlocks?
    \[ OK | Cancel \]" - - if(STATE_PURCHASE) - dat += "Budget: [SSshuttle.points] Credits.
    " - dat += "
    " - dat += "Caution: Purchasing dangerous shuttles may lead to mutiny and/or death.
    " - dat += "
    " - for(var/shuttle_id in SSmapping.shuttle_templates) - var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] - if(S.can_be_bought && S.credit_cost < INFINITY) - dat += "[S.name] | [S.credit_cost] Credits
    " - dat += "[S.description]
    " - if(S.prerequisites) - dat += "Prerequisites: [S.prerequisites]
    " - dat += "(Purchase)

    " - - dat += "

    \[ [(state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" - - popup.set_content(dat) - popup.open() - -/obj/machinery/computer/communications/proc/get_javascript_header(form_id) - var/dat = {""} - return dat - -/obj/machinery/computer/communications/proc/get_call_shuttle_form(ai_interface = 0) - var/form_id = "callshuttle" - var/dat = get_javascript_header(form_id) - dat += "
    " - dat += "" - dat += "" - dat += "Nature of emergency:
    " - dat += "
    Are you sure you want to call the shuttle? \[ Call \]" - return dat - -/obj/machinery/computer/communications/proc/get_cancel_shuttle_form() - var/form_id = "cancelshuttle" - var/dat = get_javascript_header(form_id) - dat += "" - dat += "" - dat += "" - - dat += "
    Are you sure you want to cancel the shuttle? \[ Cancel \]" - return dat - -/obj/machinery/computer/communications/proc/interact_ai(mob/living/silicon/ai/user) - var/dat = "" - switch(aistate) - if(STATE_DEFAULT) - if(SSshuttle.emergencyCallAmount) - if(SSshuttle.emergencyLastCallLoc) - dat += "Latest emergency signal trace attempt successful.
    Last signal origin: [format_text(SSshuttle.emergencyLastCallLoc.name)].
    " - else - dat += "Latest emergency signal trace attempt failed.
    " - if(authenticated) - dat += "Current login: [auth_id]" - else - dat += "Current login: None" - dat += "

    General Functions" - dat += "
    \[ Message List \]" - if(SSshuttle.emergency.mode == SHUTTLE_IDLE) - dat += "
    \[ Call Emergency Shuttle \]" - dat += "
    \[ Set Status Display \]" - dat += "

    Special Functions" - dat += "
    \[ Make an Announcement \]" - dat += "
    \[ Change Alert Level \]" - dat += "
    \[ Emergency Maintenance Access \]" - if(STATE_CALLSHUTTLE) - dat += get_call_shuttle_form(1) - if(STATE_MESSAGELIST) - dat += "Messages:" - for(var/i in 1 to messages.len) - var/datum/comm_message/M = messages[i] - dat += "
    [M.title]" - if(STATE_VIEWMESSAGE) - if (aicurrmsg) - dat += "[aicurrmsg.title]

    [aicurrmsg.content]" - if(!aicurrmsg.answered && aicurrmsg.possible_answers.len) - for(var/i in 1 to aicurrmsg.possible_answers.len) - var/answer = aicurrmsg.possible_answers[i] - dat += "
    \[ Answer : [answer] \]" - else if(aicurrmsg.answered) - var/answered = aicurrmsg.possible_answers[aicurrmsg.answered] - dat += "
    Archived Answer : [answered]" - dat += "

    \[ Delete \]" - else - aistate = STATE_MESSAGELIST - attack_hand(user) - return null - if(STATE_DELMESSAGE) - if(aicurrmsg) - dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" - else - aistate = STATE_MESSAGELIST - attack_hand(user) - return - - if(STATE_STATUSDISPLAY) - dat += "Set Status Displays
    " - dat += "\[ Clear \]
    " - dat += "\[ Shuttle ETA \]
    " - dat += "\[ Message \]" - dat += "
    " - dat += "\[ Alert: None |" - dat += " Red Alert |" - dat += " Lockdown |" - dat += " Biohazard \]

    " - - if(STATE_ALERT_LEVEL) - dat += "Current alert level: [get_security_level()]
    " - if(GLOB.security_level == SEC_LEVEL_DELTA) - dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." - else - dat += "Amber
    " - dat += "Blue
    " - dat += "Green" - - if(STATE_TOGGLE_EMERGENCY) - if(GLOB.emergency_access == 1) - dat += "Emergency Maintenance Access is currently ENABLED" - dat += "
    Restore maintenance access restrictions?
    \[ OK | Cancel \]" - else - dat += "Emergency Maintenance Access is currently DISABLED" - dat += "
    Lift access restrictions on maintenance and external airlocks?
    \[ OK | Cancel \]" - - dat += "

    \[ [(aistate != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" - return dat - -/obj/machinery/computer/communications/proc/make_announcement(mob/living/user, is_silicon) - if(!SScommunications.can_announce(user, is_silicon)) - to_chat(user, "Intercomms recharging. Please stand by.") - return - var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?") - if(!input || !user.canUseTopic(src)) - return - SScommunications.make_announcement(user, is_silicon, input) - deadchat_broadcast("[user.real_name] made an priority announcement from [get_area_name(usr, TRUE)].", user) - -/obj/machinery/computer/communications/proc/post_status(command, data1, data2) - - var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) - - if(!frequency) - return - - var/datum/signal/status_signal = new(list("command" = command)) - switch(command) - if("message") - status_signal.data["msg1"] = data1 - status_signal.data["msg2"] = data2 - if("alert") - status_signal.data["picture_state"] = data1 - - frequency.post_signal(src, status_signal) - - -/obj/machinery/computer/communications/Destroy() - GLOB.shuttle_caller_list -= src - SSshuttle.autoEvac() - return ..() - -/obj/machinery/computer/communications/proc/overrideCooldown() - var/obj/item/circuitboard/computer/communications/CM = circuit - CM.lastTimeUsed = 0 - -/obj/machinery/computer/communications/proc/add_message(datum/comm_message/new_message) - messages += new_message - -/datum/comm_message - var/title - var/content - var/list/possible_answers = list() - var/answered - var/datum/callback/answer_callback - -/datum/comm_message/New(new_title,new_content,new_possible_answers) - ..() - if(new_title) - title = new_title - if(new_content) - content = new_content - if(new_possible_answers) - possible_answers = new_possible_answers +// The communications computer +/obj/machinery/computer/communications + name = "communications console" + desc = "A console used for high-priority announcements and emergencies." + icon_screen = "comm" + icon_keyboard = "tech_key" + req_access = list(ACCESS_HEADS) + circuit = /obj/item/circuitboard/computer/communications + var/auth_id = "Unknown" //Who is currently logged in? + var/list/datum/comm_message/messages = list() + var/datum/comm_message/currmsg + var/datum/comm_message/aicurrmsg + var/state = STATE_DEFAULT + var/aistate = STATE_DEFAULT + var/message_cooldown = 0 + var/ai_message_cooldown = 0 + var/tmp_alertlevel = 0 + var/const/STATE_DEFAULT = 1 + var/const/STATE_CALLSHUTTLE = 2 + var/const/STATE_CANCELSHUTTLE = 3 + var/const/STATE_MESSAGELIST = 4 + var/const/STATE_VIEWMESSAGE = 5 + var/const/STATE_DELMESSAGE = 6 + var/const/STATE_STATUSDISPLAY = 7 + var/const/STATE_ALERT_LEVEL = 8 + var/const/STATE_CONFIRM_LEVEL = 9 + var/const/STATE_TOGGLE_EMERGENCY = 10 + var/const/STATE_PURCHASE = 11 + + var/stat_msg1 + var/stat_msg2 + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/communications/proc/checkCCcooldown() + var/obj/item/circuitboard/computer/communications/CM = circuit + if(CM.lastTimeUsed + 600 > world.time) + return FALSE + return TRUE + +/obj/machinery/computer/communications/Initialize() + . = ..() + GLOB.shuttle_caller_list += src + +/obj/machinery/computer/communications/Topic(href, href_list) + if(..()) + return + if(!usr.canUseTopic(src)) + return + if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 + to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") + return + usr.set_machine(src) + + + if(!href_list["operation"]) + return + var/obj/item/circuitboard/computer/communications/CM = circuit + switch(href_list["operation"]) + // main interface + if("main") + state = STATE_DEFAULT + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + if("login") + var/mob/M = usr + + var/obj/item/card/id/I = M.get_idcard(TRUE) + + if(I && istype(I)) + if(check_access(I)) + authenticated = 1 + auth_id = "[I.registered_name] ([I.assignment])" + if((ACCESS_CAPTAIN in I.access)) + authenticated = 2 + playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) + if(obj_flags & EMAGGED) + authenticated = 2 + auth_id = "Unknown" + to_chat(M, "[src] lets out a quiet alarm as its login is overridden.") + playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0) + if(prob(25)) + for(var/mob/living/silicon/ai/AI in active_ais()) + SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons + if("logout") + authenticated = 0 + playsound(src, 'sound/machines/terminal_off.ogg', 50, 0) + + if("swipeidseclevel") + var/mob/M = usr + var/obj/item/card/id/I = M.get_active_held_item() + if (istype(I, /obj/item/pda)) + var/obj/item/pda/pda = I + I = pda.id + if (I && istype(I)) + if(ACCESS_CAPTAIN in I.access) + var/old_level = GLOB.security_level + if(!tmp_alertlevel) + tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel < SEC_LEVEL_GREEN) + tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel == SEC_LEVEL_BLUE) + tmp_alertlevel = SEC_LEVEL_BLUE + if(tmp_alertlevel > SEC_LEVEL_AMBER) + tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this + set_security_level(tmp_alertlevel) + if(GLOB.security_level != old_level) + to_chat(usr, "Authorization confirmed. Modifying security level.") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + //Only notify people if an actual change happened + var/security_level = get_security_level() + log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].") + message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].") + deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] with [src] at [get_area_name(usr, TRUE)].", usr) + tmp_alertlevel = 0 + else + to_chat(usr, "You are not authorized to do this!") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + tmp_alertlevel = 0 + state = STATE_DEFAULT + else + to_chat(usr, "You need to swipe your ID!") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + + if("announce") + if(authenticated==2) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + make_announcement(usr) + + if("crossserver") + if(authenticated==2) + if(!checkCCcooldown()) + to_chat(usr, "Arrays recycling. Please stand by.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "") + if(!input || !(usr in view(1,src)) || !checkCCcooldown()) + return + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + send2otherserver("[station_name()]", input,"Comms_Console") + minor_announce(input, title = "Outgoing message to allied station") + usr.log_talk(input, LOG_SAY, tag="message to the other server") + message_admins("[ADMIN_LOOKUPFLW(usr)] has sent a message to the other server.") + deadchat_broadcast("[usr.real_name] has sent an outgoing message to the other station(s).", usr) + CM.lastTimeUsed = world.time + + if("purchase_menu") + state = STATE_PURCHASE + + if("buyshuttle") + if(authenticated==2) + var/list/shuttles = flatten_list(SSmapping.shuttle_templates) + var/datum/map_template/shuttle/S = locate(href_list["chosen_shuttle"]) in shuttles + if(S && istype(S)) + if(SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_IDLE) + to_chat(usr, "It's a bit late to buy a new shuttle, don't you think?") + return + if(SSshuttle.shuttle_purchased) + to_chat(usr, "A replacement shuttle has already been purchased.") + else if(!S.prerequisites_met()) + to_chat(usr, "You have not met the requirements for purchasing this shuttle.") + else + if(SSshuttle.points >= S.credit_cost) + var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines + if(M) + SSshuttle.shuttle_purchased = TRUE + SSshuttle.points -= S.credit_cost + minor_announce("[usr.real_name] has purchased [S.name] for [S.credit_cost] credits." , "Shuttle Purchase") + message_admins("[ADMIN_LOOKUPFLW(usr)] purchased [S.name].") + SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]") + M.unload_preview() + M.load_template(S) + M.existing_shuttle = SSshuttle.emergency + M.action_load(S) + message_admins("[S.name] loaded, purchased by [usr]") + else + to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.") + else + to_chat(usr, "Not enough credits.") + + if("callshuttle") + state = STATE_DEFAULT + if(authenticated) + state = STATE_CALLSHUTTLE + if("callshuttle2") + if(authenticated) + SSshuttle.requestEvac(usr, href_list["call"]) + if(SSshuttle.emergency.timer) + post_status("shuttle") + state = STATE_DEFAULT + if("cancelshuttle") + state = STATE_DEFAULT + if(authenticated) + state = STATE_CANCELSHUTTLE + if("cancelshuttle2") + if(authenticated) + if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) //Citadel Edit Removing auto_call caused recall. + say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.") + else + SSshuttle.cancelEvac(usr) + state = STATE_DEFAULT + if("messagelist") + currmsg = 0 + state = STATE_MESSAGELIST + if("viewmessage") + state = STATE_VIEWMESSAGE + if (!currmsg) + if(href_list["message-num"]) + var/msgnum = text2num(href_list["message-num"]) + currmsg = messages[msgnum] + else + state = STATE_MESSAGELIST + if("delmessage") + state = currmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST + if("delmessage2") + if(authenticated) + if(currmsg) + if(aicurrmsg == currmsg) + aicurrmsg = null + messages -= currmsg + currmsg = null + state = STATE_MESSAGELIST + else + state = STATE_VIEWMESSAGE + if("respond") + var/answer = text2num(href_list["answer"]) + if(!currmsg || !answer || currmsg.possible_answers.len < answer) + state = STATE_MESSAGELIST + else + if(!currmsg.answered) + currmsg.answered = answer + log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]") + if(currmsg) + currmsg.answer_callback.InvokeAsync() + state = STATE_VIEWMESSAGE + updateDialog() + if("status") + state = STATE_STATUSDISPLAY + if("securitylevel") + tmp_alertlevel = text2num( href_list["newalertlevel"] ) + if(!tmp_alertlevel) + tmp_alertlevel = 0 + state = STATE_CONFIRM_LEVEL + if("changeseclevel") + state = STATE_ALERT_LEVEL + + if("emergencyaccess") + state = STATE_TOGGLE_EMERGENCY + if("enableemergency") + make_maint_all_access() + log_game("[key_name(usr)] enabled emergency maintenance access.") + message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.") + deadchat_broadcast("[usr.real_name] enabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr) + state = STATE_DEFAULT + if("disableemergency") + revoke_maint_all_access() + log_game("[key_name(usr)] disabled emergency maintenance access.") + message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.") + deadchat_broadcast("[usr.real_name] disabled emergency maintenance access at [get_area_name(usr, TRUE)].", usr) + state = STATE_DEFAULT + + // Status display stuff + if("setstat") + playsound(src, "terminal_type", 50, 0) + switch(href_list["statdisp"]) + if("message") + post_status("message", stat_msg1, stat_msg2) + if("alert") + post_status("alert", href_list["alert"]) + else + post_status(href_list["statdisp"]) + + if("setmsg1") + stat_msg1 = reject_bad_text(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40) + updateDialog() + if("setmsg2") + stat_msg2 = reject_bad_text(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40) + updateDialog() + + // OMG CENTCOM LETTERHEAD + if("MessageCentCom") + if(authenticated) + if(!checkCCcooldown()) + to_chat(usr, "Arrays recycling. Please stand by.") + return + var/input = stripped_input(usr, "Please choose a message to transmit to CentCom via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to CentCom.", "") + if(!input || !(usr in view(1,src)) || !checkCCcooldown()) + return + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + CentCom_announce(input, usr) + to_chat(usr, "Message transmitted to Central Command.") + usr.log_talk(input, LOG_SAY, tag="CentCom announcement") + deadchat_broadcast("[usr.real_name] has messaged CentCom, \"[input]\" at [get_area_name(usr, TRUE)].", usr) + CM.lastTimeUsed = world.time + + // OMG SYNDICATE ...LETTERHEAD + if("MessageSyndicate") + if((authenticated==2) && (obj_flags & EMAGGED)) + if(!checkCCcooldown()) + to_chat(usr, "Arrays recycling. Please stand by.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to /??????/.", "") + if(!input || !(usr in view(1,src)) || !checkCCcooldown()) + return + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + Syndicate_announce(input, usr) + to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.") + usr.log_talk(input, LOG_SAY, tag="Syndicate announcement") + deadchat_broadcast("[usr.real_name] has messaged the Syndicate, \"[input]\" at [get_area_name(usr, TRUE)].", usr) + CM.lastTimeUsed = world.time + + if("RestoreBackup") + to_chat(usr, "Backup routing data restored!") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + obj_flags &= ~EMAGGED + updateDialog() + + if("nukerequest") //When there's no other way + if(authenticated==2) + if(!checkCCcooldown()) + to_chat(usr, "Arrays recycling. Please stand by.") + return + var/input = stripped_input(usr, "Please enter the reason for requesting the nuclear self-destruct codes. Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response.", "Self Destruct Code Request.","") + if(!input || !(usr in view(1,src)) || !checkCCcooldown()) + return + Nuke_request(input, usr) + to_chat(usr, "Request sent.") + usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) + priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport") + CM.lastTimeUsed = world.time + + + // AI interface + if("ai-main") + aicurrmsg = null + aistate = STATE_DEFAULT + if("ai-callshuttle") + aistate = STATE_CALLSHUTTLE + if("ai-callshuttle2") + SSshuttle.requestEvac(usr, href_list["call"]) + aistate = STATE_DEFAULT + if("ai-messagelist") + aicurrmsg = null + aistate = STATE_MESSAGELIST + if("ai-viewmessage") + aistate = STATE_VIEWMESSAGE + if (!aicurrmsg) + if(href_list["message-num"]) + var/msgnum = text2num(href_list["message-num"]) + aicurrmsg = messages[msgnum] + else + aistate = STATE_MESSAGELIST + if("ai-delmessage") + aistate = aicurrmsg ? STATE_DELMESSAGE : STATE_MESSAGELIST + if("ai-delmessage2") + if(aicurrmsg) + if(currmsg == aicurrmsg) + currmsg = null + messages -= aicurrmsg + aicurrmsg = null + aistate = STATE_MESSAGELIST + if("ai-respond") + var/answer = text2num(href_list["answer"]) + if(!aicurrmsg || !answer || aicurrmsg.possible_answers.len < answer) + aistate = STATE_MESSAGELIST + else + if(!aicurrmsg.answered) + aicurrmsg.answered = answer + log_game("[key_name(usr)] answered [aicurrmsg.title] comm message. Answer : [aicurrmsg.answered]") + if(aicurrmsg.answer_callback) + aicurrmsg.answer_callback.InvokeAsync() + aistate = STATE_VIEWMESSAGE + if("ai-status") + aistate = STATE_STATUSDISPLAY + if("ai-announce") + make_announcement(usr, 1) + if("ai-securitylevel") + tmp_alertlevel = text2num( href_list["newalertlevel"] ) + if(!tmp_alertlevel) + tmp_alertlevel = 0 + var/old_level = GLOB.security_level + if(!tmp_alertlevel) + tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel < SEC_LEVEL_GREEN) + tmp_alertlevel = SEC_LEVEL_GREEN + if(tmp_alertlevel == SEC_LEVEL_BLUE) + tmp_alertlevel = SEC_LEVEL_BLUE + if(tmp_alertlevel > SEC_LEVEL_AMBER) + tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this + set_security_level(tmp_alertlevel) + if(GLOB.security_level != old_level) + //Only notify people if an actual change happened + var/security_level = get_security_level() + log_game("[key_name(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].") + message_admins("[ADMIN_LOOKUPFLW(usr)] has changed the security level to [security_level] from [src] at [AREACOORD(usr)].") + deadchat_broadcast("[usr.real_name] has changed the security level to [security_level] from [src] at [get_area_name(usr, TRUE)].", usr) + tmp_alertlevel = 0 + aistate = STATE_DEFAULT + if("ai-changeseclevel") + aistate = STATE_ALERT_LEVEL + if("ai-emergencyaccess") + aistate = STATE_TOGGLE_EMERGENCY + if("ai-enableemergency") + make_maint_all_access() + log_game("[key_name(usr)] enabled emergency maintenance access.") + message_admins("[ADMIN_LOOKUPFLW(usr)] enabled emergency maintenance access.") + deadchat_broadcast("[usr.real_name] enabled emergency maintenance access.", usr) + aistate = STATE_DEFAULT + if("ai-disableemergency") + revoke_maint_all_access() + log_game("[key_name(usr)] disabled emergency maintenance access.") + message_admins("[ADMIN_LOOKUPFLW(usr)] disabled emergency maintenance access.") + deadchat_broadcast("[usr.real_name] disabled emergency maintenance access.", usr) + aistate = STATE_DEFAULT + + updateUsrDialog() + +/obj/machinery/computer/communications/attackby(obj/I, mob/user, params) + if(istype(I, /obj/item/card/id)) + attack_hand(user) + else + return ..() + +/obj/machinery/computer/communications/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + SSshuttle.shuttle_purchase_requirements_met |= "emagged" + if(authenticated == 1) + authenticated = 2 + to_chat(user, "You scramble the communication routing circuits!") + playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + return TRUE + +/obj/machinery/computer/communications/ui_interact(mob/user) + . = ..() + if (z > 6) + to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") + return + + var/dat = "" + if(SSshuttle.emergency.mode == SHUTTLE_CALL) + var/timeleft = SSshuttle.emergency.timeLeft() + dat += "Emergency shuttle\n
    \nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]" + + + var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + + if(issilicon(user)) + var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access + if(dat2) + dat += dat2 + popup.set_content(dat) + popup.open() + return + + switch(state) + if(STATE_DEFAULT) + if (authenticated) + if(SSshuttle.emergencyCallAmount) + if(SSshuttle.emergencyLastCallLoc) + dat += "Most recent shuttle call/recall traced to: [format_text(SSshuttle.emergencyLastCallLoc.name)]
    " + else + dat += "Unable to trace most recent shuttle call/recall signal.
    " + dat += "Logged in as: [auth_id]" + dat += "
    " + dat += "
    \[ Log Out \]
    " + dat += "
    General Functions" + dat += "
    \[ Message List \]" + switch(SSshuttle.emergency.mode) + if(SHUTTLE_IDLE, SHUTTLE_RECALL) + dat += "
    \[ Call Emergency Shuttle \]" + else + dat += "
    \[ Cancel Shuttle Call \]" + + dat += "
    \[ Set Status Display \]" + if (authenticated==2) + dat += "

    Captain Functions" + dat += "
    \[ Make a Captain's Announcement \]" + var/cross_servers_count = length(CONFIG_GET(keyed_list/cross_server)) + if(cross_servers_count) + dat += "
    \[ Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""] \]" + if(SSmapping.config.allow_custom_shuttles) + dat += "
    \[ Purchase Shuttle \]" + dat += "
    \[ Change Alert Level \]" + dat += "
    \[ Emergency Maintenance Access \]" + dat += "
    \[ Request Nuclear Authentication Codes \]" + if(!(obj_flags & EMAGGED)) + dat += "
    \[ Send Message to CentCom \]" + else + dat += "
    \[ Send Message to \[UNKNOWN\] \]" + dat += "
    \[ Restore Backup Routing Data \]" + else + dat += "
    \[ Log In \]" + if(STATE_CALLSHUTTLE) + dat += get_call_shuttle_form() + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + if(STATE_CANCELSHUTTLE) + dat += get_cancel_shuttle_form() + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + if(STATE_MESSAGELIST) + dat += "Messages:" + for(var/i in 1 to messages.len) + var/datum/comm_message/M = messages[i] + dat += "
    [M.title]" + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + if(STATE_VIEWMESSAGE) + if (currmsg) + dat += "[currmsg.title]

    [currmsg.content]" + if(!currmsg.answered && currmsg.possible_answers.len) + for(var/i in 1 to currmsg.possible_answers.len) + var/answer = currmsg.possible_answers[i] + dat += "
    \[ Answer : [answer] \]" + else if(currmsg.answered) + var/answered = currmsg.possible_answers[currmsg.answered] + dat += "
    Archived Answer : [answered]" + dat += "

    \[ Delete \]" + else + aistate = STATE_MESSAGELIST + attack_hand(user) + return + if(STATE_DELMESSAGE) + if (currmsg) + dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" + else + state = STATE_MESSAGELIST + attack_hand(user) + return + if(STATE_STATUSDISPLAY) + dat += "Set Status Displays
    " + dat += "\[ Clear \]
    " + dat += "\[ Shuttle ETA \]
    " + dat += "\[ Message \]" + dat += "
    " + dat += "\[ Alert: None |" + dat += " Red Alert |" + dat += " Lockdown |" + dat += " Biohazard \]

    " + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + if(STATE_ALERT_LEVEL) + dat += "Current alert level: [get_security_level()]
    " + if(GLOB.security_level == SEC_LEVEL_DELTA) + dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." + else + dat += "Amber
    " + dat += "Blue
    " + dat += "Green" + if(STATE_CONFIRM_LEVEL) + dat += "Current alert level: [get_security_level()]
    " + dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]
    " + dat += "Swipe ID to confirm change.
    " + if(STATE_TOGGLE_EMERGENCY) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + if(GLOB.emergency_access == 1) + dat += "Emergency Maintenance Access is currently ENABLED" + dat += "
    Restore maintenance access restrictions?
    \[ OK | Cancel \]" + else + dat += "Emergency Maintenance Access is currently DISABLED" + dat += "
    Lift access restrictions on maintenance and external airlocks?
    \[ OK | Cancel \]" + + if(STATE_PURCHASE) + dat += "Budget: [SSshuttle.points] Credits.
    " + dat += "
    " + dat += "Caution: Purchasing dangerous shuttles may lead to mutiny and/or death.
    " + dat += "
    " + for(var/shuttle_id in SSmapping.shuttle_templates) + var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] + if(S.can_be_bought && S.credit_cost < INFINITY) + dat += "[S.name] | [S.credit_cost] Credits
    " + dat += "[S.description]
    " + if(S.prerequisites) + dat += "Prerequisites: [S.prerequisites]
    " + dat += "(Purchase)

    " + + dat += "

    \[ [(state != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" + + popup.set_content(dat) + popup.open() + +/obj/machinery/computer/communications/proc/get_javascript_header(form_id) + var/dat = {""} + return dat + +/obj/machinery/computer/communications/proc/get_call_shuttle_form(ai_interface = 0) + var/form_id = "callshuttle" + var/dat = get_javascript_header(form_id) + dat += "" + dat += "" + dat += "" + dat += "Nature of emergency:
    " + dat += "
    Are you sure you want to call the shuttle? \[ Call \]" + return dat + +/obj/machinery/computer/communications/proc/get_cancel_shuttle_form() + var/form_id = "cancelshuttle" + var/dat = get_javascript_header(form_id) + dat += "" + dat += "" + dat += "" + + dat += "
    Are you sure you want to cancel the shuttle? \[ Cancel \]" + return dat + +/obj/machinery/computer/communications/proc/interact_ai(mob/living/silicon/ai/user) + var/dat = "" + switch(aistate) + if(STATE_DEFAULT) + if(SSshuttle.emergencyCallAmount) + if(SSshuttle.emergencyLastCallLoc) + dat += "Latest emergency signal trace attempt successful.
    Last signal origin: [format_text(SSshuttle.emergencyLastCallLoc.name)].
    " + else + dat += "Latest emergency signal trace attempt failed.
    " + if(authenticated) + dat += "Current login: [auth_id]" + else + dat += "Current login: None" + dat += "

    General Functions" + dat += "
    \[ Message List \]" + if(SSshuttle.emergency.mode == SHUTTLE_IDLE) + dat += "
    \[ Call Emergency Shuttle \]" + dat += "
    \[ Set Status Display \]" + dat += "

    Special Functions" + dat += "
    \[ Make an Announcement \]" + dat += "
    \[ Change Alert Level \]" + dat += "
    \[ Emergency Maintenance Access \]" + if(STATE_CALLSHUTTLE) + dat += get_call_shuttle_form(1) + if(STATE_MESSAGELIST) + dat += "Messages:" + for(var/i in 1 to messages.len) + var/datum/comm_message/M = messages[i] + dat += "
    [M.title]" + if(STATE_VIEWMESSAGE) + if (aicurrmsg) + dat += "[aicurrmsg.title]

    [aicurrmsg.content]" + if(!aicurrmsg.answered && aicurrmsg.possible_answers.len) + for(var/i in 1 to aicurrmsg.possible_answers.len) + var/answer = aicurrmsg.possible_answers[i] + dat += "
    \[ Answer : [answer] \]" + else if(aicurrmsg.answered) + var/answered = aicurrmsg.possible_answers[aicurrmsg.answered] + dat += "
    Archived Answer : [answered]" + dat += "

    \[ Delete \]" + else + aistate = STATE_MESSAGELIST + attack_hand(user) + return null + if(STATE_DELMESSAGE) + if(aicurrmsg) + dat += "Are you sure you want to delete this message? \[ OK | Cancel \]" + else + aistate = STATE_MESSAGELIST + attack_hand(user) + return + + if(STATE_STATUSDISPLAY) + dat += "Set Status Displays
    " + dat += "\[ Clear \]
    " + dat += "\[ Shuttle ETA \]
    " + dat += "\[ Message \]" + dat += "
    " + dat += "\[ Alert: None |" + dat += " Red Alert |" + dat += " Lockdown |" + dat += " Biohazard \]

    " + + if(STATE_ALERT_LEVEL) + dat += "Current alert level: [get_security_level()]
    " + if(GLOB.security_level == SEC_LEVEL_DELTA) + dat += "The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate." + else + dat += "Amber
    " + dat += "Blue
    " + dat += "Green" + + if(STATE_TOGGLE_EMERGENCY) + if(GLOB.emergency_access == 1) + dat += "Emergency Maintenance Access is currently ENABLED" + dat += "
    Restore maintenance access restrictions?
    \[ OK | Cancel \]" + else + dat += "Emergency Maintenance Access is currently DISABLED" + dat += "
    Lift access restrictions on maintenance and external airlocks?
    \[ OK | Cancel \]" + + dat += "

    \[ [(aistate != STATE_DEFAULT) ? "Main Menu | " : ""]Close \]" + return dat + +/obj/machinery/computer/communications/proc/make_announcement(mob/living/user, is_silicon) + if(!SScommunications.can_announce(user, is_silicon)) + to_chat(user, "Intercomms recharging. Please stand by.") + return + var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?") + if(!input || !user.canUseTopic(src)) + return + SScommunications.make_announcement(user, is_silicon, input) + deadchat_broadcast("[user.real_name] made an priority announcement from [get_area_name(usr, TRUE)].", user) + +/obj/machinery/computer/communications/proc/post_status(command, data1, data2) + + var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) + + if(!frequency) + return + + var/datum/signal/status_signal = new(list("command" = command)) + switch(command) + if("message") + status_signal.data["msg1"] = data1 + status_signal.data["msg2"] = data2 + if("alert") + status_signal.data["picture_state"] = data1 + + frequency.post_signal(src, status_signal) + + +/obj/machinery/computer/communications/Destroy() + GLOB.shuttle_caller_list -= src + SSshuttle.autoEvac() + return ..() + +/obj/machinery/computer/communications/proc/overrideCooldown() + var/obj/item/circuitboard/computer/communications/CM = circuit + CM.lastTimeUsed = 0 + +/obj/machinery/computer/communications/proc/add_message(datum/comm_message/new_message) + messages += new_message + +/datum/comm_message + var/title + var/content + var/list/possible_answers = list() + var/answered + var/datum/callback/answer_callback + +/datum/comm_message/New(new_title,new_content,new_possible_answers) + ..() + if(new_title) + title = new_title + if(new_content) + content = new_content + if(new_possible_answers) + possible_answers = new_possible_answers diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index c11f7d9edc..f6d0fcfc0d 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -1,210 +1,210 @@ -#define SENSORS_UPDATE_PERIOD 100 //How often the sensor data updates. - -/obj/machinery/computer/crew - name = "crew monitoring console" - desc = "Used to monitor active health sensors built into most of the crew's uniforms." - icon_screen = "crew" - icon_keyboard = "med_key" - use_power = IDLE_POWER_USE - idle_power_usage = 250 - active_power_usage = 500 - circuit = /obj/item/circuitboard/computer/crew - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/crew/syndie - icon_keyboard = "syndie_key" - -/obj/machinery/computer/crew/interact(mob/user) - GLOB.crewmonitor.show(user,src) - -GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) - -/datum/crewmonitor - var/list/ui_sources = list() //List of user -> ui source - var/list/jobs - var/list/data_by_z = list() - var/list/last_update = list() - -/datum/crewmonitor/New() - . = ..() - - var/list/jobs = new/list() - jobs["Captain"] = 00 - jobs["Head of Security"] = 10 - jobs["Warden"] = 11 - jobs["Security Officer"] = 12 - jobs["Detective"] = 13 - jobs["Chief Medical Officer"] = 20 - jobs["Chemist"] = 21 - jobs["Geneticist"] = 22 - jobs["Virologist"] = 23 - jobs["Medical Doctor"] = 24 - jobs["Research Director"] = 30 - jobs["Scientist"] = 31 - jobs["Roboticist"] = 32 - jobs["Chief Engineer"] = 40 - jobs["Station Engineer"] = 41 - jobs["Atmospheric Technician"] = 42 - jobs["Quartermaster"] = 50 - jobs["Shaft Miner"] = 51 - jobs["Cargo Technician"] = 52 - jobs["Head of Personnel"] = 60 - jobs["Bartender"] = 61 - jobs["Cook"] = 62 - jobs["Botanist"] = 63 - jobs["Curator"] = 64 - jobs["Chaplain"] = 65 - jobs["Clown"] = 66 - jobs["Mime"] = 67 - jobs["Janitor"] = 68 - jobs["Lawyer"] = 69 - jobs["Admiral"] = 200 - jobs["CentCom Commander"] = 210 - jobs["Custodian"] = 211 - jobs["Medical Officer"] = 212 - jobs["Research Officer"] = 213 - jobs["Emergency Response Team Commander"] = 220 - jobs["Security Response Officer"] = 221 - jobs["Engineer Response Officer"] = 222 - jobs["Medical Response Officer"] = 223 - jobs["Assistant"] = 999 //Unknowns/custom jobs should appear after civilians, and before assistants - - src.jobs = jobs - -/datum/crewmonitor/Destroy() - return ..() - -/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if (!ui) - ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state) - ui.open() - -/datum/crewmonitor/proc/show(mob/M, source) - ui_sources[M] = source - ui_interact(M) - -/datum/crewmonitor/ui_host(mob/user) - return ui_sources[user] - -/datum/crewmonitor/ui_data(mob/user) - var/z = user.z - if(!z) - var/turf/T = get_turf(user) - z = T.z - var/list/zdata = update_data(z) - . = list() - .["sensors"] = zdata - .["link_allowed"] = isAI(user) - -/datum/crewmonitor/proc/update_data(z) - if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD) - return data_by_z["[z]"] - - var/list/results_damaged = list() - var/list/results_undamaged = list() - - var/obj/item/clothing/under/U - var/obj/item/card/id/I - var/turf/pos - var/ijob - var/name - var/assignment - var/oxydam - var/toxdam - var/burndam - var/brutedam - var/totaldam - var/area - var/pos_x - var/pos_y - var/life_status - - for(var/mob/living/carbon/human/H in GLOB.carbon_list) - var/nanite_sensors = FALSE - if(H in SSnanites.nanite_monitored_mobs) - nanite_sensors = TRUE - // Check if their z-level is correct and if they are wearing a uniform. - // Accept H.z==0 as well in case the mob is inside an object. - if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under) || nanite_sensors) - U = H.w_uniform - - // Are the suit sensors on? - if (nanite_sensors || ((U.has_sensor > 0) && U.sensor_mode)) - pos = H.z == 0 || (nanite_sensors || U.sensor_mode == SENSOR_COORDS) ? get_turf(H) : null - - // Special case: If the mob is inside an object confirm the z-level on turf level. - if (H.z == 0 && (!pos || pos.z != z)) - continue - - I = H.wear_id ? H.wear_id.GetID() : null - - if (I) - name = I.registered_name - assignment = I.assignment - ijob = jobs[I.assignment] - else - name = "Unknown" - assignment = "" - ijob = 80 - - if (nanite_sensors || U.sensor_mode >= SENSOR_LIVING) - life_status = (!H.stat ? TRUE : FALSE) - else - life_status = null - - if (nanite_sensors || U.sensor_mode >= SENSOR_VITALS) - oxydam = round(H.getOxyLoss(),1) - toxdam = round(H.getToxLoss(),1) - burndam = round(H.getFireLoss(),1) - brutedam = round(H.getBruteLoss(),1) - totaldam = oxydam + toxdam + burndam + brutedam - else - oxydam = null - toxdam = null - burndam = null - brutedam = null - totaldam = 0 - - if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS) - if (!pos) - pos = get_turf(H) - area = get_area_name(H, TRUE) - pos_x = pos.x - pos_y = pos.y - else - area = null - pos_x = null - pos_y = null - - var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null)) - - if(totaldam) - results_damaged[++results_damaged.len] = total_list - else - results_undamaged[++results_undamaged.len] = total_list - - var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare) - - data_by_z["[z]"] = returning - last_update["[z]"] = world.time - - return returning - -/proc/ijob_compare(list/a,list/b) - return a["ijob"] - b["ijob"] - -/proc/damage_compare(list/a,list/b) - return b["totaldam"] - a["totaldam"] - -/datum/crewmonitor/ui_act(action,params) - var/mob/living/silicon/ai/AI = usr - if(!istype(AI)) - return - switch (action) - if ("select_person") - AI.ai_camera_track(params["name"]) - +#define SENSORS_UPDATE_PERIOD 100 //How often the sensor data updates. + +/obj/machinery/computer/crew + name = "crew monitoring console" + desc = "Used to monitor active health sensors built into most of the crew's uniforms." + icon_screen = "crew" + icon_keyboard = "med_key" + use_power = IDLE_POWER_USE + idle_power_usage = 250 + active_power_usage = 500 + circuit = /obj/item/circuitboard/computer/crew + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/crew/syndie + icon_keyboard = "syndie_key" + +/obj/machinery/computer/crew/interact(mob/user) + GLOB.crewmonitor.show(user,src) + +GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) + +/datum/crewmonitor + var/list/ui_sources = list() //List of user -> ui source + var/list/jobs + var/list/data_by_z = list() + var/list/last_update = list() + +/datum/crewmonitor/New() + . = ..() + + var/list/jobs = new/list() + jobs["Captain"] = 00 + jobs["Head of Security"] = 10 + jobs["Warden"] = 11 + jobs["Security Officer"] = 12 + jobs["Detective"] = 13 + jobs["Chief Medical Officer"] = 20 + jobs["Chemist"] = 21 + jobs["Geneticist"] = 22 + jobs["Virologist"] = 23 + jobs["Medical Doctor"] = 24 + jobs["Research Director"] = 30 + jobs["Scientist"] = 31 + jobs["Roboticist"] = 32 + jobs["Chief Engineer"] = 40 + jobs["Station Engineer"] = 41 + jobs["Atmospheric Technician"] = 42 + jobs["Quartermaster"] = 50 + jobs["Shaft Miner"] = 51 + jobs["Cargo Technician"] = 52 + jobs["Head of Personnel"] = 60 + jobs["Bartender"] = 61 + jobs["Cook"] = 62 + jobs["Botanist"] = 63 + jobs["Curator"] = 64 + jobs["Chaplain"] = 65 + jobs["Clown"] = 66 + jobs["Mime"] = 67 + jobs["Janitor"] = 68 + jobs["Lawyer"] = 69 + jobs["Admiral"] = 200 + jobs["CentCom Commander"] = 210 + jobs["Custodian"] = 211 + jobs["Medical Officer"] = 212 + jobs["Research Officer"] = 213 + jobs["Emergency Response Team Commander"] = 220 + jobs["Security Response Officer"] = 221 + jobs["Engineer Response Officer"] = 222 + jobs["Medical Response Officer"] = 223 + jobs["Assistant"] = 999 //Unknowns/custom jobs should appear after civilians, and before assistants + + src.jobs = jobs + +/datum/crewmonitor/Destroy() + return ..() + +/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if (!ui) + ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state) + ui.open() + +/datum/crewmonitor/proc/show(mob/M, source) + ui_sources[M] = source + ui_interact(M) + +/datum/crewmonitor/ui_host(mob/user) + return ui_sources[user] + +/datum/crewmonitor/ui_data(mob/user) + var/z = user.z + if(!z) + var/turf/T = get_turf(user) + z = T.z + var/list/zdata = update_data(z) + . = list() + .["sensors"] = zdata + .["link_allowed"] = isAI(user) + +/datum/crewmonitor/proc/update_data(z) + if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD) + return data_by_z["[z]"] + + var/list/results_damaged = list() + var/list/results_undamaged = list() + + var/obj/item/clothing/under/U + var/obj/item/card/id/I + var/turf/pos + var/ijob + var/name + var/assignment + var/oxydam + var/toxdam + var/burndam + var/brutedam + var/totaldam + var/area + var/pos_x + var/pos_y + var/life_status + + for(var/mob/living/carbon/human/H in GLOB.carbon_list) + var/nanite_sensors = FALSE + if(H in SSnanites.nanite_monitored_mobs) + nanite_sensors = TRUE + // Check if their z-level is correct and if they are wearing a uniform. + // Accept H.z==0 as well in case the mob is inside an object. + if ((H.z == 0 || H.z == z) && istype(H.w_uniform, /obj/item/clothing/under) || nanite_sensors) + U = H.w_uniform + + // Are the suit sensors on? + if (nanite_sensors || ((U.has_sensor > 0) && U.sensor_mode)) + pos = H.z == 0 || (nanite_sensors || U.sensor_mode == SENSOR_COORDS) ? get_turf(H) : null + + // Special case: If the mob is inside an object confirm the z-level on turf level. + if (H.z == 0 && (!pos || pos.z != z)) + continue + + I = H.wear_id ? H.wear_id.GetID() : null + + if (I) + name = I.registered_name + assignment = I.assignment + ijob = jobs[I.assignment] + else + name = "Unknown" + assignment = "" + ijob = 80 + + if (nanite_sensors || U.sensor_mode >= SENSOR_LIVING) + life_status = (!H.stat ? TRUE : FALSE) + else + life_status = null + + if (nanite_sensors || U.sensor_mode >= SENSOR_VITALS) + oxydam = round(H.getOxyLoss(),1) + toxdam = round(H.getToxLoss(),1) + burndam = round(H.getFireLoss(),1) + brutedam = round(H.getBruteLoss(),1) + totaldam = oxydam + toxdam + burndam + brutedam + else + oxydam = null + toxdam = null + burndam = null + brutedam = null + totaldam = 0 + + if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS) + if (!pos) + pos = get_turf(H) + area = get_area_name(H, TRUE) + pos_x = pos.x + pos_y = pos.y + else + area = null + pos_x = null + pos_y = null + + var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null)) + + if(totaldam) + results_damaged[++results_damaged.len] = total_list + else + results_undamaged[++results_undamaged.len] = total_list + + var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare) + + data_by_z["[z]"] = returning + last_update["[z]"] = world.time + + return returning + +/proc/ijob_compare(list/a,list/b) + return a["ijob"] - b["ijob"] + +/proc/damage_compare(list/a,list/b) + return b["totaldam"] - a["totaldam"] + +/datum/crewmonitor/ui_act(action,params) + var/mob/living/silicon/ai/AI = usr + if(!istype(AI)) + return + switch (action) + if ("select_person") + AI.ai_camera_track(params["name"]) + #undef SENSORS_UPDATE_PERIOD \ No newline at end of file diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm index 25b82ac143..fa6d4327a4 100644 --- a/code/game/machinery/computer/law.dm +++ b/code/game/machinery/computer/law.dm @@ -1,72 +1,72 @@ - - -/obj/machinery/computer/upload - var/mob/living/silicon/current = null //The target of future law uploads - icon_screen = "command" - -/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/aiModule)) - var/obj/item/aiModule/M = O - if(src.stat & (NOPOWER|BROKEN|MAINT)) - return - if(!current) - to_chat(user, "You haven't selected anything to transmit laws to!") - return - if(!can_upload_to(current)) - to_chat(user, "Upload failed! Check to make sure [current.name] is functioning properly.") - current = null - return - var/turf/currentloc = get_turf(current) - if(currentloc && user.z != currentloc.z) - to_chat(user, "Upload failed! Unable to establish a connection to [current.name]. You're too far away!") - current = null - return - M.install(current.laws, user) - else - return ..() - -/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S) - if(S.stat == DEAD) - return 0 - return 1 - -/obj/machinery/computer/upload/ai - name = "\improper AI upload console" - desc = "Used to upload laws to the AI." - circuit = /obj/item/circuitboard/computer/aiupload - -/obj/machinery/computer/upload/ai/interact(mob/user) - src.current = select_active_ai(user) - - if (!src.current) - to_chat(user, "No active AIs detected!") - else - to_chat(user, "[src.current.name] selected for law changes.") - -/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A) - if(!A || !isAI(A)) - return 0 - if(A.control_disabled) - return 0 - return ..() - - -/obj/machinery/computer/upload/borg - name = "cyborg upload console" - desc = "Used to upload laws to Cyborgs." - circuit = /obj/item/circuitboard/computer/borgupload - -/obj/machinery/computer/upload/borg/interact(mob/user) - src.current = select_active_free_borg(user) - - if(!src.current) - to_chat(user, "No active unslaved cyborgs detected!") - else - to_chat(user, "[src.current.name] selected for law changes.") - -/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B) - if(!B || !iscyborg(B)) - return 0 - if(B.scrambledcodes || B.emagged) - return 0 + + +/obj/machinery/computer/upload + var/mob/living/silicon/current = null //The target of future law uploads + icon_screen = "command" + +/obj/machinery/computer/upload/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/aiModule)) + var/obj/item/aiModule/M = O + if(src.stat & (NOPOWER|BROKEN|MAINT)) + return + if(!current) + to_chat(user, "You haven't selected anything to transmit laws to!") + return + if(!can_upload_to(current)) + to_chat(user, "Upload failed! Check to make sure [current.name] is functioning properly.") + current = null + return + var/turf/currentloc = get_turf(current) + if(currentloc && user.z != currentloc.z) + to_chat(user, "Upload failed! Unable to establish a connection to [current.name]. You're too far away!") + current = null + return + M.install(current.laws, user) + else + return ..() + +/obj/machinery/computer/upload/proc/can_upload_to(mob/living/silicon/S) + if(S.stat == DEAD) + return 0 + return 1 + +/obj/machinery/computer/upload/ai + name = "\improper AI upload console" + desc = "Used to upload laws to the AI." + circuit = /obj/item/circuitboard/computer/aiupload + +/obj/machinery/computer/upload/ai/interact(mob/user) + src.current = select_active_ai(user) + + if (!src.current) + to_chat(user, "No active AIs detected!") + else + to_chat(user, "[src.current.name] selected for law changes.") + +/obj/machinery/computer/upload/ai/can_upload_to(mob/living/silicon/ai/A) + if(!A || !isAI(A)) + return 0 + if(A.control_disabled) + return 0 + return ..() + + +/obj/machinery/computer/upload/borg + name = "cyborg upload console" + desc = "Used to upload laws to Cyborgs." + circuit = /obj/item/circuitboard/computer/borgupload + +/obj/machinery/computer/upload/borg/interact(mob/user) + src.current = select_active_free_borg(user) + + if(!src.current) + to_chat(user, "No active unslaved cyborgs detected!") + else + to_chat(user, "[src.current.name] selected for law changes.") + +/obj/machinery/computer/upload/borg/can_upload_to(mob/living/silicon/robot/B) + if(!B || !iscyborg(B)) + return 0 + if(B.scrambledcodes || B.emagged) + return 0 return ..() \ No newline at end of file diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 33de8bfce2..29055e87c3 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -1,585 +1,585 @@ - - -/obj/machinery/computer/med_data//TODO:SANITY - name = "medical records console" - desc = "This can be used to check medical records." - icon_screen = "medcomp" - icon_keyboard = "med_key" - req_one_access = list(ACCESS_MEDICAL, ACCESS_FORENSICS_LOCKERS) - circuit = /obj/item/circuitboard/computer/med_data - var/rank = null - var/screen = null - var/datum/data/record/active1 - var/datum/data/record/active2 - var/temp = null - var/printing = null - //Sorting Variables - var/sortBy = "name" - var/order = 1 // -1 = Descending - 1 = Ascending - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/med_data/syndie - icon_keyboard = "syndie_key" - -/obj/machinery/computer/med_data/ui_interact(mob/user) - . = ..() - if(isliving(user)) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - var/dat - if(temp) - dat = text("[temp]

    Clear Screen") - else - if(authenticated) - switch(screen) - if(1) - dat += {" -Search Records -
    List Records -
    -
    Virus Database -
    Medbot Tracking -
    -
    Record Maintenance -
    {Log Out}
    -"} - if(2) - dat += {" -

    - - - - -
    Records:
    - - - - - - - - -"} - - - if(!isnull(GLOB.data_core.general)) - for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) - var/blood_type = "" - var/b_dna = "" - for(var/datum/data/record/E in GLOB.data_core.medical) - if((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) - blood_type = E.fields["blood_type"] - b_dna = E.fields["b_dna"] - var/background - - if(R.fields["m_stat"] == "*Insane*" || R.fields["p_stat"] == "*Deceased*") - background = "'background-color:#990000;'" - else if(R.fields["p_stat"] == "*Unconscious*" || R.fields["m_stat"] == "*Unstable*") - background = "'background-color:#CD6500;'" - else if(R.fields["p_stat"] == "Physically Unfit" || R.fields["m_stat"] == "*Watch*") - background = "'background-color:#3BB9FF;'" - else - background = "'background-color:#4F7529;'" - - dat += text("", background, R.fields["id"], R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["fingerprint"], b_dna) - dat += text("", blood_type) - dat += text("", R.fields["p_stat"]) - dat += text("", R.fields["m_stat"]) - dat += "
    NameIDFingerprints (F) | DNA (D)Blood TypePhysical StatusMental Status
    [][]F: []
    D: []
    [][][]

    " - dat += "
    Back" - if(3) - dat += "Records Maintenance
    \nBackup To Disk
    \nUpload From Disk
    \nDelete All Records
    \n
    \nBack" - if(4) - - dat += "" - if(active1 in GLOB.data_core.general) - if(istype(active1.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P1 = active1.fields["photo_front"] - user << browse_rsc(P1.picture.picture_image, "photo_front") - if(istype(active1.fields["photo_side"], /obj/item/photo)) - var/obj/item/photo/P2 = active1.fields["photo_side"] - user << browse_rsc(P2.picture.picture_image, "photo_side") - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - - dat += "" - if(active2 in GLOB.data_core.medical) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" //(per disease info placed in log/comment section) - dat += "" - dat += "" - - dat += "" - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - dat += "" - counter++ - dat += "" - - dat += "" - else - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
    Medical Record
    Name:[active1.fields["name"]]
    ID:[active1.fields["id"]]
    Gender: [active1.fields["gender"]] 
    Age: [active1.fields["age"]] 
    Species: [active1.fields["species"]] 
    Fingerprint: [active1.fields["fingerprint"]] 
    Physical Status: [active1.fields["p_stat"]] 
    Mental Status: [active1.fields["m_stat"]] 
    General Record Lost!

    Medical Data
    Blood Type: [active2.fields["blood_type"]] 
    DNA: [active2.fields["b_dna"]] 

    Minor Disabilities:

     [active2.fields["mi_dis"]] 
    Details: [active2.fields["mi_dis_d"]] 

    Major Disabilities:

     [active2.fields["ma_dis"]] 
    Details: [active2.fields["ma_dis_d"]] 

    Allergies:

     [active2.fields["alg"]] 
    Details: [active2.fields["alg_d"]] 

    Current Diseases:

     [active2.fields["cdi"]] 
    Details: [active2.fields["cdi_d"]] 

    Important Notes:

     [active2.fields["notes"]] 

    Comments/Log
    [active2.fields[text("com_[]", counter)]]
    Delete Entry
    Add Entry

    Delete Record (Medical Only)
    Medical Record Lost!

    New Record
    Print Record
    Back
    " - if(5) - dat += "
    Virus Database
    " - for(var/Dt in typesof(/datum/disease/)) - var/datum/disease/Dis = new Dt(0) - if(istype(Dis, /datum/disease/advance)) - continue // TODO (tm): Add advance diseases to the virus database which no one uses. - if(!Dis.desc) - continue - dat += "
    [Dis.name]" - dat += "
    Back" - if(6) - dat += "
    Medical Robot Monitor
    " - dat += "Back" - dat += "
    Medical Robots:" - var/bdat = null - for(var/mob/living/simple_animal/bot/medbot/M in GLOB.alive_mob_list) - if(M.z != z) - continue //only find medibots on the same z-level as the computer - var/turf/bl = get_turf(M) - if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up - bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.on ? "Online" : "Offline"]
    " - if((!isnull(M.reagent_glass)) && M.use_beaker) - bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]
    " - else - bdat += "Using Internal Synthesizer.
    " - - if(!bdat) - dat += "
    None detected
    " - else - dat += "
    [bdat]" - - else - else - dat += "{Log In}" - var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() - -/obj/machinery/computer/med_data/Topic(href, href_list) - . = ..() - if(.) - return . - if(!(active1 in GLOB.data_core.general)) - active1 = null - if(!(active2 in GLOB.data_core.medical)) - active2 = null - - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) - usr.set_machine(src) - if(href_list["temp"]) - temp = null - else if(href_list["logout"]) - authenticated = null - screen = null - active1 = null - active2 = null - playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) - else if(href_list["choice"]) - // SORTING! - if(href_list["choice"] == "Sorting") - // Reverse the order if clicked twice - if(sortBy == href_list["sort"]) - if(order == 1) - order = -1 - else - order = 1 - else - // New sorting order! - sortBy = href_list["sort"] - order = initial(order) - else if(href_list["login"]) - var/mob/M = usr - var/obj/item/card/id/I = M.get_idcard(TRUE) - if(issilicon(M)) - active1 = null - active2 = null - authenticated = 1 - rank = "AI" - screen = 1 - else if(IsAdminGhost(M)) - active1 = null - active2 = null - authenticated = 1 - rank = "Central Command" - screen = 1 - else if(istype(I) && check_access(I)) - active1 = null - active2 = null - authenticated = I.registered_name - rank = I.assignment - screen = 1 - else - to_chat(usr, "Unauthorized access.") - playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) - if(authenticated) - if(href_list["screen"]) - screen = text2num(href_list["screen"]) - if(screen < 1) - screen = 1 - - active1 = null - active2 = null - - else if(href_list["vir"]) - var/type = href_list["vir"] - var/datum/disease/Dis = new type(0) - var/AfS = "" - for(var/mob/M in Dis.viable_mobtypes) - AfS += " [initial(M.name)];" - temp = {"Name: [Dis.name] -
    Number of stages: [Dis.max_stages] -
    Spread: [Dis.spread_text] Transmission -
    Possible Cure: [(Dis.cure_text||"none")] -
    Affected Lifeforms:[AfS] -
    -
    Notes: [Dis.desc] -
    -
    Severity: [Dis.severity]"} - - else if(href_list["del_all"]) - temp = "Are you sure you wish to delete all records?
    \n\tYes
    \n\tNo
    " - - else if(href_list["del_all2"]) - investigate_log("[key_name(usr)] has deleted all medical records.", INVESTIGATE_RECORDS) - GLOB.data_core.medical.Cut() - temp = "All records deleted." - - else if(href_list["field"]) - var/a1 = active1 - var/a2 = active2 - switch(href_list["field"]) - if("fingerprint") - if(active1) - var/t1 = stripped_input("Please input fingerprint hash:", "Med. records", active1.fields["fingerprint"], null) - if(!canUseMedicalRecordsConsole(usr, t1, a1)) - return - active1.fields["fingerprint"] = t1 - if("gender") - if(active1) - if(active1.fields["gender"] == "Male") - active1.fields["gender"] = "Female" - else if(active1.fields["gender"] == "Female") - active1.fields["gender"] = "Other" - else - active1.fields["gender"] = "Male" - if("age") - if(active1) - var/t1 = input("Please input age:", "Med. records", active1.fields["age"], null) as num - if(!canUseMedicalRecordsConsole(usr, t1, a1)) - return - active1.fields["age"] = t1 - if("species") - if(active1) - var/t1 = stripped_input("Please input species name", "Med. records", active1.fields["species"], null) - if(!canUseMedicalRecordsConsole(usr, t1, a1)) - return - active1.fields["species"] = t1 - if("mi_dis") - if(active2) - var/t1 = stripped_input("Please input minor disabilities list:", "Med. records", active2.fields["mi_dis"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["mi_dis"] = t1 - if("mi_dis_d") - if(active2) - var/t1 = stripped_input("Please summarize minor dis.:", "Med. records", active2.fields["mi_dis_d"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["mi_dis_d"] = t1 - if("ma_dis") - if(active2) - var/t1 = stripped_input("Please input major disabilities list:", "Med. records", active2.fields["ma_dis"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["ma_dis"] = t1 - if("ma_dis_d") - if(active2) - var/t1 = stripped_input("Please summarize major dis.:", "Med. records", active2.fields["ma_dis_d"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["ma_dis_d"] = t1 - if("alg") - if(active2) - var/t1 = stripped_input("Please state allergies:", "Med. records", active2.fields["alg"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["alg"] = t1 - if("alg_d") - if(active2) - var/t1 = stripped_input("Please summarize allergies:", "Med. records", active2.fields["alg_d"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["alg_d"] = t1 - if("cdi") - if(active2) - var/t1 = stripped_input("Please state diseases:", "Med. records", active2.fields["cdi"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["cdi"] = t1 - if("cdi_d") - if(active2) - var/t1 = stripped_input("Please summarize diseases:", "Med. records", active2.fields["cdi_d"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["cdi_d"] = t1 - if("notes") - if(active2) - var/t1 = stripped_input("Please summarize notes:", "Med. records", active2.fields["notes"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["notes"] = t1 - if("p_stat") - if(active1) - temp = "Physical Condition:
    \n\t*Deceased*
    \n\t*Unconscious*
    \n\tActive
    \n\tPhysically Unfit
    " - if("m_stat") - if(active1) - temp = "Mental Condition:
    \n\t*Insane*
    \n\t*Unstable*
    \n\t*Watch*
    \n\tStable
    " - if("blood_type") - if(active2) - temp = "Blood Type:
    \n\tA- A+
    \n\tB- B+
    \n\tAB- AB+
    \n\tO- O+
    " - if("b_dna") - if(active2) - var/t1 = stripped_input("Please input DNA hash:", "Med. records", active2.fields["b_dna"], null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - active2.fields["b_dna"] = t1 - if("show_photo_front") - if(active1) - if(active1.fields["photo_front"]) - if(istype(active1.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_front"] - P.show(usr) - if("show_photo_side") - if(active1) - if(active1.fields["photo_side"]) - if(istype(active1.fields["photo_side"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_side"] - P.show(usr) - else - - else if(href_list["p_stat"]) - if(active1) - switch(href_list["p_stat"]) - if("deceased") - active1.fields["p_stat"] = "*Deceased*" - if("unconscious") - active1.fields["p_stat"] = "*Unconscious*" - if("active") - active1.fields["p_stat"] = "Active" - if("unfit") - active1.fields["p_stat"] = "Physically Unfit" - - else if(href_list["m_stat"]) - if(active1) - switch(href_list["m_stat"]) - if("insane") - active1.fields["m_stat"] = "*Insane*" - if("unstable") - active1.fields["m_stat"] = "*Unstable*" - if("watch") - active1.fields["m_stat"] = "*Watch*" - if("stable") - active1.fields["m_stat"] = "Stable" - - - else if(href_list["blood_type"]) - if(active2) - switch(href_list["blood_type"]) - if("an") - active2.fields["blood_type"] = "A-" - if("bn") - active2.fields["blood_type"] = "B-" - if("abn") - active2.fields["blood_type"] = "AB-" - if("on") - active2.fields["blood_type"] = "O-" - if("ap") - active2.fields["blood_type"] = "A+" - if("bp") - active2.fields["blood_type"] = "B+" - if("abp") - active2.fields["blood_type"] = "AB+" - if("op") - active2.fields["blood_type"] = "O+" - - - else if(href_list["del_r"]) - if(active2) - temp = "Are you sure you wish to delete the record (Medical Portion Only)?
    \n\tYes
    \n\tNo
    " - - else if(href_list["del_r2"]) - investigate_log("[key_name(usr)] has deleted the medical records for [active1.fields["name"]].", INVESTIGATE_RECORDS) - if(active2) - qdel(active2) - active2 = null - - else if(href_list["d_rec"]) - active1 = find_record("id", href_list["d_rec"], GLOB.data_core.general) - if(active1) - active2 = find_record("id", href_list["d_rec"], GLOB.data_core.medical) - if(!active2) - active1 = null - screen = 4 - - else if(href_list["new"]) - if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) - var/datum/data/record/R = new /datum/data/record( ) - R.fields["name"] = active1.fields["name"] - R.fields["id"] = active1.fields["id"] - R.name = text("Medical Record #[]", R.fields["id"]) - R.fields["blood_type"] = "Unknown" - R.fields["b_dna"] = "Unknown" - R.fields["mi_dis"] = "None" - R.fields["mi_dis_d"] = "No minor disabilities have been diagnosed." - R.fields["ma_dis"] = "None" - R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - R.fields["alg"] = "None" - R.fields["alg_d"] = "No allergies have been detected in this patient." - R.fields["cdi"] = "None" - R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - R.fields["notes"] = "No notes." - GLOB.data_core.medical += R - active2 = R - screen = 4 - - else if(href_list["add_c"]) - if(!(active2 in GLOB.data_core.medical)) - return - var/a2 = active2 - var/t1 = stripped_multiline_input("Add Comment:", "Med. records", null, null) - if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) - return - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
    []", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) - - else if(href_list["del_c"]) - if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) - active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" - - else if(href_list["search"]) - var/t1 = stripped_input(usr, "Search String: (Name, DNA, or ID)", "Med. records") - if(!canUseMedicalRecordsConsole(usr, t1)) - return - active1 = null - active2 = null - t1 = lowertext(t1) - for(var/datum/data/record/R in GLOB.data_core.medical) - if((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))) - active2 = R - else - //Foreach continue //goto(3229) - if(!( active2 )) - temp = text("Could not locate record [].", sanitize(t1)) - else - for(var/datum/data/record/E in GLOB.data_core.general) - if((E.fields["name"] == active2.fields["name"] || E.fields["id"] == active2.fields["id"])) - active1 = E - else - //Foreach continue //goto(3334) - screen = 4 - - else if(href_list["print_p"]) - if(!( printing )) - printing = 1 - GLOB.data_core.medicalPrintCount++ - playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) - sleep(30) - var/obj/item/paper/P = new /obj/item/paper( loc ) - P.info = "
    Medical Record - (MR-[GLOB.data_core.medicalPrintCount])

    " - if(active1 in GLOB.data_core.general) - P.info += text("Name: [] ID: []
    \nGender: []
    \nAge: []
    ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"]) - P.info += "\nSpecies: [active1.fields["species"]]
    " - P.info += text("\nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"]) - else - P.info += "General Record Lost!
    " - if(active2 in GLOB.data_core.medical) - P.info += text("
    \n
    Medical Data

    \nBlood Type: []
    \nDNA: []
    \n
    \nMinor Disabilities: []
    \nDetails: []
    \n
    \nMajor Disabilities: []
    \nDetails: []
    \n
    \nAllergies: []
    \nDetails: []
    \n
    \nCurrent Diseases: [] (per disease info placed in log/comment section)
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", active2.fields["blood_type"], active2.fields["b_dna"], active2.fields["mi_dis"], active2.fields["mi_dis_d"], active2.fields["ma_dis"], active2.fields["ma_dis_d"], active2.fields["alg"], active2.fields["alg_d"], active2.fields["cdi"], active2.fields["cdi_d"], active2.fields["notes"]) - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - P.info += text("[]
    ", active2.fields[text("com_[]", counter)]) - counter++ - P.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, active1.fields["name"]) - else - P.info += "Medical Record Lost!
    " - P.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, "Record Lost") - P.info += "" - P.update_icon() - printing = null - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/med_data/emp_act(severity) - . = ..() - if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) - for(var/datum/data/record/R in GLOB.data_core.medical) - if(prob(10/severity)) - switch(rand(1,6)) - if(1) - if(prob(10)) - R.fields["name"] = random_unique_lizard_name(R.fields["gender"],1) - else - R.fields["name"] = random_unique_name(R.fields["gender"],1) - if(2) - R.fields["gender"] = pick("Male", "Female", "Other") - if(3) - R.fields["age"] = rand(AGE_MIN, AGE_MAX) - if(4) - R.fields["blood_type"] = random_blood_type() - if(5) - R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit") - if(6) - R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") - continue - - else if(prob(1)) - qdel(R) - continue - -/obj/machinery/computer/med_data/proc/canUseMedicalRecordsConsole(mob/user, message = 1, record1, record2) - if(user) - if(message) - if(authenticated) - if(user.canUseTopic(src, !issilicon(user))) - if(!record1 || record1 == active1) - if(!record2 || record2 == active2) - return 1 - return 0 - -/obj/machinery/computer/med_data/laptop - name = "medical laptop" - desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table." - icon_state = "laptop" - icon_screen = "medlaptop" - icon_keyboard = "laptop_key" - clockwork = TRUE //it'd look weird - pass_flags = PASSTABLE + + +/obj/machinery/computer/med_data//TODO:SANITY + name = "medical records console" + desc = "This can be used to check medical records." + icon_screen = "medcomp" + icon_keyboard = "med_key" + req_one_access = list(ACCESS_MEDICAL, ACCESS_FORENSICS_LOCKERS) + circuit = /obj/item/circuitboard/computer/med_data + var/rank = null + var/screen = null + var/datum/data/record/active1 + var/datum/data/record/active2 + var/temp = null + var/printing = null + //Sorting Variables + var/sortBy = "name" + var/order = 1 // -1 = Descending - 1 = Ascending + + light_color = LIGHT_COLOR_BLUE + +/obj/machinery/computer/med_data/syndie + icon_keyboard = "syndie_key" + +/obj/machinery/computer/med_data/ui_interact(mob/user) + . = ..() + if(isliving(user)) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + var/dat + if(temp) + dat = text("[temp]

    Clear Screen") + else + if(authenticated) + switch(screen) + if(1) + dat += {" +Search Records +
    List Records +
    +
    Virus Database +
    Medbot Tracking +
    +
    Record Maintenance +
    {Log Out}
    +"} + if(2) + dat += {" +

    + + + + +
    Records:
    + + + + + + + + +"} + + + if(!isnull(GLOB.data_core.general)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) + var/blood_type = "" + var/b_dna = "" + for(var/datum/data/record/E in GLOB.data_core.medical) + if((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) + blood_type = E.fields["blood_type"] + b_dna = E.fields["b_dna"] + var/background + + if(R.fields["m_stat"] == "*Insane*" || R.fields["p_stat"] == "*Deceased*") + background = "'background-color:#990000;'" + else if(R.fields["p_stat"] == "*Unconscious*" || R.fields["m_stat"] == "*Unstable*") + background = "'background-color:#CD6500;'" + else if(R.fields["p_stat"] == "Physically Unfit" || R.fields["m_stat"] == "*Watch*") + background = "'background-color:#3BB9FF;'" + else + background = "'background-color:#4F7529;'" + + dat += text("", background, R.fields["id"], R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["fingerprint"], b_dna) + dat += text("", blood_type) + dat += text("", R.fields["p_stat"]) + dat += text("", R.fields["m_stat"]) + dat += "
    NameIDFingerprints (F) | DNA (D)Blood TypePhysical StatusMental Status
    [][]F: []
    D: []
    [][][]

    " + dat += "
    Back" + if(3) + dat += "Records Maintenance
    \nBackup To Disk
    \nUpload From Disk
    \nDelete All Records
    \n
    \nBack" + if(4) + + dat += "" + if(active1 in GLOB.data_core.general) + if(istype(active1.fields["photo_front"], /obj/item/photo)) + var/obj/item/photo/P1 = active1.fields["photo_front"] + user << browse_rsc(P1.picture.picture_image, "photo_front") + if(istype(active1.fields["photo_side"], /obj/item/photo)) + var/obj/item/photo/P2 = active1.fields["photo_side"] + user << browse_rsc(P2.picture.picture_image, "photo_side") + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + else + dat += "" + + dat += "" + if(active2 in GLOB.data_core.medical) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" //(per disease info placed in log/comment section) + dat += "" + dat += "" + + dat += "" + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + dat += "" + counter++ + dat += "" + + dat += "" + else + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
    Medical Record
    Name:[active1.fields["name"]]
    ID:[active1.fields["id"]]
    Gender: [active1.fields["gender"]] 
    Age: [active1.fields["age"]] 
    Species: [active1.fields["species"]] 
    Fingerprint: [active1.fields["fingerprint"]] 
    Physical Status: [active1.fields["p_stat"]] 
    Mental Status: [active1.fields["m_stat"]] 
    General Record Lost!

    Medical Data
    Blood Type: [active2.fields["blood_type"]] 
    DNA: [active2.fields["b_dna"]] 

    Minor Disabilities:

     [active2.fields["mi_dis"]] 
    Details: [active2.fields["mi_dis_d"]] 

    Major Disabilities:

     [active2.fields["ma_dis"]] 
    Details: [active2.fields["ma_dis_d"]] 

    Allergies:

     [active2.fields["alg"]] 
    Details: [active2.fields["alg_d"]] 

    Current Diseases:

     [active2.fields["cdi"]] 
    Details: [active2.fields["cdi_d"]] 

    Important Notes:

     [active2.fields["notes"]] 

    Comments/Log
    [active2.fields[text("com_[]", counter)]]
    Delete Entry
    Add Entry

    Delete Record (Medical Only)
    Medical Record Lost!

    New Record
    Print Record
    Back
    " + if(5) + dat += "
    Virus Database
    " + for(var/Dt in typesof(/datum/disease/)) + var/datum/disease/Dis = new Dt(0) + if(istype(Dis, /datum/disease/advance)) + continue // TODO (tm): Add advance diseases to the virus database which no one uses. + if(!Dis.desc) + continue + dat += "
    [Dis.name]" + dat += "
    Back" + if(6) + dat += "
    Medical Robot Monitor
    " + dat += "Back" + dat += "
    Medical Robots:" + var/bdat = null + for(var/mob/living/simple_animal/bot/medbot/M in GLOB.alive_mob_list) + if(M.z != z) + continue //only find medibots on the same z-level as the computer + var/turf/bl = get_turf(M) + if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up + bdat += "[M.name] - \[[bl.x],[bl.y]\] - [M.on ? "Online" : "Offline"]
    " + if((!isnull(M.reagent_glass)) && M.use_beaker) + bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]
    " + else + bdat += "Using Internal Synthesizer.
    " + + if(!bdat) + dat += "
    None detected
    " + else + dat += "
    [bdat]" + + else + else + dat += "{Log In}" + var/datum/browser/popup = new(user, "med_rec", "Medical Records Console", 600, 400) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + +/obj/machinery/computer/med_data/Topic(href, href_list) + . = ..() + if(.) + return . + if(!(active1 in GLOB.data_core.general)) + active1 = null + if(!(active2 in GLOB.data_core.medical)) + active2 = null + + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) + usr.set_machine(src) + if(href_list["temp"]) + temp = null + else if(href_list["logout"]) + authenticated = null + screen = null + active1 = null + active2 = null + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) + else if(href_list["choice"]) + // SORTING! + if(href_list["choice"] == "Sorting") + // Reverse the order if clicked twice + if(sortBy == href_list["sort"]) + if(order == 1) + order = -1 + else + order = 1 + else + // New sorting order! + sortBy = href_list["sort"] + order = initial(order) + else if(href_list["login"]) + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if(issilicon(M)) + active1 = null + active2 = null + authenticated = 1 + rank = "AI" + screen = 1 + else if(IsAdminGhost(M)) + active1 = null + active2 = null + authenticated = 1 + rank = "Central Command" + screen = 1 + else if(istype(I) && check_access(I)) + active1 = null + active2 = null + authenticated = I.registered_name + rank = I.assignment + screen = 1 + else + to_chat(usr, "Unauthorized access.") + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) + if(authenticated) + if(href_list["screen"]) + screen = text2num(href_list["screen"]) + if(screen < 1) + screen = 1 + + active1 = null + active2 = null + + else if(href_list["vir"]) + var/type = href_list["vir"] + var/datum/disease/Dis = new type(0) + var/AfS = "" + for(var/mob/M in Dis.viable_mobtypes) + AfS += " [initial(M.name)];" + temp = {"Name: [Dis.name] +
    Number of stages: [Dis.max_stages] +
    Spread: [Dis.spread_text] Transmission +
    Possible Cure: [(Dis.cure_text||"none")] +
    Affected Lifeforms:[AfS] +
    +
    Notes: [Dis.desc] +
    +
    Severity: [Dis.severity]"} + + else if(href_list["del_all"]) + temp = "Are you sure you wish to delete all records?
    \n\tYes
    \n\tNo
    " + + else if(href_list["del_all2"]) + investigate_log("[key_name(usr)] has deleted all medical records.", INVESTIGATE_RECORDS) + GLOB.data_core.medical.Cut() + temp = "All records deleted." + + else if(href_list["field"]) + var/a1 = active1 + var/a2 = active2 + switch(href_list["field"]) + if("fingerprint") + if(active1) + var/t1 = stripped_input("Please input fingerprint hash:", "Med. records", active1.fields["fingerprint"], null) + if(!canUseMedicalRecordsConsole(usr, t1, a1)) + return + active1.fields["fingerprint"] = t1 + if("gender") + if(active1) + if(active1.fields["gender"] == "Male") + active1.fields["gender"] = "Female" + else if(active1.fields["gender"] == "Female") + active1.fields["gender"] = "Other" + else + active1.fields["gender"] = "Male" + if("age") + if(active1) + var/t1 = input("Please input age:", "Med. records", active1.fields["age"], null) as num + if(!canUseMedicalRecordsConsole(usr, t1, a1)) + return + active1.fields["age"] = t1 + if("species") + if(active1) + var/t1 = stripped_input("Please input species name", "Med. records", active1.fields["species"], null) + if(!canUseMedicalRecordsConsole(usr, t1, a1)) + return + active1.fields["species"] = t1 + if("mi_dis") + if(active2) + var/t1 = stripped_input("Please input minor disabilities list:", "Med. records", active2.fields["mi_dis"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["mi_dis"] = t1 + if("mi_dis_d") + if(active2) + var/t1 = stripped_input("Please summarize minor dis.:", "Med. records", active2.fields["mi_dis_d"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["mi_dis_d"] = t1 + if("ma_dis") + if(active2) + var/t1 = stripped_input("Please input major disabilities list:", "Med. records", active2.fields["ma_dis"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["ma_dis"] = t1 + if("ma_dis_d") + if(active2) + var/t1 = stripped_input("Please summarize major dis.:", "Med. records", active2.fields["ma_dis_d"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["ma_dis_d"] = t1 + if("alg") + if(active2) + var/t1 = stripped_input("Please state allergies:", "Med. records", active2.fields["alg"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["alg"] = t1 + if("alg_d") + if(active2) + var/t1 = stripped_input("Please summarize allergies:", "Med. records", active2.fields["alg_d"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["alg_d"] = t1 + if("cdi") + if(active2) + var/t1 = stripped_input("Please state diseases:", "Med. records", active2.fields["cdi"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["cdi"] = t1 + if("cdi_d") + if(active2) + var/t1 = stripped_input("Please summarize diseases:", "Med. records", active2.fields["cdi_d"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["cdi_d"] = t1 + if("notes") + if(active2) + var/t1 = stripped_input("Please summarize notes:", "Med. records", active2.fields["notes"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["notes"] = t1 + if("p_stat") + if(active1) + temp = "Physical Condition:
    \n\t*Deceased*
    \n\t*Unconscious*
    \n\tActive
    \n\tPhysically Unfit
    " + if("m_stat") + if(active1) + temp = "Mental Condition:
    \n\t*Insane*
    \n\t*Unstable*
    \n\t*Watch*
    \n\tStable
    " + if("blood_type") + if(active2) + temp = "Blood Type:
    \n\tA- A+
    \n\tB- B+
    \n\tAB- AB+
    \n\tO- O+
    " + if("b_dna") + if(active2) + var/t1 = stripped_input("Please input DNA hash:", "Med. records", active2.fields["b_dna"], null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + active2.fields["b_dna"] = t1 + if("show_photo_front") + if(active1) + if(active1.fields["photo_front"]) + if(istype(active1.fields["photo_front"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_front"] + P.show(usr) + if("show_photo_side") + if(active1) + if(active1.fields["photo_side"]) + if(istype(active1.fields["photo_side"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_side"] + P.show(usr) + else + + else if(href_list["p_stat"]) + if(active1) + switch(href_list["p_stat"]) + if("deceased") + active1.fields["p_stat"] = "*Deceased*" + if("unconscious") + active1.fields["p_stat"] = "*Unconscious*" + if("active") + active1.fields["p_stat"] = "Active" + if("unfit") + active1.fields["p_stat"] = "Physically Unfit" + + else if(href_list["m_stat"]) + if(active1) + switch(href_list["m_stat"]) + if("insane") + active1.fields["m_stat"] = "*Insane*" + if("unstable") + active1.fields["m_stat"] = "*Unstable*" + if("watch") + active1.fields["m_stat"] = "*Watch*" + if("stable") + active1.fields["m_stat"] = "Stable" + + + else if(href_list["blood_type"]) + if(active2) + switch(href_list["blood_type"]) + if("an") + active2.fields["blood_type"] = "A-" + if("bn") + active2.fields["blood_type"] = "B-" + if("abn") + active2.fields["blood_type"] = "AB-" + if("on") + active2.fields["blood_type"] = "O-" + if("ap") + active2.fields["blood_type"] = "A+" + if("bp") + active2.fields["blood_type"] = "B+" + if("abp") + active2.fields["blood_type"] = "AB+" + if("op") + active2.fields["blood_type"] = "O+" + + + else if(href_list["del_r"]) + if(active2) + temp = "Are you sure you wish to delete the record (Medical Portion Only)?
    \n\tYes
    \n\tNo
    " + + else if(href_list["del_r2"]) + investigate_log("[key_name(usr)] has deleted the medical records for [active1.fields["name"]].", INVESTIGATE_RECORDS) + if(active2) + qdel(active2) + active2 = null + + else if(href_list["d_rec"]) + active1 = find_record("id", href_list["d_rec"], GLOB.data_core.general) + if(active1) + active2 = find_record("id", href_list["d_rec"], GLOB.data_core.medical) + if(!active2) + active1 = null + screen = 4 + + else if(href_list["new"]) + if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) + var/datum/data/record/R = new /datum/data/record( ) + R.fields["name"] = active1.fields["name"] + R.fields["id"] = active1.fields["id"] + R.name = text("Medical Record #[]", R.fields["id"]) + R.fields["blood_type"] = "Unknown" + R.fields["b_dna"] = "Unknown" + R.fields["mi_dis"] = "None" + R.fields["mi_dis_d"] = "No minor disabilities have been diagnosed." + R.fields["ma_dis"] = "None" + R.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + R.fields["alg"] = "None" + R.fields["alg_d"] = "No allergies have been detected in this patient." + R.fields["cdi"] = "None" + R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + R.fields["notes"] = "No notes." + GLOB.data_core.medical += R + active2 = R + screen = 4 + + else if(href_list["add_c"]) + if(!(active2 in GLOB.data_core.medical)) + return + var/a2 = active2 + var/t1 = stripped_multiline_input("Add Comment:", "Med. records", null, null) + if(!canUseMedicalRecordsConsole(usr, t1, null, a2)) + return + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + counter++ + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
    []", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) + + else if(href_list["del_c"]) + if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) + active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" + + else if(href_list["search"]) + var/t1 = stripped_input(usr, "Search String: (Name, DNA, or ID)", "Med. records") + if(!canUseMedicalRecordsConsole(usr, t1)) + return + active1 = null + active2 = null + t1 = lowertext(t1) + for(var/datum/data/record/R in GLOB.data_core.medical) + if((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))) + active2 = R + else + //Foreach continue //goto(3229) + if(!( active2 )) + temp = text("Could not locate record [].", sanitize(t1)) + else + for(var/datum/data/record/E in GLOB.data_core.general) + if((E.fields["name"] == active2.fields["name"] || E.fields["id"] == active2.fields["id"])) + active1 = E + else + //Foreach continue //goto(3334) + screen = 4 + + else if(href_list["print_p"]) + if(!( printing )) + printing = 1 + GLOB.data_core.medicalPrintCount++ + playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) + sleep(30) + var/obj/item/paper/P = new /obj/item/paper( loc ) + P.info = "
    Medical Record - (MR-[GLOB.data_core.medicalPrintCount])

    " + if(active1 in GLOB.data_core.general) + P.info += text("Name: [] ID: []
    \nGender: []
    \nAge: []
    ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"]) + P.info += "\nSpecies: [active1.fields["species"]]
    " + P.info += text("\nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"]) + else + P.info += "General Record Lost!
    " + if(active2 in GLOB.data_core.medical) + P.info += text("
    \n
    Medical Data

    \nBlood Type: []
    \nDNA: []
    \n
    \nMinor Disabilities: []
    \nDetails: []
    \n
    \nMajor Disabilities: []
    \nDetails: []
    \n
    \nAllergies: []
    \nDetails: []
    \n
    \nCurrent Diseases: [] (per disease info placed in log/comment section)
    \nDetails: []
    \n
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", active2.fields["blood_type"], active2.fields["b_dna"], active2.fields["mi_dis"], active2.fields["mi_dis_d"], active2.fields["ma_dis"], active2.fields["ma_dis_d"], active2.fields["alg"], active2.fields["alg_d"], active2.fields["cdi"], active2.fields["cdi_d"], active2.fields["notes"]) + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + P.info += text("[]
    ", active2.fields[text("com_[]", counter)]) + counter++ + P.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, active1.fields["name"]) + else + P.info += "Medical Record Lost!
    " + P.name = text("MR-[] '[]'", GLOB.data_core.medicalPrintCount, "Record Lost") + P.info += "" + P.update_icon() + printing = null + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/med_data/emp_act(severity) + . = ..() + if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) + for(var/datum/data/record/R in GLOB.data_core.medical) + if(prob(10/severity)) + switch(rand(1,6)) + if(1) + if(prob(10)) + R.fields["name"] = random_unique_lizard_name(R.fields["gender"],1) + else + R.fields["name"] = random_unique_name(R.fields["gender"],1) + if(2) + R.fields["gender"] = pick("Male", "Female", "Other") + if(3) + R.fields["age"] = rand(AGE_MIN, AGE_MAX) + if(4) + R.fields["blood_type"] = random_blood_type() + if(5) + R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit") + if(6) + R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") + continue + + else if(prob(1)) + qdel(R) + continue + +/obj/machinery/computer/med_data/proc/canUseMedicalRecordsConsole(mob/user, message = 1, record1, record2) + if(user) + if(message) + if(authenticated) + if(user.canUseTopic(src, !issilicon(user))) + if(!record1 || record1 == active1) + if(!record2 || record2 == active2) + return 1 + return 0 + +/obj/machinery/computer/med_data/laptop + name = "medical laptop" + desc = "A cheap Nanotrasen medical laptop, it functions as a medical records computer. It's bolted to the table." + icon_state = "laptop" + icon_screen = "medlaptop" + icon_keyboard = "laptop_key" + clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm index b71f572e68..1388e3c8de 100644 --- a/code/game/machinery/computer/pod.dm +++ b/code/game/machinery/computer/pod.dm @@ -1,133 +1,133 @@ -/obj/machinery/computer/pod - name = "mass driver launch control" - desc = "A combined blastdoor and mass driver control unit." - var/obj/machinery/mass_driver/connected = null - var/title = "Mass Driver Controls" - var/id = 1 - var/timing = 0 - var/time = 30 - var/range = 4 - - -/obj/machinery/computer/pod/Initialize() - . = ..() - for(var/obj/machinery/mass_driver/M in range(range, src)) - if(M.id == id) - connected = M - - -/obj/machinery/computer/pod/proc/alarm() - if(stat & (NOPOWER|BROKEN)) - return - - if(!connected) - say("Cannot locate mass driver connector. Cancelling firing sequence!") - return - - for(var/obj/machinery/door/poddoor/M in range(range, src)) - if(M.id == id) - M.open() - - sleep(20) - for(var/obj/machinery/mass_driver/M in range(range, src)) - if(M.id == id) - M.power = connected.power - M.drive() - - sleep(50) - for(var/obj/machinery/door/poddoor/M in range(range, src)) - if(M.id == id) - M.close() - -/obj/machinery/computer/pod/ui_interact(mob/user) - . = ..() - if(!allowed(user)) - to_chat(user, "Access denied.") - return - - var/dat = "" - if(connected) - var/d2 - if(timing) //door controls do not need timers. - d2 = "Stop Time Launch" - else - d2 = "Initiate Time Launch" - dat += "
    \nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] - - + +" - var/temp = "" - var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 ) - for(var/t in L) - if(t == connected.power) - temp += "[t] " - else - temp += "[t] " - dat += "
    \nPower Level: [temp]
    \nFiring Sequence
    \nTest Fire Driver
    \nToggle Outer Door
    " - else - dat += "
    \nToggle Outer Door
    " - dat += "

    Close" - add_fingerprint(usr) - var/datum/browser/popup = new(user, "computer", title, 400, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() - -/obj/machinery/computer/pod/process() - if(!..()) - return - if(timing) - if(time > 0) - time = round(time) - 1 - else - alarm() - time = 0 - timing = 0 - updateDialog() - - -/obj/machinery/computer/pod/Topic(href, href_list) - if(..()) - return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) - usr.set_machine(src) - if(href_list["power"]) - var/t = text2num(href_list["power"]) - t = min(max(0.25, t), 16) - if(connected) - connected.power = t - if(href_list["alarm"]) - alarm() - if(href_list["time"]) - timing = text2num(href_list["time"]) - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 120) - if(href_list["door"]) - for(var/obj/machinery/door/poddoor/M in range(range, src)) - if(M.id == id) - if(M.density) - M.open() - else - M.close() - if(href_list["drive"]) - for(var/obj/machinery/mass_driver/M in range(range, src)) - if(M.id == id) - M.power = connected.power - M.drive() - updateUsrDialog() - -/obj/machinery/computer/pod/old - name = "\improper DoorMex control console" - title = "Door Controls" - icon_state = "oldcomp" - icon_screen = "library" - icon_keyboard = null - -/obj/machinery/computer/pod/old/syndicate - name = "\improper ProComp Executive IIc" - desc = "The Syndicate operate on a tight budget. Operates external airlocks." - title = "External Airlock Controls" - req_access = list(ACCESS_SYNDICATE) - -/obj/machinery/computer/pod/old/swf - name = "\improper Magix System IV" - desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorcerer's Edition." +/obj/machinery/computer/pod + name = "mass driver launch control" + desc = "A combined blastdoor and mass driver control unit." + var/obj/machinery/mass_driver/connected = null + var/title = "Mass Driver Controls" + var/id = 1 + var/timing = 0 + var/time = 30 + var/range = 4 + + +/obj/machinery/computer/pod/Initialize() + . = ..() + for(var/obj/machinery/mass_driver/M in range(range, src)) + if(M.id == id) + connected = M + + +/obj/machinery/computer/pod/proc/alarm() + if(stat & (NOPOWER|BROKEN)) + return + + if(!connected) + say("Cannot locate mass driver connector. Cancelling firing sequence!") + return + + for(var/obj/machinery/door/poddoor/M in range(range, src)) + if(M.id == id) + M.open() + + sleep(20) + for(var/obj/machinery/mass_driver/M in range(range, src)) + if(M.id == id) + M.power = connected.power + M.drive() + + sleep(50) + for(var/obj/machinery/door/poddoor/M in range(range, src)) + if(M.id == id) + M.close() + +/obj/machinery/computer/pod/ui_interact(mob/user) + . = ..() + if(!allowed(user)) + to_chat(user, "Access denied.") + return + + var/dat = "" + if(connected) + var/d2 + if(timing) //door controls do not need timers. + d2 = "Stop Time Launch" + else + d2 = "Initiate Time Launch" + dat += "
    \nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] - - + +" + var/temp = "" + var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 ) + for(var/t in L) + if(t == connected.power) + temp += "[t] " + else + temp += "[t] " + dat += "
    \nPower Level: [temp]
    \nFiring Sequence
    \nTest Fire Driver
    \nToggle Outer Door
    " + else + dat += "
    \nToggle Outer Door
    " + dat += "

    Close" + add_fingerprint(usr) + var/datum/browser/popup = new(user, "computer", title, 400, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) + popup.open() + +/obj/machinery/computer/pod/process() + if(!..()) + return + if(timing) + if(time > 0) + time = round(time) - 1 + else + alarm() + time = 0 + timing = 0 + updateDialog() + + +/obj/machinery/computer/pod/Topic(href, href_list) + if(..()) + return + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr)) + usr.set_machine(src) + if(href_list["power"]) + var/t = text2num(href_list["power"]) + t = min(max(0.25, t), 16) + if(connected) + connected.power = t + if(href_list["alarm"]) + alarm() + if(href_list["time"]) + timing = text2num(href_list["time"]) + if(href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 120) + if(href_list["door"]) + for(var/obj/machinery/door/poddoor/M in range(range, src)) + if(M.id == id) + if(M.density) + M.open() + else + M.close() + if(href_list["drive"]) + for(var/obj/machinery/mass_driver/M in range(range, src)) + if(M.id == id) + M.power = connected.power + M.drive() + updateUsrDialog() + +/obj/machinery/computer/pod/old + name = "\improper DoorMex control console" + title = "Door Controls" + icon_state = "oldcomp" + icon_screen = "library" + icon_keyboard = null + +/obj/machinery/computer/pod/old/syndicate + name = "\improper ProComp Executive IIc" + desc = "The Syndicate operate on a tight budget. Operates external airlocks." + title = "External Airlock Controls" + req_access = list(ACCESS_SYNDICATE) + +/obj/machinery/computer/pod/old/swf + name = "\improper Magix System IV" + desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorcerer's Edition." diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 5c8d189a7f..5573c56386 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,165 +1,165 @@ -/obj/machinery/computer/robotics - name = "robotics control console" - desc = "Used to remotely lockdown or detonate linked Cyborgs and Drones." - icon_screen = "robot" - icon_keyboard = "rd_key" - req_access = list(ACCESS_ROBOTICS) - circuit = /obj/item/circuitboard/computer/robotics - var/temp = null - - light_color = LIGHT_COLOR_PINK - -/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R) - if(!istype(R)) - return 0 - if(isAI(user)) - if (R.connected_ai != user) - return 0 - if(iscyborg(user)) - if (R != user) - return 0 - if(R.scrambledcodes) - return 0 - return 1 - -/obj/machinery/computer/robotics/ui_interact(mob/user) - . = ..() - if (src.z > 6) - to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") - return - user.set_machine(src) - var/dat - var/robots = 0 - for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs) - if(!can_control(user, R)) - continue - robots++ - dat += "[R.name] |" - if(R.stat) - dat += " Not Responding |" - else if (!R.canmove) - dat += " Locked Down |" - else - dat += " Operating Normally |" - if (!R.canmove) - else if(R.cell) - dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |" - else - dat += " No Cell Installed |" - if(R.module) - dat += " Module Installed ([R.module.name]) |" - else - dat += " No Module Installed |" - if(R.connected_ai) - dat += " Slaved to [R.connected_ai.name] |" - else - dat += " Independent from AI |" - if(issilicon(user) && user != R) - var/mob/living/silicon/S = user - if(is_servant_of_ratvar(S)) - dat += "(Convert) " - else if(S.hack_software && !R.emagged) - dat += "(Hack) " - else if(IsAdminGhost(user) && !R.emagged) - dat += "(Hack) " - dat += "([R.canmove ? "Lockdown" : "Release"]) " - dat += "(Destroy)" - dat += "
    " - - if(!robots) - dat += "No Cyborg Units detected within access parameters." - dat += "
    " - - var/drones = 0 - for(var/mob/living/simple_animal/drone/D in GLOB.drones_list) - if(D.hacked) - continue - drones++ - dat += "[D.name] |" - if(D.stat) - dat += " Not Responding |" - dat += "(Destroy)" - dat += "
    " - - if(!drones) - dat += "No Drone Units detected within access parameters." - - var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/machinery/computer/robotics/Topic(href, href_list) - if(..()) - return - - if (href_list["temp"]) - src.temp = null - - else if (href_list["killbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) - var/turf/T = get_turf(R) - message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!") - log_game("\[key_name(usr)] detonated [key_name(R)]!") - if(R.connected_ai) - to_chat(R.connected_ai, "

    ALERT - Cyborg detonation detected: [R.name]
    ") - R.self_destruct() - else - to_chat(usr, "Access Denied.") - - else if (href_list["stopbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) - message_admins("[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!") - log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!") - R.SetLockdown(!R.lockcharge) - to_chat(R, "[!R.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") - if(R.connected_ai) - to_chat(R.connected_ai, "[!R.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
    ") - - else - to_chat(usr, "Access Denied.") - - else if (href_list["magbot"]) - var/mob/living/silicon/S = usr - if((istype(S) && S.hack_software) || IsAdminGhost(usr)) - var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs - if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R)) - log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!") - message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!") - R.SetEmagged(1) - - else if(href_list["convert"]) - if(isAI(usr) && is_servant_of_ratvar(usr)) - var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs - if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr) - log_game("[key_name(usr)] converted [key_name(R)] using robotic console!") - message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!") - add_servant_of_ratvar(R) - - else if (href_list["killdrone"]) - if(src.allowed(usr)) - var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list - if(D.hacked) - to_chat(usr, "ERROR: [D] is not responding to external commands.") - else - var/turf/T = get_turf(D) - message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!") - log_game("[key_name(usr)] detonated [key_name(D)]!") - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, D) - s.start() - D.visible_message("\the [D] self destructs!") - D.gib() - - - src.updateUsrDialog() - return +/obj/machinery/computer/robotics + name = "robotics control console" + desc = "Used to remotely lockdown or detonate linked Cyborgs and Drones." + icon_screen = "robot" + icon_keyboard = "rd_key" + req_access = list(ACCESS_ROBOTICS) + circuit = /obj/item/circuitboard/computer/robotics + var/temp = null + + light_color = LIGHT_COLOR_PINK + +/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R) + if(!istype(R)) + return 0 + if(isAI(user)) + if (R.connected_ai != user) + return 0 + if(iscyborg(user)) + if (R != user) + return 0 + if(R.scrambledcodes) + return 0 + return 1 + +/obj/machinery/computer/robotics/ui_interact(mob/user) + . = ..() + if (src.z > 6) + to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") + return + user.set_machine(src) + var/dat + var/robots = 0 + for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs) + if(!can_control(user, R)) + continue + robots++ + dat += "[R.name] |" + if(R.stat) + dat += " Not Responding |" + else if (!R.canmove) + dat += " Locked Down |" + else + dat += " Operating Normally |" + if (!R.canmove) + else if(R.cell) + dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |" + else + dat += " No Cell Installed |" + if(R.module) + dat += " Module Installed ([R.module.name]) |" + else + dat += " No Module Installed |" + if(R.connected_ai) + dat += " Slaved to [R.connected_ai.name] |" + else + dat += " Independent from AI |" + if(issilicon(user) && user != R) + var/mob/living/silicon/S = user + if(is_servant_of_ratvar(S)) + dat += "(Convert) " + else if(S.hack_software && !R.emagged) + dat += "(Hack) " + else if(IsAdminGhost(user) && !R.emagged) + dat += "(Hack) " + dat += "([R.canmove ? "Lockdown" : "Release"]) " + dat += "(Destroy)" + dat += "
    " + + if(!robots) + dat += "No Cyborg Units detected within access parameters." + dat += "
    " + + var/drones = 0 + for(var/mob/living/simple_animal/drone/D in GLOB.drones_list) + if(D.hacked) + continue + drones++ + dat += "[D.name] |" + if(D.stat) + dat += " Not Responding |" + dat += "(Destroy)" + dat += "
    " + + if(!drones) + dat += "No Drone Units detected within access parameters." + + var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + return + +/obj/machinery/computer/robotics/Topic(href, href_list) + if(..()) + return + + if (href_list["temp"]) + src.temp = null + + else if (href_list["killbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs + if(can_control(usr, R)) + var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") + if(choice == "Confirm" && can_control(usr, R) && !..()) + var/turf/T = get_turf(R) + message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!") + log_game("\[key_name(usr)] detonated [key_name(R)]!") + if(R.connected_ai) + to_chat(R.connected_ai, "

    ALERT - Cyborg detonation detected: [R.name]
    ") + R.self_destruct() + else + to_chat(usr, "Access Denied.") + + else if (href_list["stopbot"]) + if(src.allowed(usr)) + var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs + if(can_control(usr, R)) + var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") + if(choice == "Confirm" && can_control(usr, R) && !..()) + message_admins("[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!") + log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!") + R.SetLockdown(!R.lockcharge) + to_chat(R, "[!R.lockcharge ? "Your lockdown has been lifted!" : "You have been locked down!"]") + if(R.connected_ai) + to_chat(R.connected_ai, "[!R.lockcharge ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
    ") + + else + to_chat(usr, "Access Denied.") + + else if (href_list["magbot"]) + var/mob/living/silicon/S = usr + if((istype(S) && S.hack_software) || IsAdminGhost(usr)) + var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs + if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R)) + log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!") + message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!") + R.SetEmagged(1) + + else if(href_list["convert"]) + if(isAI(usr) && is_servant_of_ratvar(usr)) + var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs + if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr) + log_game("[key_name(usr)] converted [key_name(R)] using robotic console!") + message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!") + add_servant_of_ratvar(R) + + else if (href_list["killdrone"]) + if(src.allowed(usr)) + var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list + if(D.hacked) + to_chat(usr, "ERROR: [D] is not responding to external commands.") + else + var/turf/T = get_turf(D) + message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!") + log_game("[key_name(usr)] detonated [key_name(D)]!") + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(3, 1, D) + s.start() + D.visible_message("\the [D] self destructs!") + D.gib() + + + src.updateUsrDialog() + return diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index c9f2f28ab1..aabb1fe408 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -1,812 +1,812 @@ -/obj/machinery/computer/secure_data//TODO:SANITY - name = "security records console" - desc = "Used to view and edit personnel's security records." - icon_screen = "security" - icon_keyboard = "security_key" - req_one_access = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS) - circuit = /obj/item/circuitboard/computer/secure_data - var/rank = null - var/screen = null - var/datum/data/record/active1 = null - var/datum/data/record/active2 = null - var/temp = null - var/printing = null - var/can_change_id = 0 - var/list/Perp - var/tempname = null - //Sorting Variables - var/sortBy = "name" - var/order = 1 // -1 = Descending - 1 = Ascending - - light_color = LIGHT_COLOR_RED - -/obj/machinery/computer/secure_data/syndie - icon_keyboard = "syndie_key" - -/obj/machinery/computer/secure_data/laptop - name = "security laptop" - desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table." - icon_state = "laptop" - icon_screen = "seclaptop" - icon_keyboard = "laptop_key" - clockwork = TRUE //it'd look weird - pass_flags = PASSTABLE - -//Someone needs to break down the dat += into chunks instead of long ass lines. -/obj/machinery/computer/secure_data/ui_interact(mob/user) - . = ..() - if(isliving(user)) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) - if(src.z > 6) - to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") - return - var/dat - - if(temp) - dat = "[temp]

    Clear Screen" - else - dat = "" - if(authenticated) - switch(screen) - if(1) - - //body tag start + onload and onkeypress (onkeyup) javascript event calls - dat += "" - //search bar javascript - dat += {" - - - - - - - - "} - dat += {" -

    "} - dat += "New Record
    " - //search bar - dat += {" - - - - -
    - Search: -
    - "} - dat += {" -

    - - - - -
    Records:
    - - - - - - - - - -"} - if(!isnull(GLOB.data_core.general)) - for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) - var/crimstat = "" - for(var/datum/data/record/E in GLOB.data_core.security) - if((E.fields["name"] == R.fields["name"]) && (E.fields["id"] == R.fields["id"])) - crimstat = E.fields["criminal"] - var/background - switch(crimstat) - if("*Arrest*") - background = "'background-color:#990000;'" - if("Incarcerated") - background = "'background-color:#CD6500;'" - if("Paroled") - background = "'background-color:#CD6500;'" - if("Discharged") - background = "'background-color:#006699;'" - if("None") - background = "'background-color:#4F7529;'" - if("") - background = "''" //"'background-color:#FFFFFF;'" - crimstat = "No Record." - dat += "" - dat += text("", R.fields["name"], R.fields["id"], R.fields["rank"], R.fields["fingerprint"], R.fields["name"]) - dat += text("", R.fields["id"]) - dat += text("", R.fields["rank"]) - dat += text("", R.fields["fingerprint"]) - dat += text("", crimstat) - dat += {" -
    NameIDRankFingerprintsCriminal Status
    [][][][][]
    - -
    "} - dat += "Record Maintenance

    " - dat += "{Log Out}" - if(2) - dat += "Records Maintenance
    " - dat += "
    Delete All Records

    Back" - if(3) - dat += "Security Record
    " - if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) - if(istype(active1.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P1 = active1.fields["photo_front"] - user << browse_rsc(P1.picture.picture_image, "photo_front") - if(istype(active1.fields["photo_side"], /obj/item/photo)) - var/obj/item/photo/P2 = active1.fields["photo_side"] - user << browse_rsc(P2.picture.picture_image, "photo_side") - dat += {" -
    - - - - "} - dat += "" - dat += {" - - - -
    Name: [active1.fields["name"]] 
    ID: [active1.fields["id"]] 
    Gender: [active1.fields["gender"]] 
    Age: [active1.fields["age"]] 
    Species: [active1.fields["species"]] 
    Rank: [active1.fields["rank"]] 
    Fingerprint: [active1.fields["fingerprint"]] 
    Physical Status: [active1.fields["p_stat"]] 
    Mental Status: [active1.fields["m_stat"]] 
    -

    - Print photo
    - Update front photo

    - Print photo
    - Update side photo
    -
    "} - else - dat += "
    General Record Lost!
    " - if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2))) - dat += "Security Data" - dat += "
    Criminal Status: [active2.fields["criminal"]]" - dat += "

    Minor Crimes: Add New" - - - dat +={" - - - - - - - "} - for(var/datum/data/crime/c in active2.fields["mi_crim"]) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
    CrimeDetailsAuthorTime AddedDel
    [c.crimeName][c.crimeDetails][c.author][c.time]\[X\]
    " - - - dat += "
    Major Crimes: Add New" - - dat +={" - - - - - - - "} - for(var/datum/data/crime/c in active2.fields["ma_crim"]) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
    CrimeDetailsAuthorTime AddedDel
    [c.crimeName][c.crimeDetails][c.author][c.time]\[X\]
    " - - dat += "
    \nImportant Notes:
    \n\t [active2.fields["notes"]] " - dat += "

    Comments/Log
    " - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - dat += (active2.fields[text("com_[]", counter)] + "
    ") - if(active2.fields[text("com_[]", counter)] != "Deleted") - dat += text("Delete Entry

    ", counter) - counter++ - dat += "Add Entry

    " - dat += "Delete Record (Security Only)
    " - else - dat += "Security Record Lost!
    " - dat += "New Security Record

    " - dat += "Delete Record (ALL)
    Print Record
    Print Wanted Poster
    Back

    " - dat += "{Log Out}" - else - else - dat += "{Log In}" - var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/*Revised /N -I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. -What a mess.*/ -/obj/machinery/computer/secure_data/Topic(href, href_list) - . = ..() - if(.) - return . - if(!( GLOB.data_core.general.Find(active1) )) - active1 = null - if(!( GLOB.data_core.security.Find(active2) )) - active2 = null - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) - usr.set_machine(src) - switch(href_list["choice"]) -// SORTING! - if("Sorting") - // Reverse the order if clicked twice - if(sortBy == href_list["sort"]) - if(order == 1) - order = -1 - else - order = 1 - else - // New sorting order! - sortBy = href_list["sort"] - order = initial(order) -//BASIC FUNCTIONS - if("Clear Screen") - temp = null - - if("Return") - screen = 1 - active1 = null - active2 = null - - if("Log Out") - authenticated = null - screen = null - active1 = null - active2 = null - playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) - - if("Log In") - var/mob/M = usr - var/obj/item/card/id/I = M.get_idcard(TRUE) - if(issilicon(M)) - var/mob/living/silicon/borg = M - active1 = null - active2 = null - authenticated = borg.name - rank = "AI" - screen = 1 - else if(IsAdminGhost(M)) - active1 = null - active2 = null - authenticated = M.client.holder.admin_signature - rank = "Central Command" - screen = 1 - else if(I && check_access(I)) - active1 = null - active2 = null - authenticated = I.registered_name - rank = I.assignment - screen = 1 - else - to_chat(usr, "Unauthorized Access.") - playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) - -//RECORD FUNCTIONS - if("Record Maintenance") - screen = 2 - active1 = null - active2 = null - - if("Browse Record") - var/datum/data/record/R = locate(href_list["d_rec"]) in GLOB.data_core.general - if(!R) - temp = "Record Not Found!" - else - active1 = active2 = R - for(var/datum/data/record/E in GLOB.data_core.security) - if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - active2 = E - screen = 3 - - - if("Print Record") - if(!( printing )) - printing = 1 - GLOB.data_core.securityPrintCount++ - playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) - sleep(30) - var/obj/item/paper/P = new /obj/item/paper( loc ) - P.info = "
    Security Record - (SR-[GLOB.data_core.securityPrintCount])

    " - if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))) - P.info += text("Name: [] ID: []
    \nGender: []
    \nAge: []
    ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"]) - P.info += "\nSpecies: [active1.fields["species"]]
    " - P.info += text("\nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"]) - else - P.info += "General Record Lost!
    " - if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2))) - P.info += text("
    \n
    Security Data

    \nCriminal Status: []", active2.fields["criminal"]) - - P.info += "
    \n
    \nMinor Crimes:
    \n" - P.info +={" - - - - - -"} - for(var/datum/data/crime/c in active2.fields["mi_crim"]) - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "
    CrimeDetailsAuthorTime Added
    [c.crimeName][c.crimeDetails][c.author][c.time]
    " - - P.info += "
    \nMajor Crimes:
    \n" - P.info +={" - - - - - -"} - for(var/datum/data/crime/c in active2.fields["ma_crim"]) - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "" - P.info += "
    CrimeDetailsAuthorTime Added
    [c.crimeName][c.crimeDetails][c.author][c.time]
    " - - - P.info += text("
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", active2.fields["notes"]) - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - P.info += text("[]
    ", active2.fields[text("com_[]", counter)]) - counter++ - P.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, active1.fields["name"]) - else - P.info += "Security Record Lost!
    " - P.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, "Record Lost") - P.info += "" - P.update_icon() - printing = null - if("Print Poster") - if(!( printing )) - var/wanted_name = stripped_input(usr, "Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"]) - if(wanted_name) - var/default_description = "A poster declaring [wanted_name] to be a dangerous individual, wanted by Nanotrasen. Report any sightings to security immediately." - var/list/major_crimes = active2.fields["ma_crim"] - var/list/minor_crimes = active2.fields["mi_crim"] - if(major_crimes.len + minor_crimes.len) - default_description += "\n[wanted_name] is wanted for the following crimes:\n" - if(minor_crimes.len) - default_description += "\nMinor Crimes:" - for(var/datum/data/crime/c in active2.fields["mi_crim"]) - default_description += "\n[c.crimeName]\n" - default_description += "[c.crimeDetails]\n" - if(major_crimes.len) - default_description += "\nMajor Crimes:" - for(var/datum/data/crime/c in active2.fields["ma_crim"]) - default_description += "\n[c.crimeName]\n" - default_description += "[c.crimeDetails]\n" - - var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Wanted Poster", default_description, null) - if(info) - playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) - printing = 1 - sleep(30) - if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists. - var/obj/item/photo/photo = active1.fields["photo_front"] - new /obj/item/poster/wanted(loc, photo.picture.picture_image, wanted_name, info) - printing = 0 - -//RECORD DELETE - if("Delete All Records") - temp = "" - temp += "Are you sure you wish to delete all Security records?
    " - temp += "Yes
    " - temp += "No" - - if("Purge All Records") - investigate_log("[key_name(usr)] has purged all the security records.", INVESTIGATE_RECORDS) - for(var/datum/data/record/R in GLOB.data_core.security) - qdel(R) - GLOB.data_core.security.Cut() - temp = "All Security records deleted." - - if("Add Entry") - if(!( istype(active2, /datum/data/record) )) - return - var/a2 = active2 - var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null) - if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) - return - var/counter = 1 - while(active2.fields[text("com_[]", counter)]) - counter++ - active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
    []", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) - - if("Delete Record (ALL)") - if(active1) - temp = "
    Are you sure you wish to delete the record (ALL)?
    " - temp += "Yes
    " - temp += "No" - - if("Delete Record (Security)") - if(active2) - temp = "
    Are you sure you wish to delete the record (Security Portion Only)?
    " - temp += "Yes
    " - temp += "No" - - if("Delete Entry") - if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) - active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" -//RECORD CREATE - if("New Record (Security)") - if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) - var/datum/data/record/R = new /datum/data/record() - R.fields["name"] = active1.fields["name"] - R.fields["id"] = active1.fields["id"] - R.name = text("Security Record #[]", R.fields["id"]) - R.fields["criminal"] = "None" - R.fields["mi_crim"] = list() - R.fields["ma_crim"] = list() - R.fields["notes"] = "No notes." - GLOB.data_core.security += R - active2 = R - screen = 3 - - if("New Record (General)") - //General Record - var/datum/data/record/G = new /datum/data/record() - G.fields["name"] = "New Record" - G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]" - G.fields["rank"] = "Unassigned" - G.fields["gender"] = "Male" - G.fields["age"] = "Unknown" - G.fields["species"] = "Human" - G.fields["photo_front"] = new /icon() - G.fields["photo_side"] = new /icon() - G.fields["fingerprint"] = "?????" - G.fields["p_stat"] = "Active" - G.fields["m_stat"] = "Stable" - GLOB.data_core.general += G - active1 = G - - //Security Record - var/datum/data/record/R = new /datum/data/record() - R.fields["name"] = active1.fields["name"] - R.fields["id"] = active1.fields["id"] - R.name = text("Security Record #[]", R.fields["id"]) - R.fields["criminal"] = "None" - R.fields["mi_crim"] = list() - R.fields["ma_crim"] = list() - R.fields["notes"] = "No notes." - GLOB.data_core.security += R - active2 = R - - //Medical Record - var/datum/data/record/M = new /datum/data/record() - M.fields["id"] = active1.fields["id"] - M.fields["name"] = active1.fields["name"] - M.fields["blood_type"] = "?" - M.fields["b_dna"] = "?????" - M.fields["mi_dis"] = "None" - M.fields["mi_dis_d"] = "No minor disabilities have been declared." - M.fields["ma_dis"] = "None" - M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." - M.fields["alg"] = "None" - M.fields["alg_d"] = "No allergies have been detected in this patient." - M.fields["cdi"] = "None" - M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - M.fields["notes"] = "No notes." - GLOB.data_core.medical += M - - - -//FIELD FUNCTIONS - if("Edit Field") - var/a1 = active1 - var/a2 = active2 - - switch(href_list["field"]) - if("name") - if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record)) - var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) - if(!canUseSecurityRecordsConsole(usr, t1, a1)) - return - if(istype(active1, /datum/data/record)) - active1.fields["name"] = t1 - if(istype(active2, /datum/data/record)) - active2.fields["name"] = t1 - if("id") - if(istype(active2, /datum/data/record) || istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input id:", "Secure. records", active1.fields["id"], null) - if(!canUseSecurityRecordsConsole(usr, t1, a1)) - return - if(istype(active1, /datum/data/record)) - active1.fields["id"] = t1 - if(istype(active2, /datum/data/record)) - active2.fields["id"] = t1 - if("fingerprint") - if(istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) - if(!canUseSecurityRecordsConsole(usr, t1, a1)) - return - active1.fields["fingerprint"] = t1 - if("gender") - if(istype(active1, /datum/data/record)) - if(active1.fields["gender"] == "Male") - active1.fields["gender"] = "Female" - else if(active1.fields["gender"] == "Female") - active1.fields["gender"] = "Other" - else - active1.fields["gender"] = "Male" - if("age") - if(istype(active1, /datum/data/record)) - var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num - if(!canUseSecurityRecordsConsole(usr, "age", a1)) - return - active1.fields["age"] = t1 - if("species") - if(istype(active1, /datum/data/record)) - var/t1 = input("Select a species", "Species Selection") as null|anything in GLOB.roundstart_races - if(!canUseSecurityRecordsConsole(usr, t1, a1)) - return - active1.fields["species"] = t1 - if("show_photo_front") - if(active1.fields["photo_front"]) - if(istype(active1.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_front"] - P.show(usr) - if("upd_photo_front") - var/obj/item/photo/photo = get_photo(usr) - if(photo) - qdel(active1.fields["photo_front"]) - //Lets center it to a 32x32. - var/icon/I = photo.picture.picture_image - var/w = I.Width() - var/h = I.Height() - var/dw = w - 32 - var/dh = w - 32 - I.Crop(dw/2, dh/2, w - dw/2, h - dh/2) - active1.fields["photo_front"] = photo - if("print_photo_front") - if(active1.fields["photo_front"]) - if(istype(active1.fields["photo_front"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_front"] - print_photo(P.picture.picture_image, active1.fields["name"]) - if("show_photo_side") - if(active1.fields["photo_side"]) - if(istype(active1.fields["photo_side"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_side"] - P.show(usr) - if("upd_photo_side") - var/obj/item/photo/photo = get_photo(usr) - if(photo) - qdel(active1.fields["photo_side"]) - //Lets center it to a 32x32. - var/icon/I = photo.picture.picture_image - var/w = I.Width() - var/h = I.Height() - var/dw = w - 32 - var/dh = w - 32 - I.Crop(dw/2, dh/2, w - dw/2, h - dh/2) - active1.fields["photo_side"] = photo - if("print_photo_side") - if(active1.fields["photo_side"]) - if(istype(active1.fields["photo_side"], /obj/item/photo)) - var/obj/item/photo/P = active1.fields["photo_side"] - print_photo(P.picture.picture_image, active1.fields["name"]) - if("mi_crim_add") - if(istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input minor crime names:", "Secure. records", "", null) - var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null) - if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) - GLOB.data_core.addMinorCrime(active1.fields["id"], crime) - investigate_log("New Minor Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - if("mi_crim_delete") - if(istype(active1, /datum/data/record)) - if(href_list["cdataid"]) - if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) - return - GLOB.data_core.removeMinorCrime(active1.fields["id"], href_list["cdataid"]) - if("ma_crim_add") - if(istype(active1, /datum/data/record)) - var/t1 = stripped_input(usr, "Please input major crime names:", "Secure. records", "", null) - var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null) - if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) - GLOB.data_core.addMajorCrime(active1.fields["id"], crime) - investigate_log("New Major Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) - if("ma_crim_delete") - if(istype(active1, /datum/data/record)) - if(href_list["cdataid"]) - if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) - return - GLOB.data_core.removeMajorCrime(active1.fields["id"], href_list["cdataid"]) - if("notes") - if(istype(active2, /datum/data/record)) - var/t1 = stripped_input(usr, "Please summarize notes:", "Secure. records", active2.fields["notes"], null) - if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) - return - active2.fields["notes"] = t1 - if("criminal") - if(istype(active2, /datum/data/record)) - temp = "
    Criminal Status:
    " - temp += "" - if("rank") - var/list/L = list( "Head of Personnel", "Captain", "AI", "Central Command" ) - //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N - if((istype(active1, /datum/data/record) && L.Find(rank))) - temp = "
    Rank:
    " - temp += "
      " - for(var/rank in get_all_jobs()) - temp += "
    • [rank]
    • " - temp += "
    " - else - alert(usr, "You do not have the required rank to do this!") -//TEMPORARY MENU FUNCTIONS - else//To properly clear as per clear screen. - temp=null - switch(href_list["choice"]) - if("Change Rank") - if(active1) - active1.fields["rank"] = href_list["rank"] - if(href_list["rank"] in get_all_jobs()) - active1.fields["real_rank"] = href_list["real_rank"] - - if("Change Criminal Status") - if(active2) - var/old_field = active2.fields["criminal"] - switch(href_list["criminal2"]) - if("none") - active2.fields["criminal"] = "None" - if("arrest") - active2.fields["criminal"] = "*Arrest*" - if("incarcerated") - active2.fields["criminal"] = "Incarcerated" - if("paroled") - active2.fields["criminal"] = "Paroled" - if("released") - active2.fields["criminal"] = "Discharged" - investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [key_name(usr)].", INVESTIGATE_RECORDS) - for(var/mob/living/carbon/human/H in GLOB.carbon_list) - H.sec_hud_set_security_status() - if("Delete Record (Security) Execute") - investigate_log("[key_name(usr)] has deleted the security records for [active1.fields["name"]].", INVESTIGATE_RECORDS) - if(active2) - qdel(active2) - active2 = null - - if("Delete Record (ALL) Execute") - if(active1) - investigate_log("[key_name(usr)] has deleted all records for [active1.fields["name"]].", INVESTIGATE_RECORDS) - for(var/datum/data/record/R in GLOB.data_core.medical) - if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) - qdel(R) - break - qdel(active1) - active1 = null - - if(active2) - qdel(active2) - active2 = null - else - temp = "This function does not appear to be working at the moment. Our apologies." - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/secure_data/proc/get_photo(mob/user) - var/obj/item/photo/P = null - if(issilicon(user)) - var/mob/living/silicon/tempAI = user - var/datum/picture/selection = tempAI.GetPhoto(user) - if(selection) - P = new(null, selection) - else if(istype(user.get_active_held_item(), /obj/item/photo)) - P = user.get_active_held_item() - return P - -/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, person_name) - if (printing) - return - printing = TRUE - sleep(20) - var/obj/item/photo/P = new/obj/item/photo(drop_location()) - var/datum/picture/toEmbed = new(name = person_name, desc = "The photo on file for [person_name].", image = temp) - P.set_picture(toEmbed, TRUE, TRUE) - P.pixel_x = rand(-10, 10) - P.pixel_y = rand(-10, 10) - printing = FALSE - -/obj/machinery/computer/secure_data/emp_act(severity) - . = ..() - - if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_SELF) - return - - for(var/datum/data/record/R in GLOB.data_core.security) - if(prob(10/severity)) - switch(rand(1,8)) - if(1) - if(prob(10)) - R.fields["name"] = "[pick(lizard_name(MALE),lizard_name(FEMALE))]" - else - R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]" - if(2) - R.fields["gender"] = pick("Male", "Female", "Other") - if(3) - R.fields["age"] = rand(5, 85) - if(4) - R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged") - if(5) - R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit") - if(6) - R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") - if(7) - R.fields["species"] = pick(GLOB.roundstart_races) - if(8) - var/datum/data/record/G = pick(GLOB.data_core.general) - R.fields["photo_front"] = G.fields["photo_front"] - R.fields["photo_side"] = G.fields["photo_side"] - continue - - else if(prob(1)) - qdel(R) - continue - -/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2) - if(user) - if(authenticated) - if(user.canUseTopic(src, !issilicon(user))) - if(!trim(message1)) - return 0 - if(!record1 || record1 == active1) - if(!record2 || record2 == active2) - return 1 - return 0 - +/obj/machinery/computer/secure_data//TODO:SANITY + name = "security records console" + desc = "Used to view and edit personnel's security records." + icon_screen = "security" + icon_keyboard = "security_key" + req_one_access = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS) + circuit = /obj/item/circuitboard/computer/secure_data + var/rank = null + var/screen = null + var/datum/data/record/active1 = null + var/datum/data/record/active2 = null + var/temp = null + var/printing = null + var/can_change_id = 0 + var/list/Perp + var/tempname = null + //Sorting Variables + var/sortBy = "name" + var/order = 1 // -1 = Descending - 1 = Ascending + + light_color = LIGHT_COLOR_RED + +/obj/machinery/computer/secure_data/syndie + icon_keyboard = "syndie_key" + +/obj/machinery/computer/secure_data/laptop + name = "security laptop" + desc = "A cheap Nanotrasen security laptop, it functions as a security records console. It's bolted to the table." + icon_state = "laptop" + icon_screen = "seclaptop" + icon_keyboard = "laptop_key" + clockwork = TRUE //it'd look weird + pass_flags = PASSTABLE + +//Someone needs to break down the dat += into chunks instead of long ass lines. +/obj/machinery/computer/secure_data/ui_interact(mob/user) + . = ..() + if(isliving(user)) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + if(src.z > 6) + to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") + return + var/dat + + if(temp) + dat = "[temp]

    Clear Screen" + else + dat = "" + if(authenticated) + switch(screen) + if(1) + + //body tag start + onload and onkeypress (onkeyup) javascript event calls + dat += "" + //search bar javascript + dat += {" + + + + + + + + "} + dat += {" +

    "} + dat += "New Record
    " + //search bar + dat += {" + + + + +
    + Search: +
    + "} + dat += {" +

    + + + + +
    Records:
    + + + + + + + + + +"} + if(!isnull(GLOB.data_core.general)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) + var/crimstat = "" + for(var/datum/data/record/E in GLOB.data_core.security) + if((E.fields["name"] == R.fields["name"]) && (E.fields["id"] == R.fields["id"])) + crimstat = E.fields["criminal"] + var/background + switch(crimstat) + if("*Arrest*") + background = "'background-color:#990000;'" + if("Incarcerated") + background = "'background-color:#CD6500;'" + if("Paroled") + background = "'background-color:#CD6500;'" + if("Discharged") + background = "'background-color:#006699;'" + if("None") + background = "'background-color:#4F7529;'" + if("") + background = "''" //"'background-color:#FFFFFF;'" + crimstat = "No Record." + dat += "" + dat += text("", R.fields["name"], R.fields["id"], R.fields["rank"], R.fields["fingerprint"], R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["rank"]) + dat += text("", R.fields["fingerprint"]) + dat += text("", crimstat) + dat += {" +
    NameIDRankFingerprintsCriminal Status
    [][][][][]
    + +
    "} + dat += "Record Maintenance

    " + dat += "{Log Out}" + if(2) + dat += "Records Maintenance
    " + dat += "
    Delete All Records

    Back" + if(3) + dat += "Security Record
    " + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) + if(istype(active1.fields["photo_front"], /obj/item/photo)) + var/obj/item/photo/P1 = active1.fields["photo_front"] + user << browse_rsc(P1.picture.picture_image, "photo_front") + if(istype(active1.fields["photo_side"], /obj/item/photo)) + var/obj/item/photo/P2 = active1.fields["photo_side"] + user << browse_rsc(P2.picture.picture_image, "photo_side") + dat += {" +
    + + + + "} + dat += "" + dat += {" + + + +
    Name: [active1.fields["name"]] 
    ID: [active1.fields["id"]] 
    Gender: [active1.fields["gender"]] 
    Age: [active1.fields["age"]] 
    Species: [active1.fields["species"]] 
    Rank: [active1.fields["rank"]] 
    Fingerprint: [active1.fields["fingerprint"]] 
    Physical Status: [active1.fields["p_stat"]] 
    Mental Status: [active1.fields["m_stat"]] 
    +

    + Print photo
    + Update front photo

    + Print photo
    + Update side photo
    +
    "} + else + dat += "
    General Record Lost!
    " + if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2))) + dat += "Security Data" + dat += "
    Criminal Status: [active2.fields["criminal"]]" + dat += "

    Minor Crimes: Add New" + + + dat +={" + + + + + + + "} + for(var/datum/data/crime/c in active2.fields["mi_crim"]) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
    CrimeDetailsAuthorTime AddedDel
    [c.crimeName][c.crimeDetails][c.author][c.time]\[X\]
    " + + + dat += "
    Major Crimes: Add New" + + dat +={" + + + + + + + "} + for(var/datum/data/crime/c in active2.fields["ma_crim"]) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
    CrimeDetailsAuthorTime AddedDel
    [c.crimeName][c.crimeDetails][c.author][c.time]\[X\]
    " + + dat += "
    \nImportant Notes:
    \n\t [active2.fields["notes"]] " + dat += "

    Comments/Log
    " + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + dat += (active2.fields[text("com_[]", counter)] + "
    ") + if(active2.fields[text("com_[]", counter)] != "Deleted") + dat += text("Delete Entry

    ", counter) + counter++ + dat += "Add Entry

    " + dat += "Delete Record (Security Only)
    " + else + dat += "Security Record Lost!
    " + dat += "New Security Record

    " + dat += "Delete Record (ALL)
    Print Record
    Print Wanted Poster
    Back

    " + dat += "{Log Out}" + else + else + dat += "{Log In}" + var/datum/browser/popup = new(user, "secure_rec", "Security Records Console", 600, 400) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + return + +/*Revised /N +I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. +What a mess.*/ +/obj/machinery/computer/secure_data/Topic(href, href_list) + . = ..() + if(.) + return . + if(!( GLOB.data_core.general.Find(active1) )) + active1 = null + if(!( GLOB.data_core.security.Find(active2) )) + active2 = null + if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr)) + usr.set_machine(src) + switch(href_list["choice"]) +// SORTING! + if("Sorting") + // Reverse the order if clicked twice + if(sortBy == href_list["sort"]) + if(order == 1) + order = -1 + else + order = 1 + else + // New sorting order! + sortBy = href_list["sort"] + order = initial(order) +//BASIC FUNCTIONS + if("Clear Screen") + temp = null + + if("Return") + screen = 1 + active1 = null + active2 = null + + if("Log Out") + authenticated = null + screen = null + active1 = null + active2 = null + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) + + if("Log In") + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if(issilicon(M)) + var/mob/living/silicon/borg = M + active1 = null + active2 = null + authenticated = borg.name + rank = "AI" + screen = 1 + else if(IsAdminGhost(M)) + active1 = null + active2 = null + authenticated = M.client.holder.admin_signature + rank = "Central Command" + screen = 1 + else if(I && check_access(I)) + active1 = null + active2 = null + authenticated = I.registered_name + rank = I.assignment + screen = 1 + else + to_chat(usr, "Unauthorized Access.") + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) + +//RECORD FUNCTIONS + if("Record Maintenance") + screen = 2 + active1 = null + active2 = null + + if("Browse Record") + var/datum/data/record/R = locate(href_list["d_rec"]) in GLOB.data_core.general + if(!R) + temp = "Record Not Found!" + else + active1 = active2 = R + for(var/datum/data/record/E in GLOB.data_core.security) + if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + active2 = E + screen = 3 + + + if("Print Record") + if(!( printing )) + printing = 1 + GLOB.data_core.securityPrintCount++ + playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) + sleep(30) + var/obj/item/paper/P = new /obj/item/paper( loc ) + P.info = "
    Security Record - (SR-[GLOB.data_core.securityPrintCount])

    " + if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1))) + P.info += text("Name: [] ID: []
    \nGender: []
    \nAge: []
    ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"]) + P.info += "\nSpecies: [active1.fields["species"]]
    " + P.info += text("\nFingerprint: []
    \nPhysical Status: []
    \nMental Status: []
    ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"]) + else + P.info += "General Record Lost!
    " + if((istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2))) + P.info += text("
    \n
    Security Data

    \nCriminal Status: []", active2.fields["criminal"]) + + P.info += "
    \n
    \nMinor Crimes:
    \n" + P.info +={" + + + + + +"} + for(var/datum/data/crime/c in active2.fields["mi_crim"]) + P.info += "" + P.info += "" + P.info += "" + P.info += "" + P.info += "" + P.info += "
    CrimeDetailsAuthorTime Added
    [c.crimeName][c.crimeDetails][c.author][c.time]
    " + + P.info += "
    \nMajor Crimes:
    \n" + P.info +={" + + + + + +"} + for(var/datum/data/crime/c in active2.fields["ma_crim"]) + P.info += "" + P.info += "" + P.info += "" + P.info += "" + P.info += "" + P.info += "
    CrimeDetailsAuthorTime Added
    [c.crimeName][c.crimeDetails][c.author][c.time]
    " + + + P.info += text("
    \nImportant Notes:
    \n\t[]
    \n
    \n
    Comments/Log

    ", active2.fields["notes"]) + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + P.info += text("[]
    ", active2.fields[text("com_[]", counter)]) + counter++ + P.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, active1.fields["name"]) + else + P.info += "Security Record Lost!
    " + P.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, "Record Lost") + P.info += "" + P.update_icon() + printing = null + if("Print Poster") + if(!( printing )) + var/wanted_name = stripped_input(usr, "Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"]) + if(wanted_name) + var/default_description = "A poster declaring [wanted_name] to be a dangerous individual, wanted by Nanotrasen. Report any sightings to security immediately." + var/list/major_crimes = active2.fields["ma_crim"] + var/list/minor_crimes = active2.fields["mi_crim"] + if(major_crimes.len + minor_crimes.len) + default_description += "\n[wanted_name] is wanted for the following crimes:\n" + if(minor_crimes.len) + default_description += "\nMinor Crimes:" + for(var/datum/data/crime/c in active2.fields["mi_crim"]) + default_description += "\n[c.crimeName]\n" + default_description += "[c.crimeDetails]\n" + if(major_crimes.len) + default_description += "\nMajor Crimes:" + for(var/datum/data/crime/c in active2.fields["ma_crim"]) + default_description += "\n[c.crimeName]\n" + default_description += "[c.crimeDetails]\n" + + var/info = stripped_multiline_input(usr, "Please input a description for the poster:", "Print Wanted Poster", default_description, null) + if(info) + playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1) + printing = 1 + sleep(30) + if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))//make sure the record still exists. + var/obj/item/photo/photo = active1.fields["photo_front"] + new /obj/item/poster/wanted(loc, photo.picture.picture_image, wanted_name, info) + printing = 0 + +//RECORD DELETE + if("Delete All Records") + temp = "" + temp += "Are you sure you wish to delete all Security records?
    " + temp += "Yes
    " + temp += "No" + + if("Purge All Records") + investigate_log("[key_name(usr)] has purged all the security records.", INVESTIGATE_RECORDS) + for(var/datum/data/record/R in GLOB.data_core.security) + qdel(R) + GLOB.data_core.security.Cut() + temp = "All Security records deleted." + + if("Add Entry") + if(!( istype(active2, /datum/data/record) )) + return + var/a2 = active2 + var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null) + if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) + return + var/counter = 1 + while(active2.fields[text("com_[]", counter)]) + counter++ + active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], []
    []", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1) + + if("Delete Record (ALL)") + if(active1) + temp = "
    Are you sure you wish to delete the record (ALL)?
    " + temp += "Yes
    " + temp += "No" + + if("Delete Record (Security)") + if(active2) + temp = "
    Are you sure you wish to delete the record (Security Portion Only)?
    " + temp += "Yes
    " + temp += "No" + + if("Delete Entry") + if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])])) + active2.fields[text("com_[]", href_list["del_c"])] = "Deleted" +//RECORD CREATE + if("New Record (Security)") + if((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) ))) + var/datum/data/record/R = new /datum/data/record() + R.fields["name"] = active1.fields["name"] + R.fields["id"] = active1.fields["id"] + R.name = text("Security Record #[]", R.fields["id"]) + R.fields["criminal"] = "None" + R.fields["mi_crim"] = list() + R.fields["ma_crim"] = list() + R.fields["notes"] = "No notes." + GLOB.data_core.security += R + active2 = R + screen = 3 + + if("New Record (General)") + //General Record + var/datum/data/record/G = new /datum/data/record() + G.fields["name"] = "New Record" + G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]" + G.fields["rank"] = "Unassigned" + G.fields["gender"] = "Male" + G.fields["age"] = "Unknown" + G.fields["species"] = "Human" + G.fields["photo_front"] = new /icon() + G.fields["photo_side"] = new /icon() + G.fields["fingerprint"] = "?????" + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + GLOB.data_core.general += G + active1 = G + + //Security Record + var/datum/data/record/R = new /datum/data/record() + R.fields["name"] = active1.fields["name"] + R.fields["id"] = active1.fields["id"] + R.name = text("Security Record #[]", R.fields["id"]) + R.fields["criminal"] = "None" + R.fields["mi_crim"] = list() + R.fields["ma_crim"] = list() + R.fields["notes"] = "No notes." + GLOB.data_core.security += R + active2 = R + + //Medical Record + var/datum/data/record/M = new /datum/data/record() + M.fields["id"] = active1.fields["id"] + M.fields["name"] = active1.fields["name"] + M.fields["blood_type"] = "?" + M.fields["b_dna"] = "?????" + M.fields["mi_dis"] = "None" + M.fields["mi_dis_d"] = "No minor disabilities have been declared." + M.fields["ma_dis"] = "None" + M.fields["ma_dis_d"] = "No major disabilities have been diagnosed." + M.fields["alg"] = "None" + M.fields["alg_d"] = "No allergies have been detected in this patient." + M.fields["cdi"] = "None" + M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." + M.fields["notes"] = "No notes." + GLOB.data_core.medical += M + + + +//FIELD FUNCTIONS + if("Edit Field") + var/a1 = active1 + var/a2 = active2 + + switch(href_list["field"]) + if("name") + if(istype(active1, /datum/data/record) || istype(active2, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input name:", "Secure. records", active1.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + if(!canUseSecurityRecordsConsole(usr, t1, a1)) + return + if(istype(active1, /datum/data/record)) + active1.fields["name"] = t1 + if(istype(active2, /datum/data/record)) + active2.fields["name"] = t1 + if("id") + if(istype(active2, /datum/data/record) || istype(active1, /datum/data/record)) + var/t1 = stripped_input(usr, "Please input id:", "Secure. records", active1.fields["id"], null) + if(!canUseSecurityRecordsConsole(usr, t1, a1)) + return + if(istype(active1, /datum/data/record)) + active1.fields["id"] = t1 + if(istype(active2, /datum/data/record)) + active2.fields["id"] = t1 + if("fingerprint") + if(istype(active1, /datum/data/record)) + var/t1 = stripped_input(usr, "Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) + if(!canUseSecurityRecordsConsole(usr, t1, a1)) + return + active1.fields["fingerprint"] = t1 + if("gender") + if(istype(active1, /datum/data/record)) + if(active1.fields["gender"] == "Male") + active1.fields["gender"] = "Female" + else if(active1.fields["gender"] == "Female") + active1.fields["gender"] = "Other" + else + active1.fields["gender"] = "Male" + if("age") + if(istype(active1, /datum/data/record)) + var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num + if(!canUseSecurityRecordsConsole(usr, "age", a1)) + return + active1.fields["age"] = t1 + if("species") + if(istype(active1, /datum/data/record)) + var/t1 = input("Select a species", "Species Selection") as null|anything in GLOB.roundstart_races + if(!canUseSecurityRecordsConsole(usr, t1, a1)) + return + active1.fields["species"] = t1 + if("show_photo_front") + if(active1.fields["photo_front"]) + if(istype(active1.fields["photo_front"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_front"] + P.show(usr) + if("upd_photo_front") + var/obj/item/photo/photo = get_photo(usr) + if(photo) + qdel(active1.fields["photo_front"]) + //Lets center it to a 32x32. + var/icon/I = photo.picture.picture_image + var/w = I.Width() + var/h = I.Height() + var/dw = w - 32 + var/dh = w - 32 + I.Crop(dw/2, dh/2, w - dw/2, h - dh/2) + active1.fields["photo_front"] = photo + if("print_photo_front") + if(active1.fields["photo_front"]) + if(istype(active1.fields["photo_front"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_front"] + print_photo(P.picture.picture_image, active1.fields["name"]) + if("show_photo_side") + if(active1.fields["photo_side"]) + if(istype(active1.fields["photo_side"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_side"] + P.show(usr) + if("upd_photo_side") + var/obj/item/photo/photo = get_photo(usr) + if(photo) + qdel(active1.fields["photo_side"]) + //Lets center it to a 32x32. + var/icon/I = photo.picture.picture_image + var/w = I.Width() + var/h = I.Height() + var/dw = w - 32 + var/dh = w - 32 + I.Crop(dw/2, dh/2, w - dw/2, h - dh/2) + active1.fields["photo_side"] = photo + if("print_photo_side") + if(active1.fields["photo_side"]) + if(istype(active1.fields["photo_side"], /obj/item/photo)) + var/obj/item/photo/P = active1.fields["photo_side"] + print_photo(P.picture.picture_image, active1.fields["name"]) + if("mi_crim_add") + if(istype(active1, /datum/data/record)) + var/t1 = stripped_input(usr, "Please input minor crime names:", "Secure. records", "", null) + var/t2 = stripped_input(usr, "Please input minor crime details:", "Secure. records", "", null) + if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) + return + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) + GLOB.data_core.addMinorCrime(active1.fields["id"], crime) + investigate_log("New Minor Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) + if("mi_crim_delete") + if(istype(active1, /datum/data/record)) + if(href_list["cdataid"]) + if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) + return + GLOB.data_core.removeMinorCrime(active1.fields["id"], href_list["cdataid"]) + if("ma_crim_add") + if(istype(active1, /datum/data/record)) + var/t1 = stripped_input(usr, "Please input major crime names:", "Secure. records", "", null) + var/t2 = stripped_input(usr, "Please input major crime details:", "Secure. records", "", null) + if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) + return + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, authenticated, STATION_TIME_TIMESTAMP("hh:mm:ss")) + GLOB.data_core.addMajorCrime(active1.fields["id"], crime) + investigate_log("New Major Crime: [t1]: [t2] | Added to [active1.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS) + if("ma_crim_delete") + if(istype(active1, /datum/data/record)) + if(href_list["cdataid"]) + if(!canUseSecurityRecordsConsole(usr, "delete", null, a2)) + return + GLOB.data_core.removeMajorCrime(active1.fields["id"], href_list["cdataid"]) + if("notes") + if(istype(active2, /datum/data/record)) + var/t1 = stripped_input(usr, "Please summarize notes:", "Secure. records", active2.fields["notes"], null) + if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) + return + active2.fields["notes"] = t1 + if("criminal") + if(istype(active2, /datum/data/record)) + temp = "
    Criminal Status:
    " + temp += "" + if("rank") + var/list/L = list( "Head of Personnel", "Captain", "AI", "Central Command" ) + //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N + if((istype(active1, /datum/data/record) && L.Find(rank))) + temp = "
    Rank:
    " + temp += "
      " + for(var/rank in get_all_jobs()) + temp += "
    • [rank]
    • " + temp += "
    " + else + alert(usr, "You do not have the required rank to do this!") +//TEMPORARY MENU FUNCTIONS + else//To properly clear as per clear screen. + temp=null + switch(href_list["choice"]) + if("Change Rank") + if(active1) + active1.fields["rank"] = href_list["rank"] + if(href_list["rank"] in get_all_jobs()) + active1.fields["real_rank"] = href_list["real_rank"] + + if("Change Criminal Status") + if(active2) + var/old_field = active2.fields["criminal"] + switch(href_list["criminal2"]) + if("none") + active2.fields["criminal"] = "None" + if("arrest") + active2.fields["criminal"] = "*Arrest*" + if("incarcerated") + active2.fields["criminal"] = "Incarcerated" + if("paroled") + active2.fields["criminal"] = "Paroled" + if("released") + active2.fields["criminal"] = "Discharged" + investigate_log("[active1.fields["name"]] has been set from [old_field] to [active2.fields["criminal"]] by [key_name(usr)].", INVESTIGATE_RECORDS) + for(var/mob/living/carbon/human/H in GLOB.carbon_list) + H.sec_hud_set_security_status() + if("Delete Record (Security) Execute") + investigate_log("[key_name(usr)] has deleted the security records for [active1.fields["name"]].", INVESTIGATE_RECORDS) + if(active2) + qdel(active2) + active2 = null + + if("Delete Record (ALL) Execute") + if(active1) + investigate_log("[key_name(usr)] has deleted all records for [active1.fields["name"]].", INVESTIGATE_RECORDS) + for(var/datum/data/record/R in GLOB.data_core.medical) + if((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) + qdel(R) + break + qdel(active1) + active1 = null + + if(active2) + qdel(active2) + active2 = null + else + temp = "This function does not appear to be working at the moment. Our apologies." + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/secure_data/proc/get_photo(mob/user) + var/obj/item/photo/P = null + if(issilicon(user)) + var/mob/living/silicon/tempAI = user + var/datum/picture/selection = tempAI.GetPhoto(user) + if(selection) + P = new(null, selection) + else if(istype(user.get_active_held_item(), /obj/item/photo)) + P = user.get_active_held_item() + return P + +/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, person_name) + if (printing) + return + printing = TRUE + sleep(20) + var/obj/item/photo/P = new/obj/item/photo(drop_location()) + var/datum/picture/toEmbed = new(name = person_name, desc = "The photo on file for [person_name].", image = temp) + P.set_picture(toEmbed, TRUE, TRUE) + P.pixel_x = rand(-10, 10) + P.pixel_y = rand(-10, 10) + printing = FALSE + +/obj/machinery/computer/secure_data/emp_act(severity) + . = ..() + + if(stat & (BROKEN|NOPOWER) || . & EMP_PROTECT_SELF) + return + + for(var/datum/data/record/R in GLOB.data_core.security) + if(prob(10/severity)) + switch(rand(1,8)) + if(1) + if(prob(10)) + R.fields["name"] = "[pick(lizard_name(MALE),lizard_name(FEMALE))]" + else + R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]" + if(2) + R.fields["gender"] = pick("Male", "Female", "Other") + if(3) + R.fields["age"] = rand(5, 85) + if(4) + R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Paroled", "Discharged") + if(5) + R.fields["p_stat"] = pick("*Unconscious*", "Active", "Physically Unfit") + if(6) + R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") + if(7) + R.fields["species"] = pick(GLOB.roundstart_races) + if(8) + var/datum/data/record/G = pick(GLOB.data_core.general) + R.fields["photo_front"] = G.fields["photo_front"] + R.fields["photo_side"] = G.fields["photo_side"] + continue + + else if(prob(1)) + qdel(R) + continue + +/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2) + if(user) + if(authenticated) + if(user.canUseTopic(src, !issilicon(user))) + if(!trim(message1)) + return 0 + if(!record1 || record1 == active1) + if(!record2 || record2 == active2) + return 1 + return 0 + diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 36ba4b0c94..1b700fdf36 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -1,98 +1,98 @@ -/obj/machinery/computer/station_alert - name = "station alert console" - desc = "Used to access the station's automated alert system." - icon_screen = "alert:0" - icon_keyboard = "atmos_key" - circuit = /obj/item/circuitboard/computer/stationalert - var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list()) - - light_color = LIGHT_COLOR_CYAN - -/obj/machinery/computer/station_alert/Initialize() - . = ..() - GLOB.alert_consoles += src - -/obj/machinery/computer/station_alert/Destroy() - GLOB.alert_consoles -= src - return ..() - -/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state) - ui.open() - -/obj/machinery/computer/station_alert/ui_data(mob/user) - . = list() - - .["alarms"] = list() - for(var/class in alarms) - .["alarms"][class] = list() - for(var/area in alarms[class]) - .["alarms"][class] += area - -/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) - if(source.z != z) - return - if(stat & (BROKEN)) - return - - var/list/L = alarms[class] - for(var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/sources = alarm[3] - if (!(source in sources)) - sources += source - return 1 - var/obj/machinery/camera/C = null - var/list/CL = null - if(O && islist(O)) - CL = O - if (CL.len == 1) - C = CL[1] - else if(O && istype(O, /obj/machinery/camera)) - C = O - L[A.name] = list(A, (C ? C : O), list(source)) - return 1 - - -/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin) - if(stat & (BROKEN)) - return - var/list/L = alarms[class] - var/cleared = 0 - for (var/I in L) - if (I == A.name) - var/list/alarm = L[I] - var/list/srcs = alarm[3] - if (origin in srcs) - srcs -= origin - if (srcs.len == 0) - cleared = 1 - L -= I - return !cleared - -/obj/machinery/computer/station_alert/update_icon() - ..() - cut_overlays() - SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) - var/overlay_state = icon_screen - if(stat & (NOPOWER|BROKEN)) - add_overlay("[icon_keyboard]_off") - return - add_overlay(icon_keyboard) - var/active_alarms = FALSE - for(var/cat in alarms) - var/list/L = alarms[cat] - if(L.len) - active_alarms = TRUE - if(active_alarms) - overlay_state = "alert:2" - add_overlay("alert:2") - else - overlay_state = "alert:0" - add_overlay("alert:0") - SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) - SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) +/obj/machinery/computer/station_alert + name = "station alert console" + desc = "Used to access the station's automated alert system." + icon_screen = "alert:0" + icon_keyboard = "atmos_key" + circuit = /obj/item/circuitboard/computer/stationalert + var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list()) + + light_color = LIGHT_COLOR_CYAN + +/obj/machinery/computer/station_alert/Initialize() + . = ..() + GLOB.alert_consoles += src + +/obj/machinery/computer/station_alert/Destroy() + GLOB.alert_consoles -= src + return ..() + +/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "station_alert", name, 300, 500, master_ui, state) + ui.open() + +/obj/machinery/computer/station_alert/ui_data(mob/user) + . = list() + + .["alarms"] = list() + for(var/class in alarms) + .["alarms"][class] = list() + for(var/area in alarms[class]) + .["alarms"][class] += area + +/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) + if(source.z != z) + return + if(stat & (BROKEN)) + return + + var/list/L = alarms[class] + for(var/I in L) + if (I == A.name) + var/list/alarm = L[I] + var/list/sources = alarm[3] + if (!(source in sources)) + sources += source + return 1 + var/obj/machinery/camera/C = null + var/list/CL = null + if(O && islist(O)) + CL = O + if (CL.len == 1) + C = CL[1] + else if(O && istype(O, /obj/machinery/camera)) + C = O + L[A.name] = list(A, (C ? C : O), list(source)) + return 1 + + +/obj/machinery/computer/station_alert/proc/cancelAlarm(class, area/A, obj/origin) + if(stat & (BROKEN)) + return + var/list/L = alarms[class] + var/cleared = 0 + for (var/I in L) + if (I == A.name) + var/list/alarm = L[I] + var/list/srcs = alarm[3] + if (origin in srcs) + srcs -= origin + if (srcs.len == 0) + cleared = 1 + L -= I + return !cleared + +/obj/machinery/computer/station_alert/update_icon() + ..() + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + var/overlay_state = icon_screen + if(stat & (NOPOWER|BROKEN)) + add_overlay("[icon_keyboard]_off") + return + add_overlay(icon_keyboard) + var/active_alarms = FALSE + for(var/cat in alarms) + var/list/L = alarms[cat] + if(L.len) + active_alarms = TRUE + if(active_alarms) + overlay_state = "alert:2" + add_overlay("alert:2") + else + overlay_state = "alert:0" + add_overlay("alert:0") + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index 75e4a866f0..768faa8301 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -1,215 +1,215 @@ -#define NUKESCALINGMODIFIER 1 - -GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")) - -/obj/machinery/computer/telecrystals - name = "\improper telecrystal assignment station" - desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..." - icon_state = "tcstation" - icon_keyboard = "tcstation_key" - icon_screen = "syndie" - clockwork = TRUE //it'd look weird, at least if ratvar ever got there - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - - light_color = LIGHT_COLOR_RED - -///////////////////////////////////////////// -/obj/machinery/computer/telecrystals/uplinker - name = "\improper telecrystal upload/receive station" - desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \ - you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant." - var/obj/item/uplinkholder = null - var/obj/machinery/computer/telecrystals/boss/linkedboss = null - -/obj/machinery/computer/telecrystals/uplinker/Initialize() - . = ..() - - var/ID = pick_n_take(GLOB.possible_uplinker_IDs) - if(!ID) - ID = rand(1,999) - name = "[name] [ID]" - -/obj/machinery/computer/telecrystals/uplinker/attackby(obj/item/I, mob/user, params) - if(uplinkholder) - to_chat(user, "[src] already has an uplink in it.") - return - var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink) - if(hidden_uplink) - if(!user.transferItemToLoc(I, src)) - return - uplinkholder = I - I.add_fingerprint(user) - update_icon() - updateUsrDialog() - else - to_chat(user, "[I] doesn't appear to be an uplink...") - -/obj/machinery/computer/telecrystals/uplinker/update_icon() - ..() - if(uplinkholder) - add_overlay("[initial(icon_state)]-closed") - -/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink() - if(uplinkholder) - uplinkholder.forceMove(drop_location()) - uplinkholder = null - update_icon() - -/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1) - if(uplinkholder && linkedboss) - var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) - if(amt < 0) - linkedboss.storedcrystals += hidden_uplink.telecrystals - if(addLog) - linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].") - hidden_uplink.telecrystals = 0 - else if(amt <= hidden_uplink.telecrystals) - hidden_uplink.telecrystals -= amt - linkedboss.storedcrystals += amt - if(addLog) - linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].") - -/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1) - if(uplinkholder && linkedboss) - var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) - if(amt < 0) - hidden_uplink.telecrystals += linkedboss.storedcrystals - if(addLog) - linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].") - linkedboss.storedcrystals = 0 - else if(amt <= linkedboss.storedcrystals) - hidden_uplink.telecrystals += amt - linkedboss.storedcrystals -= amt - if(addLog) - linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].") - -/////// - -/obj/machinery/computer/telecrystals/uplinker/ui_interact(mob/user) - . = ..() - var/dat = "" - if(linkedboss) - dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.

    " - else - dat += "No linked management consoles detected. Scan for uplink stations using the management console.

    " - - if(uplinkholder) - var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) - dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.
    " - if(linkedboss) - dat += "Donate TC: 1 | 5 | All" - dat += "
    Eject Uplink" - - - var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list) - if(..()) - return - - if(href_list["donate"]) - var/tcamt = text2num(href_list["donate"]) - donateTC(tcamt) - - if(href_list["eject"]) - ejectuplink() - - src.updateUsrDialog() - - -///////////////////////////////////////// -/obj/machinery/computer/telecrystals/boss - name = "team telecrystal management console" - desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \ - Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \ - based on the danger rating of the mission." - icon_state = "computer" - icon_screen = "tcboss" - icon_keyboard = "syndie_key" - var/virgin = 1 - var/scanrange = 10 - var/storedcrystals = 0 - var/list/TCstations = list() - var/list/transferlog = list() - -/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage) - transferlog += ("[STATION_TIME_TIMESTAMP("hh:mm:ss")] [logmessage]") - -/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers() - for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc)) - if(!A.linkedboss) - TCstations += A - A.linkedboss = src - if(virgin) - getDangerous() - virgin = 0 - -/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population. - var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop) - var/danger = GLOB.joined_player_list.len - nukeops.len - danger = CEILING(danger, 10) - scaleTC(danger) - -/obj/machinery/computer/telecrystals/boss/proc/scaleTC(amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc. - storedcrystals += amt * NUKESCALINGMODIFIER - -///////// - -/obj/machinery/computer/telecrystals/boss/ui_interact(mob/user) - . = ..() - var/dat = "" - dat += "Scan for TC stations.
    " - dat += "[storedcrystals] telecrystals are available for distribution.
    " - dat += "

    " - - - for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) - dat += "[A.name] | " - if(A.uplinkholder) - var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink) - dat += "[hidden_uplink.telecrystals] telecrystals." - if(storedcrystals) - dat+= "
    Add TC: 1 | 5 | 10 | All" - dat += "
    " - - if(TCstations.len && storedcrystals) - dat += "

    Evenly distribute remaining TC.

    " - - - for(var/entry in transferlog) - dat += "[entry]
    " - - - var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/telecrystals/boss/Topic(href, href_list) - if(..()) - return - - if(href_list["scan"]) - scanUplinkers() - - if(href_list["give"]) - var/tcamt = text2num(href_list["give"]) - if(TCstations.len) // sanity - var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations - A.giveTC(tcamt) - - if(href_list["distrib"]) - var/sanity = 0 - while(storedcrystals && sanity < 100) - for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) - A.giveTC(1,0) - sanity++ - logTransfer("[src] evenly distributed telecrystals.") - - src.updateUsrDialog() - return - -#undef NUKESCALINGMODIFIER +#define NUKESCALINGMODIFIER 1 + +GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")) + +/obj/machinery/computer/telecrystals + name = "\improper telecrystal assignment station" + desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..." + icon_state = "tcstation" + icon_keyboard = "tcstation_key" + icon_screen = "syndie" + clockwork = TRUE //it'd look weird, at least if ratvar ever got there + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + + light_color = LIGHT_COLOR_RED + +///////////////////////////////////////////// +/obj/machinery/computer/telecrystals/uplinker + name = "\improper telecrystal upload/receive station" + desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \ + you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant." + var/obj/item/uplinkholder = null + var/obj/machinery/computer/telecrystals/boss/linkedboss = null + +/obj/machinery/computer/telecrystals/uplinker/Initialize() + . = ..() + + var/ID = pick_n_take(GLOB.possible_uplinker_IDs) + if(!ID) + ID = rand(1,999) + name = "[name] [ID]" + +/obj/machinery/computer/telecrystals/uplinker/attackby(obj/item/I, mob/user, params) + if(uplinkholder) + to_chat(user, "[src] already has an uplink in it.") + return + var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink) + if(hidden_uplink) + if(!user.transferItemToLoc(I, src)) + return + uplinkholder = I + I.add_fingerprint(user) + update_icon() + updateUsrDialog() + else + to_chat(user, "[I] doesn't appear to be an uplink...") + +/obj/machinery/computer/telecrystals/uplinker/update_icon() + ..() + if(uplinkholder) + add_overlay("[initial(icon_state)]-closed") + +/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink() + if(uplinkholder) + uplinkholder.forceMove(drop_location()) + uplinkholder = null + update_icon() + +/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1) + if(uplinkholder && linkedboss) + var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) + if(amt < 0) + linkedboss.storedcrystals += hidden_uplink.telecrystals + if(addLog) + linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].") + hidden_uplink.telecrystals = 0 + else if(amt <= hidden_uplink.telecrystals) + hidden_uplink.telecrystals -= amt + linkedboss.storedcrystals += amt + if(addLog) + linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].") + +/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1) + if(uplinkholder && linkedboss) + var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) + if(amt < 0) + hidden_uplink.telecrystals += linkedboss.storedcrystals + if(addLog) + linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].") + linkedboss.storedcrystals = 0 + else if(amt <= linkedboss.storedcrystals) + hidden_uplink.telecrystals += amt + linkedboss.storedcrystals -= amt + if(addLog) + linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].") + +/////// + +/obj/machinery/computer/telecrystals/uplinker/ui_interact(mob/user) + . = ..() + var/dat = "" + if(linkedboss) + dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.

    " + else + dat += "No linked management consoles detected. Scan for uplink stations using the management console.

    " + + if(uplinkholder) + var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink) + dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.
    " + if(linkedboss) + dat += "Donate TC: 1 | 5 | All" + dat += "
    Eject Uplink" + + + var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list) + if(..()) + return + + if(href_list["donate"]) + var/tcamt = text2num(href_list["donate"]) + donateTC(tcamt) + + if(href_list["eject"]) + ejectuplink() + + src.updateUsrDialog() + + +///////////////////////////////////////// +/obj/machinery/computer/telecrystals/boss + name = "team telecrystal management console" + desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \ + Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \ + based on the danger rating of the mission." + icon_state = "computer" + icon_screen = "tcboss" + icon_keyboard = "syndie_key" + var/virgin = 1 + var/scanrange = 10 + var/storedcrystals = 0 + var/list/TCstations = list() + var/list/transferlog = list() + +/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage) + transferlog += ("[STATION_TIME_TIMESTAMP("hh:mm:ss")] [logmessage]") + +/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers() + for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc)) + if(!A.linkedboss) + TCstations += A + A.linkedboss = src + if(virgin) + getDangerous() + virgin = 0 + +/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population. + var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop) + var/danger = GLOB.joined_player_list.len - nukeops.len + danger = CEILING(danger, 10) + scaleTC(danger) + +/obj/machinery/computer/telecrystals/boss/proc/scaleTC(amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc. + storedcrystals += amt * NUKESCALINGMODIFIER + +///////// + +/obj/machinery/computer/telecrystals/boss/ui_interact(mob/user) + . = ..() + var/dat = "" + dat += "Scan for TC stations.
    " + dat += "[storedcrystals] telecrystals are available for distribution.
    " + dat += "

    " + + + for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) + dat += "[A.name] | " + if(A.uplinkholder) + var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink) + dat += "[hidden_uplink.telecrystals] telecrystals." + if(storedcrystals) + dat+= "
    Add TC: 1 | 5 | 10 | All" + dat += "
    " + + if(TCstations.len && storedcrystals) + dat += "

    Evenly distribute remaining TC.

    " + + + for(var/entry in transferlog) + dat += "[entry]
    " + + + var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +/obj/machinery/computer/telecrystals/boss/Topic(href, href_list) + if(..()) + return + + if(href_list["scan"]) + scanUplinkers() + + if(href_list["give"]) + var/tcamt = text2num(href_list["give"]) + if(TCstations.len) // sanity + var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations + A.giveTC(tcamt) + + if(href_list["distrib"]) + var/sanity = 0 + while(storedcrystals && sanity < 100) + for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) + A.giveTC(1,0) + sanity++ + logTransfer("[src] evenly distributed telecrystals.") + + src.updateUsrDialog() + return + +#undef NUKESCALINGMODIFIER diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 7a39e73ad3..96487915dd 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -1,279 +1,279 @@ -/obj/structure/frame - name = "frame" - icon = 'icons/obj/stock_parts.dmi' - icon_state = "box_0" - density = TRUE - max_integrity = 250 - var/obj/item/circuitboard/machine/circuit = null - var/state = 1 - -/obj/structure/frame/examine(user) - . = ..() - if(circuit) - . += "It has \a [circuit] installed." - - -/obj/structure/frame/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - new /obj/item/stack/sheet/metal(loc, 5) - if(circuit) - circuit.forceMove(loc) - circuit = null - qdel(src) - - -/obj/structure/frame/machine - name = "machine frame" - var/list/components = null - var/list/req_components = null - var/list/req_component_names = null // user-friendly names of components - -/obj/structure/frame/machine/examine(user) - . = ..() - if(state == 3 && req_components && req_component_names) - var/hasContent = 0 - var/requires = "It requires" - - for(var/i = 1 to req_components.len) - var/tname = req_components[i] - var/amt = req_components[tname] - if(amt == 0) - continue - var/use_and = i == req_components.len - requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]" - hasContent = 1 - - if(hasContent) - . += requires + "." - else - . += "It does not require any more components." - -/obj/structure/frame/machine/proc/update_namelist() - if(!req_components) - return - - req_component_names = new() - for(var/tname in req_components) - if(ispath(tname, /obj/item/stack)) - var/obj/item/stack/S = tname - var/singular_name = initial(S.singular_name) - if(singular_name) - req_component_names[tname] = singular_name - else - req_component_names[tname] = initial(S.name) - else - var/obj/O = tname - req_component_names[tname] = initial(O.name) - -/obj/structure/frame/machine/proc/get_req_components_amt() - var/amt = 0 - for(var/path in req_components) - amt += req_components[path] - return amt - -/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params) - switch(state) - if(1) - if(istype(P, /obj/item/circuitboard/machine)) - to_chat(user, "The frame needs wiring first!") - return - else if(istype(P, /obj/item/circuitboard)) - to_chat(user, "This frame does not accept circuit boards of this type!") - return - if(istype(P, /obj/item/stack/cable_coil)) - if(!P.tool_start_check(user, amount=5)) - return - - to_chat(user, "You start to add cables to the frame...") - if(P.use_tool(src, user, 20, volume=50, amount=5)) - to_chat(user, "You add cables to the frame.") - state = 2 - icon_state = "box_1" - - return - if(istype(P, /obj/item/screwdriver) && !anchored) - user.visible_message("[user] disassembles the frame.", \ - "You start to disassemble the frame...", "You hear banging and clanking.") - if(P.use_tool(src, user, 40, volume=50)) - if(state == 1) - to_chat(user, "You disassemble the frame.") - var/obj/item/stack/sheet/metal/M = new (loc, 5) - M.add_fingerprint(user) - qdel(src) - return - if(istype(P, /obj/item/wrench)) - to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") - if(P.use_tool(src, user, 40, volume=75)) - if(state == 1) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - setAnchored(!anchored) - return - - if(2) - if(istype(P, /obj/item/wrench)) - to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") - if(P.use_tool(src, user, 40, volume=75)) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - setAnchored(!anchored) - return - - if(istype(P, /obj/item/circuitboard/machine)) - var/obj/item/circuitboard/machine/B = P - if(!anchored && B.needs_anchored) - to_chat(user, "The frame needs to be secured first!") - return - if(!user.transferItemToLoc(B, src)) - return - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) - to_chat(user, "You add the circuit board to the frame.") - circuit = B - icon_state = "box_2" - state = 3 - components = list() - req_components = B.req_components.Copy() - update_namelist() - return - - else if(istype(P, /obj/item/circuitboard)) - to_chat(user, "This frame does not accept circuit boards of this type!") - return - - if(istype(P, /obj/item/wirecutters)) - P.play_tool_sound(src) - to_chat(user, "You remove the cables.") - state = 1 - icon_state = "box_0" - new /obj/item/stack/cable_coil(drop_location(), 5) - return - - if(3) - if(istype(P, /obj/item/crowbar)) - P.play_tool_sound(src) - state = 2 - circuit.forceMove(drop_location()) - components.Remove(circuit) - circuit = null - if(components.len == 0) - to_chat(user, "You remove the circuit board.") - else - to_chat(user, "You remove the circuit board and other components.") - for(var/atom/movable/AM in components) - AM.forceMove(drop_location()) - desc = initial(desc) - req_components = null - components = null - icon_state = "box_1" - return - - if(istype(P, /obj/item/wrench) && !circuit.needs_anchored) - to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") - if(P.use_tool(src, user, 40, volume=75)) - to_chat(user, "You [anchored ? "un" : ""]secure [name].") - setAnchored(!anchored) - return - - if(istype(P, /obj/item/screwdriver)) - var/component_check = 1 - for(var/R in req_components) - if(req_components[R] > 0) - component_check = 0 - break - if(component_check) - P.play_tool_sound(src) - var/obj/machinery/new_machine = new circuit.build_path(loc) - new_machine.setAnchored(anchored) - new_machine.on_construction() - for(var/obj/O in new_machine.component_parts) - qdel(O) - new_machine.component_parts = list() - for(var/obj/O in src) - O.moveToNullspace() - new_machine.component_parts += O - if(new_machine.circuit) - QDEL_NULL(new_machine.circuit) - new_machine.circuit = circuit - circuit.moveToNullspace() - new_machine.RefreshParts() - qdel(src) - return - - if(istype(P, /obj/item/storage/part_replacer) && P.contents.len && get_req_components_amt()) - var/obj/item/storage/part_replacer/replacer = P - var/list/added_components = list() - var/list/part_list = list() - - //Assemble a list of current parts, then sort them by their rating! - for(var/obj/item/co in replacer) - part_list += co - //Sort the parts. This ensures that higher tier items are applied first. - part_list = sortTim(part_list, /proc/cmp_rped_sort) - - for(var/path in req_components) - while(req_components[path] > 0 && (locate(path) in part_list)) - var/obj/item/part = (locate(path) in part_list) - part_list -= part - if(istype(part,/obj/item/stack)) - var/obj/item/stack/S = part - var/used_amt = min(round(S.get_amount()), req_components[path]) - if(!used_amt || !S.use(used_amt)) - continue - var/NS = new S.merge_type(src, used_amt) - added_components[NS] = path - req_components[path] -= used_amt - else - added_components[part] = path - if(SEND_SIGNAL(replacer, COMSIG_TRY_STORAGE_TAKE, part, src)) - req_components[path]-- - - for(var/obj/item/part in added_components) - if(istype(part,/obj/item/stack)) - var/obj/item/stack/S = part - var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with - if(NS) - S.merge(NS) - if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore - components += part - to_chat(user, "[part.name] applied.") - if(added_components.len) - replacer.play_rped_sound() - return - - if(isitem(P) && get_req_components_amt()) - for(var/I in req_components) - if(istype(P, I) && (req_components[I] > 0)) - if(istype(P, /obj/item/stack)) - var/obj/item/stack/S = P - var/used_amt = min(round(S.get_amount()), req_components[I]) - - if(used_amt && S.use(used_amt)) - var/obj/item/stack/NS = locate(S.merge_type) in components - - if(!NS) - NS = new S.merge_type(src, used_amt) - components += NS - else - NS.add(used_amt) - - req_components[I] -= used_amt - to_chat(user, "You add [P] to [src].") - return - if(!user.transferItemToLoc(P, src)) - break - to_chat(user, "You add [P] to [src].") - components += P - req_components[I]-- - return 1 - to_chat(user, "You cannot add that to the machine!") - return 0 - if(user.a_intent == INTENT_HARM) - return ..() - -/obj/structure/frame/machine/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(state >= 2) - new /obj/item/stack/cable_coil(loc , 5) - for(var/X in components) - var/obj/item/I = X - I.forceMove(loc) - - ..() +/obj/structure/frame + name = "frame" + icon = 'icons/obj/stock_parts.dmi' + icon_state = "box_0" + density = TRUE + max_integrity = 250 + var/obj/item/circuitboard/machine/circuit = null + var/state = 1 + +/obj/structure/frame/examine(user) + . = ..() + if(circuit) + . += "It has \a [circuit] installed." + + +/obj/structure/frame/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + new /obj/item/stack/sheet/metal(loc, 5) + if(circuit) + circuit.forceMove(loc) + circuit = null + qdel(src) + + +/obj/structure/frame/machine + name = "machine frame" + var/list/components = null + var/list/req_components = null + var/list/req_component_names = null // user-friendly names of components + +/obj/structure/frame/machine/examine(user) + . = ..() + if(state == 3 && req_components && req_component_names) + var/hasContent = 0 + var/requires = "It requires" + + for(var/i = 1 to req_components.len) + var/tname = req_components[i] + var/amt = req_components[tname] + if(amt == 0) + continue + var/use_and = i == req_components.len + requires += "[(hasContent ? (use_and ? ", and" : ",") : "")] [amt] [amt == 1 ? req_component_names[tname] : "[req_component_names[tname]]\s"]" + hasContent = 1 + + if(hasContent) + . += requires + "." + else + . += "It does not require any more components." + +/obj/structure/frame/machine/proc/update_namelist() + if(!req_components) + return + + req_component_names = new() + for(var/tname in req_components) + if(ispath(tname, /obj/item/stack)) + var/obj/item/stack/S = tname + var/singular_name = initial(S.singular_name) + if(singular_name) + req_component_names[tname] = singular_name + else + req_component_names[tname] = initial(S.name) + else + var/obj/O = tname + req_component_names[tname] = initial(O.name) + +/obj/structure/frame/machine/proc/get_req_components_amt() + var/amt = 0 + for(var/path in req_components) + amt += req_components[path] + return amt + +/obj/structure/frame/machine/attackby(obj/item/P, mob/user, params) + switch(state) + if(1) + if(istype(P, /obj/item/circuitboard/machine)) + to_chat(user, "The frame needs wiring first!") + return + else if(istype(P, /obj/item/circuitboard)) + to_chat(user, "This frame does not accept circuit boards of this type!") + return + if(istype(P, /obj/item/stack/cable_coil)) + if(!P.tool_start_check(user, amount=5)) + return + + to_chat(user, "You start to add cables to the frame...") + if(P.use_tool(src, user, 20, volume=50, amount=5)) + to_chat(user, "You add cables to the frame.") + state = 2 + icon_state = "box_1" + + return + if(istype(P, /obj/item/screwdriver) && !anchored) + user.visible_message("[user] disassembles the frame.", \ + "You start to disassemble the frame...", "You hear banging and clanking.") + if(P.use_tool(src, user, 40, volume=50)) + if(state == 1) + to_chat(user, "You disassemble the frame.") + var/obj/item/stack/sheet/metal/M = new (loc, 5) + M.add_fingerprint(user) + qdel(src) + return + if(istype(P, /obj/item/wrench)) + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + if(P.use_tool(src, user, 40, volume=75)) + if(state == 1) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + setAnchored(!anchored) + return + + if(2) + if(istype(P, /obj/item/wrench)) + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + if(P.use_tool(src, user, 40, volume=75)) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + setAnchored(!anchored) + return + + if(istype(P, /obj/item/circuitboard/machine)) + var/obj/item/circuitboard/machine/B = P + if(!anchored && B.needs_anchored) + to_chat(user, "The frame needs to be secured first!") + return + if(!user.transferItemToLoc(B, src)) + return + playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) + to_chat(user, "You add the circuit board to the frame.") + circuit = B + icon_state = "box_2" + state = 3 + components = list() + req_components = B.req_components.Copy() + update_namelist() + return + + else if(istype(P, /obj/item/circuitboard)) + to_chat(user, "This frame does not accept circuit boards of this type!") + return + + if(istype(P, /obj/item/wirecutters)) + P.play_tool_sound(src) + to_chat(user, "You remove the cables.") + state = 1 + icon_state = "box_0" + new /obj/item/stack/cable_coil(drop_location(), 5) + return + + if(3) + if(istype(P, /obj/item/crowbar)) + P.play_tool_sound(src) + state = 2 + circuit.forceMove(drop_location()) + components.Remove(circuit) + circuit = null + if(components.len == 0) + to_chat(user, "You remove the circuit board.") + else + to_chat(user, "You remove the circuit board and other components.") + for(var/atom/movable/AM in components) + AM.forceMove(drop_location()) + desc = initial(desc) + req_components = null + components = null + icon_state = "box_1" + return + + if(istype(P, /obj/item/wrench) && !circuit.needs_anchored) + to_chat(user, "You start [anchored ? "un" : ""]securing [name]...") + if(P.use_tool(src, user, 40, volume=75)) + to_chat(user, "You [anchored ? "un" : ""]secure [name].") + setAnchored(!anchored) + return + + if(istype(P, /obj/item/screwdriver)) + var/component_check = 1 + for(var/R in req_components) + if(req_components[R] > 0) + component_check = 0 + break + if(component_check) + P.play_tool_sound(src) + var/obj/machinery/new_machine = new circuit.build_path(loc) + new_machine.setAnchored(anchored) + new_machine.on_construction() + for(var/obj/O in new_machine.component_parts) + qdel(O) + new_machine.component_parts = list() + for(var/obj/O in src) + O.moveToNullspace() + new_machine.component_parts += O + if(new_machine.circuit) + QDEL_NULL(new_machine.circuit) + new_machine.circuit = circuit + circuit.moveToNullspace() + new_machine.RefreshParts() + qdel(src) + return + + if(istype(P, /obj/item/storage/part_replacer) && P.contents.len && get_req_components_amt()) + var/obj/item/storage/part_replacer/replacer = P + var/list/added_components = list() + var/list/part_list = list() + + //Assemble a list of current parts, then sort them by their rating! + for(var/obj/item/co in replacer) + part_list += co + //Sort the parts. This ensures that higher tier items are applied first. + part_list = sortTim(part_list, /proc/cmp_rped_sort) + + for(var/path in req_components) + while(req_components[path] > 0 && (locate(path) in part_list)) + var/obj/item/part = (locate(path) in part_list) + part_list -= part + if(istype(part,/obj/item/stack)) + var/obj/item/stack/S = part + var/used_amt = min(round(S.get_amount()), req_components[path]) + if(!used_amt || !S.use(used_amt)) + continue + var/NS = new S.merge_type(src, used_amt) + added_components[NS] = path + req_components[path] -= used_amt + else + added_components[part] = path + if(SEND_SIGNAL(replacer, COMSIG_TRY_STORAGE_TAKE, part, src)) + req_components[path]-- + + for(var/obj/item/part in added_components) + if(istype(part,/obj/item/stack)) + var/obj/item/stack/S = part + var/obj/item/stack/NS = locate(S.merge_type) in components //find a stack to merge with + if(NS) + S.merge(NS) + if(!QDELETED(part)) //If we're a stack and we merged we might not exist anymore + components += part + to_chat(user, "[part.name] applied.") + if(added_components.len) + replacer.play_rped_sound() + return + + if(isitem(P) && get_req_components_amt()) + for(var/I in req_components) + if(istype(P, I) && (req_components[I] > 0)) + if(istype(P, /obj/item/stack)) + var/obj/item/stack/S = P + var/used_amt = min(round(S.get_amount()), req_components[I]) + + if(used_amt && S.use(used_amt)) + var/obj/item/stack/NS = locate(S.merge_type) in components + + if(!NS) + NS = new S.merge_type(src, used_amt) + components += NS + else + NS.add(used_amt) + + req_components[I] -= used_amt + to_chat(user, "You add [P] to [src].") + return + if(!user.transferItemToLoc(P, src)) + break + to_chat(user, "You add [P] to [src].") + components += P + req_components[I]-- + return 1 + to_chat(user, "You cannot add that to the machine!") + return 0 + if(user.a_intent == INTENT_HARM) + return ..() + +/obj/structure/frame/machine/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(state >= 2) + new /obj/item/stack/cable_coil(loc , 5) + for(var/X in components) + var/obj/item/I = X + I.forceMove(loc) + + ..() diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index cf46e6b0fd..42649a9ff2 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -1,43 +1,43 @@ -/obj/machinery/door/airlock/alarmlock - name = "glass alarm airlock" - icon = 'icons/obj/doors/airlocks/station2/glass.dmi' - overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' - opacity = 0 - assemblytype = /obj/structure/door_assembly/door_assembly_public - glass = TRUE - - var/datum/radio_frequency/air_connection - var/air_frequency = FREQ_ATMOS_ALARMS - autoclose = FALSE - -/obj/machinery/door/airlock/alarmlock/Initialize() - . = ..() - air_connection = new - -/obj/machinery/door/airlock/alarmlock/Destroy() - SSradio.remove_object(src,air_frequency) - air_connection = null - return ..() - -/obj/machinery/door/airlock/alarmlock/Initialize() - . = ..() - SSradio.remove_object(src, air_frequency) - air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM) - open() - -/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) - ..() - if(stat & (NOPOWER|BROKEN)) - return - - var/alarm_area = signal.data["zone"] - var/alert = signal.data["alert"] - - if(alarm_area == get_area_name(src)) - switch(alert) - if("severe") - autoclose = TRUE - close() - if("minor", "clear") - autoclose = FALSE +/obj/machinery/door/airlock/alarmlock + name = "glass alarm airlock" + icon = 'icons/obj/doors/airlocks/station2/glass.dmi' + overlays_file = 'icons/obj/doors/airlocks/station2/overlays.dmi' + opacity = 0 + assemblytype = /obj/structure/door_assembly/door_assembly_public + glass = TRUE + + var/datum/radio_frequency/air_connection + var/air_frequency = FREQ_ATMOS_ALARMS + autoclose = FALSE + +/obj/machinery/door/airlock/alarmlock/Initialize() + . = ..() + air_connection = new + +/obj/machinery/door/airlock/alarmlock/Destroy() + SSradio.remove_object(src,air_frequency) + air_connection = null + return ..() + +/obj/machinery/door/airlock/alarmlock/Initialize() + . = ..() + SSradio.remove_object(src, air_frequency) + air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM) + open() + +/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) + ..() + if(stat & (NOPOWER|BROKEN)) + return + + var/alarm_area = signal.data["zone"] + var/alert = signal.data["alert"] + + if(alarm_area == get_area_name(src)) + switch(alert) + if("severe") + autoclose = TRUE + close() + if("minor", "clear") + autoclose = FALSE open() \ No newline at end of file diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 5c8cd4ffb8..beaf47d0a3 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -1,256 +1,256 @@ -#define CHARS_PER_LINE 5 -#define FONT_SIZE "5pt" -#define FONT_COLOR "#09f" -#define FONT_STYLE "Arial Black" -#define MAX_TIMER 9000 - -#define PRESET_SHORT 1200 -#define PRESET_MEDIUM 1800 -#define PRESET_LONG 3000 - - - -/////////////////////////////////////////////////////////////////////////////////////////////// -// Brig Door control displays. -// Description: This is a controls the timer for the brig doors, displays the timer on itself and -// has a popup window when used, allowing to set the timer. -// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code -// Date: 01/September/2010 -// Programmer: Veryinky -///////////////////////////////////////////////////////////////////////////////////////////////// -/obj/machinery/door_timer - name = "door timer" - icon = 'icons/obj/status_display.dmi' - icon_state = "frame" - desc = "A remote control for a door." - req_access = list(ACCESS_SECURITY) - density = FALSE - var/id = null // id of linked machinery/lockers - - var/activation_time = 0 - var/timer_duration = 0 - - var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing - var/list/obj/machinery/targets = list() - var/obj/item/radio/Radio //needed to send messages to sec radio - - maptext_height = 26 - maptext_width = 32 - -/obj/machinery/door_timer/Initialize() - . = ..() - - Radio = new/obj/item/radio(src) - Radio.listening = 0 - -/obj/machinery/door_timer/Initialize() - . = ..() - if(id != null) - for(var/obj/machinery/door/window/brigdoor/M in urange(20, src)) - if (M.id == id) - targets += M - - for(var/obj/machinery/flasher/F in urange(20, src)) - if(F.id == id) - targets += F - - for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src)) - if(C.id == id) - targets += C - - if(!targets.len) - stat |= BROKEN - update_icon() - - -//Main door timer loop, if it's timing and time is >0 reduce time by 1. -// if it's less than 0, open door, reset timer -// update the door_timer window and the icon -/obj/machinery/door_timer/process() - if(stat & (NOPOWER|BROKEN)) - return - - if(timing) - if(world.realtime - activation_time >= timer_duration) - timer_end() // open doors, reset timer, clear status screen - update_icon() - -// has the door power sitatuation changed, if so update icon. -/obj/machinery/door_timer/power_change() - ..() - update_icon() - - -// open/closedoor checks if door_timer has power, if so it checks if the -// linked door is open/closed (by density) then opens it/closes it. -/obj/machinery/door_timer/proc/timer_start() - if(stat & (NOPOWER|BROKEN)) - return 0 - - activation_time = world.realtime - timing = TRUE - - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(door.density) - continue - INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close) - - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) - continue - if(C.opened && !C.close()) - continue - C.locked = TRUE - C.update_icon() - return 1 - - -/obj/machinery/door_timer/proc/timer_end(forced = FALSE) - - if(stat & (NOPOWER|BROKEN)) - return 0 - - if(!forced) - Radio.set_frequency(FREQ_SECURITY) - Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY) - - timing = FALSE - activation_time = null - set_timer(0) - update_icon() - - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(!door.density) - continue - INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open) - - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) - continue - if(C.opened) - continue - C.locked = FALSE - C.update_icon() - - return 1 - - -/obj/machinery/door_timer/proc/time_left(seconds = FALSE) - . = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0)) - if(seconds) - . /= 10 - -/obj/machinery/door_timer/proc/set_timer(value) - var/new_time = CLAMP(value,0,MAX_TIMER) - . = new_time == timer_duration //return 1 on no change - timer_duration = new_time - -/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "brig_timer", name, 300, 200, master_ui, state) - ui.open() - -//icon update function -// if NOPOWER, display blank -// if BROKEN, display blue screen of death icon AI uses -// if timing=true, run update display function -/obj/machinery/door_timer/update_icon() - if(stat & (NOPOWER)) - icon_state = "frame" - return - - if(stat & (BROKEN)) - set_picture("ai_bsod") - return - - if(timing) - var/disp1 = id - var/time_left = time_left(seconds = TRUE) - var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]" - if(length(disp2) > CHARS_PER_LINE) - disp2 = "Error" - update_display(disp1, disp2) - else - if(maptext) - maptext = "" - return - - -// Adds an icon in case the screen is broken/off, stolen from status_display.dm -/obj/machinery/door_timer/proc/set_picture(state) - if(maptext) - maptext = "" - cut_overlays() - add_overlay(mutable_appearance('icons/obj/status_display.dmi', state)) - - -//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display -// Stolen from status_display -/obj/machinery/door_timer/proc/update_display(line1, line2) - var/new_text = {"
    [line1]
    [line2]
    "} - if(maptext != new_text) - maptext = new_text - -/obj/machinery/door_timer/ui_data() - var/list/data = list() - var/time_left = time_left(seconds = TRUE) - data["seconds"] = round(time_left % 60) - data["minutes"] = round((time_left - data["seconds"]) / 60) - data["timing"] = timing - data["flash_charging"] = FALSE - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 150) > world.time) - data["flash_charging"] = TRUE - break - return data - - -/obj/machinery/door_timer/ui_act(action, params) - if(..()) - return - . = TRUE - - if(!allowed(usr)) - to_chat(usr, "Access denied.") - return FALSE - - switch(action) - if("time") - var/value = text2num(params["adjust"]) - if(value) - . = set_timer(time_left()+value) - if("start") - timer_start() - if("stop") - timer_end(forced = TRUE) - if("flash") - for(var/obj/machinery/flasher/F in targets) - F.flash() - if("preset") - var/preset = params["preset"] - var/preset_time = time_left() - switch(preset) - if("short") - preset_time = PRESET_SHORT - if("medium") - preset_time = PRESET_MEDIUM - if("long") - preset_time = PRESET_LONG - . = set_timer(preset_time) - if(timing) - activation_time = world.realtime - else - . = FALSE - - -#undef PRESET_SHORT -#undef PRESET_MEDIUM -#undef PRESET_LONG - -#undef MAX_TIMER -#undef FONT_SIZE -#undef FONT_COLOR -#undef FONT_STYLE -#undef CHARS_PER_LINE +#define CHARS_PER_LINE 5 +#define FONT_SIZE "5pt" +#define FONT_COLOR "#09f" +#define FONT_STYLE "Arial Black" +#define MAX_TIMER 9000 + +#define PRESET_SHORT 1200 +#define PRESET_MEDIUM 1800 +#define PRESET_LONG 3000 + + + +/////////////////////////////////////////////////////////////////////////////////////////////// +// Brig Door control displays. +// Description: This is a controls the timer for the brig doors, displays the timer on itself and +// has a popup window when used, allowing to set the timer. +// Code Notes: Combination of old brigdoor.dm code from rev4407 and the status_display.dm code +// Date: 01/September/2010 +// Programmer: Veryinky +///////////////////////////////////////////////////////////////////////////////////////////////// +/obj/machinery/door_timer + name = "door timer" + icon = 'icons/obj/status_display.dmi' + icon_state = "frame" + desc = "A remote control for a door." + req_access = list(ACCESS_SECURITY) + density = FALSE + var/id = null // id of linked machinery/lockers + + var/activation_time = 0 + var/timer_duration = 0 + + var/timing = FALSE // boolean, true/1 timer is on, false/0 means it's not timing + var/list/obj/machinery/targets = list() + var/obj/item/radio/Radio //needed to send messages to sec radio + + maptext_height = 26 + maptext_width = 32 + +/obj/machinery/door_timer/Initialize() + . = ..() + + Radio = new/obj/item/radio(src) + Radio.listening = 0 + +/obj/machinery/door_timer/Initialize() + . = ..() + if(id != null) + for(var/obj/machinery/door/window/brigdoor/M in urange(20, src)) + if (M.id == id) + targets += M + + for(var/obj/machinery/flasher/F in urange(20, src)) + if(F.id == id) + targets += F + + for(var/obj/structure/closet/secure_closet/brig/C in urange(20, src)) + if(C.id == id) + targets += C + + if(!targets.len) + stat |= BROKEN + update_icon() + + +//Main door timer loop, if it's timing and time is >0 reduce time by 1. +// if it's less than 0, open door, reset timer +// update the door_timer window and the icon +/obj/machinery/door_timer/process() + if(stat & (NOPOWER|BROKEN)) + return + + if(timing) + if(world.realtime - activation_time >= timer_duration) + timer_end() // open doors, reset timer, clear status screen + update_icon() + +// has the door power sitatuation changed, if so update icon. +/obj/machinery/door_timer/power_change() + ..() + update_icon() + + +// open/closedoor checks if door_timer has power, if so it checks if the +// linked door is open/closed (by density) then opens it/closes it. +/obj/machinery/door_timer/proc/timer_start() + if(stat & (NOPOWER|BROKEN)) + return 0 + + activation_time = world.realtime + timing = TRUE + + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(door.density) + continue + INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/close) + + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) + continue + if(C.opened && !C.close()) + continue + C.locked = TRUE + C.update_icon() + return 1 + + +/obj/machinery/door_timer/proc/timer_end(forced = FALSE) + + if(stat & (NOPOWER|BROKEN)) + return 0 + + if(!forced) + Radio.set_frequency(FREQ_SECURITY) + Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY) + + timing = FALSE + activation_time = null + set_timer(0) + update_icon() + + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(!door.density) + continue + INVOKE_ASYNC(door, /obj/machinery/door/window/brigdoor.proc/open) + + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) + continue + if(C.opened) + continue + C.locked = FALSE + C.update_icon() + + return 1 + + +/obj/machinery/door_timer/proc/time_left(seconds = FALSE) + . = max(0,timer_duration - (activation_time ? world.realtime - activation_time : 0)) + if(seconds) + . /= 10 + +/obj/machinery/door_timer/proc/set_timer(value) + var/new_time = CLAMP(value,0,MAX_TIMER) + . = new_time == timer_duration //return 1 on no change + timer_duration = new_time + +/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ + datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "brig_timer", name, 300, 200, master_ui, state) + ui.open() + +//icon update function +// if NOPOWER, display blank +// if BROKEN, display blue screen of death icon AI uses +// if timing=true, run update display function +/obj/machinery/door_timer/update_icon() + if(stat & (NOPOWER)) + icon_state = "frame" + return + + if(stat & (BROKEN)) + set_picture("ai_bsod") + return + + if(timing) + var/disp1 = id + var/time_left = time_left(seconds = TRUE) + var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]~[add_zero(num2text(time_left % 60), 2)]" + if(length(disp2) > CHARS_PER_LINE) + disp2 = "Error" + update_display(disp1, disp2) + else + if(maptext) + maptext = "" + return + + +// Adds an icon in case the screen is broken/off, stolen from status_display.dm +/obj/machinery/door_timer/proc/set_picture(state) + if(maptext) + maptext = "" + cut_overlays() + add_overlay(mutable_appearance('icons/obj/status_display.dmi', state)) + + +//Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display +// Stolen from status_display +/obj/machinery/door_timer/proc/update_display(line1, line2) + var/new_text = {"
    [line1]
    [line2]
    "} + if(maptext != new_text) + maptext = new_text + +/obj/machinery/door_timer/ui_data() + var/list/data = list() + var/time_left = time_left(seconds = TRUE) + data["seconds"] = round(time_left % 60) + data["minutes"] = round((time_left - data["seconds"]) / 60) + data["timing"] = timing + data["flash_charging"] = FALSE + for(var/obj/machinery/flasher/F in targets) + if(F.last_flash && (F.last_flash + 150) > world.time) + data["flash_charging"] = TRUE + break + return data + + +/obj/machinery/door_timer/ui_act(action, params) + if(..()) + return + . = TRUE + + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return FALSE + + switch(action) + if("time") + var/value = text2num(params["adjust"]) + if(value) + . = set_timer(time_left()+value) + if("start") + timer_start() + if("stop") + timer_end(forced = TRUE) + if("flash") + for(var/obj/machinery/flasher/F in targets) + F.flash() + if("preset") + var/preset = params["preset"] + var/preset_time = time_left() + switch(preset) + if("short") + preset_time = PRESET_SHORT + if("medium") + preset_time = PRESET_MEDIUM + if("long") + preset_time = PRESET_LONG + . = set_timer(preset_time) + if(timing) + activation_time = world.realtime + else + . = FALSE + + +#undef PRESET_SHORT +#undef PRESET_MEDIUM +#undef PRESET_LONG + +#undef MAX_TIMER +#undef FONT_SIZE +#undef FONT_COLOR +#undef FONT_STYLE +#undef CHARS_PER_LINE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index ee8742e84f..2e43670624 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -1,385 +1,385 @@ -/obj/machinery/door - name = "door" - desc = "It opens and closes." - icon = 'icons/obj/doors/Doorint.dmi' - icon_state = "door1" - opacity = 1 - density = TRUE - layer = OPEN_DOOR_LAYER - power_channel = ENVIRON - max_integrity = 350 - armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70) - CanAtmosPass = ATMOS_PASS_DENSITY - flags_1 = PREVENT_CLICK_UNDER_1 - - interaction_flags_atom = INTERACT_ATOM_UI_INTERACT - - var/secondsElectrified = 0 - var/shockedby - var/visible = TRUE - var/operating = FALSE - var/glass = FALSE - var/welded = FALSE - var/normalspeed = 1 - var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors - var/emergency = FALSE // Emergency access override - var/sub_door = FALSE // true if it's meant to go under another door. - var/closingLayer = CLOSED_DOOR_LAYER - var/autoclose = FALSE //does it automatically close after some time - var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them. - var/locked = FALSE //whether the door is bolted or not. - var/assemblytype //the type of door frame to drop during deconstruction - var/datum/effect_system/spark_spread/spark_system - var/damage_deflection = 10 - var/real_explosion_block //ignore this, just use explosion_block - var/red_alert_access = FALSE //if TRUE, this door will always open on red alert - var/poddoor = FALSE - var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access - -/obj/machinery/door/examine(mob/user) - . = ..() - if(red_alert_access) - if(GLOB.security_level >= SEC_LEVEL_RED) - . += "Due to a security threat, its access requirements have been lifted!" - else - . += "In the event of a red alert, its access requirements will automatically lift." - if(!poddoor) - . += "Its maintenance panel is screwed in place." - -/obj/machinery/door/check_access_list(list/access_list) - if(red_alert_access && GLOB.security_level >= SEC_LEVEL_RED) - return TRUE - return ..() - -/obj/machinery/door/Initialize() - . = ..() - set_init_door_layer() - update_freelook_sight() - air_update_turf(1) - GLOB.airlocks += src - spark_system = new /datum/effect_system/spark_spread - spark_system.set_up(2, 1, src) - - //doors only block while dense though so we have to use the proc - real_explosion_block = explosion_block - explosion_block = EXPLOSION_BLOCK_PROC - -/obj/machinery/door/proc/set_init_door_layer() - if(density) - layer = closingLayer - else - layer = initial(layer) - -/obj/machinery/door/power_change() - ..() - update_icon() - -/obj/machinery/door/Destroy() - update_freelook_sight() - GLOB.airlocks -= src - if(spark_system) - qdel(spark_system) - spark_system = null - return ..() - -/obj/machinery/door/Bumped(atom/movable/AM) - if(operating || (obj_flags & EMAGGED)) - return - if(ismob(AM)) - var/mob/B = AM - if((isdrone(B) || iscyborg(B)) && B.stat) - return - if(isliving(AM)) - var/mob/living/M = AM - if(world.time - M.last_bumped <= 10) - return //Can bump-open one airlock per second. This is to prevent shock spam. - M.last_bumped = world.time - if(M.restrained() && !check_access(null)) - return - bumpopen(M) - return - - if(ismecha(AM)) - var/obj/mecha/mecha = AM - if(density) - if(mecha.occupant) - if(world.time - mecha.occupant.last_bumped <= 10) - return - mecha.occupant.last_bumped = world.time - if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access))) - open() - else - do_animate("deny") - return - return - -/obj/machinery/door/Move() - var/turf/T = loc - . = ..() - move_update_air(T) - -/obj/machinery/door/CanPass(atom/movable/mover, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return !opacity - return !density - -/obj/machinery/door/proc/bumpopen(mob/user) - if(operating) - return - src.add_fingerprint(user) - if(!src.requiresID()) - user = null - - if(density && !(obj_flags & EMAGGED)) - if(allowed(user)) - open() - else - do_animate("deny") - return - -/obj/machinery/door/attack_hand(mob/user) - . = ..() - if(.) - return - return try_to_activate_door(user) - -/obj/machinery/door/attack_tk(mob/user) - if(requiresID() && !allowed(null)) - return - ..() - -/obj/machinery/door/proc/try_to_activate_door(mob/user) - add_fingerprint(user) - if(operating || (obj_flags & EMAGGED)) - return - if(!requiresID()) - user = null //so allowed(user) always succeeds - if(allowed(user)) - if(density) - open() - else - close() - return - if(density) - do_animate("deny") - -/obj/machinery/door/allowed(mob/M) - if(emergency) - return TRUE - if(unrestricted_side(M)) - return TRUE - return ..() - -/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter) - return get_dir(src, M) & unres_sides - -/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user) - return - -/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user) - return - -/obj/machinery/door/attackby(obj/item/I, mob/user, params) - if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe))) - try_to_crowbar(I, user) - return 1 - else if(istype(I, /obj/item/weldingtool)) - try_to_weld(I, user) - return 1 - else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM) - try_to_activate_door(user) - return 1 - return ..() - -/obj/machinery/door/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) - if(damage_flag == "melee" && damage_amount < damage_deflection) - return 0 - . = ..() - -/obj/machinery/door/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) - . = ..() - if(. && obj_integrity > 0) - if(damage_amount >= 10 && prob(30)) - spark_system.start() - -/obj/machinery/door/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - switch(damage_type) - if(BRUTE) - if(glass) - playsound(loc, 'sound/effects/glasshit.ogg', 90, 1) - else if(damage_amount) - playsound(loc, 'sound/weapons/smash.ogg', 50, 1) - else - playsound(src, 'sound/weapons/tap.ogg', 50, 1) - if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, 1) - -/obj/machinery/door/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) ) - INVOKE_ASYNC(src, .proc/open) - if(prob(severity*10 - 20)) - if(secondsElectrified == 0) - secondsElectrified = -1 - LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse") - addtimer(CALLBACK(src, .proc/unelectrify), 300) - -/obj/machinery/door/proc/unelectrify() - secondsElectrified = 0 - -/obj/machinery/door/update_icon() - if(density) - icon_state = "door1" - else - icon_state = "door0" - -/obj/machinery/door/proc/do_animate(animation) - switch(animation) - if("opening") - if(panel_open) - flick("o_doorc0", src) - else - flick("doorc0", src) - if("closing") - if(panel_open) - flick("o_doorc1", src) - else - flick("doorc1", src) - if("deny") - if(!stat) - flick("door_deny", src) - - -/obj/machinery/door/proc/open() - if(!density) - return 1 - if(operating) - return - operating = TRUE - do_animate("opening") - set_opacity(0) - sleep(5) - density = FALSE - sleep(5) - layer = initial(layer) - update_icon() - set_opacity(0) - operating = FALSE - air_update_turf(1) - update_freelook_sight() - if(autoclose) - spawn(autoclose) - close() - return 1 - -/obj/machinery/door/proc/close() - if(density) - return TRUE - if(operating || welded) - return - if(safe) - for(var/atom/movable/M in get_turf(src)) - if(M.density && M != src) //something is blocking the door - if(autoclose) - autoclose_in(60) - return - - operating = TRUE - - do_animate("closing") - layer = closingLayer - sleep(5) - density = TRUE - sleep(5) - update_icon() - if(visible && !glass) - set_opacity(1) - operating = FALSE - air_update_turf(1) - update_freelook_sight() - if(safe) - CheckForMobs() - else - crush() - return 1 - -/obj/machinery/door/proc/CheckForMobs() - if(locate(/mob/living) in get_turf(src)) - sleep(1) - open() - -/obj/machinery/door/proc/crush() - for(var/mob/living/L in get_turf(src)) - L.visible_message("[src] closes on [L], crushing [L.p_them()]!", "[src] closes on you and crushes you!") - if(isalien(L)) //For xenos - L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. - L.emote("roar") - else if(ishuman(L)) //For humans - L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - L.emote("scream") - L.Knockdown(100) - else if(ismonkey(L)) //For monkeys - L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - L.Knockdown(100) - else //for simple_animals & borgs - L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) - var/turf/location = get_turf(src) - //add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does. - if(iscarbon(L)) - var/mob/living/carbon/C = L - C.bleed(DOOR_CRUSH_DAMAGE) - else - L.add_splatter_floor(location) - for(var/obj/mecha/M in get_turf(src)) - M.take_damage(DOOR_CRUSH_DAMAGE) - -/obj/machinery/door/proc/autoclose() - if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose) - close() - -/obj/machinery/door/proc/autoclose_in(wait) - addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE) - -/obj/machinery/door/proc/requiresID() - return 1 - -/obj/machinery/door/proc/hasPower() - return !(stat & NOPOWER) - -/obj/machinery/door/proc/update_freelook_sight() - if(!glass && GLOB.cameranet) - GLOB.cameranet.updateVisibility(src, 0) - -/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended. - if(opacity || heat_proof) - return 1 - return 0 - -/obj/machinery/door/morgue - icon = 'icons/obj/doors/doormorgue.dmi' - -/obj/machinery/door/get_dumping_location(obj/item/storage/source,mob/user) - return null - -/obj/machinery/door/proc/lock() - return - -/obj/machinery/door/proc/unlock() - return - -/obj/machinery/door/proc/hostile_lockdown(mob/origin) - if(!stat) //So that only powered doors are closed. - close() //Close ALL the doors! - -/obj/machinery/door/proc/disable_lockdown() - if(!stat) //Opens only powered doors. - open() //Open everything! - -/obj/machinery/door/ex_act(severity, target) - //if it blows up a wall it should blow up a door - ..(severity ? max(1, severity - 1) : 0, target) - -/obj/machinery/door/GetExplosionBlock() - return density ? real_explosion_block : 0 +/obj/machinery/door + name = "door" + desc = "It opens and closes." + icon = 'icons/obj/doors/Doorint.dmi' + icon_state = "door1" + opacity = 1 + density = TRUE + layer = OPEN_DOOR_LAYER + power_channel = ENVIRON + max_integrity = 350 + armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70) + CanAtmosPass = ATMOS_PASS_DENSITY + flags_1 = PREVENT_CLICK_UNDER_1 + + interaction_flags_atom = INTERACT_ATOM_UI_INTERACT + + var/secondsElectrified = 0 + var/shockedby + var/visible = TRUE + var/operating = FALSE + var/glass = FALSE + var/welded = FALSE + var/normalspeed = 1 + var/heat_proof = FALSE // For rglass-windowed airlocks and firedoors + var/emergency = FALSE // Emergency access override + var/sub_door = FALSE // true if it's meant to go under another door. + var/closingLayer = CLOSED_DOOR_LAYER + var/autoclose = FALSE //does it automatically close after some time + var/safe = TRUE //whether the door detects things and mobs in its way and reopen or crushes them. + var/locked = FALSE //whether the door is bolted or not. + var/assemblytype //the type of door frame to drop during deconstruction + var/datum/effect_system/spark_spread/spark_system + var/damage_deflection = 10 + var/real_explosion_block //ignore this, just use explosion_block + var/red_alert_access = FALSE //if TRUE, this door will always open on red alert + var/poddoor = FALSE + var/unres_sides = 0 //Unrestricted sides. A bitflag for which direction (if any) can open the door with no access + +/obj/machinery/door/examine(mob/user) + . = ..() + if(red_alert_access) + if(GLOB.security_level >= SEC_LEVEL_RED) + . += "Due to a security threat, its access requirements have been lifted!" + else + . += "In the event of a red alert, its access requirements will automatically lift." + if(!poddoor) + . += "Its maintenance panel is screwed in place." + +/obj/machinery/door/check_access_list(list/access_list) + if(red_alert_access && GLOB.security_level >= SEC_LEVEL_RED) + return TRUE + return ..() + +/obj/machinery/door/Initialize() + . = ..() + set_init_door_layer() + update_freelook_sight() + air_update_turf(1) + GLOB.airlocks += src + spark_system = new /datum/effect_system/spark_spread + spark_system.set_up(2, 1, src) + + //doors only block while dense though so we have to use the proc + real_explosion_block = explosion_block + explosion_block = EXPLOSION_BLOCK_PROC + +/obj/machinery/door/proc/set_init_door_layer() + if(density) + layer = closingLayer + else + layer = initial(layer) + +/obj/machinery/door/power_change() + ..() + update_icon() + +/obj/machinery/door/Destroy() + update_freelook_sight() + GLOB.airlocks -= src + if(spark_system) + qdel(spark_system) + spark_system = null + return ..() + +/obj/machinery/door/Bumped(atom/movable/AM) + if(operating || (obj_flags & EMAGGED)) + return + if(ismob(AM)) + var/mob/B = AM + if((isdrone(B) || iscyborg(B)) && B.stat) + return + if(isliving(AM)) + var/mob/living/M = AM + if(world.time - M.last_bumped <= 10) + return //Can bump-open one airlock per second. This is to prevent shock spam. + M.last_bumped = world.time + if(M.restrained() && !check_access(null)) + return + bumpopen(M) + return + + if(ismecha(AM)) + var/obj/mecha/mecha = AM + if(density) + if(mecha.occupant) + if(world.time - mecha.occupant.last_bumped <= 10) + return + mecha.occupant.last_bumped = world.time + if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access))) + open() + else + do_animate("deny") + return + return + +/obj/machinery/door/Move() + var/turf/T = loc + . = ..() + move_update_air(T) + +/obj/machinery/door/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return !opacity + return !density + +/obj/machinery/door/proc/bumpopen(mob/user) + if(operating) + return + src.add_fingerprint(user) + if(!src.requiresID()) + user = null + + if(density && !(obj_flags & EMAGGED)) + if(allowed(user)) + open() + else + do_animate("deny") + return + +/obj/machinery/door/attack_hand(mob/user) + . = ..() + if(.) + return + return try_to_activate_door(user) + +/obj/machinery/door/attack_tk(mob/user) + if(requiresID() && !allowed(null)) + return + ..() + +/obj/machinery/door/proc/try_to_activate_door(mob/user) + add_fingerprint(user) + if(operating || (obj_flags & EMAGGED)) + return + if(!requiresID()) + user = null //so allowed(user) always succeeds + if(allowed(user)) + if(density) + open() + else + close() + return + if(density) + do_animate("deny") + +/obj/machinery/door/allowed(mob/M) + if(emergency) + return TRUE + if(unrestricted_side(M)) + return TRUE + return ..() + +/obj/machinery/door/proc/unrestricted_side(mob/M) //Allows for specific side of airlocks to be unrestrected (IE, can exit maint freely, but need access to enter) + return get_dir(src, M) & unres_sides + +/obj/machinery/door/proc/try_to_weld(obj/item/weldingtool/W, mob/user) + return + +/obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user) + return + +/obj/machinery/door/attackby(obj/item/I, mob/user, params) + if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe))) + try_to_crowbar(I, user) + return 1 + else if(istype(I, /obj/item/weldingtool)) + try_to_weld(I, user) + return 1 + else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM) + try_to_activate_door(user) + return 1 + return ..() + +/obj/machinery/door/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) + if(damage_flag == "melee" && damage_amount < damage_deflection) + return 0 + . = ..() + +/obj/machinery/door/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) + . = ..() + if(. && obj_integrity > 0) + if(damage_amount >= 10 && prob(30)) + spark_system.start() + +/obj/machinery/door/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + if(glass) + playsound(loc, 'sound/effects/glasshit.ogg', 90, 1) + else if(damage_amount) + playsound(loc, 'sound/weapons/smash.ogg', 50, 1) + else + playsound(src, 'sound/weapons/tap.ogg', 50, 1) + if(BURN) + playsound(src.loc, 'sound/items/welder.ogg', 100, 1) + +/obj/machinery/door/emp_act(severity) + . = ..() + if (. & EMP_PROTECT_SELF) + return + if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) ) + INVOKE_ASYNC(src, .proc/open) + if(prob(severity*10 - 20)) + if(secondsElectrified == 0) + secondsElectrified = -1 + LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse") + addtimer(CALLBACK(src, .proc/unelectrify), 300) + +/obj/machinery/door/proc/unelectrify() + secondsElectrified = 0 + +/obj/machinery/door/update_icon() + if(density) + icon_state = "door1" + else + icon_state = "door0" + +/obj/machinery/door/proc/do_animate(animation) + switch(animation) + if("opening") + if(panel_open) + flick("o_doorc0", src) + else + flick("doorc0", src) + if("closing") + if(panel_open) + flick("o_doorc1", src) + else + flick("doorc1", src) + if("deny") + if(!stat) + flick("door_deny", src) + + +/obj/machinery/door/proc/open() + if(!density) + return 1 + if(operating) + return + operating = TRUE + do_animate("opening") + set_opacity(0) + sleep(5) + density = FALSE + sleep(5) + layer = initial(layer) + update_icon() + set_opacity(0) + operating = FALSE + air_update_turf(1) + update_freelook_sight() + if(autoclose) + spawn(autoclose) + close() + return 1 + +/obj/machinery/door/proc/close() + if(density) + return TRUE + if(operating || welded) + return + if(safe) + for(var/atom/movable/M in get_turf(src)) + if(M.density && M != src) //something is blocking the door + if(autoclose) + autoclose_in(60) + return + + operating = TRUE + + do_animate("closing") + layer = closingLayer + sleep(5) + density = TRUE + sleep(5) + update_icon() + if(visible && !glass) + set_opacity(1) + operating = FALSE + air_update_turf(1) + update_freelook_sight() + if(safe) + CheckForMobs() + else + crush() + return 1 + +/obj/machinery/door/proc/CheckForMobs() + if(locate(/mob/living) in get_turf(src)) + sleep(1) + open() + +/obj/machinery/door/proc/crush() + for(var/mob/living/L in get_turf(src)) + L.visible_message("[src] closes on [L], crushing [L.p_them()]!", "[src] closes on you and crushes you!") + if(isalien(L)) //For xenos + L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. + L.emote("roar") + else if(ishuman(L)) //For humans + L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + L.emote("scream") + L.Knockdown(100) + else if(ismonkey(L)) //For monkeys + L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + L.Knockdown(100) + else //for simple_animals & borgs + L.adjustBruteLoss(DOOR_CRUSH_DAMAGE) + var/turf/location = get_turf(src) + //add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does. + if(iscarbon(L)) + var/mob/living/carbon/C = L + C.bleed(DOOR_CRUSH_DAMAGE) + else + L.add_splatter_floor(location) + for(var/obj/mecha/M in get_turf(src)) + M.take_damage(DOOR_CRUSH_DAMAGE) + +/obj/machinery/door/proc/autoclose() + if(!QDELETED(src) && !density && !operating && !locked && !welded && autoclose) + close() + +/obj/machinery/door/proc/autoclose_in(wait) + addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE) + +/obj/machinery/door/proc/requiresID() + return 1 + +/obj/machinery/door/proc/hasPower() + return !(stat & NOPOWER) + +/obj/machinery/door/proc/update_freelook_sight() + if(!glass && GLOB.cameranet) + GLOB.cameranet.updateVisibility(src, 0) + +/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended. + if(opacity || heat_proof) + return 1 + return 0 + +/obj/machinery/door/morgue + icon = 'icons/obj/doors/doormorgue.dmi' + +/obj/machinery/door/get_dumping_location(obj/item/storage/source,mob/user) + return null + +/obj/machinery/door/proc/lock() + return + +/obj/machinery/door/proc/unlock() + return + +/obj/machinery/door/proc/hostile_lockdown(mob/origin) + if(!stat) //So that only powered doors are closed. + close() //Close ALL the doors! + +/obj/machinery/door/proc/disable_lockdown() + if(!stat) //Opens only powered doors. + open() //Open everything! + +/obj/machinery/door/ex_act(severity, target) + //if it blows up a wall it should blow up a door + ..(severity ? max(1, severity - 1) : 0, target) + +/obj/machinery/door/GetExplosionBlock() + return density ? real_explosion_block : 0 diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 39b6c8da1d..0429db5792 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -1,476 +1,476 @@ -#define CONSTRUCTION_COMPLETE 0 //No construction done - functioning as normal -#define CONSTRUCTION_PANEL_OPEN 1 //Maintenance panel is open, still functioning -#define CONSTRUCTION_WIRES_EXPOSED 2 //Cover plate is removed, wires are available -#define CONSTRUCTION_GUTTED 3 //Wires are removed, circuit ready to remove -#define CONSTRUCTION_NOCIRCUIT 4 //Circuit board removed, can safely weld apart - -/obj/machinery/door/firedoor - name = "firelock" - desc = "Apply crowbar." - icon = 'icons/obj/doors/Doorfireglass.dmi' - icon_state = "door_open" - opacity = FALSE - density = FALSE - max_integrity = 300 - resistance_flags = FIRE_PROOF - heat_proof = TRUE - glass = TRUE - sub_door = TRUE - explosion_block = 1 - safe = FALSE - layer = BELOW_OPEN_DOOR_LAYER - closingLayer = CLOSED_FIREDOOR_LAYER - assemblytype = /obj/structure/firelock_frame - armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70) - interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN - var/nextstate = null - var/boltslocked = TRUE - var/list/affecting_areas - -/obj/machinery/door/firedoor/Initialize() - . = ..() - CalculateAffectingAreas() - -/obj/machinery/door/firedoor/examine(mob/user) - ..() - if(!density) - . += "It is open, but could be pried closed." - else if(!welded) - . += "It is closed, but could be pried open. Deconstruction would require it to be welded shut." - else if(boltslocked) - . += "It is welded shut. The floor bolts have been locked by screws." - else - . += "The bolt locks have been unscrewed, but the bolts themselves are still wrenched to the floor." - -/obj/machinery/door/firedoor/proc/CalculateAffectingAreas() - remove_from_areas() - affecting_areas = get_adjacent_open_areas(src) | get_area(src) - for(var/I in affecting_areas) - var/area/A = I - LAZYADD(A.firedoors, src) - -/obj/machinery/door/firedoor/closed - icon_state = "door_closed" - opacity = TRUE - density = TRUE - -//see also turf/AfterChange for adjacency shennanigans - -/obj/machinery/door/firedoor/proc/remove_from_areas() - if(affecting_areas) - for(var/I in affecting_areas) - var/area/A = I - LAZYREMOVE(A.firedoors, src) - -/obj/machinery/door/firedoor/Destroy() - remove_from_areas() - affecting_areas.Cut() - return ..() - -/obj/machinery/door/firedoor/Bumped(atom/movable/AM) - if(panel_open || operating) - return - if(!density) - return ..() - return FALSE - - -/obj/machinery/door/firedoor/power_change() - if(powered(power_channel)) - stat &= ~NOPOWER - latetoggle() - else - stat |= NOPOWER - -/obj/machinery/door/firedoor/attack_hand(mob/user) - . = ..() - if(.) - return - if(operating || !density) - return - user.changeNext_move(CLICK_CD_MELEE) - - user.visible_message("[user] bangs on \the [src].", - "You bang on \the [src].") - playsound(loc, 'sound/effects/glassknock.ogg', 10, FALSE, frequency = 32000) - -/obj/machinery/door/firedoor/attackby(obj/item/C, mob/user, params) - add_fingerprint(user) - if(operating) - return - - if(welded) - if(istype(C, /obj/item/wrench)) - if(boltslocked) - to_chat(user, "There are screws locking the bolts in place!") - return - C.play_tool_sound(src) - user.visible_message("[user] starts undoing [src]'s bolts...", \ - "You start unfastening [src]'s floor bolts...") - if(!C.use_tool(src, user, 50)) - return - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - user.visible_message("[user] unfastens [src]'s bolts.", \ - "You undo [src]'s floor bolts.") - deconstruct(TRUE) - return - if(istype(C, /obj/item/screwdriver)) - user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \ - "You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.") - C.play_tool_sound(src) - boltslocked = !boltslocked - return - - return ..() - -/obj/machinery/door/firedoor/try_to_activate_door(mob/user) - return - -/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user) - if(!W.tool_start_check(user, amount=0)) - return - user.visible_message("[user] starts [welded ? "unwelding" : "welding"] [src].", "You start welding [src].") - if(W.use_tool(src, user, 40, volume=50)) - welded = !welded - to_chat(user, "[user] [welded?"welds":"unwelds"] [src].", "You [welded ? "weld" : "unweld"] [src].") - update_icon() - -/obj/machinery/door/firedoor/try_to_crowbar(obj/item/I, mob/user) - if(welded || operating) - return - - if(density) - open() - else - close() - -/obj/machinery/door/firedoor/attack_ai(mob/user) - add_fingerprint(user) - if(welded || operating || stat & NOPOWER) - return TRUE - if(density) - open() - else - close() - return TRUE - -/obj/machinery/door/firedoor/attack_robot(mob/user) - return attack_ai(user) - -/obj/machinery/door/firedoor/attack_alien(mob/user) - add_fingerprint(user) - if(welded) - to_chat(user, "[src] refuses to budge!") - return - open() - -/obj/machinery/door/firedoor/do_animate(animation) - switch(animation) - if("opening") - flick("door_opening", src) - if("closing") - flick("door_closing", src) - -/obj/machinery/door/firedoor/update_icon() - cut_overlays() - if(density) - icon_state = "door_closed" - if(welded) - add_overlay("welded") - else - icon_state = "door_open" - if(welded) - add_overlay("welded_open") - -/obj/machinery/door/firedoor/open() - . = ..() - latetoggle() - -/obj/machinery/door/firedoor/close() - . = ..() - latetoggle() - -/obj/machinery/door/firedoor/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src)) - if(disassembled) - F.constructionStep = CONSTRUCTION_PANEL_OPEN - else - F.constructionStep = CONSTRUCTION_WIRES_EXPOSED - F.obj_integrity = F.max_integrity * 0.5 - F.update_icon() - qdel(src) - - -/obj/machinery/door/firedoor/proc/latetoggle() - if(operating || stat & NOPOWER || !nextstate) - return - switch(nextstate) - if(FIREDOOR_OPEN) - nextstate = null - open() - if(FIREDOOR_CLOSED) - nextstate = null - close() - -/obj/machinery/door/firedoor/border_only - icon = 'icons/obj/doors/edge_Doorfire.dmi' - flags_1 = ON_BORDER_1 - CanAtmosPass = ATMOS_PASS_PROC - -/obj/machinery/door/firedoor/border_only/closed - icon_state = "door_closed" - opacity = TRUE - density = TRUE - -/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return TRUE - if(get_dir(loc, target) == dir) //Make sure looking at appropriate border - return !density - else - return TRUE - -/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return TRUE - if(get_dir(loc, target) == dir) - return !density - else - return TRUE - -/obj/machinery/door/firedoor/border_only/CanAtmosPass(turf/T) - if(get_dir(loc, T) == dir) - return !density - else - return TRUE - -/obj/machinery/door/firedoor/heavy - name = "heavy firelock" - icon = 'icons/obj/doors/Doorfire.dmi' - glass = FALSE - explosion_block = 2 - assemblytype = /obj/structure/firelock_frame/heavy - max_integrity = 550 - - -/obj/item/electronics/firelock - name = "firelock circuitry" - desc = "A circuit board used in construction of firelocks." - icon_state = "mainboard" - -/obj/structure/firelock_frame - name = "firelock frame" - desc = "A partially completed firelock." - icon = 'icons/obj/doors/Doorfire.dmi' - icon_state = "frame1" - anchored = FALSE - density = TRUE - var/constructionStep = CONSTRUCTION_NOCIRCUIT - var/reinforced = 0 - -/obj/structure/firelock_frame/examine(mob/user) - . = ..() - switch(constructionStep) - if(CONSTRUCTION_PANEL_OPEN) - . += "It is unbolted from the floor. A small loosely connected metal plate is covering the wires." - if(!reinforced) - . += "It could be reinforced with plasteel." - if(CONSTRUCTION_WIRES_EXPOSED) - . += "The maintenance plate has been pried away, and wires are trailing." - if(CONSTRUCTION_GUTTED) - . += "The maintenance panel is missing wires and the circuit board is loosely connected." - if(CONSTRUCTION_NOCIRCUIT) - . += "There are no firelock electronics in the frame. The frame could be cut apart." - -/obj/structure/firelock_frame/update_icon() - ..() - icon_state = "frame[constructionStep]" - -/obj/structure/firelock_frame/attackby(obj/item/C, mob/user) - switch(constructionStep) - if(CONSTRUCTION_PANEL_OPEN) - if(istype(C, /obj/item/crowbar)) - C.play_tool_sound(src) - user.visible_message("[user] starts prying something out from [src]...", \ - "You begin prying out the wire cover...") - if(!C.use_tool(src, user, 50)) - return - if(constructionStep != CONSTRUCTION_PANEL_OPEN) - return - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - user.visible_message("[user] pries out a metal plate from [src], exposing the wires.", \ - "You remove the cover plate from [src], exposing the wires.") - constructionStep = CONSTRUCTION_WIRES_EXPOSED - update_icon() - return - if(istype(C, /obj/item/wrench)) - if(locate(/obj/machinery/door/firedoor) in get_turf(src)) - to_chat(user, "There's already a firelock there.") - return - C.play_tool_sound(src) - user.visible_message("[user] starts bolting down [src]...", \ - "You begin bolting [src]...") - if(!C.use_tool(src, user, 30)) - return - if(locate(/obj/machinery/door/firedoor) in get_turf(src)) - return - user.visible_message("[user] finishes the firelock.", \ - "You finish the firelock.") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - if(reinforced) - new /obj/machinery/door/firedoor/heavy(get_turf(src)) - else - new /obj/machinery/door/firedoor(get_turf(src)) - qdel(src) - return - if(istype(C, /obj/item/stack/sheet/plasteel)) - var/obj/item/stack/sheet/plasteel/P = C - if(reinforced) - to_chat(user, "[src] is already reinforced.") - return - if(P.get_amount() < 2) - to_chat(user, "You need more plasteel to reinforce [src].") - return - user.visible_message("[user] begins reinforcing [src]...", \ - "You begin reinforcing [src]...") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - if(do_after(user, 60, target = src)) - if(constructionStep != CONSTRUCTION_PANEL_OPEN || reinforced || P.get_amount() < 2 || !P) - return - user.visible_message("[user] reinforces [src].", \ - "You reinforce [src].") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - P.use(2) - reinforced = 1 - return - - if(CONSTRUCTION_WIRES_EXPOSED) - if(istype(C, /obj/item/wirecutters)) - C.play_tool_sound(src) - user.visible_message("[user] starts cutting the wires from [src]...", \ - "You begin removing [src]'s wires...") - if(!C.use_tool(src, user, 60)) - return - if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) - return - user.visible_message("[user] removes the wires from [src].", \ - "You remove the wiring from [src], exposing the circuit board.") - new/obj/item/stack/cable_coil(get_turf(src), 5) - constructionStep = CONSTRUCTION_GUTTED - update_icon() - return - if(istype(C, /obj/item/crowbar)) - C.play_tool_sound(src) - user.visible_message("[user] starts prying a metal plate into [src]...", \ - "You begin prying the cover plate back onto [src]...") - if(!C.use_tool(src, user, 80)) - return - if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) - return - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - user.visible_message("[user] pries the metal plate into [src].", \ - "You pry [src]'s cover plate into place, hiding the wires.") - constructionStep = CONSTRUCTION_PANEL_OPEN - update_icon() - return - if(CONSTRUCTION_GUTTED) - if(istype(C, /obj/item/crowbar)) - user.visible_message("[user] begins removing the circuit board from [src]...", \ - "You begin prying out the circuit board from [src]...") - if(!C.use_tool(src, user, 50, volume=50)) - return - if(constructionStep != CONSTRUCTION_GUTTED) - return - user.visible_message("[user] removes [src]'s circuit board.", \ - "You remove the circuit board from [src].") - new /obj/item/electronics/firelock(drop_location()) - constructionStep = CONSTRUCTION_NOCIRCUIT - update_icon() - return - if(istype(C, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/B = C - if(B.get_amount() < 5) - to_chat(user, "You need more wires to add wiring to [src].") - return - user.visible_message("[user] begins wiring [src]...", \ - "You begin adding wires to [src]...") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - if(do_after(user, 60, target = src)) - if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B) - return - user.visible_message("[user] adds wires to [src].", \ - "You wire [src].") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - B.use(5) - constructionStep = CONSTRUCTION_WIRES_EXPOSED - update_icon() - return - if(CONSTRUCTION_NOCIRCUIT) - if(istype(C, /obj/item/weldingtool)) - if(!C.tool_start_check(user, amount=1)) - return - user.visible_message("[user] begins cutting apart [src]'s frame...", \ - "You begin slicing [src] apart...") - - if(C.use_tool(src, user, 40, volume=50, amount=1)) - if(constructionStep != CONSTRUCTION_NOCIRCUIT) - return - user.visible_message("[user] cuts apart [src]!", \ - "You cut [src] into metal.") - var/turf/T = get_turf(src) - new /obj/item/stack/sheet/metal(T, 3) - if(reinforced) - new /obj/item/stack/sheet/plasteel(T, 2) - qdel(src) - return - if(istype(C, /obj/item/electronics/firelock)) - user.visible_message("[user] starts adding [C] to [src]...", \ - "You begin adding a circuit board to [src]...") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - if(!do_after(user, 40, target = src)) - return - if(constructionStep != CONSTRUCTION_NOCIRCUIT) - return - qdel(C) - user.visible_message("[user] adds a circuit to [src].", \ - "You insert and secure [C].") - playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) - constructionStep = CONSTRUCTION_GUTTED - update_icon() - return - if(istype(C, /obj/item/electroadaptive_pseudocircuit)) - var/obj/item/electroadaptive_pseudocircuit/P = C - if(!P.adapt_circuit(user, 30)) - return - user.visible_message("[user] fabricates a circuit and places it into [src].", \ - "You adapt a firelock circuit and slot it into the assembly.") - constructionStep = CONSTRUCTION_GUTTED - update_icon() - return - return ..() - -/obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if((constructionStep == CONSTRUCTION_NOCIRCUIT) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) - return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) - return FALSE - -/obj/structure/firelock_frame/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) - switch(passed_mode) - if(RCD_UPGRADE_SIMPLE_CIRCUITS) - user.visible_message("[user] fabricates a circuit and places it into [src].", \ - "You adapt a firelock circuit and slot it into the assembly.") - constructionStep = CONSTRUCTION_GUTTED - update_icon() - return TRUE - return FALSE - -/obj/structure/firelock_frame/heavy - name = "heavy firelock frame" - reinforced = TRUE - -#undef CONSTRUCTION_COMPLETE -#undef CONSTRUCTION_PANEL_OPEN -#undef CONSTRUCTION_WIRES_EXPOSED -#undef CONSTRUCTION_GUTTED -#undef CONSTRUCTION_NOCIRCUIT +#define CONSTRUCTION_COMPLETE 0 //No construction done - functioning as normal +#define CONSTRUCTION_PANEL_OPEN 1 //Maintenance panel is open, still functioning +#define CONSTRUCTION_WIRES_EXPOSED 2 //Cover plate is removed, wires are available +#define CONSTRUCTION_GUTTED 3 //Wires are removed, circuit ready to remove +#define CONSTRUCTION_NOCIRCUIT 4 //Circuit board removed, can safely weld apart + +/obj/machinery/door/firedoor + name = "firelock" + desc = "Apply crowbar." + icon = 'icons/obj/doors/Doorfireglass.dmi' + icon_state = "door_open" + opacity = FALSE + density = FALSE + max_integrity = 300 + resistance_flags = FIRE_PROOF + heat_proof = TRUE + glass = TRUE + sub_door = TRUE + explosion_block = 1 + safe = FALSE + layer = BELOW_OPEN_DOOR_LAYER + closingLayer = CLOSED_FIREDOOR_LAYER + assemblytype = /obj/structure/firelock_frame + armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70) + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN + var/nextstate = null + var/boltslocked = TRUE + var/list/affecting_areas + +/obj/machinery/door/firedoor/Initialize() + . = ..() + CalculateAffectingAreas() + +/obj/machinery/door/firedoor/examine(mob/user) + ..() + if(!density) + . += "It is open, but could be pried closed." + else if(!welded) + . += "It is closed, but could be pried open. Deconstruction would require it to be welded shut." + else if(boltslocked) + . += "It is welded shut. The floor bolts have been locked by screws." + else + . += "The bolt locks have been unscrewed, but the bolts themselves are still wrenched to the floor." + +/obj/machinery/door/firedoor/proc/CalculateAffectingAreas() + remove_from_areas() + affecting_areas = get_adjacent_open_areas(src) | get_area(src) + for(var/I in affecting_areas) + var/area/A = I + LAZYADD(A.firedoors, src) + +/obj/machinery/door/firedoor/closed + icon_state = "door_closed" + opacity = TRUE + density = TRUE + +//see also turf/AfterChange for adjacency shennanigans + +/obj/machinery/door/firedoor/proc/remove_from_areas() + if(affecting_areas) + for(var/I in affecting_areas) + var/area/A = I + LAZYREMOVE(A.firedoors, src) + +/obj/machinery/door/firedoor/Destroy() + remove_from_areas() + affecting_areas.Cut() + return ..() + +/obj/machinery/door/firedoor/Bumped(atom/movable/AM) + if(panel_open || operating) + return + if(!density) + return ..() + return FALSE + + +/obj/machinery/door/firedoor/power_change() + if(powered(power_channel)) + stat &= ~NOPOWER + latetoggle() + else + stat |= NOPOWER + +/obj/machinery/door/firedoor/attack_hand(mob/user) + . = ..() + if(.) + return + if(operating || !density) + return + user.changeNext_move(CLICK_CD_MELEE) + + user.visible_message("[user] bangs on \the [src].", + "You bang on \the [src].") + playsound(loc, 'sound/effects/glassknock.ogg', 10, FALSE, frequency = 32000) + +/obj/machinery/door/firedoor/attackby(obj/item/C, mob/user, params) + add_fingerprint(user) + if(operating) + return + + if(welded) + if(istype(C, /obj/item/wrench)) + if(boltslocked) + to_chat(user, "There are screws locking the bolts in place!") + return + C.play_tool_sound(src) + user.visible_message("[user] starts undoing [src]'s bolts...", \ + "You start unfastening [src]'s floor bolts...") + if(!C.use_tool(src, user, 50)) + return + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + user.visible_message("[user] unfastens [src]'s bolts.", \ + "You undo [src]'s floor bolts.") + deconstruct(TRUE) + return + if(istype(C, /obj/item/screwdriver)) + user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \ + "You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.") + C.play_tool_sound(src) + boltslocked = !boltslocked + return + + return ..() + +/obj/machinery/door/firedoor/try_to_activate_door(mob/user) + return + +/obj/machinery/door/firedoor/try_to_weld(obj/item/weldingtool/W, mob/user) + if(!W.tool_start_check(user, amount=0)) + return + user.visible_message("[user] starts [welded ? "unwelding" : "welding"] [src].", "You start welding [src].") + if(W.use_tool(src, user, 40, volume=50)) + welded = !welded + to_chat(user, "[user] [welded?"welds":"unwelds"] [src].", "You [welded ? "weld" : "unweld"] [src].") + update_icon() + +/obj/machinery/door/firedoor/try_to_crowbar(obj/item/I, mob/user) + if(welded || operating) + return + + if(density) + open() + else + close() + +/obj/machinery/door/firedoor/attack_ai(mob/user) + add_fingerprint(user) + if(welded || operating || stat & NOPOWER) + return TRUE + if(density) + open() + else + close() + return TRUE + +/obj/machinery/door/firedoor/attack_robot(mob/user) + return attack_ai(user) + +/obj/machinery/door/firedoor/attack_alien(mob/user) + add_fingerprint(user) + if(welded) + to_chat(user, "[src] refuses to budge!") + return + open() + +/obj/machinery/door/firedoor/do_animate(animation) + switch(animation) + if("opening") + flick("door_opening", src) + if("closing") + flick("door_closing", src) + +/obj/machinery/door/firedoor/update_icon() + cut_overlays() + if(density) + icon_state = "door_closed" + if(welded) + add_overlay("welded") + else + icon_state = "door_open" + if(welded) + add_overlay("welded_open") + +/obj/machinery/door/firedoor/open() + . = ..() + latetoggle() + +/obj/machinery/door/firedoor/close() + . = ..() + latetoggle() + +/obj/machinery/door/firedoor/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src)) + if(disassembled) + F.constructionStep = CONSTRUCTION_PANEL_OPEN + else + F.constructionStep = CONSTRUCTION_WIRES_EXPOSED + F.obj_integrity = F.max_integrity * 0.5 + F.update_icon() + qdel(src) + + +/obj/machinery/door/firedoor/proc/latetoggle() + if(operating || stat & NOPOWER || !nextstate) + return + switch(nextstate) + if(FIREDOOR_OPEN) + nextstate = null + open() + if(FIREDOOR_CLOSED) + nextstate = null + close() + +/obj/machinery/door/firedoor/border_only + icon = 'icons/obj/doors/edge_Doorfire.dmi' + flags_1 = ON_BORDER_1 + CanAtmosPass = ATMOS_PASS_PROC + +/obj/machinery/door/firedoor/border_only/closed + icon_state = "door_closed" + opacity = TRUE + density = TRUE + +/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return TRUE + if(get_dir(loc, target) == dir) //Make sure looking at appropriate border + return !density + else + return TRUE + +/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return TRUE + if(get_dir(loc, target) == dir) + return !density + else + return TRUE + +/obj/machinery/door/firedoor/border_only/CanAtmosPass(turf/T) + if(get_dir(loc, T) == dir) + return !density + else + return TRUE + +/obj/machinery/door/firedoor/heavy + name = "heavy firelock" + icon = 'icons/obj/doors/Doorfire.dmi' + glass = FALSE + explosion_block = 2 + assemblytype = /obj/structure/firelock_frame/heavy + max_integrity = 550 + + +/obj/item/electronics/firelock + name = "firelock circuitry" + desc = "A circuit board used in construction of firelocks." + icon_state = "mainboard" + +/obj/structure/firelock_frame + name = "firelock frame" + desc = "A partially completed firelock." + icon = 'icons/obj/doors/Doorfire.dmi' + icon_state = "frame1" + anchored = FALSE + density = TRUE + var/constructionStep = CONSTRUCTION_NOCIRCUIT + var/reinforced = 0 + +/obj/structure/firelock_frame/examine(mob/user) + . = ..() + switch(constructionStep) + if(CONSTRUCTION_PANEL_OPEN) + . += "It is unbolted from the floor. A small loosely connected metal plate is covering the wires." + if(!reinforced) + . += "It could be reinforced with plasteel." + if(CONSTRUCTION_WIRES_EXPOSED) + . += "The maintenance plate has been pried away, and wires are trailing." + if(CONSTRUCTION_GUTTED) + . += "The maintenance panel is missing wires and the circuit board is loosely connected." + if(CONSTRUCTION_NOCIRCUIT) + . += "There are no firelock electronics in the frame. The frame could be cut apart." + +/obj/structure/firelock_frame/update_icon() + ..() + icon_state = "frame[constructionStep]" + +/obj/structure/firelock_frame/attackby(obj/item/C, mob/user) + switch(constructionStep) + if(CONSTRUCTION_PANEL_OPEN) + if(istype(C, /obj/item/crowbar)) + C.play_tool_sound(src) + user.visible_message("[user] starts prying something out from [src]...", \ + "You begin prying out the wire cover...") + if(!C.use_tool(src, user, 50)) + return + if(constructionStep != CONSTRUCTION_PANEL_OPEN) + return + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + user.visible_message("[user] pries out a metal plate from [src], exposing the wires.", \ + "You remove the cover plate from [src], exposing the wires.") + constructionStep = CONSTRUCTION_WIRES_EXPOSED + update_icon() + return + if(istype(C, /obj/item/wrench)) + if(locate(/obj/machinery/door/firedoor) in get_turf(src)) + to_chat(user, "There's already a firelock there.") + return + C.play_tool_sound(src) + user.visible_message("[user] starts bolting down [src]...", \ + "You begin bolting [src]...") + if(!C.use_tool(src, user, 30)) + return + if(locate(/obj/machinery/door/firedoor) in get_turf(src)) + return + user.visible_message("[user] finishes the firelock.", \ + "You finish the firelock.") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + if(reinforced) + new /obj/machinery/door/firedoor/heavy(get_turf(src)) + else + new /obj/machinery/door/firedoor(get_turf(src)) + qdel(src) + return + if(istype(C, /obj/item/stack/sheet/plasteel)) + var/obj/item/stack/sheet/plasteel/P = C + if(reinforced) + to_chat(user, "[src] is already reinforced.") + return + if(P.get_amount() < 2) + to_chat(user, "You need more plasteel to reinforce [src].") + return + user.visible_message("[user] begins reinforcing [src]...", \ + "You begin reinforcing [src]...") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + if(do_after(user, 60, target = src)) + if(constructionStep != CONSTRUCTION_PANEL_OPEN || reinforced || P.get_amount() < 2 || !P) + return + user.visible_message("[user] reinforces [src].", \ + "You reinforce [src].") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + P.use(2) + reinforced = 1 + return + + if(CONSTRUCTION_WIRES_EXPOSED) + if(istype(C, /obj/item/wirecutters)) + C.play_tool_sound(src) + user.visible_message("[user] starts cutting the wires from [src]...", \ + "You begin removing [src]'s wires...") + if(!C.use_tool(src, user, 60)) + return + if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) + return + user.visible_message("[user] removes the wires from [src].", \ + "You remove the wiring from [src], exposing the circuit board.") + new/obj/item/stack/cable_coil(get_turf(src), 5) + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return + if(istype(C, /obj/item/crowbar)) + C.play_tool_sound(src) + user.visible_message("[user] starts prying a metal plate into [src]...", \ + "You begin prying the cover plate back onto [src]...") + if(!C.use_tool(src, user, 80)) + return + if(constructionStep != CONSTRUCTION_WIRES_EXPOSED) + return + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + user.visible_message("[user] pries the metal plate into [src].", \ + "You pry [src]'s cover plate into place, hiding the wires.") + constructionStep = CONSTRUCTION_PANEL_OPEN + update_icon() + return + if(CONSTRUCTION_GUTTED) + if(istype(C, /obj/item/crowbar)) + user.visible_message("[user] begins removing the circuit board from [src]...", \ + "You begin prying out the circuit board from [src]...") + if(!C.use_tool(src, user, 50, volume=50)) + return + if(constructionStep != CONSTRUCTION_GUTTED) + return + user.visible_message("[user] removes [src]'s circuit board.", \ + "You remove the circuit board from [src].") + new /obj/item/electronics/firelock(drop_location()) + constructionStep = CONSTRUCTION_NOCIRCUIT + update_icon() + return + if(istype(C, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/B = C + if(B.get_amount() < 5) + to_chat(user, "You need more wires to add wiring to [src].") + return + user.visible_message("[user] begins wiring [src]...", \ + "You begin adding wires to [src]...") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + if(do_after(user, 60, target = src)) + if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B) + return + user.visible_message("[user] adds wires to [src].", \ + "You wire [src].") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + B.use(5) + constructionStep = CONSTRUCTION_WIRES_EXPOSED + update_icon() + return + if(CONSTRUCTION_NOCIRCUIT) + if(istype(C, /obj/item/weldingtool)) + if(!C.tool_start_check(user, amount=1)) + return + user.visible_message("[user] begins cutting apart [src]'s frame...", \ + "You begin slicing [src] apart...") + + if(C.use_tool(src, user, 40, volume=50, amount=1)) + if(constructionStep != CONSTRUCTION_NOCIRCUIT) + return + user.visible_message("[user] cuts apart [src]!", \ + "You cut [src] into metal.") + var/turf/T = get_turf(src) + new /obj/item/stack/sheet/metal(T, 3) + if(reinforced) + new /obj/item/stack/sheet/plasteel(T, 2) + qdel(src) + return + if(istype(C, /obj/item/electronics/firelock)) + user.visible_message("[user] starts adding [C] to [src]...", \ + "You begin adding a circuit board to [src]...") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + if(!do_after(user, 40, target = src)) + return + if(constructionStep != CONSTRUCTION_NOCIRCUIT) + return + qdel(C) + user.visible_message("[user] adds a circuit to [src].", \ + "You insert and secure [C].") + playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return + if(istype(C, /obj/item/electroadaptive_pseudocircuit)) + var/obj/item/electroadaptive_pseudocircuit/P = C + if(!P.adapt_circuit(user, 30)) + return + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a firelock circuit and slot it into the assembly.") + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return + return ..() + +/obj/structure/firelock_frame/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) + if((constructionStep == CONSTRUCTION_NOCIRCUIT) && (the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS)) + return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) + return FALSE + +/obj/structure/firelock_frame/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_UPGRADE_SIMPLE_CIRCUITS) + user.visible_message("[user] fabricates a circuit and places it into [src].", \ + "You adapt a firelock circuit and slot it into the assembly.") + constructionStep = CONSTRUCTION_GUTTED + update_icon() + return TRUE + return FALSE + +/obj/structure/firelock_frame/heavy + name = "heavy firelock frame" + reinforced = TRUE + +#undef CONSTRUCTION_COMPLETE +#undef CONSTRUCTION_PANEL_OPEN +#undef CONSTRUCTION_WIRES_EXPOSED +#undef CONSTRUCTION_GUTTED +#undef CONSTRUCTION_NOCIRCUIT diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index ebc1e94e97..af95ee230c 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -1,91 +1,91 @@ -/obj/machinery/door/poddoor - name = "blast door" - desc = "A heavy duty blast door that opens mechanically." - icon = 'icons/obj/doors/blastdoor.dmi' - icon_state = "closed" - var/id = 1 - layer = BLASTDOOR_LAYER - closingLayer = CLOSED_BLASTDOOR_LAYER - sub_door = TRUE - explosion_block = 3 - heat_proof = TRUE - safe = FALSE - max_integrity = 600 - armor = list("melee" = 50, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70) - resistance_flags = FIRE_PROOF - damage_deflection = 70 - poddoor = TRUE - -/obj/machinery/door/poddoor/preopen - icon_state = "open" - density = FALSE - opacity = 0 - -/obj/machinery/door/poddoor/ert - desc = "A heavy duty blast door that only opens for dire emergencies." - -//special poddoors that open when emergency shuttle docks at centcom -/obj/machinery/door/poddoor/shuttledock - var/checkdir = 4 //door won't open if turf in this dir is `turftype` - var/turftype = /turf/open/space - -/obj/machinery/door/poddoor/shuttledock/proc/check() - var/turf/T = get_step(src, checkdir) - if(!istype(T, turftype)) - INVOKE_ASYNC(src, .proc/open) - else - INVOKE_ASYNC(src, .proc/close) - -/obj/machinery/door/poddoor/incinerator_toxmix - name = "combustion chamber vent" - id = INCINERATOR_TOXMIX_VENT - -/obj/machinery/door/poddoor/incinerator_atmos_main - name = "turbine vent" - id = INCINERATOR_ATMOS_MAINVENT - -/obj/machinery/door/poddoor/incinerator_atmos_aux - name = "combustion chamber vent" - id = INCINERATOR_ATMOS_AUXVENT - -/obj/machinery/door/poddoor/incinerator_syndicatelava_main - name = "turbine vent" - id = INCINERATOR_SYNDICATELAVA_MAINVENT - -/obj/machinery/door/poddoor/incinerator_syndicatelava_aux - name = "combustion chamber vent" - id = INCINERATOR_SYNDICATELAVA_AUXVENT - -/obj/machinery/door/poddoor/Bumped(atom/movable/AM) - if(density) - return 0 - else - return ..() - -//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. -/obj/machinery/door/poddoor/ex_act(severity, target) - if(severity == 3) - return - ..() - -/obj/machinery/door/poddoor/do_animate(animation) - switch(animation) - if("opening") - flick("opening", src) - playsound(src, 'sound/machines/blastdoor.ogg', 30, 1) - if("closing") - flick("closing", src) - playsound(src, 'sound/machines/blastdoor.ogg', 30, 1) - -/obj/machinery/door/poddoor/update_icon() - if(density) - icon_state = "closed" - else - icon_state = "open" - -/obj/machinery/door/poddoor/try_to_activate_door(mob/user) - return - -/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) - if(stat & NOPOWER) - open(1) +/obj/machinery/door/poddoor + name = "blast door" + desc = "A heavy duty blast door that opens mechanically." + icon = 'icons/obj/doors/blastdoor.dmi' + icon_state = "closed" + var/id = 1 + layer = BLASTDOOR_LAYER + closingLayer = CLOSED_BLASTDOOR_LAYER + sub_door = TRUE + explosion_block = 3 + heat_proof = TRUE + safe = FALSE + max_integrity = 600 + armor = list("melee" = 50, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70) + resistance_flags = FIRE_PROOF + damage_deflection = 70 + poddoor = TRUE + +/obj/machinery/door/poddoor/preopen + icon_state = "open" + density = FALSE + opacity = 0 + +/obj/machinery/door/poddoor/ert + desc = "A heavy duty blast door that only opens for dire emergencies." + +//special poddoors that open when emergency shuttle docks at centcom +/obj/machinery/door/poddoor/shuttledock + var/checkdir = 4 //door won't open if turf in this dir is `turftype` + var/turftype = /turf/open/space + +/obj/machinery/door/poddoor/shuttledock/proc/check() + var/turf/T = get_step(src, checkdir) + if(!istype(T, turftype)) + INVOKE_ASYNC(src, .proc/open) + else + INVOKE_ASYNC(src, .proc/close) + +/obj/machinery/door/poddoor/incinerator_toxmix + name = "combustion chamber vent" + id = INCINERATOR_TOXMIX_VENT + +/obj/machinery/door/poddoor/incinerator_atmos_main + name = "turbine vent" + id = INCINERATOR_ATMOS_MAINVENT + +/obj/machinery/door/poddoor/incinerator_atmos_aux + name = "combustion chamber vent" + id = INCINERATOR_ATMOS_AUXVENT + +/obj/machinery/door/poddoor/incinerator_syndicatelava_main + name = "turbine vent" + id = INCINERATOR_SYNDICATELAVA_MAINVENT + +/obj/machinery/door/poddoor/incinerator_syndicatelava_aux + name = "combustion chamber vent" + id = INCINERATOR_SYNDICATELAVA_AUXVENT + +/obj/machinery/door/poddoor/Bumped(atom/movable/AM) + if(density) + return 0 + else + return ..() + +//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. +/obj/machinery/door/poddoor/ex_act(severity, target) + if(severity == 3) + return + ..() + +/obj/machinery/door/poddoor/do_animate(animation) + switch(animation) + if("opening") + flick("opening", src) + playsound(src, 'sound/machines/blastdoor.ogg', 30, 1) + if("closing") + flick("closing", src) + playsound(src, 'sound/machines/blastdoor.ogg', 30, 1) + +/obj/machinery/door/poddoor/update_icon() + if(density) + icon_state = "closed" + else + icon_state = "open" + +/obj/machinery/door/poddoor/try_to_activate_door(mob/user) + return + +/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) + if(stat & NOPOWER) + open(1) diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 7ee9891c4c..bd58649b97 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -1,13 +1,13 @@ -/obj/machinery/door/poddoor/shutters - gender = PLURAL - name = "shutters" - desc = "Heavy duty metal shutters that open mechanically." - icon = 'icons/obj/doors/shutters.dmi' - layer = SHUTTER_LAYER - closingLayer = SHUTTER_LAYER - damage_deflection = 20 - -/obj/machinery/door/poddoor/shutters/preopen - icon_state = "open" - density = FALSE - opacity = 0 +/obj/machinery/door/poddoor/shutters + gender = PLURAL + name = "shutters" + desc = "Heavy duty metal shutters that open mechanically." + icon = 'icons/obj/doors/shutters.dmi' + layer = SHUTTER_LAYER + closingLayer = SHUTTER_LAYER + damage_deflection = 20 + +/obj/machinery/door/poddoor/shutters/preopen + icon_state = "open" + density = FALSE + opacity = 0 diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 702f700617..828624adb4 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -1,22 +1,22 @@ -/obj/machinery/door/unpowered - -/obj/machinery/door/unpowered/Bumped(atom/movable/AM) - if(src.locked) - return - ..() - return - - -/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params) - if(locked) - return - else - return ..() - -/obj/machinery/door/unpowered/shuttle - icon = 'icons/turf/shuttle.dmi' - name = "door" - icon_state = "door1" - opacity = 1 - density = TRUE +/obj/machinery/door/unpowered + +/obj/machinery/door/unpowered/Bumped(atom/movable/AM) + if(src.locked) + return + ..() + return + + +/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params) + if(locked) + return + else + return ..() + +/obj/machinery/door/unpowered/shuttle + icon = 'icons/turf/shuttle.dmi' + name = "door" + icon_state = "door1" + opacity = 1 + density = TRUE explosion_block = 1 \ No newline at end of file diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 933bb4f42a..bd9b7325fb 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -1,535 +1,535 @@ -/obj/machinery/door/window - name = "interior door" - desc = "A strong door." - icon = 'icons/obj/doors/windoor.dmi' - icon_state = "left" - layer = ABOVE_WINDOW_LAYER - closingLayer = ABOVE_WINDOW_LAYER - resistance_flags = ACID_PROOF - var/base_state = "left" - max_integrity = 150 //If you change this, consider changing ../door/window/brigdoor/ max_integrity at the bottom of this .dm file - integrity_failure = 0 - armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100) - visible = FALSE - flags_1 = ON_BORDER_1 - opacity = 0 - CanAtmosPass = ATMOS_PASS_PROC - interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN - var/obj/item/electronics/airlock/electronics = null - var/reinf = 0 - var/shards = 2 - var/rods = 2 - var/cable = 1 - var/list/debris = list() - -/obj/machinery/door/window/Initialize(mapload, set_dir) - . = ..() - if(set_dir) - setDir(set_dir) - if(src.req_access && src.req_access.len) - src.icon_state = "[src.icon_state]" - src.base_state = src.icon_state - for(var/i in 1 to shards) - debris += new /obj/item/shard(src) - if(rods) - debris += new /obj/item/stack/rods(src, rods) - if(cable) - debris += new /obj/item/stack/cable_coil(src, cable) - -/obj/machinery/door/window/ComponentInitialize() - . = ..() - AddComponent(/datum/component/ntnet_interface) - -/obj/machinery/door/window/Destroy() - density = FALSE - QDEL_LIST(debris) - if(obj_integrity == 0) - playsound(src, "shatter", 70, 1) - electronics = null - return ..() - -/obj/machinery/door/window/update_icon() - if(density) - icon_state = base_state - else - icon_state = "[src.base_state]open" - -/obj/machinery/door/window/proc/open_and_close() - open() - if(src.check_access(null)) - sleep(50) - else //secure doors close faster - sleep(20) - close() - -/obj/machinery/door/window/Bumped(atom/movable/AM) - if( operating || !src.density ) - return - if (!( ismob(AM) )) - if(ismecha(AM)) - var/obj/mecha/mecha = AM - if(mecha.occupant && src.allowed(mecha.occupant)) - open_and_close() - else - do_animate("deny") - return - if (!( SSticker )) - return - var/mob/M = AM - if(M.restrained() || ((isdrone(M) || iscyborg(M)) && M.stat)) - return - bumpopen(M) - -/obj/machinery/door/window/bumpopen(mob/user) - if( operating || !src.density ) - return - src.add_fingerprint(user) - if(!src.requiresID()) - user = null - - if(allowed(user)) - open_and_close() - else - do_animate("deny") - return - -/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) //Make sure looking at appropriate border - return !density - if(istype(mover, /obj/structure/window)) - var/obj/structure/window/W = mover - if(!valid_window_location(loc, W.ini_dir)) - return FALSE - else if(istype(mover, /obj/structure/windoor_assembly)) - var/obj/structure/windoor_assembly/W = mover - if(!valid_window_location(loc, W.ini_dir)) - return FALSE - else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir)) - return FALSE - else - return 1 - -/obj/machinery/door/window/CanAtmosPass(turf/T) - if(get_dir(loc, T) == dir) - return !density - else - return 1 - -//used in the AStar algorithm to determinate if the turf the door is on is passable -/obj/machinery/door/window/CanAStarPass(obj/item/card/id/ID, to_dir) - return !density || (dir != to_dir) || (check_access(ID) && hasPower()) - -/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return 1 - if(get_dir(loc, target) == dir) - return !density - else - return 1 - -/obj/machinery/door/window/open(forced=0) - if (src.operating == 1) //doors can still open when emag-disabled - return 0 - if(!forced) - if(!hasPower()) - return 0 - if(forced < 2) - if(obj_flags & EMAGGED) - return 0 - if(!src.operating) //in case of emag - operating = TRUE - do_animate("opening") - playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) - src.icon_state ="[src.base_state]open" - sleep(10) - - density = FALSE -// src.sd_set_opacity(0) //TODO: why is this here? Opaque windoors? ~Carn - air_update_turf(1) - update_freelook_sight() - - if(operating == 1) //emag again - operating = FALSE - return 1 - -/obj/machinery/door/window/close(forced=0) - if (src.operating) - return 0 - if(!forced) - if(!hasPower()) - return 0 - if(forced < 2) - if(obj_flags & EMAGGED) - return 0 - operating = TRUE - do_animate("closing") - playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) - src.icon_state = src.base_state - - density = TRUE - air_update_turf(1) - update_freelook_sight() - sleep(10) - - operating = FALSE - return 1 - -/obj/machinery/door/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - switch(damage_type) - if(BRUTE) - playsound(loc, 'sound/effects/glasshit.ogg', 90, 1) - if(BURN) - playsound(src.loc, 'sound/items/welder.ogg', 100, 1) - - -/obj/machinery/door/window/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1) && !disassembled) - for(var/obj/fragment in debris) - fragment.forceMove(get_turf(src)) - transfer_fingerprints_to(fragment) - debris -= fragment - qdel(src) - -/obj/machinery/door/window/narsie_act() - add_atom_colour("#7D1919", FIXED_COLOUR_PRIORITY) - -/obj/machinery/door/window/ratvar_act() - var/obj/machinery/door/window/clockwork/C = new(loc, dir) - C.name = name - qdel(src) - -/obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > T0C + (reinf ? 1600 : 800)) - take_damage(round(exposed_volume / 200), BURN, 0, 0) - ..() - -/obj/machinery/door/window/emag_act(mob/user) - . = ..() - if(operating || !density || obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - operating = TRUE - flick("[src.base_state]spark", src) - playsound(src, "sparks", 75, 1) - addtimer(CALLBACK(src, .proc/open_windows_me), 6) - return TRUE - -/obj/machinery/door/window/proc/open_windows_me() - operating = FALSE - desc += "
    Its access panel is smoking slightly." - open(2) - -/obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params) - - if(operating) - return - - add_fingerprint(user) - if(!(flags_1&NODECONSTRUCT_1)) - if(istype(I, /obj/item/screwdriver)) - if(density || operating) - to_chat(user, "You need to open the door to access the maintenance panel!") - return - I.play_tool_sound(src) - panel_open = !panel_open - to_chat(user, "You [panel_open ? "open":"close"] the maintenance panel of the [src.name].") - return - - if(istype(I, /obj/item/crowbar)) - if(panel_open && !density && !operating) - user.visible_message("[user] removes the electronics from the [src.name].", \ - "You start to remove electronics from the [src.name]...") - if(I.use_tool(src, user, 40, volume=50)) - if(panel_open && !density && !operating && src.loc) - var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) - switch(base_state) - if("left") - WA.facing = "l" - if("right") - WA.facing = "r" - if("leftsecure") - WA.facing = "l" - WA.secure = TRUE - if("rightsecure") - WA.facing = "r" - WA.secure = TRUE - WA.setAnchored(TRUE) - WA.state= "02" - WA.setDir(src.dir) - WA.ini_dir = src.dir - WA.update_icon() - WA.created_name = src.name - - if(obj_flags & EMAGGED) - to_chat(user, "You discard the damaged electronics.") - qdel(src) - return - - to_chat(user, "You remove the airlock electronics.") - - var/obj/item/electronics/airlock/ae - if(!electronics) - ae = new/obj/item/electronics/airlock( src.loc ) - if(req_one_access) - ae.one_access = 1 - ae.accesses = src.req_one_access - else - ae.accesses = src.req_access - else - ae = electronics - electronics = null - ae.forceMove(drop_location()) - - qdel(src) - return - return ..() - -/obj/machinery/door/window/interact(mob/user) //for sillycones - try_to_activate_door(user) - -/obj/machinery/door/window/try_to_crowbar(obj/item/I, mob/user) - if(!hasPower()) - if(density) - open(2) - else - close(2) - else - to_chat(user, "The door's motors resist your efforts to force it!") - -/obj/machinery/door/window/do_animate(animation) - switch(animation) - if("opening") - flick("[src.base_state]opening", src) - if("closing") - flick("[src.base_state]closing", src) - if("deny") - flick("[src.base_state]deny", src) - -/obj/machinery/door/window/check_access_ntnet(datum/netdata/data) - return !requiresID() || ..() - -/obj/machinery/door/window/ntnet_receive(datum/netdata/data) - // Check if the airlock is powered. - if(!hasPower()) - return - - // Check packet access level. - if(!check_access_ntnet(data)) - return - - // Handle received packet. - var/command = lowertext(data.data["data"]) - var/command_value = lowertext(data.data["data_secondary"]) - switch(command) - if("open") - if(command_value == "on" && !density) - return - - if(command_value == "off" && density) - return - - if(density) - INVOKE_ASYNC(src, .proc/open) - else - INVOKE_ASYNC(src, .proc/close) - if("touch") - INVOKE_ASYNC(src, .proc/open_and_close) - -/obj/machinery/door/window/brigdoor - name = "secure door" - icon_state = "leftsecure" - base_state = "leftsecure" - var/id = null - max_integrity = 300 //Stronger doors for prison (regular window door health is 200) - reinf = 1 - explosion_block = 1 - -/obj/machinery/door/window/brigdoor/security/cell - name = "cell door" - desc = "For keeping in criminal scum." - req_access = list(ACCESS_BRIG) - -/obj/machinery/door/window/brigdoor/security/holding - name = "holding cell door" - req_one_access = list(ACCESS_SEC_DOORS, ACCESS_LAWYER) //love for the lawyer - -/obj/machinery/door/window/clockwork - name = "brass windoor" - desc = "A thin door with translucent brass paneling." - icon_state = "clockwork" - base_state = "clockwork" - shards = 0 - rods = 0 - resistance_flags = FIRE_PROOF | ACID_PROOF - var/made_glow = FALSE - -/obj/machinery/door/window/clockwork/Initialize(mapload, set_dir) - . = ..() - for(var/i in 1 to 2) - debris += new/obj/item/clockwork/alloy_shards/medium/gear_bit/large(src) - change_construction_value(2) - -/obj/machinery/door/window/clockwork/setDir(direct) - if(!made_glow) - var/obj/effect/E = new /obj/effect/temp_visual/ratvar/door/window(get_turf(src)) - E.setDir(direct) - made_glow = TRUE - ..() - -/obj/machinery/door/window/clockwork/Destroy() - change_construction_value(-2) - return ..() - -/obj/machinery/door/window/clockwork/emp_act(severity) - if(prob(80/severity)) - open() - -/obj/machinery/door/window/clockwork/ratvar_act() - if(GLOB.ratvar_awakens) - obj_integrity = max_integrity - -/obj/machinery/door/window/clockwork/hasPower() - return TRUE //yup that's power all right - -/obj/machinery/door/window/clockwork/narsie_act() - take_damage(rand(30, 60), BRUTE) - if(src) - var/previouscolor = color - color = "#960000" - animate(src, color = previouscolor, time = 8) - addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8) - -/obj/machinery/door/window/clockwork/allowed(mob/M) - if(is_servant_of_ratvar(M)) - return 1 - return 0 - -/obj/machinery/door/window/northleft - dir = NORTH - -/obj/machinery/door/window/eastleft - dir = EAST - -/obj/machinery/door/window/westleft - dir = WEST - -/obj/machinery/door/window/southleft - dir = SOUTH - -/obj/machinery/door/window/northright - dir = NORTH - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/eastright - dir = EAST - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/westright - dir = WEST - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/southright - dir = SOUTH - icon_state = "right" - base_state = "right" - -/obj/machinery/door/window/brigdoor/northleft - dir = NORTH - -/obj/machinery/door/window/brigdoor/eastleft - dir = EAST - -/obj/machinery/door/window/brigdoor/westleft - dir = WEST - -/obj/machinery/door/window/brigdoor/southleft - dir = SOUTH - -/obj/machinery/door/window/brigdoor/northright - dir = NORTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/eastright - dir = EAST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/westright - dir = WEST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/southright - dir = SOUTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/cell/northleft - dir = NORTH - -/obj/machinery/door/window/brigdoor/security/cell/eastleft - dir = EAST - -/obj/machinery/door/window/brigdoor/security/cell/westleft - dir = WEST - -/obj/machinery/door/window/brigdoor/security/cell/southleft - dir = SOUTH - -/obj/machinery/door/window/brigdoor/security/cell/northright - dir = NORTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/cell/eastright - dir = EAST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/cell/westright - dir = WEST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/cell/southright - dir = SOUTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/holding/northleft - dir = NORTH - -/obj/machinery/door/window/brigdoor/security/holding/eastleft - dir = EAST - -/obj/machinery/door/window/brigdoor/security/holding/westleft - dir = WEST - -/obj/machinery/door/window/brigdoor/security/holding/southleft - dir = SOUTH - -/obj/machinery/door/window/brigdoor/security/holding/northright - dir = NORTH - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/holding/eastright - dir = EAST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/holding/westright - dir = WEST - icon_state = "rightsecure" - base_state = "rightsecure" - -/obj/machinery/door/window/brigdoor/security/holding/southright - dir = SOUTH - icon_state = "rightsecure" - base_state = "rightsecure" +/obj/machinery/door/window + name = "interior door" + desc = "A strong door." + icon = 'icons/obj/doors/windoor.dmi' + icon_state = "left" + layer = ABOVE_WINDOW_LAYER + closingLayer = ABOVE_WINDOW_LAYER + resistance_flags = ACID_PROOF + var/base_state = "left" + max_integrity = 150 //If you change this, consider changing ../door/window/brigdoor/ max_integrity at the bottom of this .dm file + integrity_failure = 0 + armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100) + visible = FALSE + flags_1 = ON_BORDER_1 + opacity = 0 + CanAtmosPass = ATMOS_PASS_PROC + interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN + var/obj/item/electronics/airlock/electronics = null + var/reinf = 0 + var/shards = 2 + var/rods = 2 + var/cable = 1 + var/list/debris = list() + +/obj/machinery/door/window/Initialize(mapload, set_dir) + . = ..() + if(set_dir) + setDir(set_dir) + if(src.req_access && src.req_access.len) + src.icon_state = "[src.icon_state]" + src.base_state = src.icon_state + for(var/i in 1 to shards) + debris += new /obj/item/shard(src) + if(rods) + debris += new /obj/item/stack/rods(src, rods) + if(cable) + debris += new /obj/item/stack/cable_coil(src, cable) + +/obj/machinery/door/window/ComponentInitialize() + . = ..() + AddComponent(/datum/component/ntnet_interface) + +/obj/machinery/door/window/Destroy() + density = FALSE + QDEL_LIST(debris) + if(obj_integrity == 0) + playsound(src, "shatter", 70, 1) + electronics = null + return ..() + +/obj/machinery/door/window/update_icon() + if(density) + icon_state = base_state + else + icon_state = "[src.base_state]open" + +/obj/machinery/door/window/proc/open_and_close() + open() + if(src.check_access(null)) + sleep(50) + else //secure doors close faster + sleep(20) + close() + +/obj/machinery/door/window/Bumped(atom/movable/AM) + if( operating || !src.density ) + return + if (!( ismob(AM) )) + if(ismecha(AM)) + var/obj/mecha/mecha = AM + if(mecha.occupant && src.allowed(mecha.occupant)) + open_and_close() + else + do_animate("deny") + return + if (!( SSticker )) + return + var/mob/M = AM + if(M.restrained() || ((isdrone(M) || iscyborg(M)) && M.stat)) + return + bumpopen(M) + +/obj/machinery/door/window/bumpopen(mob/user) + if( operating || !src.density ) + return + src.add_fingerprint(user) + if(!src.requiresID()) + user = null + + if(allowed(user)) + open_and_close() + else + do_animate("deny") + return + +/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) //Make sure looking at appropriate border + return !density + if(istype(mover, /obj/structure/window)) + var/obj/structure/window/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/structure/windoor_assembly)) + var/obj/structure/windoor_assembly/W = mover + if(!valid_window_location(loc, W.ini_dir)) + return FALSE + else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir)) + return FALSE + else + return 1 + +/obj/machinery/door/window/CanAtmosPass(turf/T) + if(get_dir(loc, T) == dir) + return !density + else + return 1 + +//used in the AStar algorithm to determinate if the turf the door is on is passable +/obj/machinery/door/window/CanAStarPass(obj/item/card/id/ID, to_dir) + return !density || (dir != to_dir) || (check_access(ID) && hasPower()) + +/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return 1 + if(get_dir(loc, target) == dir) + return !density + else + return 1 + +/obj/machinery/door/window/open(forced=0) + if (src.operating == 1) //doors can still open when emag-disabled + return 0 + if(!forced) + if(!hasPower()) + return 0 + if(forced < 2) + if(obj_flags & EMAGGED) + return 0 + if(!src.operating) //in case of emag + operating = TRUE + do_animate("opening") + playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) + src.icon_state ="[src.base_state]open" + sleep(10) + + density = FALSE +// src.sd_set_opacity(0) //TODO: why is this here? Opaque windoors? ~Carn + air_update_turf(1) + update_freelook_sight() + + if(operating == 1) //emag again + operating = FALSE + return 1 + +/obj/machinery/door/window/close(forced=0) + if (src.operating) + return 0 + if(!forced) + if(!hasPower()) + return 0 + if(forced < 2) + if(obj_flags & EMAGGED) + return 0 + operating = TRUE + do_animate("closing") + playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) + src.icon_state = src.base_state + + density = TRUE + air_update_turf(1) + update_freelook_sight() + sleep(10) + + operating = FALSE + return 1 + +/obj/machinery/door/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + switch(damage_type) + if(BRUTE) + playsound(loc, 'sound/effects/glasshit.ogg', 90, 1) + if(BURN) + playsound(src.loc, 'sound/items/welder.ogg', 100, 1) + + +/obj/machinery/door/window/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1) && !disassembled) + for(var/obj/fragment in debris) + fragment.forceMove(get_turf(src)) + transfer_fingerprints_to(fragment) + debris -= fragment + qdel(src) + +/obj/machinery/door/window/narsie_act() + add_atom_colour("#7D1919", FIXED_COLOUR_PRIORITY) + +/obj/machinery/door/window/ratvar_act() + var/obj/machinery/door/window/clockwork/C = new(loc, dir) + C.name = name + qdel(src) + +/obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > T0C + (reinf ? 1600 : 800)) + take_damage(round(exposed_volume / 200), BURN, 0, 0) + ..() + +/obj/machinery/door/window/emag_act(mob/user) + . = ..() + if(operating || !density || obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + operating = TRUE + flick("[src.base_state]spark", src) + playsound(src, "sparks", 75, 1) + addtimer(CALLBACK(src, .proc/open_windows_me), 6) + return TRUE + +/obj/machinery/door/window/proc/open_windows_me() + operating = FALSE + desc += "
    Its access panel is smoking slightly." + open(2) + +/obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params) + + if(operating) + return + + add_fingerprint(user) + if(!(flags_1&NODECONSTRUCT_1)) + if(istype(I, /obj/item/screwdriver)) + if(density || operating) + to_chat(user, "You need to open the door to access the maintenance panel!") + return + I.play_tool_sound(src) + panel_open = !panel_open + to_chat(user, "You [panel_open ? "open":"close"] the maintenance panel of the [src.name].") + return + + if(istype(I, /obj/item/crowbar)) + if(panel_open && !density && !operating) + user.visible_message("[user] removes the electronics from the [src.name].", \ + "You start to remove electronics from the [src.name]...") + if(I.use_tool(src, user, 40, volume=50)) + if(panel_open && !density && !operating && src.loc) + var/obj/structure/windoor_assembly/WA = new /obj/structure/windoor_assembly(src.loc) + switch(base_state) + if("left") + WA.facing = "l" + if("right") + WA.facing = "r" + if("leftsecure") + WA.facing = "l" + WA.secure = TRUE + if("rightsecure") + WA.facing = "r" + WA.secure = TRUE + WA.setAnchored(TRUE) + WA.state= "02" + WA.setDir(src.dir) + WA.ini_dir = src.dir + WA.update_icon() + WA.created_name = src.name + + if(obj_flags & EMAGGED) + to_chat(user, "You discard the damaged electronics.") + qdel(src) + return + + to_chat(user, "You remove the airlock electronics.") + + var/obj/item/electronics/airlock/ae + if(!electronics) + ae = new/obj/item/electronics/airlock( src.loc ) + if(req_one_access) + ae.one_access = 1 + ae.accesses = src.req_one_access + else + ae.accesses = src.req_access + else + ae = electronics + electronics = null + ae.forceMove(drop_location()) + + qdel(src) + return + return ..() + +/obj/machinery/door/window/interact(mob/user) //for sillycones + try_to_activate_door(user) + +/obj/machinery/door/window/try_to_crowbar(obj/item/I, mob/user) + if(!hasPower()) + if(density) + open(2) + else + close(2) + else + to_chat(user, "The door's motors resist your efforts to force it!") + +/obj/machinery/door/window/do_animate(animation) + switch(animation) + if("opening") + flick("[src.base_state]opening", src) + if("closing") + flick("[src.base_state]closing", src) + if("deny") + flick("[src.base_state]deny", src) + +/obj/machinery/door/window/check_access_ntnet(datum/netdata/data) + return !requiresID() || ..() + +/obj/machinery/door/window/ntnet_receive(datum/netdata/data) + // Check if the airlock is powered. + if(!hasPower()) + return + + // Check packet access level. + if(!check_access_ntnet(data)) + return + + // Handle received packet. + var/command = lowertext(data.data["data"]) + var/command_value = lowertext(data.data["data_secondary"]) + switch(command) + if("open") + if(command_value == "on" && !density) + return + + if(command_value == "off" && density) + return + + if(density) + INVOKE_ASYNC(src, .proc/open) + else + INVOKE_ASYNC(src, .proc/close) + if("touch") + INVOKE_ASYNC(src, .proc/open_and_close) + +/obj/machinery/door/window/brigdoor + name = "secure door" + icon_state = "leftsecure" + base_state = "leftsecure" + var/id = null + max_integrity = 300 //Stronger doors for prison (regular window door health is 200) + reinf = 1 + explosion_block = 1 + +/obj/machinery/door/window/brigdoor/security/cell + name = "cell door" + desc = "For keeping in criminal scum." + req_access = list(ACCESS_BRIG) + +/obj/machinery/door/window/brigdoor/security/holding + name = "holding cell door" + req_one_access = list(ACCESS_SEC_DOORS, ACCESS_LAWYER) //love for the lawyer + +/obj/machinery/door/window/clockwork + name = "brass windoor" + desc = "A thin door with translucent brass paneling." + icon_state = "clockwork" + base_state = "clockwork" + shards = 0 + rods = 0 + resistance_flags = FIRE_PROOF | ACID_PROOF + var/made_glow = FALSE + +/obj/machinery/door/window/clockwork/Initialize(mapload, set_dir) + . = ..() + for(var/i in 1 to 2) + debris += new/obj/item/clockwork/alloy_shards/medium/gear_bit/large(src) + change_construction_value(2) + +/obj/machinery/door/window/clockwork/setDir(direct) + if(!made_glow) + var/obj/effect/E = new /obj/effect/temp_visual/ratvar/door/window(get_turf(src)) + E.setDir(direct) + made_glow = TRUE + ..() + +/obj/machinery/door/window/clockwork/Destroy() + change_construction_value(-2) + return ..() + +/obj/machinery/door/window/clockwork/emp_act(severity) + if(prob(80/severity)) + open() + +/obj/machinery/door/window/clockwork/ratvar_act() + if(GLOB.ratvar_awakens) + obj_integrity = max_integrity + +/obj/machinery/door/window/clockwork/hasPower() + return TRUE //yup that's power all right + +/obj/machinery/door/window/clockwork/narsie_act() + take_damage(rand(30, 60), BRUTE) + if(src) + var/previouscolor = color + color = "#960000" + animate(src, color = previouscolor, time = 8) + addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8) + +/obj/machinery/door/window/clockwork/allowed(mob/M) + if(is_servant_of_ratvar(M)) + return 1 + return 0 + +/obj/machinery/door/window/northleft + dir = NORTH + +/obj/machinery/door/window/eastleft + dir = EAST + +/obj/machinery/door/window/westleft + dir = WEST + +/obj/machinery/door/window/southleft + dir = SOUTH + +/obj/machinery/door/window/northright + dir = NORTH + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/eastright + dir = EAST + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/westright + dir = WEST + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/southright + dir = SOUTH + icon_state = "right" + base_state = "right" + +/obj/machinery/door/window/brigdoor/northleft + dir = NORTH + +/obj/machinery/door/window/brigdoor/eastleft + dir = EAST + +/obj/machinery/door/window/brigdoor/westleft + dir = WEST + +/obj/machinery/door/window/brigdoor/southleft + dir = SOUTH + +/obj/machinery/door/window/brigdoor/northright + dir = NORTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/eastright + dir = EAST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/westright + dir = WEST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/southright + dir = SOUTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/cell/northleft + dir = NORTH + +/obj/machinery/door/window/brigdoor/security/cell/eastleft + dir = EAST + +/obj/machinery/door/window/brigdoor/security/cell/westleft + dir = WEST + +/obj/machinery/door/window/brigdoor/security/cell/southleft + dir = SOUTH + +/obj/machinery/door/window/brigdoor/security/cell/northright + dir = NORTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/cell/eastright + dir = EAST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/cell/westright + dir = WEST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/cell/southright + dir = SOUTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/holding/northleft + dir = NORTH + +/obj/machinery/door/window/brigdoor/security/holding/eastleft + dir = EAST + +/obj/machinery/door/window/brigdoor/security/holding/westleft + dir = WEST + +/obj/machinery/door/window/brigdoor/security/holding/southleft + dir = SOUTH + +/obj/machinery/door/window/brigdoor/security/holding/northright + dir = NORTH + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/holding/eastright + dir = EAST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/holding/westright + dir = WEST + icon_state = "rightsecure" + base_state = "rightsecure" + +/obj/machinery/door/window/brigdoor/security/holding/southright + dir = SOUTH + icon_state = "rightsecure" + base_state = "rightsecure" diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 65f7602215..db806ef3ac 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -1,188 +1,188 @@ -GLOBAL_LIST_EMPTY(doppler_arrays) - -/obj/machinery/doppler_array - name = "tachyon-doppler array" - desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\n" - icon = 'icons/obj/machines/research.dmi' - icon_state = "tdoppler" - density = TRUE - var/integrated = FALSE - var/list_limit = 100 - var/cooldown = 10 - var/next_announce = 0 - var/max_dist = 150 - verb_say = "states coldly" - var/list/message_log = list() - -/obj/machinery/doppler_array/Initialize() - . = ..() - GLOB.doppler_arrays += src - -/obj/machinery/doppler_array/ComponentInitialize() - . = ..() - AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message)) - -/obj/machinery/doppler_array/Destroy() - GLOB.doppler_arrays -= src - return ..() - -/obj/machinery/doppler_array/ui_interact(mob/user) - . = ..() - if(stat) - return FALSE - - var/list/dat = list() - for(var/i in 1 to LAZYLEN(message_log)) - dat += "Log recording #[i]: [message_log[i]]

    " - dat += "Delete logs
    " - dat += "
    " - dat += "(Refresh)
    " - dat += "" - var/datum/browser/popup = new(user, "computer", name, 400, 500) - popup.set_content(dat.Join(" ")) - popup.open() - -/obj/machinery/doppler_array/Topic(href, href_list) - if(..()) - return - if(href_list["delete_log"]) - LAZYCLEARLIST(message_log) - if(href_list["refresh"]) - updateUsrDialog() - - updateUsrDialog() - return - -/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/wrench)) - if(!anchored && !isinspace()) - anchored = TRUE - power_change() - to_chat(user, "You fasten [src].") - else if(anchored) - anchored = FALSE - power_change() - to_chat(user, "You unfasten [src].") - I.play_tool_sound(src) - else - return ..() - -/obj/machinery/doppler_array/proc/rot_message(mob/user) - to_chat(user, "You adjust [src]'s dish to face to the [dir2text(dir)].") - playsound(src, 'sound/items/screwdriver2.ogg', 50, 1) - -/obj/machinery/doppler_array/proc/sense_explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, - took, orig_dev_range, orig_heavy_range, orig_light_range) - if(stat & NOPOWER) - return FALSE - var/turf/zone = get_turf(src) - if(zone.z != epicenter.z) - return FALSE - - if(next_announce > world.time) - return FALSE - next_announce = world.time + cooldown - - var/distance = get_dist(epicenter, zone) - var/direct = get_dir(zone, epicenter) - - if(distance > max_dist) - return FALSE - if(!(direct & dir) && !integrated) - return FALSE - - - var/list/messages = list("Explosive disturbance detected.", \ - "Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \ - "Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].") - - // If the bomb was capped, say its theoretical size. - if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range) - messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]." - - if(integrated) - var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc - if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit)) - return FALSE - helm.display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]") - else - for(var/message in messages) - say(message) - if(LAZYLEN(message_log) > list_limit) - say("Storage buffer is full! Clearing buffers...") - LAZYCLEARLIST(message_log) - LAZYADD(message_log, messages.Join(" ")) - return TRUE - -/obj/machinery/doppler_array/examine(mob/user) - . = ..() - . += "Its dish is facing to the [dir2text(dir)]." - -/obj/machinery/doppler_array/process() - return PROCESS_KILL - -/obj/machinery/doppler_array/power_change() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" - else - if(powered() && anchored) - icon_state = initial(icon_state) - stat &= ~NOPOWER - else - icon_state = "[initial(icon_state)]-off" - stat |= NOPOWER - -//Portable version, built into EOD equipment. It simply provides an explosion's three damage levels. -/obj/machinery/doppler_array/integrated - name = "integrated tachyon-doppler module" - integrated = TRUE - max_dist = 21 //Should detect most explosions in hearing range. - use_power = NO_POWER_USE - -/obj/machinery/doppler_array/research - name = "tachyon-doppler research array" - desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research." - var/datum/techweb/linked_techweb - -/obj/machinery/doppler_array/research/sense_explosion(turf/epicenter, dev, heavy, light, time, orig_dev, orig_heavy, orig_light) //probably needs a way to ignore admin explosives later on - . = ..() - if(!.) - return FALSE - if(!istype(linked_techweb)) - say("Warning: No linked research system!") - return - - var/point_gain = 0 - - /*****The Point Calculator*****/ - - if(orig_light < 10) - say("Explosion not large enough for research calculations.") - return - else if(orig_light < 4500) - point_gain = (83300 * orig_light) / (orig_light + 3000) - else - point_gain = TECHWEB_BOMB_POINTCAP - - /*****The Point Capper*****/ - if(point_gain > linked_techweb.largest_bomb_value) - if(point_gain <= TECHWEB_BOMB_POINTCAP || linked_techweb.largest_bomb_value < TECHWEB_BOMB_POINTCAP) - var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math - linked_techweb.largest_bomb_value = point_gain - point_gain -= old_tech_largest_bomb_value - point_gain = min(point_gain,TECHWEB_BOMB_POINTCAP) - else - linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP - point_gain = 1000 - - linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain) - say("Gained [point_gain] points from explosion dataset.") - - else //you've made smaller bombs - say("Data already captured. Aborting.") - return - - -/obj/machinery/doppler_array/research/science/Initialize() - . = ..() +GLOBAL_LIST_EMPTY(doppler_arrays) + +/obj/machinery/doppler_array + name = "tachyon-doppler array" + desc = "A highly precise directional sensor array which measures the release of quants from decaying tachyons. The doppler shifting of the mirror-image formed by these quants can reveal the size, location and temporal affects of energetic disturbances within a large radius ahead of the array.\n" + icon = 'icons/obj/machines/research.dmi' + icon_state = "tdoppler" + density = TRUE + var/integrated = FALSE + var/list_limit = 100 + var/cooldown = 10 + var/next_announce = 0 + var/max_dist = 150 + verb_say = "states coldly" + var/list/message_log = list() + +/obj/machinery/doppler_array/Initialize() + . = ..() + GLOB.doppler_arrays += src + +/obj/machinery/doppler_array/ComponentInitialize() + . = ..() + AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message)) + +/obj/machinery/doppler_array/Destroy() + GLOB.doppler_arrays -= src + return ..() + +/obj/machinery/doppler_array/ui_interact(mob/user) + . = ..() + if(stat) + return FALSE + + var/list/dat = list() + for(var/i in 1 to LAZYLEN(message_log)) + dat += "Log recording #[i]: [message_log[i]]

    " + dat += "Delete logs
    " + dat += "
    " + dat += "(Refresh)
    " + dat += "" + var/datum/browser/popup = new(user, "computer", name, 400, 500) + popup.set_content(dat.Join(" ")) + popup.open() + +/obj/machinery/doppler_array/Topic(href, href_list) + if(..()) + return + if(href_list["delete_log"]) + LAZYCLEARLIST(message_log) + if(href_list["refresh"]) + updateUsrDialog() + + updateUsrDialog() + return + +/obj/machinery/doppler_array/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/wrench)) + if(!anchored && !isinspace()) + anchored = TRUE + power_change() + to_chat(user, "You fasten [src].") + else if(anchored) + anchored = FALSE + power_change() + to_chat(user, "You unfasten [src].") + I.play_tool_sound(src) + else + return ..() + +/obj/machinery/doppler_array/proc/rot_message(mob/user) + to_chat(user, "You adjust [src]'s dish to face to the [dir2text(dir)].") + playsound(src, 'sound/items/screwdriver2.ogg', 50, 1) + +/obj/machinery/doppler_array/proc/sense_explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, + took, orig_dev_range, orig_heavy_range, orig_light_range) + if(stat & NOPOWER) + return FALSE + var/turf/zone = get_turf(src) + if(zone.z != epicenter.z) + return FALSE + + if(next_announce > world.time) + return FALSE + next_announce = world.time + cooldown + + var/distance = get_dist(epicenter, zone) + var/direct = get_dir(zone, epicenter) + + if(distance > max_dist) + return FALSE + if(!(direct & dir) && !integrated) + return FALSE + + + var/list/messages = list("Explosive disturbance detected.", \ + "Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \ + "Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].") + + // If the bomb was capped, say its theoretical size. + if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range) + messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]." + + if(integrated) + var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc + if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit)) + return FALSE + helm.display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]") + else + for(var/message in messages) + say(message) + if(LAZYLEN(message_log) > list_limit) + say("Storage buffer is full! Clearing buffers...") + LAZYCLEARLIST(message_log) + LAZYADD(message_log, messages.Join(" ")) + return TRUE + +/obj/machinery/doppler_array/examine(mob/user) + . = ..() + . += "Its dish is facing to the [dir2text(dir)]." + +/obj/machinery/doppler_array/process() + return PROCESS_KILL + +/obj/machinery/doppler_array/power_change() + if(stat & BROKEN) + icon_state = "[initial(icon_state)]-broken" + else + if(powered() && anchored) + icon_state = initial(icon_state) + stat &= ~NOPOWER + else + icon_state = "[initial(icon_state)]-off" + stat |= NOPOWER + +//Portable version, built into EOD equipment. It simply provides an explosion's three damage levels. +/obj/machinery/doppler_array/integrated + name = "integrated tachyon-doppler module" + integrated = TRUE + max_dist = 21 //Should detect most explosions in hearing range. + use_power = NO_POWER_USE + +/obj/machinery/doppler_array/research + name = "tachyon-doppler research array" + desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research." + var/datum/techweb/linked_techweb + +/obj/machinery/doppler_array/research/sense_explosion(turf/epicenter, dev, heavy, light, time, orig_dev, orig_heavy, orig_light) //probably needs a way to ignore admin explosives later on + . = ..() + if(!.) + return FALSE + if(!istype(linked_techweb)) + say("Warning: No linked research system!") + return + + var/point_gain = 0 + + /*****The Point Calculator*****/ + + if(orig_light < 10) + say("Explosion not large enough for research calculations.") + return + else if(orig_light < 4500) + point_gain = (83300 * orig_light) / (orig_light + 3000) + else + point_gain = TECHWEB_BOMB_POINTCAP + + /*****The Point Capper*****/ + if(point_gain > linked_techweb.largest_bomb_value) + if(point_gain <= TECHWEB_BOMB_POINTCAP || linked_techweb.largest_bomb_value < TECHWEB_BOMB_POINTCAP) + var/old_tech_largest_bomb_value = linked_techweb.largest_bomb_value //held so we can pull old before we do math + linked_techweb.largest_bomb_value = point_gain + point_gain -= old_tech_largest_bomb_value + point_gain = min(point_gain,TECHWEB_BOMB_POINTCAP) + else + linked_techweb.largest_bomb_value = TECHWEB_BOMB_POINTCAP + point_gain = 1000 + + linked_techweb.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, point_gain) + say("Gained [point_gain] points from explosion dataset.") + + else //you've made smaller bombs + say("Data already captured. Aborting.") + return + + +/obj/machinery/doppler_array/research/science/Initialize() + . = ..() linked_techweb = SSresearch.science_tech \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm index 3b9322d207..ad49abb398 100644 --- a/code/game/machinery/embedded_controller/access_controller.dm +++ b/code/game/machinery/embedded_controller/access_controller.dm @@ -1,315 +1,315 @@ -#define CLOSING 1 -#define OPENING 2 -#define CYCLE 3 -#define CYCLE_EXTERIOR 4 -#define CYCLE_INTERIOR 5 - -/obj/machinery/doorButtons - power_channel = ENVIRON - use_power = IDLE_POWER_USE - idle_power_usage = 2 - active_power_usage = 4 - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - var/idSelf - -/obj/machinery/doorButtons/attackby(obj/O, mob/user) - return attack_hand(user) - -/obj/machinery/doorButtons/proc/findObjsByTag() - return - -/obj/machinery/doorButtons/Initialize() - ..() - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/doorButtons/LateInitialize() - findObjsByTag() - -/obj/machinery/doorButtons/emag_act(mob/user) - . = ..() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - req_access = list() - req_one_access = list() - playsound(src, "sparks", 100, 1) - to_chat(user, "You short out the access controller.") - return TRUE - -/obj/machinery/doorButtons/proc/removeMe() - - -/obj/machinery/doorButtons/access_button - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "access_button_standby" - name = "access button" - desc = "A button used for the explicit purpose of opening an airlock." - var/idDoor - var/obj/machinery/door/airlock/door - var/obj/machinery/doorButtons/airlock_controller/controller - var/busy - -/obj/machinery/doorButtons/access_button/findObjsByTag() - for(var/obj/machinery/doorButtons/airlock_controller/A in GLOB.machines) - if(A.idSelf == idSelf) - controller = A - break - for(var/obj/machinery/door/airlock/I in GLOB.machines) - if(I.id_tag == idDoor) - door = I - break - -/obj/machinery/doorButtons/access_button/interact(mob/user) - if(busy) - return - if(!allowed(user)) - to_chat(user, "Access denied.") - return - if(controller && !controller.busy && door) - if(controller.stat & NOPOWER) - return - busy = TRUE - update_icon() - if(door.density) - if(!controller.exteriorAirlock || !controller.interiorAirlock) - controller.onlyOpen(door) - else - if(controller.exteriorAirlock.density && controller.interiorAirlock.density) - controller.onlyOpen(door) - else - controller.cycleClose(door) - else - controller.onlyClose(door) - sleep(20) - busy = FALSE - update_icon() - -/obj/machinery/doorButtons/access_button/update_icon() - if(stat & NOPOWER) - icon_state = "access_button_off" - else - if(busy) - icon_state = "access_button_cycle" - else - icon_state = "access_button_standby" - -/obj/machinery/doorButtons/access_button/power_change() - ..() - update_icon() - -/obj/machinery/doorButtons/access_button/removeMe(obj/O) - if(O == door) - door = null - - - -/obj/machinery/doorButtons/airlock_controller - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "access_control_standby" - name = "access console" - desc = "A small console that can cycle opening between two airlocks." - var/obj/machinery/door/airlock/interiorAirlock - var/obj/machinery/door/airlock/exteriorAirlock - var/idInterior - var/idExterior - var/busy - var/lostPower - -/obj/machinery/doorButtons/airlock_controller/removeMe(obj/O) - if(O == interiorAirlock) - interiorAirlock = null - else if(O == exteriorAirlock) - exteriorAirlock = null - -/obj/machinery/doorButtons/airlock_controller/Destroy() - for(var/obj/machinery/doorButtons/access_button/A in GLOB.machines) - if(A.controller == src) - A.controller = null - return ..() - -/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list) - if(..()) - return - if(busy) - return - if(!allowed(usr)) - to_chat(usr, "Access denied.") - return - switch(href_list["command"]) - if("close_exterior") - onlyClose(exteriorAirlock) - if("close_interior") - onlyClose(interiorAirlock) - if("cycle_exterior") - cycleClose(exteriorAirlock) - if("cycle_interior") - cycleClose(interiorAirlock) - if("open_exterior") - onlyOpen(exteriorAirlock) - if("open_interior") - onlyOpen(interiorAirlock) - -/obj/machinery/doorButtons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A) - if(A) - busy = CLOSING - update_icon() - openDoor(A) - -/obj/machinery/doorButtons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A) - if(A) - busy = CLOSING - closeDoor(A) - -/obj/machinery/doorButtons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A) - set waitfor = FALSE - if(A.density) - goIdle() - return 0 - update_icon() - A.unbolt() - . = 1 - if(A && A.close()) - if(stat & NOPOWER || lostPower || !A || QDELETED(A)) - goIdle(1) - return - A.bolt() - if(busy == CLOSING) - goIdle(1) - else - goIdle(1) - -/obj/machinery/doorButtons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A) - if(!A || !exteriorAirlock || !interiorAirlock) - return - if(exteriorAirlock.density == interiorAirlock.density || !A.density) - return - busy = CYCLE - update_icon() - if(A == interiorAirlock) - if(closeDoor(exteriorAirlock)) - busy = CYCLE_INTERIOR - else - if(closeDoor(interiorAirlock)) - busy = CYCLE_EXTERIOR - -/obj/machinery/doorButtons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A) - if(!A) - goIdle(1) - if(A == exteriorAirlock) - if(interiorAirlock) - if(!interiorAirlock.density || !interiorAirlock.locked) - return - else - if(exteriorAirlock) - if(!exteriorAirlock.density || !exteriorAirlock.locked) - return - if(busy != OPENING) - busy = OPENING - openDoor(A) - -/obj/machinery/doorButtons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A) - if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density)) - goIdle(1) - return - A.unbolt() - spawn() - if(A && A.open()) - if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A)) - A.bolt() - goIdle(1) - -/obj/machinery/doorButtons/airlock_controller/proc/goIdle(update) - lostPower = 0 - busy = FALSE - if(update) - update_icon() - updateUsrDialog() - -/obj/machinery/doorButtons/airlock_controller/process() - if(stat & NOPOWER) - return - if(busy == CYCLE_EXTERIOR) - cycleOpen(exteriorAirlock) - else if(busy == CYCLE_INTERIOR) - cycleOpen(interiorAirlock) - -/obj/machinery/doorButtons/airlock_controller/power_change() - ..() - if(stat & NOPOWER) - lostPower = 1 - else - if(!busy) - lostPower = 0 - update_icon() - -/obj/machinery/doorButtons/airlock_controller/findObjsByTag() - for(var/obj/machinery/door/airlock/A in GLOB.machines) - if(A.id_tag == idInterior) - interiorAirlock = A - else if(A.id_tag == idExterior) - exteriorAirlock = A - -/obj/machinery/doorButtons/airlock_controller/update_icon() - if(stat & NOPOWER) - icon_state = "access_control_off" - return - if(busy || lostPower) - icon_state = "access_control_process" - else - icon_state = "access_control_standby" - -/obj/machinery/doorButtons/airlock_controller/ui_interact(mob/user) - var/datum/browser/popup = new(user, "computer", name) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.set_content(returnText()) - popup.open() - -/obj/machinery/doorButtons/airlock_controller/proc/returnText() - var/output - if(!exteriorAirlock && !interiorAirlock) - return "ERROR ERROR ERROR ERROR" - if(lostPower) - output = "Initializing..." - else - if(!exteriorAirlock || !interiorAirlock) - if(!exteriorAirlock) - if(interiorAirlock.density) - output = "Open Interior Airlock
    " - else - output = "Close Interior Airlock
    " - else - if(exteriorAirlock.density) - output = "Open Exterior Airlock
    " - else - output = "Close Exterior Airlock
    " - else - if(exteriorAirlock.density) - if(interiorAirlock.density) - output = {"Open Exterior Airlock
    - Open Interior Airlock
    "} - else - output = {"Cycle to Exterior Airlock
    - Close Interior Airlock
    "} - else - if(interiorAirlock.density) - output = {"Close Exterior Airlock
    - Cycle to Interior Airlock
    "} - else - output = {"Close Exterior Airlock
    - Close Interior Airlock
    "} - - - output = {"Access Control Console
    - [output]
    "} - if(exteriorAirlock) - output += "Exterior Door: [exteriorAirlock.density ? "closed" : "open"]
    " - if(interiorAirlock) - output += "Interior Door: [interiorAirlock.density ? "closed" : "open"]
    " - - return output - -#undef CLOSING -#undef OPENING -#undef CYCLE -#undef CYCLE_EXTERIOR -#undef CYCLE_INTERIOR +#define CLOSING 1 +#define OPENING 2 +#define CYCLE 3 +#define CYCLE_EXTERIOR 4 +#define CYCLE_INTERIOR 5 + +/obj/machinery/doorButtons + power_channel = ENVIRON + use_power = IDLE_POWER_USE + idle_power_usage = 2 + active_power_usage = 4 + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/idSelf + +/obj/machinery/doorButtons/attackby(obj/O, mob/user) + return attack_hand(user) + +/obj/machinery/doorButtons/proc/findObjsByTag() + return + +/obj/machinery/doorButtons/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/doorButtons/LateInitialize() + findObjsByTag() + +/obj/machinery/doorButtons/emag_act(mob/user) + . = ..() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + req_access = list() + req_one_access = list() + playsound(src, "sparks", 100, 1) + to_chat(user, "You short out the access controller.") + return TRUE + +/obj/machinery/doorButtons/proc/removeMe() + + +/obj/machinery/doorButtons/access_button + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "access_button_standby" + name = "access button" + desc = "A button used for the explicit purpose of opening an airlock." + var/idDoor + var/obj/machinery/door/airlock/door + var/obj/machinery/doorButtons/airlock_controller/controller + var/busy + +/obj/machinery/doorButtons/access_button/findObjsByTag() + for(var/obj/machinery/doorButtons/airlock_controller/A in GLOB.machines) + if(A.idSelf == idSelf) + controller = A + break + for(var/obj/machinery/door/airlock/I in GLOB.machines) + if(I.id_tag == idDoor) + door = I + break + +/obj/machinery/doorButtons/access_button/interact(mob/user) + if(busy) + return + if(!allowed(user)) + to_chat(user, "Access denied.") + return + if(controller && !controller.busy && door) + if(controller.stat & NOPOWER) + return + busy = TRUE + update_icon() + if(door.density) + if(!controller.exteriorAirlock || !controller.interiorAirlock) + controller.onlyOpen(door) + else + if(controller.exteriorAirlock.density && controller.interiorAirlock.density) + controller.onlyOpen(door) + else + controller.cycleClose(door) + else + controller.onlyClose(door) + sleep(20) + busy = FALSE + update_icon() + +/obj/machinery/doorButtons/access_button/update_icon() + if(stat & NOPOWER) + icon_state = "access_button_off" + else + if(busy) + icon_state = "access_button_cycle" + else + icon_state = "access_button_standby" + +/obj/machinery/doorButtons/access_button/power_change() + ..() + update_icon() + +/obj/machinery/doorButtons/access_button/removeMe(obj/O) + if(O == door) + door = null + + + +/obj/machinery/doorButtons/airlock_controller + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "access_control_standby" + name = "access console" + desc = "A small console that can cycle opening between two airlocks." + var/obj/machinery/door/airlock/interiorAirlock + var/obj/machinery/door/airlock/exteriorAirlock + var/idInterior + var/idExterior + var/busy + var/lostPower + +/obj/machinery/doorButtons/airlock_controller/removeMe(obj/O) + if(O == interiorAirlock) + interiorAirlock = null + else if(O == exteriorAirlock) + exteriorAirlock = null + +/obj/machinery/doorButtons/airlock_controller/Destroy() + for(var/obj/machinery/doorButtons/access_button/A in GLOB.machines) + if(A.controller == src) + A.controller = null + return ..() + +/obj/machinery/doorButtons/airlock_controller/Topic(href, href_list) + if(..()) + return + if(busy) + return + if(!allowed(usr)) + to_chat(usr, "Access denied.") + return + switch(href_list["command"]) + if("close_exterior") + onlyClose(exteriorAirlock) + if("close_interior") + onlyClose(interiorAirlock) + if("cycle_exterior") + cycleClose(exteriorAirlock) + if("cycle_interior") + cycleClose(interiorAirlock) + if("open_exterior") + onlyOpen(exteriorAirlock) + if("open_interior") + onlyOpen(interiorAirlock) + +/obj/machinery/doorButtons/airlock_controller/proc/onlyOpen(obj/machinery/door/airlock/A) + if(A) + busy = CLOSING + update_icon() + openDoor(A) + +/obj/machinery/doorButtons/airlock_controller/proc/onlyClose(obj/machinery/door/airlock/A) + if(A) + busy = CLOSING + closeDoor(A) + +/obj/machinery/doorButtons/airlock_controller/proc/closeDoor(obj/machinery/door/airlock/A) + set waitfor = FALSE + if(A.density) + goIdle() + return 0 + update_icon() + A.unbolt() + . = 1 + if(A && A.close()) + if(stat & NOPOWER || lostPower || !A || QDELETED(A)) + goIdle(1) + return + A.bolt() + if(busy == CLOSING) + goIdle(1) + else + goIdle(1) + +/obj/machinery/doorButtons/airlock_controller/proc/cycleClose(obj/machinery/door/airlock/A) + if(!A || !exteriorAirlock || !interiorAirlock) + return + if(exteriorAirlock.density == interiorAirlock.density || !A.density) + return + busy = CYCLE + update_icon() + if(A == interiorAirlock) + if(closeDoor(exteriorAirlock)) + busy = CYCLE_INTERIOR + else + if(closeDoor(interiorAirlock)) + busy = CYCLE_EXTERIOR + +/obj/machinery/doorButtons/airlock_controller/proc/cycleOpen(obj/machinery/door/airlock/A) + if(!A) + goIdle(1) + if(A == exteriorAirlock) + if(interiorAirlock) + if(!interiorAirlock.density || !interiorAirlock.locked) + return + else + if(exteriorAirlock) + if(!exteriorAirlock.density || !exteriorAirlock.locked) + return + if(busy != OPENING) + busy = OPENING + openDoor(A) + +/obj/machinery/doorButtons/airlock_controller/proc/openDoor(obj/machinery/door/airlock/A) + if(exteriorAirlock && interiorAirlock && (!exteriorAirlock.density || !interiorAirlock.density)) + goIdle(1) + return + A.unbolt() + spawn() + if(A && A.open()) + if(stat | (NOPOWER) && !lostPower && A && !QDELETED(A)) + A.bolt() + goIdle(1) + +/obj/machinery/doorButtons/airlock_controller/proc/goIdle(update) + lostPower = 0 + busy = FALSE + if(update) + update_icon() + updateUsrDialog() + +/obj/machinery/doorButtons/airlock_controller/process() + if(stat & NOPOWER) + return + if(busy == CYCLE_EXTERIOR) + cycleOpen(exteriorAirlock) + else if(busy == CYCLE_INTERIOR) + cycleOpen(interiorAirlock) + +/obj/machinery/doorButtons/airlock_controller/power_change() + ..() + if(stat & NOPOWER) + lostPower = 1 + else + if(!busy) + lostPower = 0 + update_icon() + +/obj/machinery/doorButtons/airlock_controller/findObjsByTag() + for(var/obj/machinery/door/airlock/A in GLOB.machines) + if(A.id_tag == idInterior) + interiorAirlock = A + else if(A.id_tag == idExterior) + exteriorAirlock = A + +/obj/machinery/doorButtons/airlock_controller/update_icon() + if(stat & NOPOWER) + icon_state = "access_control_off" + return + if(busy || lostPower) + icon_state = "access_control_process" + else + icon_state = "access_control_standby" + +/obj/machinery/doorButtons/airlock_controller/ui_interact(mob/user) + var/datum/browser/popup = new(user, "computer", name) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.set_content(returnText()) + popup.open() + +/obj/machinery/doorButtons/airlock_controller/proc/returnText() + var/output + if(!exteriorAirlock && !interiorAirlock) + return "ERROR ERROR ERROR ERROR" + if(lostPower) + output = "Initializing..." + else + if(!exteriorAirlock || !interiorAirlock) + if(!exteriorAirlock) + if(interiorAirlock.density) + output = "Open Interior Airlock
    " + else + output = "Close Interior Airlock
    " + else + if(exteriorAirlock.density) + output = "Open Exterior Airlock
    " + else + output = "Close Exterior Airlock
    " + else + if(exteriorAirlock.density) + if(interiorAirlock.density) + output = {"Open Exterior Airlock
    + Open Interior Airlock
    "} + else + output = {"Cycle to Exterior Airlock
    + Close Interior Airlock
    "} + else + if(interiorAirlock.density) + output = {"Close Exterior Airlock
    + Cycle to Interior Airlock
    "} + else + output = {"Close Exterior Airlock
    + Close Interior Airlock
    "} + + + output = {"Access Control Console
    + [output]
    "} + if(exteriorAirlock) + output += "Exterior Door: [exteriorAirlock.density ? "closed" : "open"]
    " + if(interiorAirlock) + output += "Interior Door: [interiorAirlock.density ? "closed" : "open"]
    " + + return output + +#undef CLOSING +#undef OPENING +#undef CYCLE +#undef CYCLE_EXTERIOR +#undef CYCLE_INTERIOR diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm index 0036b41804..9f1ebe67a9 100644 --- a/code/game/machinery/embedded_controller/airlock_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_controller.dm @@ -1,315 +1,315 @@ -//States for airlock_control -#define AIRLOCK_STATE_INOPEN -2 -#define AIRLOCK_STATE_PRESSURIZE -1 -#define AIRLOCK_STATE_CLOSED 0 -#define AIRLOCK_STATE_DEPRESSURIZE 1 -#define AIRLOCK_STATE_OUTOPEN 2 - -/datum/computer/file/embedded_program/airlock_controller - var/id_tag - var/exterior_door_tag //Burn chamber facing door - var/interior_door_tag //Station facing door - var/airpump_tag //See: dp_vent_pump.dm - var/sensor_tag //See: /obj/machinery/airlock_sensor - var/sanitize_external //Before the interior airlock opens, do we first drain all gases inside the chamber and then repressurize? - - state = AIRLOCK_STATE_CLOSED - var/target_state = AIRLOCK_STATE_CLOSED - var/sensor_pressure = null - -/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal) - var/receive_tag = signal.data["tag"] - if(!receive_tag) - return - - if(receive_tag==sensor_tag) - if(signal.data["pressure"]) - sensor_pressure = text2num(signal.data["pressure"]) - - else if(receive_tag==exterior_door_tag) - memory["exterior_status"] = signal.data["door_status"] - - else if(receive_tag==interior_door_tag) - memory["interior_status"] = signal.data["door_status"] - - else if(receive_tag==airpump_tag) - if(signal.data["power"]) - memory["pump_status"] = signal.data["direction"] - else - memory["pump_status"] = "off" - - else if(receive_tag==id_tag) - switch(signal.data["command"]) - if("cycle") - if(state < AIRLOCK_STATE_CLOSED) - target_state = AIRLOCK_STATE_OUTOPEN - else - target_state = AIRLOCK_STATE_INOPEN - -/datum/computer/file/embedded_program/airlock_controller/receive_user_command(command) - switch(command) - if("cycle_closed") - target_state = AIRLOCK_STATE_CLOSED - if("cycle_exterior") - target_state = AIRLOCK_STATE_OUTOPEN - if("cycle_interior") - target_state = AIRLOCK_STATE_INOPEN - if("abort") - target_state = AIRLOCK_STATE_CLOSED - -/datum/computer/file/embedded_program/airlock_controller/process() - var/process_again = 1 - while(process_again) - process_again = 0 - switch(state) - if(AIRLOCK_STATE_INOPEN) // state -2 - if(target_state > state) - if(memory["interior_status"] == "closed") - state = AIRLOCK_STATE_CLOSED - process_again = 1 - else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_close" - ))) - else - if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "power" = 0, - "sigtype" = "command" - ))) - - if(AIRLOCK_STATE_PRESSURIZE) - if(target_state < state) - if(sensor_pressure >= ONE_ATMOSPHERE*0.95) - if(memory["interior_status"] == "open") - state = AIRLOCK_STATE_INOPEN - process_again = 1 - else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_open" - ))) - else - var/datum/signal/signal = new(list( - "tag" = airpump_tag, - "sigtype" = "command" - )) - if(memory["pump_status"] == "siphon") - signal.data["stabilize"] = 1 - else if(memory["pump_status"] != "release") - signal.data["power"] = 1 - post_signal(signal) - else if(target_state > state) - state = AIRLOCK_STATE_CLOSED - process_again = 1 - - if(AIRLOCK_STATE_CLOSED) - if(target_state > state) - if(memory["interior_status"] == "closed") - state = AIRLOCK_STATE_DEPRESSURIZE - process_again = 1 - else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_close" - ))) - else if(target_state < state) - if(memory["exterior_status"] == "closed") - state = AIRLOCK_STATE_PRESSURIZE - process_again = 1 - else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_close" - ))) - - else - if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "power" = 0, - "sigtype" = "command" - ))) - - if(AIRLOCK_STATE_DEPRESSURIZE) - var/target_pressure = ONE_ATMOSPHERE*0.05 - if(sanitize_external) - target_pressure = ONE_ATMOSPHERE*0.01 - - if(sensor_pressure <= target_pressure) - if(target_state > state) - if(memory["exterior_status"] == "open") - state = AIRLOCK_STATE_OUTOPEN - else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_open" - ))) - else if(target_state < state) - state = AIRLOCK_STATE_CLOSED - process_again = 1 - else if((target_state < state) && !sanitize_external) - state = AIRLOCK_STATE_CLOSED - process_again = 1 - else - var/datum/signal/signal = new(list( - "tag" = airpump_tag, - "sigtype" = "command" - )) - if(memory["pump_status"] == "release") - signal.data["purge"] = 1 - else if(memory["pump_status"] != "siphon") - signal.data["power"] = 1 - post_signal(signal) - - if(AIRLOCK_STATE_OUTOPEN) //state 2 - if(target_state < state) - if(memory["exterior_status"] == "closed") - if(sanitize_external) - state = AIRLOCK_STATE_DEPRESSURIZE - process_again = 1 - else - state = AIRLOCK_STATE_CLOSED - process_again = 1 - else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_close" - ))) - else - if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "power" = 0, - "sigtype" = "command" - ))) - - memory["sensor_pressure"] = sensor_pressure - memory["processing"] = state != target_state - //sensor_pressure = null //not sure if we can comment this out. Uncomment in case of problems -rastaf0 - - return 1 - - -/obj/machinery/embedded_controller/radio/airlock_controller - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_control_standby" - - name = "airlock console" - density = FALSE - - frequency = FREQ_AIRLOCK_CONTROL - power_channel = ENVIRON - - // Setup parameters only - var/id_tag - var/exterior_door_tag - var/interior_door_tag - var/airpump_tag - var/sensor_tag - var/sanitize_external - -/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_toxmix - name = "Incinerator Access Console" - airpump_tag = INCINERATOR_TOXMIX_DP_VENTPUMP - exterior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR - id_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER - interior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR - sanitize_external = TRUE - sensor_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR - -/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos - name = "Incinerator Access Console" - airpump_tag = INCINERATOR_ATMOS_DP_VENTPUMP - exterior_door_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR - id_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER - interior_door_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR - sanitize_external = TRUE - sensor_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR - -/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_syndicatelava - name = "Incinerator Access Console" - airpump_tag = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP - exterior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR - id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER - interior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR - sanitize_external = TRUE - sensor_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR - -/obj/machinery/embedded_controller/radio/airlock_controller/Initialize(mapload) - . = ..() - if(!mapload) - return - - var/datum/computer/file/embedded_program/airlock_controller/new_prog = new - - new_prog.id_tag = id_tag - new_prog.exterior_door_tag = exterior_door_tag - new_prog.interior_door_tag = interior_door_tag - new_prog.airpump_tag = airpump_tag - new_prog.sensor_tag = sensor_tag - new_prog.sanitize_external = sanitize_external - - new_prog.master = src - program = new_prog - -/obj/machinery/embedded_controller/radio/airlock_controller/update_icon() - if(on && program) - if(program.memory["processing"]) - icon_state = "airlock_control_process" - else - icon_state = "airlock_control_standby" - else - icon_state = "airlock_control_off" - - -/obj/machinery/embedded_controller/radio/airlock_controller/return_text() - var/state_options = null - - var/state = 0 - var/sensor_pressure = "----" - var/exterior_status = "----" - var/interior_status = "----" - var/pump_status = "----" - var/current_status = "Inactive
     " - if(program) - state = program.state - sensor_pressure = program.memory["sensor_pressure"] ? program.memory["sensor_pressure"] : "----" - exterior_status = program.memory["exterior_status"] ? program.memory["exterior_status"] : "----" - interior_status = program.memory["interior_status"] ? program.memory["interior_status"] : "----" - pump_status = program.memory["pump_status"] ? program.memory["pump_status"] : "----" - - switch(state) - if(AIRLOCK_STATE_INOPEN) - state_options = {"Close Interior Airlock
    -Cycle to Exterior Airlock
    "} - current_status = "Interior Airlock Open
    Chamber Pressurized" - if(AIRLOCK_STATE_PRESSURIZE) - state_options = "Abort Cycling
    " - current_status = "Cycling to Interior Airlock
    Chamber Pressurizing" - if(AIRLOCK_STATE_CLOSED) - state_options = {"Open Interior Airlock
    -Open Exterior Airlock
    "} - if(AIRLOCK_STATE_DEPRESSURIZE) - state_options = "Abort Cycling
    " - current_status = "Cycling to Exterior Airlock
    Chamber Depressurizing" - if(AIRLOCK_STATE_OUTOPEN) - state_options = {"Cycle to Interior Airlock
    -Close Exterior Airlock
    "} - current_status = "Exterior Airlock Open
    Chamber Depressurized" - - var/output = {"

    Airlock Status

    -
    -
    Current Status:
    [current_status]
    -
     
    -
    \> Chamber Pressure:
    [sensor_pressure] kPa
    -
    \> Control Pump:
    [pump_status]
    -
    \> Interior Door:
    [interior_status]
    -
    \> Exterior Door:
    [exterior_status]
    -
    -
    -[state_options]"} - +//States for airlock_control +#define AIRLOCK_STATE_INOPEN -2 +#define AIRLOCK_STATE_PRESSURIZE -1 +#define AIRLOCK_STATE_CLOSED 0 +#define AIRLOCK_STATE_DEPRESSURIZE 1 +#define AIRLOCK_STATE_OUTOPEN 2 + +/datum/computer/file/embedded_program/airlock_controller + var/id_tag + var/exterior_door_tag //Burn chamber facing door + var/interior_door_tag //Station facing door + var/airpump_tag //See: dp_vent_pump.dm + var/sensor_tag //See: /obj/machinery/airlock_sensor + var/sanitize_external //Before the interior airlock opens, do we first drain all gases inside the chamber and then repressurize? + + state = AIRLOCK_STATE_CLOSED + var/target_state = AIRLOCK_STATE_CLOSED + var/sensor_pressure = null + +/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal) + var/receive_tag = signal.data["tag"] + if(!receive_tag) + return + + if(receive_tag==sensor_tag) + if(signal.data["pressure"]) + sensor_pressure = text2num(signal.data["pressure"]) + + else if(receive_tag==exterior_door_tag) + memory["exterior_status"] = signal.data["door_status"] + + else if(receive_tag==interior_door_tag) + memory["interior_status"] = signal.data["door_status"] + + else if(receive_tag==airpump_tag) + if(signal.data["power"]) + memory["pump_status"] = signal.data["direction"] + else + memory["pump_status"] = "off" + + else if(receive_tag==id_tag) + switch(signal.data["command"]) + if("cycle") + if(state < AIRLOCK_STATE_CLOSED) + target_state = AIRLOCK_STATE_OUTOPEN + else + target_state = AIRLOCK_STATE_INOPEN + +/datum/computer/file/embedded_program/airlock_controller/receive_user_command(command) + switch(command) + if("cycle_closed") + target_state = AIRLOCK_STATE_CLOSED + if("cycle_exterior") + target_state = AIRLOCK_STATE_OUTOPEN + if("cycle_interior") + target_state = AIRLOCK_STATE_INOPEN + if("abort") + target_state = AIRLOCK_STATE_CLOSED + +/datum/computer/file/embedded_program/airlock_controller/process() + var/process_again = 1 + while(process_again) + process_again = 0 + switch(state) + if(AIRLOCK_STATE_INOPEN) // state -2 + if(target_state > state) + if(memory["interior_status"] == "closed") + state = AIRLOCK_STATE_CLOSED + process_again = 1 + else + post_signal(new /datum/signal(list( + "tag" = interior_door_tag, + "command" = "secure_close" + ))) + else + if(memory["pump_status"] != "off") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "power" = 0, + "sigtype" = "command" + ))) + + if(AIRLOCK_STATE_PRESSURIZE) + if(target_state < state) + if(sensor_pressure >= ONE_ATMOSPHERE*0.95) + if(memory["interior_status"] == "open") + state = AIRLOCK_STATE_INOPEN + process_again = 1 + else + post_signal(new /datum/signal(list( + "tag" = interior_door_tag, + "command" = "secure_open" + ))) + else + var/datum/signal/signal = new(list( + "tag" = airpump_tag, + "sigtype" = "command" + )) + if(memory["pump_status"] == "siphon") + signal.data["stabilize"] = 1 + else if(memory["pump_status"] != "release") + signal.data["power"] = 1 + post_signal(signal) + else if(target_state > state) + state = AIRLOCK_STATE_CLOSED + process_again = 1 + + if(AIRLOCK_STATE_CLOSED) + if(target_state > state) + if(memory["interior_status"] == "closed") + state = AIRLOCK_STATE_DEPRESSURIZE + process_again = 1 + else + post_signal(new /datum/signal(list( + "tag" = interior_door_tag, + "command" = "secure_close" + ))) + else if(target_state < state) + if(memory["exterior_status"] == "closed") + state = AIRLOCK_STATE_PRESSURIZE + process_again = 1 + else + post_signal(new /datum/signal(list( + "tag" = exterior_door_tag, + "command" = "secure_close" + ))) + + else + if(memory["pump_status"] != "off") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "power" = 0, + "sigtype" = "command" + ))) + + if(AIRLOCK_STATE_DEPRESSURIZE) + var/target_pressure = ONE_ATMOSPHERE*0.05 + if(sanitize_external) + target_pressure = ONE_ATMOSPHERE*0.01 + + if(sensor_pressure <= target_pressure) + if(target_state > state) + if(memory["exterior_status"] == "open") + state = AIRLOCK_STATE_OUTOPEN + else + post_signal(new /datum/signal(list( + "tag" = exterior_door_tag, + "command" = "secure_open" + ))) + else if(target_state < state) + state = AIRLOCK_STATE_CLOSED + process_again = 1 + else if((target_state < state) && !sanitize_external) + state = AIRLOCK_STATE_CLOSED + process_again = 1 + else + var/datum/signal/signal = new(list( + "tag" = airpump_tag, + "sigtype" = "command" + )) + if(memory["pump_status"] == "release") + signal.data["purge"] = 1 + else if(memory["pump_status"] != "siphon") + signal.data["power"] = 1 + post_signal(signal) + + if(AIRLOCK_STATE_OUTOPEN) //state 2 + if(target_state < state) + if(memory["exterior_status"] == "closed") + if(sanitize_external) + state = AIRLOCK_STATE_DEPRESSURIZE + process_again = 1 + else + state = AIRLOCK_STATE_CLOSED + process_again = 1 + else + post_signal(new /datum/signal(list( + "tag" = exterior_door_tag, + "command" = "secure_close" + ))) + else + if(memory["pump_status"] != "off") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "power" = 0, + "sigtype" = "command" + ))) + + memory["sensor_pressure"] = sensor_pressure + memory["processing"] = state != target_state + //sensor_pressure = null //not sure if we can comment this out. Uncomment in case of problems -rastaf0 + + return 1 + + +/obj/machinery/embedded_controller/radio/airlock_controller + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_control_standby" + + name = "airlock console" + density = FALSE + + frequency = FREQ_AIRLOCK_CONTROL + power_channel = ENVIRON + + // Setup parameters only + var/id_tag + var/exterior_door_tag + var/interior_door_tag + var/airpump_tag + var/sensor_tag + var/sanitize_external + +/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_toxmix + name = "Incinerator Access Console" + airpump_tag = INCINERATOR_TOXMIX_DP_VENTPUMP + exterior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_EXTERIOR + id_tag = INCINERATOR_TOXMIX_AIRLOCK_CONTROLLER + interior_door_tag = INCINERATOR_TOXMIX_AIRLOCK_INTERIOR + sanitize_external = TRUE + sensor_tag = INCINERATOR_TOXMIX_AIRLOCK_SENSOR + +/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_atmos + name = "Incinerator Access Console" + airpump_tag = INCINERATOR_ATMOS_DP_VENTPUMP + exterior_door_tag = INCINERATOR_ATMOS_AIRLOCK_EXTERIOR + id_tag = INCINERATOR_ATMOS_AIRLOCK_CONTROLLER + interior_door_tag = INCINERATOR_ATMOS_AIRLOCK_INTERIOR + sanitize_external = TRUE + sensor_tag = INCINERATOR_ATMOS_AIRLOCK_SENSOR + +/obj/machinery/embedded_controller/radio/airlock_controller/incinerator_syndicatelava + name = "Incinerator Access Console" + airpump_tag = INCINERATOR_SYNDICATELAVA_DP_VENTPUMP + exterior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_EXTERIOR + id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER + interior_door_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_INTERIOR + sanitize_external = TRUE + sensor_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR + +/obj/machinery/embedded_controller/radio/airlock_controller/Initialize(mapload) + . = ..() + if(!mapload) + return + + var/datum/computer/file/embedded_program/airlock_controller/new_prog = new + + new_prog.id_tag = id_tag + new_prog.exterior_door_tag = exterior_door_tag + new_prog.interior_door_tag = interior_door_tag + new_prog.airpump_tag = airpump_tag + new_prog.sensor_tag = sensor_tag + new_prog.sanitize_external = sanitize_external + + new_prog.master = src + program = new_prog + +/obj/machinery/embedded_controller/radio/airlock_controller/update_icon() + if(on && program) + if(program.memory["processing"]) + icon_state = "airlock_control_process" + else + icon_state = "airlock_control_standby" + else + icon_state = "airlock_control_off" + + +/obj/machinery/embedded_controller/radio/airlock_controller/return_text() + var/state_options = null + + var/state = 0 + var/sensor_pressure = "----" + var/exterior_status = "----" + var/interior_status = "----" + var/pump_status = "----" + var/current_status = "Inactive
     " + if(program) + state = program.state + sensor_pressure = program.memory["sensor_pressure"] ? program.memory["sensor_pressure"] : "----" + exterior_status = program.memory["exterior_status"] ? program.memory["exterior_status"] : "----" + interior_status = program.memory["interior_status"] ? program.memory["interior_status"] : "----" + pump_status = program.memory["pump_status"] ? program.memory["pump_status"] : "----" + + switch(state) + if(AIRLOCK_STATE_INOPEN) + state_options = {"Close Interior Airlock
    +Cycle to Exterior Airlock
    "} + current_status = "Interior Airlock Open
    Chamber Pressurized" + if(AIRLOCK_STATE_PRESSURIZE) + state_options = "Abort Cycling
    " + current_status = "Cycling to Interior Airlock
    Chamber Pressurizing" + if(AIRLOCK_STATE_CLOSED) + state_options = {"Open Interior Airlock
    +Open Exterior Airlock
    "} + if(AIRLOCK_STATE_DEPRESSURIZE) + state_options = "Abort Cycling
    " + current_status = "Cycling to Exterior Airlock
    Chamber Depressurizing" + if(AIRLOCK_STATE_OUTOPEN) + state_options = {"Cycle to Interior Airlock
    +Close Exterior Airlock
    "} + current_status = "Exterior Airlock Open
    Chamber Depressurized" + + var/output = {"

    Airlock Status

    +
    +
    Current Status:
    [current_status]
    +
     
    +
    \> Chamber Pressure:
    [sensor_pressure] kPa
    +
    \> Control Pump:
    [pump_status]
    +
    \> Interior Door:
    [interior_status]
    +
    \> Exterior Door:
    [exterior_status]
    +
    +
    +[state_options]"} + return output \ No newline at end of file diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 063cfa6805..f1a2ef9acc 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -1,87 +1,87 @@ -/datum/computer/file/embedded_program - var/list/memory = list() - var/state - var/obj/machinery/embedded_controller/master - -/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line) - if(master) - master.post_signal(signal, comm_line) - else - qdel(signal) - -/datum/computer/file/embedded_program/proc/receive_user_command(command) - -/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal) - return null - -/datum/computer/file/embedded_program/process() - return 0 - -/obj/machinery/embedded_controller - var/datum/computer/file/embedded_program/program - - name = "embedded controller" - density = FALSE - - var/on = TRUE - -/obj/machinery/embedded_controller/ui_interact(mob/user) - . = ..() - user.set_machine(src) - var/datum/browser/popup = new(user, "computer", name) // Set up the popup browser window - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.set_content(return_text()) - popup.open() - -/obj/machinery/embedded_controller/update_icon() - -/obj/machinery/embedded_controller/proc/return_text() - -/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) - return 0 - -/obj/machinery/embedded_controller/receive_signal(datum/signal/signal) - if(istype(signal) && program) - program.receive_signal(signal) - -/obj/machinery/embedded_controller/Topic(href, href_list) - if(..()) - return 0 - - if(program) - program.receive_user_command(href_list["command"]) - addtimer(CALLBACK(program, /datum/computer/file/embedded_program.proc/process), 5) - - usr.set_machine(src) - addtimer(CALLBACK(src, .proc/updateDialog), 5) - -/obj/machinery/embedded_controller/process() - if(program) - program.process() - - update_icon() - src.updateDialog() - -/obj/machinery/embedded_controller/radio - var/frequency - var/datum/radio_frequency/radio_connection - -/obj/machinery/embedded_controller/radio/Destroy() - SSradio.remove_object(src,frequency) - return ..() - -/obj/machinery/embedded_controller/radio/Initialize() - . = ..() - set_frequency(frequency) - -/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal) - signal.transmission_method = TRANSMISSION_RADIO - if(radio_connection) - return radio_connection.post_signal(src, signal) - else - signal = null - -/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency) +/datum/computer/file/embedded_program + var/list/memory = list() + var/state + var/obj/machinery/embedded_controller/master + +/datum/computer/file/embedded_program/proc/post_signal(datum/signal/signal, comm_line) + if(master) + master.post_signal(signal, comm_line) + else + qdel(signal) + +/datum/computer/file/embedded_program/proc/receive_user_command(command) + +/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal) + return null + +/datum/computer/file/embedded_program/process() + return 0 + +/obj/machinery/embedded_controller + var/datum/computer/file/embedded_program/program + + name = "embedded controller" + density = FALSE + + var/on = TRUE + +/obj/machinery/embedded_controller/ui_interact(mob/user) + . = ..() + user.set_machine(src) + var/datum/browser/popup = new(user, "computer", name) // Set up the popup browser window + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.set_content(return_text()) + popup.open() + +/obj/machinery/embedded_controller/update_icon() + +/obj/machinery/embedded_controller/proc/return_text() + +/obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) + return 0 + +/obj/machinery/embedded_controller/receive_signal(datum/signal/signal) + if(istype(signal) && program) + program.receive_signal(signal) + +/obj/machinery/embedded_controller/Topic(href, href_list) + if(..()) + return 0 + + if(program) + program.receive_user_command(href_list["command"]) + addtimer(CALLBACK(program, /datum/computer/file/embedded_program.proc/process), 5) + + usr.set_machine(src) + addtimer(CALLBACK(src, .proc/updateDialog), 5) + +/obj/machinery/embedded_controller/process() + if(program) + program.process() + + update_icon() + src.updateDialog() + +/obj/machinery/embedded_controller/radio + var/frequency + var/datum/radio_frequency/radio_connection + +/obj/machinery/embedded_controller/radio/Destroy() + SSradio.remove_object(src,frequency) + return ..() + +/obj/machinery/embedded_controller/radio/Initialize() + . = ..() + set_frequency(frequency) + +/obj/machinery/embedded_controller/radio/post_signal(datum/signal/signal) + signal.transmission_method = TRANSMISSION_RADIO + if(radio_connection) + return radio_connection.post_signal(src, signal) + else + signal = null + +/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + radio_connection = SSradio.add_object(src, frequency) diff --git a/code/game/machinery/embedded_controller/simple_vent_controller.dm b/code/game/machinery/embedded_controller/simple_vent_controller.dm index 9901d51074..33be1e3f79 100644 --- a/code/game/machinery/embedded_controller/simple_vent_controller.dm +++ b/code/game/machinery/embedded_controller/simple_vent_controller.dm @@ -1,72 +1,72 @@ -/datum/computer/file/embedded_program/simple_vent_controller - - var/airpump_tag - -/datum/computer/file/embedded_program/simple_vent_controller/receive_user_command(command) - switch(command) - if("vent_inactive") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "sigtype" = "command", - "power" = 0 - ))) - - if("vent_pump") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "sigtype" = "command", - "stabilize" = 1, - "power" = 1 - ))) - - if("vent_clear") - post_signal(new /datum/signal(list( - "tag" = airpump_tag, - "sigtype" = "command", - "purge" = 1, - "power" = 1 - ))) - -/datum/computer/file/embedded_program/simple_vent_controller/process() - return 0 - - -/obj/machinery/embedded_controller/radio/simple_vent_controller - icon = 'icons/obj/airlock_machines.dmi' - icon_state = "airlock_control_standby" - - name = "vent controller" - density = FALSE - - frequency = FREQ_ATMOS_CONTROL - power_channel = ENVIRON - - // Setup parameters only - var/airpump_tag - -/obj/machinery/embedded_controller/radio/simple_vent_controller/Initialize(mapload) - . = ..() - if(!mapload) - return - var/datum/computer/file/embedded_program/simple_vent_controller/new_prog = new - - new_prog.airpump_tag = airpump_tag - new_prog.master = src - program = new_prog - -/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon() - if(on && program) - icon_state = "airlock_control_standby" - else - icon_state = "airlock_control_off" - - -/obj/machinery/embedded_controller/radio/simple_vent_controller/return_text() - var/state_options = null - state_options = {"Deactivate Vent
    -Activate Vent / Pump
    -Activate Vent / Clear
    "} - var/output = {"Vent Control Console
    -[state_options]
    "} - - return output +/datum/computer/file/embedded_program/simple_vent_controller + + var/airpump_tag + +/datum/computer/file/embedded_program/simple_vent_controller/receive_user_command(command) + switch(command) + if("vent_inactive") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "sigtype" = "command", + "power" = 0 + ))) + + if("vent_pump") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "sigtype" = "command", + "stabilize" = 1, + "power" = 1 + ))) + + if("vent_clear") + post_signal(new /datum/signal(list( + "tag" = airpump_tag, + "sigtype" = "command", + "purge" = 1, + "power" = 1 + ))) + +/datum/computer/file/embedded_program/simple_vent_controller/process() + return 0 + + +/obj/machinery/embedded_controller/radio/simple_vent_controller + icon = 'icons/obj/airlock_machines.dmi' + icon_state = "airlock_control_standby" + + name = "vent controller" + density = FALSE + + frequency = FREQ_ATMOS_CONTROL + power_channel = ENVIRON + + // Setup parameters only + var/airpump_tag + +/obj/machinery/embedded_controller/radio/simple_vent_controller/Initialize(mapload) + . = ..() + if(!mapload) + return + var/datum/computer/file/embedded_program/simple_vent_controller/new_prog = new + + new_prog.airpump_tag = airpump_tag + new_prog.master = src + program = new_prog + +/obj/machinery/embedded_controller/radio/simple_vent_controller/update_icon() + if(on && program) + icon_state = "airlock_control_standby" + else + icon_state = "airlock_control_off" + + +/obj/machinery/embedded_controller/radio/simple_vent_controller/return_text() + var/state_options = null + state_options = {"Deactivate Vent
    +Activate Vent / Pump
    +Activate Vent / Clear
    "} + var/output = {"Vent Control Console
    +[state_options]
    "} + + return output diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index def530a14d..6f89ce0d45 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -1,205 +1,205 @@ -// It is a gizmo that flashes a small area - -/obj/machinery/flasher - name = "mounted flash" - desc = "A wall-mounted flashbulb device." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mflash1" - max_integrity = 250 - integrity_failure = 100 - light_color = LIGHT_COLOR_WHITE - light_power = FLASH_LIGHT_POWER - var/obj/item/assembly/flash/handheld/bulb - var/id = null - var/range = 2 //this is roughly the size of brig cell - var/last_flash = 0 //Don't want it getting spammed like regular flashes - var/strength = 100 //How knocked down targets are when flashed. - var/base_state = "mflash" - -/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored - name = "portable flasher" - desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements." - icon_state = "pflash1-p" - strength = 80 - anchored = FALSE - base_state = "pflash" - density = TRUE - -/obj/machinery/flasher/Initialize(mapload, ndir = 0, built = 0) - . = ..() // ..() is EXTREMELY IMPORTANT, never forget to add it - if(built) - setDir(ndir) - pixel_x = (dir & 3)? 0 : (dir == 4 ? -28 : 28) - pixel_y = (dir & 3)? (dir ==1 ? -28 : 28) : 0 - else - bulb = new(src) - -/obj/machinery/flasher/Destroy() - QDEL_NULL(bulb) - return ..() - -/obj/machinery/flasher/power_change() - if (powered() && anchored && bulb) - stat &= ~NOPOWER - if(bulb.crit_fail) - icon_state = "[base_state]1-p" - else - icon_state = "[base_state]1" - else - stat |= NOPOWER - icon_state = "[base_state]1-p" - -//Don't want to render prison breaks impossible -/obj/machinery/flasher/attackby(obj/item/W, mob/user, params) - add_fingerprint(user) - if (istype(W, /obj/item/wirecutters)) - if (bulb) - user.visible_message("[user] begins to disconnect [src]'s flashbulb.", "You begin to disconnect [src]'s flashbulb...") - if(W.use_tool(src, user, 30, volume=50) && bulb) - user.visible_message("[user] has disconnected [src]'s flashbulb!", "You disconnect [src]'s flashbulb.") - bulb.forceMove(loc) - bulb = null - power_change() - - else if (istype(W, /obj/item/assembly/flash/handheld)) - if (!bulb) - if(!user.transferItemToLoc(W, src)) - return - user.visible_message("[user] installs [W] into [src].", "You install [W] into [src].") - bulb = W - power_change() - else - to_chat(user, "A flashbulb is already installed in [src]!") - - else if (istype(W, /obj/item/wrench)) - if(!bulb) - to_chat(user, "You start unsecuring the flasher frame...") - if(W.use_tool(src, user, 40, volume=50)) - to_chat(user, "You unsecure the flasher frame.") - deconstruct(TRUE) - else - to_chat(user, "Remove a flashbulb from [src] first!") - else - return ..() - -//Let the AI trigger them directly. -/obj/machinery/flasher/attack_ai() - if (anchored) - return flash() - -/obj/machinery/flasher/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) - if(damage_flag == "melee" && damage_amount < 10) //any melee attack below 10 dmg does nothing - return 0 - . = ..() - -/obj/machinery/flasher/proc/flash() - if (!powered() || !bulb) - return - - if (bulb.crit_fail || (last_flash && world.time < src.last_flash + 150)) - return - - if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast - power_change() - return - - playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) - flick("[base_state]_flash", src) - flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color) - last_flash = world.time - use_power(1000) - - var/flashed = FALSE - for (var/mob/living/L in viewers(src, null)) - if (get_dist(src, L) > range) - continue - - if(L.flash_act(affect_silicon = 1)) - L.Knockdown(strength) - flashed = TRUE - - if(flashed) - bulb.times_used++ - - return 1 - - -/obj/machinery/flasher/emp_act(severity) - . = ..() - if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) - if(bulb && prob(75/severity)) - flash() - bulb.burn_out() - power_change() - -/obj/machinery/flasher/obj_break(damage_flag) - if(!(flags_1 & NODECONSTRUCT_1)) - if(!(stat & BROKEN)) - stat |= BROKEN - if(bulb) - bulb.burn_out() - power_change() - -/obj/machinery/flasher/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(bulb) - bulb.forceMove(loc) - bulb = null - if(disassembled) - var/obj/item/wallframe/flasher/F = new(get_turf(src)) - transfer_fingerprints_to(F) - F.id = id - playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) - else - new /obj/item/stack/sheet/metal (loc, 2) - qdel(src) - -/obj/machinery/flasher/portable/Initialize() - . = ..() - proximity_monitor = new(src, 0) - -/obj/machinery/flasher/portable/HasProximity(atom/movable/AM) - if (last_flash && world.time < last_flash + 150) - return - - if(istype(AM, /mob/living/carbon)) - var/mob/living/carbon/M = AM - if (M.m_intent != MOVE_INTENT_WALK && anchored) - flash() - -/obj/machinery/flasher/portable/attackby(obj/item/W, mob/user, params) - if (istype(W, /obj/item/wrench)) - W.play_tool_sound(src, 100) - - if (!anchored && !isinspace()) - to_chat(user, "[src] is now secured.") - add_overlay("[base_state]-s") - setAnchored(TRUE) - power_change() - proximity_monitor.SetRange(range) - else - to_chat(user, "[src] can now be moved.") - cut_overlays() - setAnchored(FALSE) - power_change() - proximity_monitor.SetRange(0) - - else - return ..() - -/obj/item/wallframe/flasher - name = "mounted flash frame" - desc = "Used for building wall-mounted flashers." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mflash_frame" - result_path = /obj/machinery/flasher - var/id = null - -/obj/item/wallframe/flasher/examine(mob/user) - . = ..() - . += "Its channel ID is '[id]'." - -/obj/item/wallframe/flasher/after_attach(var/obj/O) - ..() - var/obj/machinery/flasher/F = O - F.id = id +// It is a gizmo that flashes a small area + +/obj/machinery/flasher + name = "mounted flash" + desc = "A wall-mounted flashbulb device." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mflash1" + max_integrity = 250 + integrity_failure = 100 + light_color = LIGHT_COLOR_WHITE + light_power = FLASH_LIGHT_POWER + var/obj/item/assembly/flash/handheld/bulb + var/id = null + var/range = 2 //this is roughly the size of brig cell + var/last_flash = 0 //Don't want it getting spammed like regular flashes + var/strength = 100 //How knocked down targets are when flashed. + var/base_state = "mflash" + +/obj/machinery/flasher/portable //Portable version of the flasher. Only flashes when anchored + name = "portable flasher" + desc = "A portable flashing device. Wrench to activate and deactivate. Cannot detect slow movements." + icon_state = "pflash1-p" + strength = 80 + anchored = FALSE + base_state = "pflash" + density = TRUE + +/obj/machinery/flasher/Initialize(mapload, ndir = 0, built = 0) + . = ..() // ..() is EXTREMELY IMPORTANT, never forget to add it + if(built) + setDir(ndir) + pixel_x = (dir & 3)? 0 : (dir == 4 ? -28 : 28) + pixel_y = (dir & 3)? (dir ==1 ? -28 : 28) : 0 + else + bulb = new(src) + +/obj/machinery/flasher/Destroy() + QDEL_NULL(bulb) + return ..() + +/obj/machinery/flasher/power_change() + if (powered() && anchored && bulb) + stat &= ~NOPOWER + if(bulb.crit_fail) + icon_state = "[base_state]1-p" + else + icon_state = "[base_state]1" + else + stat |= NOPOWER + icon_state = "[base_state]1-p" + +//Don't want to render prison breaks impossible +/obj/machinery/flasher/attackby(obj/item/W, mob/user, params) + add_fingerprint(user) + if (istype(W, /obj/item/wirecutters)) + if (bulb) + user.visible_message("[user] begins to disconnect [src]'s flashbulb.", "You begin to disconnect [src]'s flashbulb...") + if(W.use_tool(src, user, 30, volume=50) && bulb) + user.visible_message("[user] has disconnected [src]'s flashbulb!", "You disconnect [src]'s flashbulb.") + bulb.forceMove(loc) + bulb = null + power_change() + + else if (istype(W, /obj/item/assembly/flash/handheld)) + if (!bulb) + if(!user.transferItemToLoc(W, src)) + return + user.visible_message("[user] installs [W] into [src].", "You install [W] into [src].") + bulb = W + power_change() + else + to_chat(user, "A flashbulb is already installed in [src]!") + + else if (istype(W, /obj/item/wrench)) + if(!bulb) + to_chat(user, "You start unsecuring the flasher frame...") + if(W.use_tool(src, user, 40, volume=50)) + to_chat(user, "You unsecure the flasher frame.") + deconstruct(TRUE) + else + to_chat(user, "Remove a flashbulb from [src] first!") + else + return ..() + +//Let the AI trigger them directly. +/obj/machinery/flasher/attack_ai() + if (anchored) + return flash() + +/obj/machinery/flasher/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) + if(damage_flag == "melee" && damage_amount < 10) //any melee attack below 10 dmg does nothing + return 0 + . = ..() + +/obj/machinery/flasher/proc/flash() + if (!powered() || !bulb) + return + + if (bulb.crit_fail || (last_flash && world.time < src.last_flash + 150)) + return + + if(!bulb.flash_recharge(30)) //Bulb can burn out if it's used too often too fast + power_change() + return + + playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) + flick("[base_state]_flash", src) + flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color) + last_flash = world.time + use_power(1000) + + var/flashed = FALSE + for (var/mob/living/L in viewers(src, null)) + if (get_dist(src, L) > range) + continue + + if(L.flash_act(affect_silicon = 1)) + L.Knockdown(strength) + flashed = TRUE + + if(flashed) + bulb.times_used++ + + return 1 + + +/obj/machinery/flasher/emp_act(severity) + . = ..() + if(!(stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF)) + if(bulb && prob(75/severity)) + flash() + bulb.burn_out() + power_change() + +/obj/machinery/flasher/obj_break(damage_flag) + if(!(flags_1 & NODECONSTRUCT_1)) + if(!(stat & BROKEN)) + stat |= BROKEN + if(bulb) + bulb.burn_out() + power_change() + +/obj/machinery/flasher/deconstruct(disassembled = TRUE) + if(!(flags_1 & NODECONSTRUCT_1)) + if(bulb) + bulb.forceMove(loc) + bulb = null + if(disassembled) + var/obj/item/wallframe/flasher/F = new(get_turf(src)) + transfer_fingerprints_to(F) + F.id = id + playsound(loc, 'sound/items/deconstruct.ogg', 50, 1) + else + new /obj/item/stack/sheet/metal (loc, 2) + qdel(src) + +/obj/machinery/flasher/portable/Initialize() + . = ..() + proximity_monitor = new(src, 0) + +/obj/machinery/flasher/portable/HasProximity(atom/movable/AM) + if (last_flash && world.time < last_flash + 150) + return + + if(istype(AM, /mob/living/carbon)) + var/mob/living/carbon/M = AM + if (M.m_intent != MOVE_INTENT_WALK && anchored) + flash() + +/obj/machinery/flasher/portable/attackby(obj/item/W, mob/user, params) + if (istype(W, /obj/item/wrench)) + W.play_tool_sound(src, 100) + + if (!anchored && !isinspace()) + to_chat(user, "[src] is now secured.") + add_overlay("[base_state]-s") + setAnchored(TRUE) + power_change() + proximity_monitor.SetRange(range) + else + to_chat(user, "[src] can now be moved.") + cut_overlays() + setAnchored(FALSE) + power_change() + proximity_monitor.SetRange(0) + + else + return ..() + +/obj/item/wallframe/flasher + name = "mounted flash frame" + desc = "Used for building wall-mounted flashers." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mflash_frame" + result_path = /obj/machinery/flasher + var/id = null + +/obj/item/wallframe/flasher/examine(mob/user) + . = ..() + . += "Its channel ID is '[id]'." + +/obj/item/wallframe/flasher/after_attach(var/obj/O) + ..() + var/obj/machinery/flasher/F = O + F.id = id diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index b1783ba940..40fc52d6a1 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -1,700 +1,700 @@ -/* Holograms! - * Contains: - * Holopad - * Hologram - * Other stuff - */ - -/* -Revised. Original based on space ninja hologram code. Which is also mine. /N -How it works: -AI clicks on holopad in camera view. View centers on holopad. -AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. -AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master. -Any number of AIs can use a holopad. /Lo6 -AI may cancel the hologram at any time by clicking on the holopad once more. - -Possible to do for anyone motivated enough: - Give an AI variable for different hologram icons. - Itegrate EMP effect to disable the unit. -*/ - - -/* - * Holopad - */ - -GLOBAL_LIST_EMPTY(network_holopads) - -#define HOLOPAD_PASSIVE_POWER_USAGE 1 -#define HOLOGRAM_POWER_USAGE 2 - -/obj/machinery/holopad - name = "holopad" - desc = "It's a floor-mounted device for projecting holographic images." - icon_state = "holopad0" - layer = LOW_OBJ_LAYER - plane = FLOOR_PLANE - flags_1 = HEAR_1 - use_power = IDLE_POWER_USE - idle_power_usage = 5 - active_power_usage = 100 - max_integrity = 300 - armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) - circuit = /obj/item/circuitboard/machine/holopad - var/list/masters //List of living mobs that use the holopad - var/list/holorays //Holoray-mob link. - var/last_request = 0 //to prevent request spam. ~Carn - var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. - var/temp = "" - var/list/holo_calls //array of /datum/holocalls - var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs - var/obj/item/disk/holodisk/disk //Record disk - var/replay_mode = FALSE //currently replaying a recording - var/loop_mode = FALSE //currently looping a recording - var/record_mode = FALSE //currently recording - var/record_start = 0 //recording start time - var/record_user //user that inititiated the recording - var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram - var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging - var/obj/effect/overlay/holoray/ray - var/ringing = FALSE - var/offset = FALSE - var/on_network = TRUE - -/obj/machinery/holopad/tutorial - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - flags_1 = NODECONSTRUCT_1 - on_network = FALSE - var/proximity_range = 1 - -/obj/machinery/holopad/tutorial/Initialize(mapload) - . = ..() - if(proximity_range) - proximity_monitor = new(src, proximity_range) - if(mapload) - var/obj/item/disk/holodisk/new_disk = locate(/obj/item/disk/holodisk) in src.loc - if(new_disk && !disk) - new_disk.forceMove(src) - disk = new_disk - -/obj/machinery/holopad/tutorial/attack_hand(mob/user) - if(!istype(user)) - return - if(user.incapacitated() || !is_operational()) - return - if(replay_mode) - replay_stop() - else if(disk && disk.record) - replay_start() - -/obj/machinery/holopad/tutorial/HasProximity(atom/movable/AM) - if (!isliving(AM)) - return - if(!replay_mode && (disk && disk.record)) - replay_start() - -/obj/machinery/holopad/Initialize() - . = ..() - if(on_network) - GLOB.network_holopads += src - -/obj/machinery/holopad/Destroy() - if(outgoing_call) - outgoing_call.ConnectionFailure(src) - - for(var/I in holo_calls) - var/datum/holocall/HC = I - HC.ConnectionFailure(src) - - for (var/I in masters) - clear_holo(I) - - if(replay_mode) - replay_stop() - if(record_mode) - record_stop() - - QDEL_NULL(disk) - - GLOB.network_holopads -= src - return ..() - -/obj/machinery/holopad/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= NOPOWER - if(replay_mode) - replay_stop() - if(record_mode) - record_stop() - if(outgoing_call) - outgoing_call.ConnectionFailure(src) - -/obj/machinery/holopad/obj_break() - . = ..() - if(outgoing_call) - outgoing_call.ConnectionFailure(src) - -/obj/machinery/holopad/RefreshParts() - var/holograph_range = 4 - for(var/obj/item/stock_parts/capacitor/B in component_parts) - holograph_range += 1 * B.rating - holo_range = holograph_range - -/obj/machinery/holopad/attackby(obj/item/P, mob/user, params) - if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) - return - - if(default_pry_open(P)) - return - - if(default_unfasten_wrench(user, P)) - return - - if(default_deconstruction_crowbar(P)) - return - - if(istype(P,/obj/item/disk/holodisk)) - if(disk) - to_chat(user,"There's already a disk inside [src]") - return - if (!user.transferItemToLoc(P,src)) - return - to_chat(user,"You insert [P] into [src]") - disk = P - updateDialog() - return - - return ..() - - -/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests. - . = ..() - if(!istype(user)) - return - - if(outgoing_call || user.incapacitated() || !is_operational()) - return - - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - if(on_network) - dat += "Request an AI's presence
    " - dat += "Call another holopad
    " - if(disk) - if(disk.record) - //Replay - dat += "Replay disk recording
    " - dat += "Loop disk recording
    " - //Clear - dat += "Clear disk recording
    " - else - //Record - dat += "Start new recording
    " - //Eject - dat += "Eject disk
    " - - if(LAZYLEN(holo_calls)) - dat += "=====================================================
    " - - if(on_network) - var/one_answered_call = FALSE - var/one_unanswered_call = FALSE - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad != src) - dat += "Answer call from [get_area(HC.calling_holopad)]
    " - one_unanswered_call = TRUE - else - one_answered_call = TRUE - - if(one_answered_call && one_unanswered_call) - dat += "=====================================================
    " - //we loop twice for formatting - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad == src) - dat += "Disconnect call from [HC.user]
    " - - - var/datum/browser/popup = new(user, "holopad", name, 300, 175) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -//Stop ringing the AI!! -/obj/machinery/holopad/proc/hangup_all_calls() - for(var/I in holo_calls) - var/datum/holocall/HC = I - HC.Disconnect(src) - -/obj/machinery/holopad/Topic(href, href_list) - if(..() || isAI(usr)) - return - add_fingerprint(usr) - if(!is_operational()) - return - if (href_list["AIrequest"]) - if(last_request + 200 < world.time) - last_request = world.time - temp = "You requested an AI's presence.
    " - temp += "Main Menu" - var/area/area = get_area(src) - for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs) - if(!AI.client) - continue - to_chat(AI, "Your presence is requested at \the [area].") - else - temp = "A request for AI presence was already sent recently.
    " - temp += "Main Menu" - - else if(href_list["Holocall"]) - if(outgoing_call) - return - - temp = "You must stand on the holopad to make a call!
    " - temp += "Main Menu" - if(usr.loc == loc) - var/list/callnames = list() - for(var/I in GLOB.network_holopads) - var/area/A = get_area(I) - if(A) - LAZYADD(callnames[A], I) - callnames -= get_area(src) - - var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames - if(QDELETED(usr) || !result || outgoing_call) - return - - if(usr.loc == loc) - temp = "Dialing...
    " - temp += "Main Menu" - new /datum/holocall(usr, src, callnames[result]) - - else if(href_list["connectcall"]) - var/datum/holocall/call_to_connect = locate(href_list["connectcall"]) - if(!QDELETED(call_to_connect)) - call_to_connect.Answer(src) - temp = "" - - else if(href_list["disconnectcall"]) - var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"]) - if(!QDELETED(call_to_disconnect)) - call_to_disconnect.Disconnect(src) - temp = "" - - else if(href_list["mainmenu"]) - temp = "" - if(outgoing_call) - outgoing_call.Disconnect() - - else if(href_list["disk_eject"]) - if(disk && !replay_mode) - disk.forceMove(drop_location()) - disk = null - - else if(href_list["replay_stop"]) - replay_stop() - else if(href_list["replay_start"]) - replay_start() - else if(href_list["loop_start"]) - loop_mode = TRUE - replay_start() - else if(href_list["record_start"]) - record_start(usr) - else if(href_list["record_stop"]) - record_stop() - else if(href_list["record_clear"]) - record_clear() - else if(href_list["offset"]) - offset++ - if (offset > 4) - offset = FALSE - var/turf/new_turf - if (!offset) - new_turf = get_turf(src) - else - new_turf = get_step(src, GLOB.cardinals[offset]) - replay_holo.forceMove(new_turf) - updateDialog() - -//do not allow AIs to answer calls or people will use it to meta the AI sattelite -/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user) - if (!istype(user)) - return - if (!on_network) - return - /*There are pretty much only three ways to interact here. - I don't need to check for client since they're clicking on an object. - This may change in the future but for now will suffice.*/ - if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. - user.eyeobj.setLoc(get_turf(src)) - else if(!LAZYLEN(masters) || !masters[user])//If there is no hologram, possibly make one. - activate_holo(user) - else//If there is a hologram, remove it. - clear_holo(user) - -/obj/machinery/holopad/process() - if(LAZYLEN(masters)) - for(var/I in masters) - var/mob/living/master = I - var/mob/living/silicon/ai/AI = master - if(!istype(AI)) - AI = null - - if(!is_operational() || !validate_user(master)) - clear_holo(master) - - if(outgoing_call) - outgoing_call.Check() - - ringing = FALSE - - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad != src) - if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) - HC.Answer(src) - break - if(outgoing_call) - HC.Disconnect(src)//can't answer calls while calling - else - playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring! - ringing = TRUE - - update_icon() - -/obj/machinery/holopad/proc/activate_holo(mob/living/user) - var/mob/living/silicon/ai/AI = user - if(!istype(AI)) - AI = null - - if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it - if (AI && istype(AI.current, /obj/machinery/holopad)) - to_chat(user, "ERROR: \black Image feed in progress.") - return - - var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. - if(AI) - Hologram.icon = AI.holo_icon - else //make it like real life - Hologram.icon = user.icon - Hologram.icon_state = user.icon_state - Hologram.copy_overlays(user, TRUE) - //codersprite some holo effects here - Hologram.alpha = 100 - Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) - Hologram.Impersonation = user - - Hologram.copy_known_languages_from(user,replace = TRUE) - Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. - Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. - Hologram.setAnchored(TRUE)//So space wind cannot drag it. - Hologram.name = "[user.name] (Hologram)"//If someone decides to right click. - Hologram.set_light(2) //hologram lighting - move_hologram() - - set_holo(user, Hologram) - visible_message("A holographic image of [user] flickers to life before your eyes!") - - return Hologram - else - to_chat(user, "ERROR: Unable to project hologram.") - -/*This is the proc for special two-way communication between AI and holopad/people talking near holopad. -For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) - . = ..() - if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. - for(var/mob/living/silicon/ai/master in masters) - if(masters[master] && speaker != master) - master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) - - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad == src && speaker != HC.hologram) - HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source) - - if(outgoing_call && speaker == outgoing_call.user) - outgoing_call.hologram.say(raw_message) - - if(record_mode && speaker == record_user) - record_message(speaker,raw_message,message_language) - -/obj/machinery/holopad/proc/SetLightsAndPower() - var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) - use_power = total_users > 0 ? ACTIVE_POWER_USE : IDLE_POWER_USE - active_power_usage = HOLOPAD_PASSIVE_POWER_USAGE + (HOLOGRAM_POWER_USAGE * total_users) - if(total_users || replay_mode) - set_light(2) - else - set_light(0) - update_icon() - -/obj/machinery/holopad/update_icon() - var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) - if(ringing) - icon_state = "holopad_ringing" - else if(total_users || replay_mode) - icon_state = "holopad1" - else - icon_state = "holopad0" - -/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) - LAZYSET(masters, user, h) - LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc)) - var/mob/living/silicon/ai/AI = user - if(istype(AI)) - AI.current = src - SetLightsAndPower() - update_holoray(user, get_turf(loc)) - return TRUE - -/obj/machinery/holopad/proc/clear_holo(mob/living/user) - qdel(masters[user]) // Get rid of user's hologram - unset_holo(user) - return TRUE - -/obj/machinery/holopad/proc/unset_holo(mob/living/user) - var/mob/living/silicon/ai/AI = user - if(istype(AI) && AI.current == src) - AI.current = null - LAZYREMOVE(masters, user) // Discard AI from the list of those who use holopad - qdel(holorays[user]) - LAZYREMOVE(holorays, user) - SetLightsAndPower() - return TRUE - -//Try to transfer hologram to another pad that can project on T -/obj/machinery/holopad/proc/transfer_to_nearby_pad(turf/T,mob/holo_owner) - var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner] - if(!h || h.HC) //Holocalls can't change source. - return FALSE - for(var/pad in GLOB.network_holopads) - var/obj/machinery/holopad/another = pad - if(another == src) - continue - if(another.validate_location(T)) - unset_holo(holo_owner) - if(another.masters && another.masters[holo_owner]) - another.clear_holo(holo_owner) - another.set_holo(holo_owner, h) - return TRUE - return FALSE - -/obj/machinery/holopad/proc/validate_user(mob/living/user) - if(QDELETED(user) || user.incapacitated() || !user.client) - return FALSE - return TRUE - -//Can we display holos there -//Area check instead of line of sight check because this is a called a lot if AI wants to move around. -/obj/machinery/holopad/proc/validate_location(turf/T,check_los = FALSE) - if(T.z == z && get_dist(T, src) <= holo_range && T.loc == get_area(src)) - return TRUE - else - return FALSE - -/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction) - if(LAZYLEN(masters) && masters[user]) - var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] - var/transfered = FALSE - if(!validate_location(new_turf)) - if(!transfer_to_nearby_pad(new_turf,user)) - clear_holo(user) - return FALSE - else - transfered = TRUE - //All is good. - holo.forceMove(new_turf) - if(direction) - holo.setDir(direction) - if(!transfered) - update_holoray(user,new_turf) - return TRUE - - -/obj/machinery/holopad/proc/update_holoray(mob/living/user, turf/new_turf) - var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] - var/obj/effect/overlay/holoray/ray = holorays[user] - var/disty = holo.y - ray.y - var/distx = holo.x - ray.x - var/newangle - if(!disty) - if(distx >= 0) - newangle = 90 - else - newangle = 270 - else - newangle = arctan(distx/disty) - if(disty < 0) - newangle += 180 - else if(distx < 0) - newangle += 360 - var/matrix/M = matrix() - if (get_dist(get_turf(holo),new_turf) <= 1) - animate(ray, transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle),time = 1) - else - ray.transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle) - -// RECORDED MESSAGES - -/obj/machinery/holopad/proc/setup_replay_holo(datum/holorecord/record) - var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. - Hologram.add_overlay(record.caller_image) - Hologram.alpha = 170 - Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) - Hologram.dir = SOUTH //for now - Hologram.grant_all_languages(omnitongue=TRUE) - var/datum/language_holder/holder = Hologram.get_language_holder() - holder.selected_default_language = record.language - Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. - Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. - Hologram.setAnchored(TRUE)//So space wind cannot drag it. - Hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click. - Hologram.set_light(2) //hologram lighting - visible_message("A holographic image of [record.caller_name] flickers to life before your eyes!") - return Hologram - -/obj/machinery/holopad/proc/replay_start() - if(!replay_mode) - replay_mode = TRUE - replay_holo = setup_replay_holo(disk.record) - temp = "Replaying...
    " - temp += "Change offset
    " - temp += "End replay" - SetLightsAndPower() - replay_entry(1) - return - -/obj/machinery/holopad/proc/replay_stop() - if(replay_mode) - replay_mode = FALSE - loop_mode = FALSE - offset = FALSE - temp = null - QDEL_NULL(replay_holo) - SetLightsAndPower() - updateDialog() - -/obj/machinery/holopad/proc/record_start(mob/living/user) - if(!user || !disk || disk.record) - return - disk.record = new - record_mode = TRUE - record_start = world.time - record_user = user - disk.record.set_caller_image(user) - temp = "Recording...
    " - temp += "End recording." - -/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language) - if(!record_mode) - return - //make this command so you can have multiple languages in single record - if((!disk.record.caller_name || disk.record.caller_name == "Unknown") && istype(speaker)) - disk.record.caller_name = speaker.name - if(!disk.record.language) - disk.record.language = language - else if(language != disk.record.language) - disk.record.entries += list(list(HOLORECORD_LANGUAGE,language)) - - var/current_delay = 0 - for(var/E in disk.record.entries) - var/list/entry = E - if(entry[1] != HOLORECORD_DELAY) - continue - current_delay += entry[2] - - var/time_delta = world.time - record_start - current_delay - - if(time_delta >= 1) - disk.record.entries += list(list(HOLORECORD_DELAY,time_delta)) - disk.record.entries += list(list(HOLORECORD_SAY,message)) - if(disk.record.entries.len >= HOLORECORD_MAX_LENGTH) - record_stop() - -/obj/machinery/holopad/proc/replay_entry(entry_number) - if(!replay_mode) - return - if (!disk.record.entries.len) // check for zero entries such as photographs and no text recordings - return // and pretty much just display them statically untill manually stopped - if(disk.record.entries.len < entry_number) - if(loop_mode) - entry_number = 1 - else - replay_stop() - return - var/list/entry = disk.record.entries[entry_number] - var/command = entry[1] - switch(command) - if(HOLORECORD_SAY) - var/message = entry[2] - if(replay_holo) - replay_holo.say(message) - if(HOLORECORD_SOUND) - playsound(src,entry[2],50,1) - if(HOLORECORD_DELAY) - addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2]) - return - if(HOLORECORD_LANGUAGE) - var/datum/language_holder/holder = replay_holo.get_language_holder() - holder.selected_default_language = entry[2] - if(HOLORECORD_PRESET) - var/preset_type = entry[2] - var/datum/preset_holoimage/H = new preset_type - replay_holo.cut_overlays() - replay_holo.add_overlay(H.build_image()) - if(HOLORECORD_RENAME) - replay_holo.name = entry[2] + " (Hologram)" - .(entry_number+1) - -/obj/machinery/holopad/proc/record_stop() - if(record_mode) - record_mode = FALSE - temp = null - record_user = null - updateDialog() - -/obj/machinery/holopad/proc/record_clear() - if(disk && disk.record) - QDEL_NULL(disk.record) - updateDialog() - -/obj/effect/overlay/holo_pad_hologram - var/mob/living/Impersonation - var/datum/holocall/HC - -/obj/effect/overlay/holo_pad_hologram/Destroy() - Impersonation = null - if(!QDELETED(HC)) - HC.Disconnect(HC.calling_holopad) - return ..() - -/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) - return TRUE - -/obj/effect/overlay/holo_pad_hologram/examine(mob/user) - if(Impersonation) - return Impersonation.examine(user) - return ..() - -/obj/effect/overlay/holoray - name = "holoray" - icon = 'icons/effects/96x96.dmi' - icon_state = "holoray" - layer = FLY_LAYER - density = FALSE - anchored = TRUE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - pixel_x = -32 - pixel_y = -32 - alpha = 100 - -#undef HOLOPAD_PASSIVE_POWER_USAGE -#undef HOLOGRAM_POWER_USAGE +/* Holograms! + * Contains: + * Holopad + * Hologram + * Other stuff + */ + +/* +Revised. Original based on space ninja hologram code. Which is also mine. /N +How it works: +AI clicks on holopad in camera view. View centers on holopad. +AI clicks again on the holopad to display a hologram. Hologram stays as long as AI is looking at the pad and it (the hologram) is in range of the pad. +AI can use the directional keys to move the hologram around, provided the above conditions are met and the AI in question is the holopad's master. +Any number of AIs can use a holopad. /Lo6 +AI may cancel the hologram at any time by clicking on the holopad once more. + +Possible to do for anyone motivated enough: + Give an AI variable for different hologram icons. + Itegrate EMP effect to disable the unit. +*/ + + +/* + * Holopad + */ + +GLOBAL_LIST_EMPTY(network_holopads) + +#define HOLOPAD_PASSIVE_POWER_USAGE 1 +#define HOLOGRAM_POWER_USAGE 2 + +/obj/machinery/holopad + name = "holopad" + desc = "It's a floor-mounted device for projecting holographic images." + icon_state = "holopad0" + layer = LOW_OBJ_LAYER + plane = FLOOR_PLANE + flags_1 = HEAR_1 + use_power = IDLE_POWER_USE + idle_power_usage = 5 + active_power_usage = 100 + max_integrity = 300 + armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) + circuit = /obj/item/circuitboard/machine/holopad + var/list/masters //List of living mobs that use the holopad + var/list/holorays //Holoray-mob link. + var/last_request = 0 //to prevent request spam. ~Carn + var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. + var/temp = "" + var/list/holo_calls //array of /datum/holocalls + var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs + var/obj/item/disk/holodisk/disk //Record disk + var/replay_mode = FALSE //currently replaying a recording + var/loop_mode = FALSE //currently looping a recording + var/record_mode = FALSE //currently recording + var/record_start = 0 //recording start time + var/record_user //user that inititiated the recording + var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram + var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging + var/obj/effect/overlay/holoray/ray + var/ringing = FALSE + var/offset = FALSE + var/on_network = TRUE + +/obj/machinery/holopad/tutorial + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + flags_1 = NODECONSTRUCT_1 + on_network = FALSE + var/proximity_range = 1 + +/obj/machinery/holopad/tutorial/Initialize(mapload) + . = ..() + if(proximity_range) + proximity_monitor = new(src, proximity_range) + if(mapload) + var/obj/item/disk/holodisk/new_disk = locate(/obj/item/disk/holodisk) in src.loc + if(new_disk && !disk) + new_disk.forceMove(src) + disk = new_disk + +/obj/machinery/holopad/tutorial/attack_hand(mob/user) + if(!istype(user)) + return + if(user.incapacitated() || !is_operational()) + return + if(replay_mode) + replay_stop() + else if(disk && disk.record) + replay_start() + +/obj/machinery/holopad/tutorial/HasProximity(atom/movable/AM) + if (!isliving(AM)) + return + if(!replay_mode && (disk && disk.record)) + replay_start() + +/obj/machinery/holopad/Initialize() + . = ..() + if(on_network) + GLOB.network_holopads += src + +/obj/machinery/holopad/Destroy() + if(outgoing_call) + outgoing_call.ConnectionFailure(src) + + for(var/I in holo_calls) + var/datum/holocall/HC = I + HC.ConnectionFailure(src) + + for (var/I in masters) + clear_holo(I) + + if(replay_mode) + replay_stop() + if(record_mode) + record_stop() + + QDEL_NULL(disk) + + GLOB.network_holopads -= src + return ..() + +/obj/machinery/holopad/power_change() + if (powered()) + stat &= ~NOPOWER + else + stat |= NOPOWER + if(replay_mode) + replay_stop() + if(record_mode) + record_stop() + if(outgoing_call) + outgoing_call.ConnectionFailure(src) + +/obj/machinery/holopad/obj_break() + . = ..() + if(outgoing_call) + outgoing_call.ConnectionFailure(src) + +/obj/machinery/holopad/RefreshParts() + var/holograph_range = 4 + for(var/obj/item/stock_parts/capacitor/B in component_parts) + holograph_range += 1 * B.rating + holo_range = holograph_range + +/obj/machinery/holopad/attackby(obj/item/P, mob/user, params) + if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) + return + + if(default_pry_open(P)) + return + + if(default_unfasten_wrench(user, P)) + return + + if(default_deconstruction_crowbar(P)) + return + + if(istype(P,/obj/item/disk/holodisk)) + if(disk) + to_chat(user,"There's already a disk inside [src]") + return + if (!user.transferItemToLoc(P,src)) + return + to_chat(user,"You insert [P] into [src]") + disk = P + updateDialog() + return + + return ..() + + +/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests. + . = ..() + if(!istype(user)) + return + + if(outgoing_call || user.incapacitated() || !is_operational()) + return + + user.set_machine(src) + var/dat + if(temp) + dat = temp + else + if(on_network) + dat += "Request an AI's presence
    " + dat += "Call another holopad
    " + if(disk) + if(disk.record) + //Replay + dat += "Replay disk recording
    " + dat += "Loop disk recording
    " + //Clear + dat += "Clear disk recording
    " + else + //Record + dat += "Start new recording
    " + //Eject + dat += "Eject disk
    " + + if(LAZYLEN(holo_calls)) + dat += "=====================================================
    " + + if(on_network) + var/one_answered_call = FALSE + var/one_unanswered_call = FALSE + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad != src) + dat += "Answer call from [get_area(HC.calling_holopad)]
    " + one_unanswered_call = TRUE + else + one_answered_call = TRUE + + if(one_answered_call && one_unanswered_call) + dat += "=====================================================
    " + //we loop twice for formatting + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad == src) + dat += "Disconnect call from [HC.user]
    " + + + var/datum/browser/popup = new(user, "holopad", name, 300, 175) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) + popup.open() + +//Stop ringing the AI!! +/obj/machinery/holopad/proc/hangup_all_calls() + for(var/I in holo_calls) + var/datum/holocall/HC = I + HC.Disconnect(src) + +/obj/machinery/holopad/Topic(href, href_list) + if(..() || isAI(usr)) + return + add_fingerprint(usr) + if(!is_operational()) + return + if (href_list["AIrequest"]) + if(last_request + 200 < world.time) + last_request = world.time + temp = "You requested an AI's presence.
    " + temp += "Main Menu" + var/area/area = get_area(src) + for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs) + if(!AI.client) + continue + to_chat(AI, "Your presence is requested at \the [area].") + else + temp = "A request for AI presence was already sent recently.
    " + temp += "Main Menu" + + else if(href_list["Holocall"]) + if(outgoing_call) + return + + temp = "You must stand on the holopad to make a call!
    " + temp += "Main Menu" + if(usr.loc == loc) + var/list/callnames = list() + for(var/I in GLOB.network_holopads) + var/area/A = get_area(I) + if(A) + LAZYADD(callnames[A], I) + callnames -= get_area(src) + + var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames + if(QDELETED(usr) || !result || outgoing_call) + return + + if(usr.loc == loc) + temp = "Dialing...
    " + temp += "Main Menu" + new /datum/holocall(usr, src, callnames[result]) + + else if(href_list["connectcall"]) + var/datum/holocall/call_to_connect = locate(href_list["connectcall"]) + if(!QDELETED(call_to_connect)) + call_to_connect.Answer(src) + temp = "" + + else if(href_list["disconnectcall"]) + var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"]) + if(!QDELETED(call_to_disconnect)) + call_to_disconnect.Disconnect(src) + temp = "" + + else if(href_list["mainmenu"]) + temp = "" + if(outgoing_call) + outgoing_call.Disconnect() + + else if(href_list["disk_eject"]) + if(disk && !replay_mode) + disk.forceMove(drop_location()) + disk = null + + else if(href_list["replay_stop"]) + replay_stop() + else if(href_list["replay_start"]) + replay_start() + else if(href_list["loop_start"]) + loop_mode = TRUE + replay_start() + else if(href_list["record_start"]) + record_start(usr) + else if(href_list["record_stop"]) + record_stop() + else if(href_list["record_clear"]) + record_clear() + else if(href_list["offset"]) + offset++ + if (offset > 4) + offset = FALSE + var/turf/new_turf + if (!offset) + new_turf = get_turf(src) + else + new_turf = get_step(src, GLOB.cardinals[offset]) + replay_holo.forceMove(new_turf) + updateDialog() + +//do not allow AIs to answer calls or people will use it to meta the AI sattelite +/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user) + if (!istype(user)) + return + if (!on_network) + return + /*There are pretty much only three ways to interact here. + I don't need to check for client since they're clicking on an object. + This may change in the future but for now will suffice.*/ + if(user.eyeobj.loc != src.loc)//Set client eye on the object if it's not already. + user.eyeobj.setLoc(get_turf(src)) + else if(!LAZYLEN(masters) || !masters[user])//If there is no hologram, possibly make one. + activate_holo(user) + else//If there is a hologram, remove it. + clear_holo(user) + +/obj/machinery/holopad/process() + if(LAZYLEN(masters)) + for(var/I in masters) + var/mob/living/master = I + var/mob/living/silicon/ai/AI = master + if(!istype(AI)) + AI = null + + if(!is_operational() || !validate_user(master)) + clear_holo(master) + + if(outgoing_call) + outgoing_call.Check() + + ringing = FALSE + + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad != src) + if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) + HC.Answer(src) + break + if(outgoing_call) + HC.Disconnect(src)//can't answer calls while calling + else + playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring! + ringing = TRUE + + update_icon() + +/obj/machinery/holopad/proc/activate_holo(mob/living/user) + var/mob/living/silicon/ai/AI = user + if(!istype(AI)) + AI = null + + if(is_operational() && (!AI || AI.eyeobj.loc == loc))//If the projector has power and client eye is on it + if (AI && istype(AI.current, /obj/machinery/holopad)) + to_chat(user, "ERROR: \black Image feed in progress.") + return + + var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. + if(AI) + Hologram.icon = AI.holo_icon + else //make it like real life + Hologram.icon = user.icon + Hologram.icon_state = user.icon_state + Hologram.copy_overlays(user, TRUE) + //codersprite some holo effects here + Hologram.alpha = 100 + Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) + Hologram.Impersonation = user + + Hologram.copy_known_languages_from(user,replace = TRUE) + Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. + Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + Hologram.setAnchored(TRUE)//So space wind cannot drag it. + Hologram.name = "[user.name] (Hologram)"//If someone decides to right click. + Hologram.set_light(2) //hologram lighting + move_hologram() + + set_holo(user, Hologram) + visible_message("A holographic image of [user] flickers to life before your eyes!") + + return Hologram + else + to_chat(user, "ERROR: Unable to project hologram.") + +/*This is the proc for special two-way communication between AI and holopad/people talking near holopad. +For the other part of the code, check silicon say.dm. Particularly robot talk.*/ +/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) + . = ..() + if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. + for(var/mob/living/silicon/ai/master in masters) + if(masters[master] && speaker != master) + master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + + for(var/I in holo_calls) + var/datum/holocall/HC = I + if(HC.connected_holopad == src && speaker != HC.hologram) + HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source) + + if(outgoing_call && speaker == outgoing_call.user) + outgoing_call.hologram.say(raw_message) + + if(record_mode && speaker == record_user) + record_message(speaker,raw_message,message_language) + +/obj/machinery/holopad/proc/SetLightsAndPower() + var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) + use_power = total_users > 0 ? ACTIVE_POWER_USE : IDLE_POWER_USE + active_power_usage = HOLOPAD_PASSIVE_POWER_USAGE + (HOLOGRAM_POWER_USAGE * total_users) + if(total_users || replay_mode) + set_light(2) + else + set_light(0) + update_icon() + +/obj/machinery/holopad/update_icon() + var/total_users = LAZYLEN(masters) + LAZYLEN(holo_calls) + if(ringing) + icon_state = "holopad_ringing" + else if(total_users || replay_mode) + icon_state = "holopad1" + else + icon_state = "holopad0" + +/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) + LAZYSET(masters, user, h) + LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc)) + var/mob/living/silicon/ai/AI = user + if(istype(AI)) + AI.current = src + SetLightsAndPower() + update_holoray(user, get_turf(loc)) + return TRUE + +/obj/machinery/holopad/proc/clear_holo(mob/living/user) + qdel(masters[user]) // Get rid of user's hologram + unset_holo(user) + return TRUE + +/obj/machinery/holopad/proc/unset_holo(mob/living/user) + var/mob/living/silicon/ai/AI = user + if(istype(AI) && AI.current == src) + AI.current = null + LAZYREMOVE(masters, user) // Discard AI from the list of those who use holopad + qdel(holorays[user]) + LAZYREMOVE(holorays, user) + SetLightsAndPower() + return TRUE + +//Try to transfer hologram to another pad that can project on T +/obj/machinery/holopad/proc/transfer_to_nearby_pad(turf/T,mob/holo_owner) + var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner] + if(!h || h.HC) //Holocalls can't change source. + return FALSE + for(var/pad in GLOB.network_holopads) + var/obj/machinery/holopad/another = pad + if(another == src) + continue + if(another.validate_location(T)) + unset_holo(holo_owner) + if(another.masters && another.masters[holo_owner]) + another.clear_holo(holo_owner) + another.set_holo(holo_owner, h) + return TRUE + return FALSE + +/obj/machinery/holopad/proc/validate_user(mob/living/user) + if(QDELETED(user) || user.incapacitated() || !user.client) + return FALSE + return TRUE + +//Can we display holos there +//Area check instead of line of sight check because this is a called a lot if AI wants to move around. +/obj/machinery/holopad/proc/validate_location(turf/T,check_los = FALSE) + if(T.z == z && get_dist(T, src) <= holo_range && T.loc == get_area(src)) + return TRUE + else + return FALSE + +/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction) + if(LAZYLEN(masters) && masters[user]) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/transfered = FALSE + if(!validate_location(new_turf)) + if(!transfer_to_nearby_pad(new_turf,user)) + clear_holo(user) + return FALSE + else + transfered = TRUE + //All is good. + holo.forceMove(new_turf) + if(direction) + holo.setDir(direction) + if(!transfered) + update_holoray(user,new_turf) + return TRUE + + +/obj/machinery/holopad/proc/update_holoray(mob/living/user, turf/new_turf) + var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] + var/obj/effect/overlay/holoray/ray = holorays[user] + var/disty = holo.y - ray.y + var/distx = holo.x - ray.x + var/newangle + if(!disty) + if(distx >= 0) + newangle = 90 + else + newangle = 270 + else + newangle = arctan(distx/disty) + if(disty < 0) + newangle += 180 + else if(distx < 0) + newangle += 360 + var/matrix/M = matrix() + if (get_dist(get_turf(holo),new_turf) <= 1) + animate(ray, transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle),time = 1) + else + ray.transform = turn(M.Scale(1,sqrt(distx*distx+disty*disty)),newangle) + +// RECORDED MESSAGES + +/obj/machinery/holopad/proc/setup_replay_holo(datum/holorecord/record) + var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location. + Hologram.add_overlay(record.caller_image) + Hologram.alpha = 170 + Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) + Hologram.dir = SOUTH //for now + Hologram.grant_all_languages(omnitongue=TRUE) + var/datum/language_holder/holder = Hologram.get_language_holder() + holder.selected_default_language = record.language + Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it. + Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + Hologram.setAnchored(TRUE)//So space wind cannot drag it. + Hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click. + Hologram.set_light(2) //hologram lighting + visible_message("A holographic image of [record.caller_name] flickers to life before your eyes!") + return Hologram + +/obj/machinery/holopad/proc/replay_start() + if(!replay_mode) + replay_mode = TRUE + replay_holo = setup_replay_holo(disk.record) + temp = "Replaying...
    " + temp += "Change offset
    " + temp += "End replay" + SetLightsAndPower() + replay_entry(1) + return + +/obj/machinery/holopad/proc/replay_stop() + if(replay_mode) + replay_mode = FALSE + loop_mode = FALSE + offset = FALSE + temp = null + QDEL_NULL(replay_holo) + SetLightsAndPower() + updateDialog() + +/obj/machinery/holopad/proc/record_start(mob/living/user) + if(!user || !disk || disk.record) + return + disk.record = new + record_mode = TRUE + record_start = world.time + record_user = user + disk.record.set_caller_image(user) + temp = "Recording...
    " + temp += "End recording." + +/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language) + if(!record_mode) + return + //make this command so you can have multiple languages in single record + if((!disk.record.caller_name || disk.record.caller_name == "Unknown") && istype(speaker)) + disk.record.caller_name = speaker.name + if(!disk.record.language) + disk.record.language = language + else if(language != disk.record.language) + disk.record.entries += list(list(HOLORECORD_LANGUAGE,language)) + + var/current_delay = 0 + for(var/E in disk.record.entries) + var/list/entry = E + if(entry[1] != HOLORECORD_DELAY) + continue + current_delay += entry[2] + + var/time_delta = world.time - record_start - current_delay + + if(time_delta >= 1) + disk.record.entries += list(list(HOLORECORD_DELAY,time_delta)) + disk.record.entries += list(list(HOLORECORD_SAY,message)) + if(disk.record.entries.len >= HOLORECORD_MAX_LENGTH) + record_stop() + +/obj/machinery/holopad/proc/replay_entry(entry_number) + if(!replay_mode) + return + if (!disk.record.entries.len) // check for zero entries such as photographs and no text recordings + return // and pretty much just display them statically untill manually stopped + if(disk.record.entries.len < entry_number) + if(loop_mode) + entry_number = 1 + else + replay_stop() + return + var/list/entry = disk.record.entries[entry_number] + var/command = entry[1] + switch(command) + if(HOLORECORD_SAY) + var/message = entry[2] + if(replay_holo) + replay_holo.say(message) + if(HOLORECORD_SOUND) + playsound(src,entry[2],50,1) + if(HOLORECORD_DELAY) + addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2]) + return + if(HOLORECORD_LANGUAGE) + var/datum/language_holder/holder = replay_holo.get_language_holder() + holder.selected_default_language = entry[2] + if(HOLORECORD_PRESET) + var/preset_type = entry[2] + var/datum/preset_holoimage/H = new preset_type + replay_holo.cut_overlays() + replay_holo.add_overlay(H.build_image()) + if(HOLORECORD_RENAME) + replay_holo.name = entry[2] + " (Hologram)" + .(entry_number+1) + +/obj/machinery/holopad/proc/record_stop() + if(record_mode) + record_mode = FALSE + temp = null + record_user = null + updateDialog() + +/obj/machinery/holopad/proc/record_clear() + if(disk && disk.record) + QDEL_NULL(disk.record) + updateDialog() + +/obj/effect/overlay/holo_pad_hologram + var/mob/living/Impersonation + var/datum/holocall/HC + +/obj/effect/overlay/holo_pad_hologram/Destroy() + Impersonation = null + if(!QDELETED(HC)) + HC.Disconnect(HC.calling_holopad) + return ..() + +/obj/effect/overlay/holo_pad_hologram/Process_Spacemove(movement_dir = 0) + return TRUE + +/obj/effect/overlay/holo_pad_hologram/examine(mob/user) + if(Impersonation) + return Impersonation.examine(user) + return ..() + +/obj/effect/overlay/holoray + name = "holoray" + icon = 'icons/effects/96x96.dmi' + icon_state = "holoray" + layer = FLY_LAYER + density = FALSE + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + pixel_x = -32 + pixel_y = -32 + alpha = 100 + +#undef HOLOPAD_PASSIVE_POWER_USAGE +#undef HOLOGRAM_POWER_USAGE diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index acc0505256..099b51db82 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -1,137 +1,137 @@ -/obj/machinery/igniter - name = "igniter" - desc = "It's useful for igniting plasma." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "igniter0" - plane = FLOOR_PLANE - use_power = IDLE_POWER_USE - idle_power_usage = 2 - active_power_usage = 4 - max_integrity = 300 - armor = list("melee" = 50, "bullet" = 30, "laser" = 70, "energy" = 50, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) - resistance_flags = FIRE_PROOF - var/id = null - var/on = FALSE - -/obj/machinery/igniter/incinerator_toxmix - id = INCINERATOR_TOXMIX_IGNITER - -/obj/machinery/igniter/incinerator_atmos - id = INCINERATOR_ATMOS_IGNITER - -/obj/machinery/igniter/incinerator_syndicatelava - id = INCINERATOR_SYNDICATELAVA_IGNITER - -/obj/machinery/igniter/on - on = TRUE - icon_state = "igniter1" - -/obj/machinery/igniter/attack_hand(mob/user) - . = ..() - if(.) - return - add_fingerprint(user) - - use_power(50) - on = !( on ) - icon_state = "igniter[on]" - -/obj/machinery/igniter/process() //ugh why is this even in process()? - if (src.on && !(stat & NOPOWER) ) - var/turf/location = src.loc - if (isturf(location)) - location.hotspot_expose(700,10,1) - return 1 - -/obj/machinery/igniter/Initialize() - . = ..() - icon_state = "igniter[on]" - -/obj/machinery/igniter/power_change() - if(!( stat & NOPOWER) ) - icon_state = "igniter[src.on]" - else - icon_state = "igniter0" - -// Wall mounted remote-control igniter. - -/obj/machinery/sparker - name = "mounted igniter" - desc = "A wall-mounted ignition device." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "migniter" - resistance_flags = FIRE_PROOF - var/id = null - var/disable = 0 - var/last_spark = 0 - var/base_state = "migniter" - var/datum/effect_system/spark_spread/spark_system - -/obj/machinery/sparker/toxmix - id = INCINERATOR_TOXMIX_IGNITER - -/obj/machinery/sparker/Initialize() - . = ..() - spark_system = new /datum/effect_system/spark_spread - spark_system.set_up(2, 1, src) - spark_system.attach(src) - -/obj/machinery/sparker/Destroy() - QDEL_NULL(spark_system) - return ..() - -/obj/machinery/sparker/power_change() - if ( powered() && disable == 0 ) - stat &= ~NOPOWER - icon_state = "[base_state]" -// src.sd_SetLuminosity(2) - else - stat |= ~NOPOWER - icon_state = "[base_state]-p" -// src.sd_SetLuminosity(0) - -/obj/machinery/sparker/attackby(obj/item/W, mob/user, params) - if (istype(W, /obj/item/screwdriver)) - add_fingerprint(user) - src.disable = !src.disable - if (src.disable) - user.visible_message("[user] has disabled \the [src]!", "You disable the connection to \the [src].") - icon_state = "[base_state]-d" - if (!src.disable) - user.visible_message("[user] has reconnected \the [src]!", "You fix the connection to \the [src].") - if(src.powered()) - icon_state = "[base_state]" - else - icon_state = "[base_state]-p" - else - return ..() - -/obj/machinery/sparker/attack_ai() - if (anchored) - return src.ignite() - else - return - -/obj/machinery/sparker/proc/ignite() - if (!(powered())) - return - - if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50)) - return - - - flick("[base_state]-spark", src) - spark_system.start() - last_spark = world.time - use_power(1000) - var/turf/location = src.loc - if (isturf(location)) - location.hotspot_expose(1000,100,1) - return 1 - -/obj/machinery/sparker/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(!(stat & (BROKEN|NOPOWER))) - ignite() +/obj/machinery/igniter + name = "igniter" + desc = "It's useful for igniting plasma." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "igniter0" + plane = FLOOR_PLANE + use_power = IDLE_POWER_USE + idle_power_usage = 2 + active_power_usage = 4 + max_integrity = 300 + armor = list("melee" = 50, "bullet" = 30, "laser" = 70, "energy" = 50, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) + resistance_flags = FIRE_PROOF + var/id = null + var/on = FALSE + +/obj/machinery/igniter/incinerator_toxmix + id = INCINERATOR_TOXMIX_IGNITER + +/obj/machinery/igniter/incinerator_atmos + id = INCINERATOR_ATMOS_IGNITER + +/obj/machinery/igniter/incinerator_syndicatelava + id = INCINERATOR_SYNDICATELAVA_IGNITER + +/obj/machinery/igniter/on + on = TRUE + icon_state = "igniter1" + +/obj/machinery/igniter/attack_hand(mob/user) + . = ..() + if(.) + return + add_fingerprint(user) + + use_power(50) + on = !( on ) + icon_state = "igniter[on]" + +/obj/machinery/igniter/process() //ugh why is this even in process()? + if (src.on && !(stat & NOPOWER) ) + var/turf/location = src.loc + if (isturf(location)) + location.hotspot_expose(700,10,1) + return 1 + +/obj/machinery/igniter/Initialize() + . = ..() + icon_state = "igniter[on]" + +/obj/machinery/igniter/power_change() + if(!( stat & NOPOWER) ) + icon_state = "igniter[src.on]" + else + icon_state = "igniter0" + +// Wall mounted remote-control igniter. + +/obj/machinery/sparker + name = "mounted igniter" + desc = "A wall-mounted ignition device." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "migniter" + resistance_flags = FIRE_PROOF + var/id = null + var/disable = 0 + var/last_spark = 0 + var/base_state = "migniter" + var/datum/effect_system/spark_spread/spark_system + +/obj/machinery/sparker/toxmix + id = INCINERATOR_TOXMIX_IGNITER + +/obj/machinery/sparker/Initialize() + . = ..() + spark_system = new /datum/effect_system/spark_spread + spark_system.set_up(2, 1, src) + spark_system.attach(src) + +/obj/machinery/sparker/Destroy() + QDEL_NULL(spark_system) + return ..() + +/obj/machinery/sparker/power_change() + if ( powered() && disable == 0 ) + stat &= ~NOPOWER + icon_state = "[base_state]" +// src.sd_SetLuminosity(2) + else + stat |= ~NOPOWER + icon_state = "[base_state]-p" +// src.sd_SetLuminosity(0) + +/obj/machinery/sparker/attackby(obj/item/W, mob/user, params) + if (istype(W, /obj/item/screwdriver)) + add_fingerprint(user) + src.disable = !src.disable + if (src.disable) + user.visible_message("[user] has disabled \the [src]!", "You disable the connection to \the [src].") + icon_state = "[base_state]-d" + if (!src.disable) + user.visible_message("[user] has reconnected \the [src]!", "You fix the connection to \the [src].") + if(src.powered()) + icon_state = "[base_state]" + else + icon_state = "[base_state]-p" + else + return ..() + +/obj/machinery/sparker/attack_ai() + if (anchored) + return src.ignite() + else + return + +/obj/machinery/sparker/proc/ignite() + if (!(powered())) + return + + if ((src.disable) || (src.last_spark && world.time < src.last_spark + 50)) + return + + + flick("[base_state]-spark", src) + spark_system.start() + last_spark = world.time + use_power(1000) + var/turf/location = src.loc + if (isturf(location)) + location.hotspot_expose(1000,100,1) + return 1 + +/obj/machinery/sparker/emp_act(severity) + . = ..() + if (. & EMP_PROTECT_SELF) + return + if(!(stat & (BROKEN|NOPOWER))) + ignite() diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 2a4b903906..e14033a959 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -1,67 +1,67 @@ -// the light switch -// can have multiple per area -// can also operate on non-loc area through "otherarea" var -/obj/machinery/light_switch - name = "light switch" - icon = 'icons/obj/power.dmi' - icon_state = "light1" - desc = "Make dark." - var/on = TRUE - var/area/area = null - var/otherarea = null - -/obj/machinery/light_switch/Initialize() - . = ..() - area = get_area(src) - - if(otherarea) - area = locate(text2path("/area/[otherarea]")) - - if(!name) - name = "light switch ([area.name])" - - on = area.lightswitch - update_icon() - -/obj/machinery/light_switch/update_icon() - if(stat & NOPOWER) - icon_state = "light-p" - else - if(on) - icon_state = "light1" - else - icon_state = "light0" - -/obj/machinery/light_switch/examine(mob/user) - . = ..() - . += "It is [on? "on" : "off"]." - -/obj/machinery/light_switch/interact(mob/user) - . = ..() - on = !on - - area.lightswitch = on - area.update_icon() - - for(var/obj/machinery/light_switch/L in area) - L.on = on - L.update_icon() - - area.power_change() - -/obj/machinery/light_switch/power_change() - - if(!otherarea) - if(powered(LIGHT)) - stat &= ~NOPOWER - else - stat |= NOPOWER - - update_icon() - -/obj/machinery/light_switch/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(!(stat & (BROKEN|NOPOWER))) - power_change() +// the light switch +// can have multiple per area +// can also operate on non-loc area through "otherarea" var +/obj/machinery/light_switch + name = "light switch" + icon = 'icons/obj/power.dmi' + icon_state = "light1" + desc = "Make dark." + var/on = TRUE + var/area/area = null + var/otherarea = null + +/obj/machinery/light_switch/Initialize() + . = ..() + area = get_area(src) + + if(otherarea) + area = locate(text2path("/area/[otherarea]")) + + if(!name) + name = "light switch ([area.name])" + + on = area.lightswitch + update_icon() + +/obj/machinery/light_switch/update_icon() + if(stat & NOPOWER) + icon_state = "light-p" + else + if(on) + icon_state = "light1" + else + icon_state = "light0" + +/obj/machinery/light_switch/examine(mob/user) + . = ..() + . += "It is [on? "on" : "off"]." + +/obj/machinery/light_switch/interact(mob/user) + . = ..() + on = !on + + area.lightswitch = on + area.update_icon() + + for(var/obj/machinery/light_switch/L in area) + L.on = on + L.update_icon() + + area.power_change() + +/obj/machinery/light_switch/power_change() + + if(!otherarea) + if(powered(LIGHT)) + stat &= ~NOPOWER + else + stat |= NOPOWER + + update_icon() + +/obj/machinery/light_switch/emp_act(severity) + . = ..() + if (. & EMP_PROTECT_SELF) + return + if(!(stat & (BROKEN|NOPOWER))) + power_change() diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 370621e0c8..9a10ede1ac 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -1,380 +1,380 @@ -// Magnetic attractor, creates variable magnetic fields and attraction. -// Can also be used to emit electron/proton beams to create a center of magnetism on another tile - -// tl;dr: it's magnets lol -// This was created for firing ranges, but I suppose this could have other applications - Doohl - -/obj/machinery/magnetic_module - icon = 'icons/obj/objects.dmi' - icon_state = "floor_magnet-f" - name = "electromagnetic generator" - desc = "A device that uses station power to create points of magnetic energy." - level = 1 // underfloor - layer = LOW_OBJ_LAYER - use_power = IDLE_POWER_USE - idle_power_usage = 50 - - var/freq = FREQ_MAGNETS // radio frequency - var/electricity_level = 1 // intensity of the magnetic pull - var/magnetic_field = 1 // the range of magnetic attraction - var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something - var/turf/center // the center of magnetic attraction - var/on = FALSE - var/magneting = FALSE - - // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down - var/center_x = 0 - var/center_y = 0 - var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer - -/obj/machinery/magnetic_module/Initialize() - ..() - var/turf/T = loc - hide(T.intact) - center = T - SSradio.add_object(src, freq, RADIO_MAGNETS) - return INITIALIZE_HINT_LATELOAD - -/obj/machinery/magnetic_module/LateInitialize() - magnetic_process() - -/obj/machinery/magnetic_module/Destroy() - SSradio.remove_object(src, freq) - center = null - return ..() - -// update the invisibility and icon -/obj/machinery/magnetic_module/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - update_icon() - -// update the icon_state -/obj/machinery/magnetic_module/update_icon() - var/state="floor_magnet" - var/onstate="" - if(!on) - onstate="0" - - if(invisibility) - icon_state = "[state][onstate]-f" // if invisible, set icon to faded version - // in case of being revealed by T-scanner - else - icon_state = "[state][onstate]" - -/obj/machinery/magnetic_module/receive_signal(datum/signal/signal) - - var/command = signal.data["command"] - var/modifier = signal.data["modifier"] - var/signal_code = signal.data["code"] - if(command && (signal_code == code)) - - Cmd(command, modifier) - - - -/obj/machinery/magnetic_module/proc/Cmd(command, modifier) - - if(command) - switch(command) - if("set-electriclevel") - if(modifier) - electricity_level = modifier - if("set-magneticfield") - if(modifier) - magnetic_field = modifier - - if("add-elec") - electricity_level++ - if(electricity_level > 12) - electricity_level = 12 - if("sub-elec") - electricity_level-- - if(electricity_level <= 0) - electricity_level = 1 - if("add-mag") - magnetic_field++ - if(magnetic_field > 4) - magnetic_field = 4 - if("sub-mag") - magnetic_field-- - if(magnetic_field <= 0) - magnetic_field = 1 - - if("set-x") - if(modifier) - center_x = modifier - if("set-y") - if(modifier) - center_y = modifier - - if("N") // NORTH - center_y++ - if("S") // SOUTH - center_y-- - if("E") // EAST - center_x++ - if("W") // WEST - center_x-- - if("C") // CENTER - center_x = 0 - center_y = 0 - if("R") // RANDOM - center_x = rand(-max_dist, max_dist) - center_y = rand(-max_dist, max_dist) - - if("set-code") - if(modifier) - code = modifier - if("toggle-power") - on = !on - - if(on) - INVOKE_ASYNC(src, .proc/magnetic_process) - - - -/obj/machinery/magnetic_module/process() - if(stat & NOPOWER) - on = FALSE - - // Sanity checks: - if(electricity_level <= 0) - electricity_level = 1 - if(magnetic_field <= 0) - magnetic_field = 1 - - - // Limitations: - if(abs(center_x) > max_dist) - center_x = max_dist - if(abs(center_y) > max_dist) - center_y = max_dist - if(magnetic_field > 4) - magnetic_field = 4 - if(electricity_level > 12) - electricity_level = 12 - - // Update power usage: - if(on) - use_power = ACTIVE_POWER_USE - active_power_usage = electricity_level*15 - else - use_power = NO_POWER_USE - - update_icon() - - -/obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the magneting - if(magneting) - return - while(on) - - magneting = TRUE - center = locate(x+center_x, y+center_y, z) - if(center) - for(var/obj/M in orange(magnetic_field, center)) - if(!M.anchored && (M.flags_1 & CONDUCT_1)) - step_towards(M, center) - - for(var/mob/living/silicon/S in orange(magnetic_field, center)) - if(isAI(S)) - continue - step_towards(S, center) - - use_power(electricity_level * 5) - sleep(13 - electricity_level) - - magneting = FALSE - - - - -/obj/machinery/magnetic_controller - name = "magnetic control console" - icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! - icon_state = "airlock_control_standby" - density = FALSE - use_power = IDLE_POWER_USE - idle_power_usage = 45 - var/frequency = FREQ_MAGNETS - var/code = 0 - var/list/magnets = list() - var/title = "Magnetic Control Console" - var/autolink = 0 // if set to 1, can't probe for other magnets! - - var/pathpos = 1 // position in the path - var/path = "w;e;e;w;s;n;n;s" // text path of the magnet - var/speed = 1 // lowest = 1, highest = 10 - var/list/rpath = list() // real path of the magnet, used in iterator - - var/moving = 0 // 1 if scheduled to loop - var/looping = 0 // 1 if looping - - var/datum/radio_frequency/radio_connection - - -/obj/machinery/magnetic_controller/Initialize() - . = ..() - if(autolink) - for(var/obj/machinery/magnetic_module/M in GLOB.machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - - if(path) // check for default path - filter_path() // renders rpath - radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS) - -/obj/machinery/magnetic_controller/Destroy() - SSradio.remove_object(src, frequency) - magnets = null - rpath = null - return ..() - -/obj/machinery/magnetic_controller/process() - if(magnets.len == 0 && autolink) - for(var/obj/machinery/magnetic_module/M in GLOB.machines) - if(M.freq == frequency && M.code == code) - magnets.Add(M) - -/obj/machinery/magnetic_controller/ui_interact(mob/user) - . = ..() - var/dat = "Magnetic Control Console

    " - if(!autolink) - dat += {" - Frequency: [frequency]
    - Code: [code]
    - Probe Generators
    - "} - - if(magnets.len >= 1) - - dat += "Magnets confirmed:
    " - var/i = 0 - for(var/obj/machinery/magnetic_module/M in magnets) - i++ - dat += "     < \[[i]\] ([M.on ? "On":"Off"]) | Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
    " - - dat += "
    Speed: - [speed] +
    " - dat += "Path: {[path]}
    " - dat += "Moving: [moving ? "Enabled":"Disabled"]" - - - user << browse(dat, "window=magnet;size=400x500") - onclose(user, "magnet") - -/obj/machinery/magnetic_controller/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - - if(href_list["radio-op"]) - - // Prepare signal beforehand, because this is a radio operation - var/datum/signal/signal = new(list("code" = code)) - - // Apply any necessary commands - switch(href_list["radio-op"]) - if("togglepower") - signal.data["command"] = "toggle-power" - - if("minuselec") - signal.data["command"] = "sub-elec" - if("pluselec") - signal.data["command"] = "add-elec" - - if("minusmag") - signal.data["command"] = "sub-mag" - if("plusmag") - signal.data["command"] = "add-mag" - - - // Broadcast the signal - - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - spawn(1) - updateUsrDialog() // pretty sure this increases responsiveness - - if(href_list["operation"]) - switch(href_list["operation"]) - if("plusspeed") - speed ++ - if(speed > 10) - speed = 10 - if("minusspeed") - speed -- - if(speed <= 0) - speed = 1 - if("setpath") - var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) - if(newpath && newpath != "") - moving = 0 // stop moving - path = newpath - pathpos = 1 // reset position - filter_path() // renders rpath - - if("togglemoving") - moving = !moving - if(moving) - spawn() MagnetMove() - - - updateUsrDialog() - -/obj/machinery/magnetic_controller/proc/MagnetMove() - if(looping) - return - - while(moving && rpath.len >= 1) - - if(stat & (BROKEN|NOPOWER)) - break - - looping = 1 - - // Prepare the radio signal - var/datum/signal/signal = new(list("code" = code)) - - if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! - pathpos = 1 - - var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive - - if(!(nextmove in list("N","S","E","W","C","R"))) - // N, S, E, W are directional - // C is center - // R is random (in magnetic field's bounds) - qdel(signal) - break // break the loop if the character located is invalid - - signal.data["command"] = nextmove - - - pathpos++ // increase iterator - - // Broadcast the signal - spawn() - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) - - if(speed == 10) - sleep(1) - else - sleep(12-speed) - - looping = 0 - - -/obj/machinery/magnetic_controller/proc/filter_path() - // Generates the rpath variable using the path string, think of this as "string2list" - // Doesn't use params2list() because of the akward way it stacks entities - rpath = list() // clear rpath - var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length - - for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path - - var/nextchar = copytext(path, i, i+1) // find next character - - if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore - rpath += copytext(path, i, i+1) // else, add to list - - // there doesn't HAVE to be separators but it makes paths syntatically visible +// Magnetic attractor, creates variable magnetic fields and attraction. +// Can also be used to emit electron/proton beams to create a center of magnetism on another tile + +// tl;dr: it's magnets lol +// This was created for firing ranges, but I suppose this could have other applications - Doohl + +/obj/machinery/magnetic_module + icon = 'icons/obj/objects.dmi' + icon_state = "floor_magnet-f" + name = "electromagnetic generator" + desc = "A device that uses station power to create points of magnetic energy." + level = 1 // underfloor + layer = LOW_OBJ_LAYER + use_power = IDLE_POWER_USE + idle_power_usage = 50 + + var/freq = FREQ_MAGNETS // radio frequency + var/electricity_level = 1 // intensity of the magnetic pull + var/magnetic_field = 1 // the range of magnetic attraction + var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something + var/turf/center // the center of magnetic attraction + var/on = FALSE + var/magneting = FALSE + + // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down + var/center_x = 0 + var/center_y = 0 + var/max_dist = 20 // absolute value of center_x,y cannot exceed this integer + +/obj/machinery/magnetic_module/Initialize() + ..() + var/turf/T = loc + hide(T.intact) + center = T + SSradio.add_object(src, freq, RADIO_MAGNETS) + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/magnetic_module/LateInitialize() + magnetic_process() + +/obj/machinery/magnetic_module/Destroy() + SSradio.remove_object(src, freq) + center = null + return ..() + +// update the invisibility and icon +/obj/machinery/magnetic_module/hide(intact) + invisibility = intact ? INVISIBILITY_MAXIMUM : 0 + update_icon() + +// update the icon_state +/obj/machinery/magnetic_module/update_icon() + var/state="floor_magnet" + var/onstate="" + if(!on) + onstate="0" + + if(invisibility) + icon_state = "[state][onstate]-f" // if invisible, set icon to faded version + // in case of being revealed by T-scanner + else + icon_state = "[state][onstate]" + +/obj/machinery/magnetic_module/receive_signal(datum/signal/signal) + + var/command = signal.data["command"] + var/modifier = signal.data["modifier"] + var/signal_code = signal.data["code"] + if(command && (signal_code == code)) + + Cmd(command, modifier) + + + +/obj/machinery/magnetic_module/proc/Cmd(command, modifier) + + if(command) + switch(command) + if("set-electriclevel") + if(modifier) + electricity_level = modifier + if("set-magneticfield") + if(modifier) + magnetic_field = modifier + + if("add-elec") + electricity_level++ + if(electricity_level > 12) + electricity_level = 12 + if("sub-elec") + electricity_level-- + if(electricity_level <= 0) + electricity_level = 1 + if("add-mag") + magnetic_field++ + if(magnetic_field > 4) + magnetic_field = 4 + if("sub-mag") + magnetic_field-- + if(magnetic_field <= 0) + magnetic_field = 1 + + if("set-x") + if(modifier) + center_x = modifier + if("set-y") + if(modifier) + center_y = modifier + + if("N") // NORTH + center_y++ + if("S") // SOUTH + center_y-- + if("E") // EAST + center_x++ + if("W") // WEST + center_x-- + if("C") // CENTER + center_x = 0 + center_y = 0 + if("R") // RANDOM + center_x = rand(-max_dist, max_dist) + center_y = rand(-max_dist, max_dist) + + if("set-code") + if(modifier) + code = modifier + if("toggle-power") + on = !on + + if(on) + INVOKE_ASYNC(src, .proc/magnetic_process) + + + +/obj/machinery/magnetic_module/process() + if(stat & NOPOWER) + on = FALSE + + // Sanity checks: + if(electricity_level <= 0) + electricity_level = 1 + if(magnetic_field <= 0) + magnetic_field = 1 + + + // Limitations: + if(abs(center_x) > max_dist) + center_x = max_dist + if(abs(center_y) > max_dist) + center_y = max_dist + if(magnetic_field > 4) + magnetic_field = 4 + if(electricity_level > 12) + electricity_level = 12 + + // Update power usage: + if(on) + use_power = ACTIVE_POWER_USE + active_power_usage = electricity_level*15 + else + use_power = NO_POWER_USE + + update_icon() + + +/obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the magneting + if(magneting) + return + while(on) + + magneting = TRUE + center = locate(x+center_x, y+center_y, z) + if(center) + for(var/obj/M in orange(magnetic_field, center)) + if(!M.anchored && (M.flags_1 & CONDUCT_1)) + step_towards(M, center) + + for(var/mob/living/silicon/S in orange(magnetic_field, center)) + if(isAI(S)) + continue + step_towards(S, center) + + use_power(electricity_level * 5) + sleep(13 - electricity_level) + + magneting = FALSE + + + + +/obj/machinery/magnetic_controller + name = "magnetic control console" + icon = 'icons/obj/airlock_machines.dmi' // uses an airlock machine icon, THINK GREEN HELP THE ENVIRONMENT - RECYCLING! + icon_state = "airlock_control_standby" + density = FALSE + use_power = IDLE_POWER_USE + idle_power_usage = 45 + var/frequency = FREQ_MAGNETS + var/code = 0 + var/list/magnets = list() + var/title = "Magnetic Control Console" + var/autolink = 0 // if set to 1, can't probe for other magnets! + + var/pathpos = 1 // position in the path + var/path = "w;e;e;w;s;n;n;s" // text path of the magnet + var/speed = 1 // lowest = 1, highest = 10 + var/list/rpath = list() // real path of the magnet, used in iterator + + var/moving = 0 // 1 if scheduled to loop + var/looping = 0 // 1 if looping + + var/datum/radio_frequency/radio_connection + + +/obj/machinery/magnetic_controller/Initialize() + . = ..() + if(autolink) + for(var/obj/machinery/magnetic_module/M in GLOB.machines) + if(M.freq == frequency && M.code == code) + magnets.Add(M) + + if(path) // check for default path + filter_path() // renders rpath + radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS) + +/obj/machinery/magnetic_controller/Destroy() + SSradio.remove_object(src, frequency) + magnets = null + rpath = null + return ..() + +/obj/machinery/magnetic_controller/process() + if(magnets.len == 0 && autolink) + for(var/obj/machinery/magnetic_module/M in GLOB.machines) + if(M.freq == frequency && M.code == code) + magnets.Add(M) + +/obj/machinery/magnetic_controller/ui_interact(mob/user) + . = ..() + var/dat = "Magnetic Control Console

    " + if(!autolink) + dat += {" + Frequency: [frequency]
    + Code: [code]
    + Probe Generators
    + "} + + if(magnets.len >= 1) + + dat += "Magnets confirmed:
    " + var/i = 0 + for(var/obj/machinery/magnetic_module/M in magnets) + i++ + dat += "     < \[[i]\] ([M.on ? "On":"Off"]) | Electricity level: - [M.electricity_level] +; Magnetic field: - [M.magnetic_field] +
    " + + dat += "
    Speed: - [speed] +
    " + dat += "Path: {[path]}
    " + dat += "Moving: [moving ? "Enabled":"Disabled"]" + + + user << browse(dat, "window=magnet;size=400x500") + onclose(user, "magnet") + +/obj/machinery/magnetic_controller/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + + if(href_list["radio-op"]) + + // Prepare signal beforehand, because this is a radio operation + var/datum/signal/signal = new(list("code" = code)) + + // Apply any necessary commands + switch(href_list["radio-op"]) + if("togglepower") + signal.data["command"] = "toggle-power" + + if("minuselec") + signal.data["command"] = "sub-elec" + if("pluselec") + signal.data["command"] = "add-elec" + + if("minusmag") + signal.data["command"] = "sub-mag" + if("plusmag") + signal.data["command"] = "add-mag" + + + // Broadcast the signal + + radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + + spawn(1) + updateUsrDialog() // pretty sure this increases responsiveness + + if(href_list["operation"]) + switch(href_list["operation"]) + if("plusspeed") + speed ++ + if(speed > 10) + speed = 10 + if("minusspeed") + speed -- + if(speed <= 0) + speed = 1 + if("setpath") + var/newpath = copytext(sanitize(input(usr, "Please define a new path!",,path) as text|null),1,MAX_MESSAGE_LEN) + if(newpath && newpath != "") + moving = 0 // stop moving + path = newpath + pathpos = 1 // reset position + filter_path() // renders rpath + + if("togglemoving") + moving = !moving + if(moving) + spawn() MagnetMove() + + + updateUsrDialog() + +/obj/machinery/magnetic_controller/proc/MagnetMove() + if(looping) + return + + while(moving && rpath.len >= 1) + + if(stat & (BROKEN|NOPOWER)) + break + + looping = 1 + + // Prepare the radio signal + var/datum/signal/signal = new(list("code" = code)) + + if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! + pathpos = 1 + + var/nextmove = uppertext(rpath[pathpos]) // makes it un-case-sensitive + + if(!(nextmove in list("N","S","E","W","C","R"))) + // N, S, E, W are directional + // C is center + // R is random (in magnetic field's bounds) + qdel(signal) + break // break the loop if the character located is invalid + + signal.data["command"] = nextmove + + + pathpos++ // increase iterator + + // Broadcast the signal + spawn() + radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + + if(speed == 10) + sleep(1) + else + sleep(12-speed) + + looping = 0 + + +/obj/machinery/magnetic_controller/proc/filter_path() + // Generates the rpath variable using the path string, think of this as "string2list" + // Doesn't use params2list() because of the akward way it stacks entities + rpath = list() // clear rpath + var/maximum_character = min( 50, length(path) ) // chooses the maximum length of the iterator. 50 max length + + for(var/i=1, i<=maximum_character, i++) // iterates through all characters in path + + var/nextchar = copytext(path, i, i+1) // find next character + + if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore + rpath += copytext(path, i, i+1) // else, add to list + + // there doesn't HAVE to be separators but it makes paths syntatically visible diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index 7ebed0ab0c..ab0a0534ab 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -1,38 +1,38 @@ -/obj/machinery/mass_driver - name = "mass driver" - desc = "The finest in spring-loaded piston toy technology, now on a space station near you." - icon = 'icons/obj/stationobjs.dmi' - icon_state = "mass_driver" - use_power = IDLE_POWER_USE - idle_power_usage = 2 - active_power_usage = 50 - var/power = 1 - var/code = 1 - var/id = 1 - var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. - - -/obj/machinery/mass_driver/proc/drive(amount) - if(stat & (BROKEN|NOPOWER)) - return - use_power(500) - var/O_limit - var/atom/target = get_edge_target_turf(src, dir) - for(var/atom/movable/O in loc) - if(!O.anchored || ismecha(O)) //Mechs need their launch platforms. - O_limit++ - if(O_limit >= 20) - audible_message("[src] lets out a screech, it doesn't seem to be able to handle the load.") - break - use_power(500) - O.throw_at(target, drive_range * power, power) - flick("mass_driver1", src) - - -/obj/machinery/mass_driver/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - if(stat & (BROKEN|NOPOWER)) - return - drive() +/obj/machinery/mass_driver + name = "mass driver" + desc = "The finest in spring-loaded piston toy technology, now on a space station near you." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "mass_driver" + use_power = IDLE_POWER_USE + idle_power_usage = 2 + active_power_usage = 50 + var/power = 1 + var/code = 1 + var/id = 1 + var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. + + +/obj/machinery/mass_driver/proc/drive(amount) + if(stat & (BROKEN|NOPOWER)) + return + use_power(500) + var/O_limit + var/atom/target = get_edge_target_turf(src, dir) + for(var/atom/movable/O in loc) + if(!O.anchored || ismecha(O)) //Mechs need their launch platforms. + O_limit++ + if(O_limit >= 20) + audible_message("[src] lets out a screech, it doesn't seem to be able to handle the load.") + break + use_power(500) + O.throw_at(target, drive_range * power, power) + flick("mass_driver1", src) + + +/obj/machinery/mass_driver/emp_act(severity) + . = ..() + if (. & EMP_PROTECT_SELF) + return + if(stat & (BROKEN|NOPOWER)) + return + drive() diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index 0f57bea656..5a567886b8 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -1,214 +1,214 @@ -// Navigation beacon for AI robots -// No longer exists on the radio controller, it is managed by a global list. - -/obj/machinery/navbeacon - - icon = 'icons/obj/objects.dmi' - icon_state = "navbeacon0-f" - name = "navigation beacon" - desc = "A radio beacon used for bot navigation." - level = 1 // underfloor - layer = LOW_OBJ_LAYER - max_integrity = 500 - armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 70, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) - - var/open = FALSE // true if cover is open - var/locked = TRUE // true if controls are locked - var/freq = FREQ_NAV_BEACON - var/location = "" // location response text - var/list/codes // assoc. list of transponder codes - var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value" - - req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS) - -/obj/machinery/navbeacon/Initialize() - . = ..() - - set_codes() - - var/turf/T = loc - hide(T.intact) - if(codes["patrol"]) - if(!GLOB.navbeacons["[z]"]) - GLOB.navbeacons["[z]"] = list() - GLOB.navbeacons["[z]"] += src //Register with the patrol list! - if(codes["delivery"]) - GLOB.deliverybeacons += src - GLOB.deliverybeacontags += location - -/obj/machinery/navbeacon/Destroy() - if (GLOB.navbeacons["[z]"]) - GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one. - GLOB.deliverybeacons -= src - return ..() - -/obj/machinery/navbeacon/onTransitZ(old_z, new_z) - if (GLOB.navbeacons["[old_z]"]) - GLOB.navbeacons["[old_z]"] -= src - if (GLOB.navbeacons["[new_z]"]) - GLOB.navbeacons["[new_z]"] += src - ..() - -// set the transponder codes assoc list from codes_txt -/obj/machinery/navbeacon/proc/set_codes() - if(!codes_txt) - return - - codes = new() - - var/list/entries = splittext(codes_txt, ";") // entries are separated by semicolons - - for(var/e in entries) - var/index = findtext(e, "=") // format is "key=value" - if(index) - var/key = copytext(e, 1, index) - var/val = copytext(e, index+1) - codes[key] = val - else - codes[e] = "1" - - -// called when turf state changes -// hide the object if turf is intact -/obj/machinery/navbeacon/hide(intact) - invisibility = intact ? INVISIBILITY_MAXIMUM : 0 - update_icon() - -// update the icon_state -/obj/machinery/navbeacon/update_icon() - var/state="navbeacon[open]" - - if(invisibility) - icon_state = "[state]-f" // if invisible, set icon to faded version - // in case revealed by T-scanner - else - icon_state = "[state]" - -/obj/machinery/navbeacon/attackby(obj/item/I, mob/user, params) - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(istype(I, /obj/item/screwdriver)) - open = !open - - user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "You [open ? "open" : "close"] the beacon's cover.") - - update_icon() - - else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda)) - if(open) - if (src.allowed(user)) - src.locked = !src.locked - to_chat(user, "Controls are now [src.locked ? "locked" : "unlocked"].") - else - to_chat(user, "Access denied.") - updateDialog() - else - to_chat(user, "You must open the cover first!") - else - return ..() - -/obj/machinery/navbeacon/attack_ai(mob/user) - interact(user, 1) - -/obj/machinery/navbeacon/attack_paw() - return - -/obj/machinery/navbeacon/ui_interact(mob/user) - . = ..() - var/ai = isAI(user) - var/turf/T = loc - if(T.intact) - return // prevent intraction when T-scanner revealed - - if(!open && !ai) // can't alter controls if not open, unless you're an AI - to_chat(user, "The beacon's control cover is closed!") - return - - - var/t - - if(locked && !ai) - t = {"Navigation Beacon

    -(swipe card to unlock controls)
    -Location: [location ? location : "(none)"]
    -Transponder Codes:

    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 v(rOfHUE Date: Sat, 4 Jan 2020 19:06:56 -0500 Subject: [PATCH 036/409] Correct price and rpd --- code/game/objects/items/RCD.dm | 1 + code/modules/research/designs/misc_designs.dm | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index b4f0f1459a..420f5467d8 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -599,6 +599,7 @@ RLD energyfactor = 66 /obj/item/construction/rcd/loaded + materials = list(MAT_METAL=48000, MAT_GLASS=32000) matter = 160 /obj/item/construction/rcd/loaded/upgraded diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index a49dd76ede..198f06ed3f 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -434,7 +434,7 @@ desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly." id = "rcd_loaded" build_type = PROTOLATHE - materials = list(MAT_METAL = 60000, MAT_GLASS = 5000) // costs more than what it did in the autolathe, this one comes loaded. + materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) // costs more than what it did in the autolathe, this one comes loaded. build_path = /obj/item/construction/rcd/loaded category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING @@ -445,7 +445,7 @@ id = "rpd" build_type = PROTOLATHE materials = list(MAT_METAL = 75000, MAT_GLASS = 37500) - build_path = /obj/item/construction/rcd/loaded + build_path = /obj/item/pipe_dispenser category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING From 46cf029a2823871e647f4f5600882e6cd88cf795 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 11:19:18 -0800 Subject: [PATCH 037/409] Update twohanded.dm --- code/game/objects/items/twohanded.dm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index d7891feaa0..a81a45d6e4 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -781,6 +781,9 @@ throwforce = 20 throw_speed = 4 attack_verb = list("gored") + var/clonechance = 50 + var/clonedamage = 12 + var/clonespeed = 0.5 /obj/item/twohanded/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) . = ..() @@ -791,9 +794,11 @@ var/mob/living/L = AM if(istype (L, /mob/living/simple_animal/hostile/illusion)) return - if(!L.stat && prob(50)) + if(!L.stat && prob(clonechance)) var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) M.faction = user.faction.Copy() + M.melee_damage_upper = M.melee_damage_lower = clonedamage + M.set_varspeed(clonespeed) M.Copy_Parent(user, 100, user.health/2.5, 12, 30) M.GiveTarget(L) @@ -1010,4 +1015,4 @@ var/client/C = user.client C.change_view(CONFIG_GET(string/default_view)) user.client.pixel_x = 0 - user.client.pixel_y = 0 \ No newline at end of file + user.client.pixel_y = 0 From 4d151b2a7ca731992c7ad972ab5b94270a5437eb Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 11:20:13 -0800 Subject: [PATCH 038/409] Update twohanded.dm --- code/game/objects/items/twohanded.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index a81a45d6e4..3802b01bc4 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -783,7 +783,7 @@ attack_verb = list("gored") var/clonechance = 50 var/clonedamage = 12 - var/clonespeed = 0.5 + var/clonespeed = 0 /obj/item/twohanded/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) . = ..() From 1a834edd5f964b3c9842b716d02c9e9b947683ec Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Sun, 5 Jan 2020 21:27:04 +0100 Subject: [PATCH 039/409] f --- .../structures/crates_lockers/closets/secure/security.dm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 058782e1ab..c671af0e5d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -19,6 +19,7 @@ new /obj/item/clothing/under/captainparade(src) new /obj/item/clothing/suit/armor/vest/capcarapace/alt(src) new /obj/item/clothing/head/caphat/parade(src) + new /obj/item/clothing/head/caphat/beret(src) new /obj/item/clothing/suit/captunic(src) new /obj/item/clothing/under/rank/captain/femformal(src) //citadel edit new /obj/item/clothing/head/crown/fancy(src) @@ -32,10 +33,7 @@ new /obj/item/gun/energy/e_gun(src) new /obj/item/door_remote/captain(src) new /obj/item/storage/photo_album/Captain(src) - if(prob(50)) - new /obj/item/clothing/head/caphat/beret(src) - else - new /obj/item/clothing/head/caphat/beret/white(src) + new /obj/item/clothing/head/caphat/beret/white(src) /obj/structure/closet/secure_closet/hop name = "\proper head of personnel's locker" From 0f909a1437f4ea84e65a215f134dc298bae88968 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 12:50:51 -0800 Subject: [PATCH 040/409] Update twohanded.dm --- code/game/objects/items/twohanded.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 3802b01bc4..3f180bdce8 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -784,6 +784,8 @@ var/clonechance = 50 var/clonedamage = 12 var/clonespeed = 0 + var/clone_replication_chance = 30 + var/clone_lifespan = 100 /obj/item/twohanded/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) . = ..() @@ -797,9 +799,8 @@ if(!L.stat && prob(clonechance)) var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) M.faction = user.faction.Copy() - M.melee_damage_upper = M.melee_damage_lower = clonedamage M.set_varspeed(clonespeed) - M.Copy_Parent(user, 100, user.health/2.5, 12, 30) + M.Copy_Parent(user, clone_lifespan, user.health/2.5, clonedamage, clone_replication_chance) M.GiveTarget(L) /obj/item/twohanded/pitchfork From ab23a934fc92746225b61e29ca3b00a0991e8eae Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:01:12 -0800 Subject: [PATCH 041/409] Update beams.dm --- code/modules/projectiles/projectile/beams.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index be73e22e6d..49c4beefab 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -117,8 +117,11 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser light_color = LIGHT_COLOR_GREEN -/obj/item/projectile/beam/emitter/singularity_pull() - return //don't want the emitters to miss +/obj/item/projectile/beam/emitter/hitscan + hitscan = TRUE + muzzle_effect_type = /obj/effect/temp_visual/impact_effect/emitter + tracer_effect_type = /obj/effect/temp_visual/tracer_effect/emitter + impact_effect_type = /obj/effect/temp_visual/impact_effect/emitter /obj/item/projectile/beam/lasertag name = "laser tag beam" @@ -207,4 +210,4 @@ . = ..() if(isopenturf(target) || istype(target, /turf/closed/indestructible))//shrunk floors wouldnt do anything except look weird, i-walls shouldnt be bypassable return - target.AddComponent(/datum/component/shrink, shrink_time) \ No newline at end of file + target.AddComponent(/datum/component/shrink, shrink_time) From 198b1d5bd4ee7d667d7ae1c04756d4de59329156 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:01:58 -0800 Subject: [PATCH 042/409] Update emitter.dm --- code/modules/power/singularity/emitter.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 71a8565d26..1be201f2b8 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -30,7 +30,7 @@ var/locked = FALSE var/allow_switch_interact = TRUE - var/projectile_type = /obj/item/projectile/beam/emitter + var/projectile_type = /obj/item/projectile/beam/emitter/hitscan var/projectile_sound = 'sound/weapons/emitter.ogg' var/datum/effect_system/spark_spread/sparks From eea8d353b6d34301cb2865afee9496f73bbb8bc2 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:03:14 -0800 Subject: [PATCH 043/409] Update tracer.dm --- .../objects/effects/temporary_visuals/projectiles/tracer.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm index 0cd4589d4c..bd2c6c6e87 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm @@ -70,3 +70,7 @@ /obj/effect/projectile/tracer/laser/wavemotion name = "particle trail" icon_state = "tracer_wavemotion" + +/obj/effect/projectile/tracer/laser/emitter + name = "emitter beam" + icon_state = "emitter" From 6e1e1aac3ecea55aaf0cc1329a6658c75cacd387 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:03:42 -0800 Subject: [PATCH 044/409] Update impact.dm --- .../objects/effects/temporary_visuals/projectiles/impact.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm index 0360c4ccc2..a98c40d4fc 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/impact.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/impact.dm @@ -39,4 +39,8 @@ /obj/effect/projectile/impact/laser/wavemotion name = "particle impact" - icon_state = "impact_wavemotion" \ No newline at end of file + icon_state = "impact_wavemotion" + +/obj/effect/projectile/impact/laser/emitter + name = "emitter impact" + icon_state = "impact_emitter" From 07885a399a68ca21697a8c5666c077a7d4d7a55b Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:04:13 -0800 Subject: [PATCH 045/409] Update muzzle.dm --- .../objects/effects/temporary_visuals/projectiles/muzzle.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm index cbd4b21d39..a7ff399734 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/muzzle.dm @@ -31,4 +31,8 @@ /obj/effect/projectile/muzzle/laser/wavemotion name = "particle backblast" - icon_state = "muzzle_wavemotion" \ No newline at end of file + icon_state = "muzzle_wavemotion" + +/obj/effect/projectile/muzzle/laser/emitter + name = "emitter flash" + icon_state = "muzzle_emitter" From f26c02801a1f14a2dd4667160bebf2e66a4a711c Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:04:51 -0800 Subject: [PATCH 046/409] Update beams.dm --- code/modules/projectiles/projectile/beams.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 49c4beefab..0a2e44213b 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -119,9 +119,9 @@ /obj/item/projectile/beam/emitter/hitscan hitscan = TRUE - muzzle_effect_type = /obj/effect/temp_visual/impact_effect/emitter - tracer_effect_type = /obj/effect/temp_visual/tracer_effect/emitter - impact_effect_type = /obj/effect/temp_visual/impact_effect/emitter + muzzle_effect_type = /obj/effect/projectile/muzzle/laser/emitter + tracer_effect_type = /obj/effect/projectile/tracer/laser/emitter + impact_effect_type = /obj/effect/projectile/impact/laser/emitter /obj/item/projectile/beam/lasertag name = "laser tag beam" From aca8c33149cdd930567729faf851a2c9afb048c3 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:08:12 -0800 Subject: [PATCH 047/409] Update beams.dm --- code/modules/projectiles/projectile/beams.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 0a2e44213b..1c5291732e 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -117,6 +117,9 @@ impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser light_color = LIGHT_COLOR_GREEN +/obj/item/projectile/beam/emitter/singularity_pull() + return + /obj/item/projectile/beam/emitter/hitscan hitscan = TRUE muzzle_effect_type = /obj/effect/projectile/muzzle/laser/emitter From 39461e2806a576ad91c7cf18b0cb12e6575c74f6 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Sun, 5 Jan 2020 15:16:04 -0800 Subject: [PATCH 048/409] Update beams.dm --- code/modules/projectiles/projectile/beams.dm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 1c5291732e..89a9079454 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -122,9 +122,10 @@ /obj/item/projectile/beam/emitter/hitscan hitscan = TRUE - muzzle_effect_type = /obj/effect/projectile/muzzle/laser/emitter - tracer_effect_type = /obj/effect/projectile/tracer/laser/emitter - impact_effect_type = /obj/effect/projectile/impact/laser/emitter + muzzle_type = /obj/effect/projectile/muzzle/laser/emitter + tracer_type = /obj/effect/projectile/tracer/laser/emitter + impact_type = /obj/effect/projectile/impact/laser/emitter + impact_effect_type = null /obj/item/projectile/beam/lasertag name = "laser tag beam" From d75a525b3cceba09e5be069c901e8d19c574bbdc Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 5 Jan 2020 19:10:48 -0800 Subject: [PATCH 049/409] let's fix arousal huh --- code/__DEFINES/citadel_defines.dm | 6 - code/__DEFINES/traits.dm | 5 +- code/__HELPERS/_cit_helpers.dm | 2 +- code/_onclick/hud/hud.dm | 3 - code/_onclick/hud/human.dm | 5 - code/datums/datumvars.dm | 4 - code/datums/mind.dm | 8 +- code/datums/traits/neutral.dm | 34 -- code/modules/client/preferences_savefile.dm | 5 - .../integrated_electronics/subtypes/input.dm | 31 -- .../modules/mob/living/carbon/damage_procs.dm | 3 - code/modules/mob/living/carbon/human/life.dm | 4 - .../mob/living/carbon/human/species.dm | 23 +- .../chemistry/reagents/drink_reagents.dm | 7 +- .../chemistry/reagents/other_reagents.dm | 7 +- code/modules/surgery/organs/vocal_cords.dm | 33 +- .../code/datums/status_effects/chems.dm | 25 +- .../code/modules/arousal/arousal.dm | 293 ++---------------- .../code/modules/arousal/genitals.dm | 45 ++- .../code/modules/arousal/organs/breasts.dm | 1 + .../code/modules/arousal/organs/penis.dm | 3 +- .../code/modules/arousal/organs/vagina.dm | 1 + .../code/modules/arousal/toys/dildos.dm | 3 +- .../code/modules/client/preferences.dm | 3 +- .../subtypes/manipulation.dm | 53 ---- .../reagents/chemistry/reagents/MKUltra.dm | 2 - .../modules/reagents/reagents/cit_reagents.dm | 72 +++-- tgstation.dme | 1 - 28 files changed, 134 insertions(+), 548 deletions(-) delete mode 100644 modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index e29be375e6..c3bf3d2891 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -72,9 +72,6 @@ #define MILK_RATE_MULT 1 #define MILK_EFFICIENCY 1 -#define AROUSAL_MINIMUM_DEFAULT 0 -#define AROUSAL_MAXIMUM_DEFAULT 100 -#define AROUSAL_START_VALUE 1 //Individual logging define #define INDIVIDUAL_LOOC_LOG "LOOC log" @@ -82,9 +79,6 @@ #define ADMIN_IC(client) "(IC)"//marks and adminhelp as an IC issue #define ADMIN_REJECT(client) "(REJT)"//Rejects an adminhelp for being unclear or otherwise unhelpful. resets their adminhelp timer -//Damage stuffs -#define AROUSAL "arousal" - //Citadel istypes #define isgenital(A) (istype(A, /obj/item/organ/genital)) diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 4f66482f51..4a7afd5762 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -161,9 +161,8 @@ #define TRAIT_TAGGER "tagger" #define TRAIT_PHOTOGRAPHER "photographer" #define TRAIT_MUSICIAN "musician" -#define TRAIT_NYMPHO "nymphomania" -#define TRAIT_MASO "masochism" -#define TRAIT_EXHIBITIONIST "exhibitionist" +#define TRAIT_PERMABONER "permanent_arousal" +#define TRAIT_NEVERBONER "never_aroused" #define TRAIT_HIGH_BLOOD "high_blood" #define TRAIT_PARA "paraplegic" #define TRAIT_EMPATH "empath" diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 8134494306..6b0c8cd848 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(meat_types, list( "Mammalian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/mammal, "Aquatic" = /obj/item/reagent_containers/food/snacks/carpmeat/aquatic, "Avian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/avian, - "Inesct" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect)) + "Insect" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect)) //Crew objective and miscreants stuff GLOBAL_VAR_INIT(miscreants_allowed, FALSE) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 09794444d1..1d1836716b 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -61,9 +61,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( // subtypes can override this to force a specific UI style var/ui_style - //Citadel stuff - var/obj/screen/arousal - /datum/hud/New(mob/owner) mymob = owner diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 78a2d2fd17..809c9161aa 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -336,11 +336,6 @@ healths = new /obj/screen/healths() healths.hud = src infodisplay += healths - //CIT CHANGE - adds arousal and stamina to hud - arousal = new /obj/screen/arousal() - arousal.icon_state = (owner.canbearoused == 1 ? "arousal0" : "") - arousal.hud = src - infodisplay += arousal staminas = new /obj/screen/staminas() staminas.hud = src diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index feac1de972..8bed902207 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -96,7 +96,6 @@ CLONE:[M.getCloneLoss()] BRAIN:[M.getOrganLoss(ORGAN_SLOT_BRAIN)] STAMINA:[M.getStaminaLoss()] - AROUSAL:[M.getArousalLoss()] "} if(GLOB.Debug2) atomsnowflake += {" @@ -1355,9 +1354,6 @@ if("stamina") L.adjustStaminaLoss(amount) newamt = L.getStaminaLoss() - if("arousal") - L.adjustArousalLoss(amount) - newamt = L.getArousalLoss() if("heart") L.adjustOrganLoss(ORGAN_SLOT_HEART, amount) newamt = L.getOrganLoss(ORGAN_SLOT_HEART) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index a0aa729a8d..33ebff17ca 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -132,12 +132,8 @@ //CIT CHANGE - makes arousal update when transfering bodies if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs. var/mob/living/L = new_character - if(L.client && L.client.prefs) - L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... - L.update_arousal_hud() //Removes the old icon - if (L.client.prefs.auto_ooc) - if (L.client.prefs.chat_toggles & CHAT_OOC) - L.client.prefs.chat_toggles ^= CHAT_OOC + if(L.client && L.client.prefs & L.client.prefs.auto_ooc & L.client.prefs.chat_toggles & CHAT_OOC) + DISABLE_BITFIELD(L.client.prefs.chat_toggles,CHAT_OOC) SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index 911929896b..91146d55a0 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -87,37 +87,3 @@ /datum/quirk/monochromatic/remove() if(quirk_holder) quirk_holder.remove_client_colour(/datum/client_colour/monochrome) - -/datum/quirk/libido - name = "Nymphomania" - desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual." - value = 0 - mob_trait = TRAIT_NYMPHO - gain_text = "You are feeling extra wild." - lose_text = "You don't feel that burning sensation anymore." - -/datum/quirk/libido/add() - quirk_holder.min_arousal = 16 - quirk_holder.arousal_rate = 3 - -/datum/quirk/libido/remove() - if(quirk_holder) - quirk_holder.min_arousal = initial(quirk_holder.min_arousal) - quirk_holder.arousal_rate = initial(quirk_holder.arousal_rate) - -/datum/quirk/maso - name = "Masochism" - desc = "You are aroused by pain." - value = 0 - mob_trait = TRAIT_MASO - gain_text = "You desire to be hurt." - lose_text = "Pain has become less exciting for you." - -/datum/quirk/exhibitionism - name = "Exhibitionism" - desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying." - value = 0 - medical_record_text = "Patient has been diagnosed with exhibitionistic disorder." - mob_trait = TRAIT_EXHIBITIONIST - gain_text = "You feel like exposing yourself to the world." - lose_text = "Indecent exposure doesn't sound as charming to you anymore." diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index d78b9fe6fd..ed8042b360 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -109,11 +109,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car else if(current_version < 23) // we are fixing a gamebreaking bug. job_preferences = list() //It loaded null from nonexistant savefile field. - if(current_version < 24 && S["feature_exhibitionist"]) - var/datum/quirk/exhibitionism/E - var/quirk_name = initial(E.name) - all_quirks += quirk_name - /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index 46f8017b10..4f9afd9ed5 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -1310,34 +1310,3 @@ set_pin_data(IC_OUTPUT, 2, regurgitated_contents) push_data() activate_pin(2) - -//Degens -/obj/item/integrated_circuit/input/bonermeter - name = "bonermeter" - desc = "Detects the target's arousal and various statistics about the target's arousal levels. Invasive!" - icon_state = "medscan" - complexity = 4 - inputs = list("target" = IC_PINTYPE_REF) - outputs = list( - "current arousal" = IC_PINTYPE_NUMBER, - "minimum arousal" = IC_PINTYPE_NUMBER, - "maximum arousal" = IC_PINTYPE_NUMBER, - "can be aroused" = IC_PINTYPE_BOOLEAN - ) - activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT) - spawn_flags = IC_SPAWN_RESEARCH - power_draw_per_use = 40 - -/obj/item/integrated_circuit/input/bonermeter/do_work() - - var/mob/living/L = get_pin_data_as_type(IC_INPUT, 1, /mob/living) - - if(!istype(L) || !L.Adjacent(get_turf(src)) ) //Invalid input - return - - set_pin_data(IC_OUTPUT, 1, L.getArousalLoss()) - set_pin_data(IC_OUTPUT, 2, L.min_arousal) - set_pin_data(IC_OUTPUT, 3, L.max_arousal) - set_pin_data(IC_OUTPUT, 4, L.canbearoused) - push_data() - activate_pin(2) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index d893108bcd..5bffc4e276 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -41,9 +41,6 @@ update_damage_overlays() else adjustStaminaLoss(damage_amount, forced = forced) - //citadel code - if(AROUSAL) - adjustArousalLoss(damage_amount) return TRUE diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 821a3472e4..7507067597 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -39,10 +39,6 @@ //Stuff jammed in your limbs hurts handle_embedded_objects() - if(stat != DEAD) - //process your dick energy - handle_arousal(times_fired) - //Update our name based on whether our face is obscured/disfigured name = get_visible_name() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 2e069297b3..a8603a2a41 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -323,12 +323,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) for(var/datum/disease/A in C.diseases) A.cure(FALSE) -//CITADEL EDIT - if(NOAROUSAL in species_traits) - C.canbearoused = FALSE - else - if(C.client) - C.canbearoused = C.client.prefs.arousable if(ishuman(C)) var/mob/living/carbon/human/H = C if(NOGENITALS in H.dna.species.species_traits) @@ -1586,8 +1580,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) "You slap [user == target ? "yourself" : "\the [target]"] in the face! ",\ "You hear a slap." ) - if (!HAS_TRAIT(target, TRAIT_NYMPHO)) - stop_wagging_tail(target) user.do_attack_animation(target, ATTACK_EFFECT_FACE_SLAP) user.adjustStaminaLossBuffered(3) return FALSE @@ -1602,14 +1594,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) "\The [user] slaps \the [target]'s ass!",\ "You slap [user == target ? "your" : "\the [target]'s"] ass!",\ "You hear a slap." - ) - if (target.canbearoused) - target.adjustArousalLoss(5) - if (target.getArousalLoss() >= 100 && ishuman(target) && HAS_TRAIT(target, TRAIT_MASO) && target.has_dna()) - target.mob_climax(forced_climax=TRUE) - if (!HAS_TRAIT(target, TRAIT_NYMPHO)) - stop_wagging_tail(target) - + ) return FALSE else if(attacker_style && attacker_style.disarm_act(user,target)) return 1 @@ -1962,10 +1947,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(BP) if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0)) H.update_damage_overlays() - if(HAS_TRAIT(H, TRAIT_MASO)) - H.adjustArousalLoss(damage_amount, 0) - if (H.getArousalLoss() >= 100 && ishuman(H) && H.has_dna()) - H.mob_climax(forced_climax=TRUE) else//no bodypart, we deal damage with a more general method. H.adjustBruteLoss(damage_amount) @@ -1996,8 +1977,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(BRAIN) var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) - if(AROUSAL) //Citadel edit - arousal - H.adjustArousalLoss(damage * hit_percent) return 1 /datum/species/proc/on_hit(obj/item/projectile/P, mob/living/carbon/human/H) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index e8551074e7..07d4b13b14 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -966,7 +966,12 @@ M.emote("nya") if(prob(20)) to_chat(M, "[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]") - M.adjustArousalLoss(5) + if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(5)) + for(var/obj/item/organ/genital/G in M.internal_organs) + if(!G.aroused_state && prob(5)) + G.aroused_state = TRUE + to_chat(M, "You feel like playing with your [G.name]!") + ..() /datum/reagent/consumable/monkey_energy diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index bd6eb4244c..60ef8053b1 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2280,5 +2280,10 @@ M.emote("nya") if(prob(20)) to_chat(M, "[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]") - M.adjustArousalLoss(2) + if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO && ishuman(M))) + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/genital/G in H.internal_organs) + if(!G.aroused_state && prob(2)) + G.aroused_state = TRUE + to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 161461d099..7df7421c69 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -578,7 +578,8 @@ cooldown = COOLDOWN_MEME for(var/V in listeners) var/mob/living/carbon/human/H = V - if(H.canbearoused && H.has_dna() && HAS_TRAIT(H, TRAIT_NYMPHO)) // probably a redundant check but for good measure + + if(H.client && H.client.prefs && H.client.prefs.cit_toggles & HYPNO) // probably a redundant check but for good measure H.mob_climax(forced_climax=TRUE) //DAB @@ -807,7 +808,7 @@ E.enthrallTally += (power_multiplier*(((length(message))/200) + 1)) //encourage players to say more than one word. else E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc - if(L.canbearoused && E.lewd) + if(E.lewd) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] is so nice to listen to."), 5) E.cooldown += 1 @@ -821,12 +822,6 @@ continue if (E.lewd) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[E.enthrallGender] has praised me!!"), 5) - if(HAS_TRAIT(L, TRAIT_NYMPHO)) - L.adjustArousalLoss(2*power_multiplier) - if(HAS_TRAIT(L, TRAIT_MASO)) - E.enthrallTally -= power_multiplier - E.resistanceTally += power_multiplier - E.cooldown += 1 else addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've been praised for doing a good job!"), 5) E.resistanceTally -= power_multiplier @@ -844,14 +839,7 @@ if(L == user) continue if (E.lewd) - if(HAS_TRAIT(L, TRAIT_MASO)) - L.adjustArousalLoss(3*power_multiplier) - descmessage += "And yet, it feels so good..!" //I don't really understand masco, is this the right sort of thing they like? - E.enthrallTally += power_multiplier - E.resistanceTally -= power_multiplier - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down...!"), 5) - else - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down..."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've let [E.enthrallGender] down..."), 5) else addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "I've failed [E.master]..."), 5) E.resistanceTally += power_multiplier @@ -1001,16 +989,6 @@ if(160 to INFINITY) speaktrigger += "I feel like I'm on the brink of losing my mind, " - //horny - if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) - switch(H.getArousalLoss()) - if(40 to 60) - speaktrigger += "I'm feeling a little horny, " - if(60 to 80) - speaktrigger += "I'm feeling horny, " - if(80 to INFINITY) - speaktrigger += "I'm really, really horny, " - //collar if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && E.lewd) speaktrigger += "I love the collar you gave me, " @@ -1111,11 +1089,10 @@ var/mob/living/carbon/human/H = V var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) if(E.phase > 1) - if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) // probably a redundant check but for good measure + if(E.lewd) // probably a redundant check but for good measure addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure."), 5) H.mob_climax(forced_climax=TRUE) H.SetStun(20) - H.setArousalLoss(H.min_arousal) E.resistanceTally = 0 //makes resistance 0, but resets arousal, resistance buildup is faster unaroused (massively so). E.enthrallTally += power_multiplier E.cooldown += 6 diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 8adc7c0745..4e43b6a8b7 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -268,10 +268,6 @@ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist) //Do resistance calc if resist is pressed# RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/owner_hear) mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain! - var/mob/living/carbon/human/H = owner - if(H)//Prefs - if(!H.canbearoused) - H.client?.prefs.cit_toggles &= ~HYPNO lewd = (owner.client?.prefs.cit_toggles & HYPNO) && (master.client?.prefs.cit_toggles & HYPNO) var/message = "[(lewd ? "I am a good pet for [enthrallGender]." : "[master] is a really inspirational person!")]" SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "enthrall", /datum/mood_event/enthrall, message) @@ -625,8 +621,6 @@ //Speak (Forces player to talk) if (lowertext(customTriggers[trigger][1]) == "speak")//trigger2 var/saytext = "Your mouth moves on it's own before you can even catch it." - if(HAS_TRAIT(C, TRAIT_NYMPHO)) - saytext += " You find yourself fully believing in the validity of what you just said and don't think to question it." addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "[saytext]"), 5) addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5) log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") @@ -639,8 +633,6 @@ //Shocking truth! else if (lowertext(customTriggers[trigger]) == "shock") - if (C.canbearoused && lewd) - C.adjustArousalLoss(5) C.jitteriness += 100 C.stuttering += 25 C.Knockdown(60) @@ -649,13 +641,11 @@ //wah intensifies wah-rks else if (lowertext(customTriggers[trigger]) == "cum")//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if (HAS_TRAIT(C, TRAIT_NYMPHO) && lewd) - if (C.getArousalLoss() > 80) - C.mob_climax(forced_climax=TRUE) - C.SetStun(10)//We got your stun effects in somewhere, Kev. - else - C.adjustArousalLoss(10) - to_chat(C, "You feel a surge of arousal!") + if (lewd) + if(ishuman(C)) + var/mob/living/carbon/human/H = C + H.mob_climax(forced_climax=TRUE) + C.SetStun(10)//We got your stun effects in somewhere, Kev. else C.throw_at(get_step_towards(hearing_args[HEARING_SPEAKER],C), 3, 1) //cut this if it's too hard to get working @@ -734,16 +724,13 @@ if(prob(5)) M.emote("me",1,"squints, shaking their head for a moment.")//shows that you're trying to resist sometimes deltaResist *= 1.5 - //nymphomania - if (M.canbearoused && HAS_TRAIT(M, TRAIT_NYMPHO))//I'm okay with this being removed. - deltaResist*= 0.5-(((2/200)*M.arousalloss)/1)//more aroused you are, the weaker resistance you can give, the less you are, the more you gain. (+/- 0.5) //chemical resistance, brain and annaphros are the key to undoing, but the subject has to to be willing to resist. if (owner.reagents.has_reagent("mannitol")) deltaResist *= 1.25 if (owner.reagents.has_reagent("neurine")) deltaResist *= 1.5 - if (!(owner.client?.prefs.cit_toggles & NO_APHRO) && M.canbearoused && lewd) + if (!(owner.client?.prefs.cit_toggles & NO_APHRO) && lewd) if (owner.reagents.has_reagent("anaphro")) deltaResist *= 1.5 if (owner.reagents.has_reagent("anaphro+")) diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index ed28185bb7..5f58121fd4 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -1,17 +1,8 @@ -//Mob vars /mob/living - var/arousalloss = 0 //How aroused the mob is. - var/min_arousal = AROUSAL_MINIMUM_DEFAULT //The lowest this mobs arousal will get. default = 0 - var/max_arousal = AROUSAL_MAXIMUM_DEFAULT //The highest this mobs arousal will get. default = 100 - var/arousal_rate = AROUSAL_START_VALUE //The base rate that arousal will increase in this mob. - var/arousal_loss_rate = AROUSAL_START_VALUE //How easily arousal can be relieved for this mob. - var/canbearoused = FALSE //Mob-level disabler for arousal. Starts off and can be enabled as features are added for different mob types. var/mb_cd_length = 5 SECONDS //5 second cooldown for masturbating because fuck spam. var/mb_cd_timer = 0 //The timer itself /mob/living/carbon/human - canbearoused = TRUE - var/saved_underwear = ""//saves their underwear so it can be toggled later var/saved_undershirt = "" var/saved_socks = "" @@ -21,8 +12,6 @@ //Species vars /datum/species - var/arousal_gain_rate = AROUSAL_START_VALUE //Rate at which this species becomes aroused - var/arousal_lose_rate = AROUSAL_START_VALUE //Multiplier for how easily arousal can be relieved var/list/cum_fluids = list("semen") var/list/milk_fluids = list("milk") var/list/femcum_fluids = list("femcum") @@ -30,7 +19,7 @@ //Mob procs /mob/living/carbon/human/proc/underwear_toggle() set name = "Toggle undergarments" - set category = "IC" + set category = "Arousal" var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling") as null|anything in list("Top", "Bottom", "Socks", "All") if(!confirm) @@ -52,131 +41,6 @@ update_body() -/mob/living/proc/handle_arousal(times_fired) - return - -/mob/living/carbon/handle_arousal(times_fired) - if(!canbearoused || !dna) - return - var/datum/species/S = dna.species - if(!S || (times_fired % 36) || !getArousalLoss() >= max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. - return - var/our_loss = arousal_rate * S.arousal_gain_rate - if(HAS_TRAIT(src, TRAIT_EXHIBITIONIST) && client) - var/amt_nude = 0 - for(var/obj/item/organ/genital/G in internal_organs) - if(G.is_exposed()) - amt_nude++ - if(amt_nude) - var/watchers = 0 - for(var/mob/living/L in view(src)) - if(L.client && !L.stat && !L.eye_blind && (src in view(L))) - watchers++ - if(watchers) - our_loss += (amt_nude * watchers) + S.arousal_gain_rate - adjustArousalLoss(our_loss) - -/mob/living/proc/getArousalLoss() - return arousalloss - -/mob/living/proc/adjustArousalLoss(amount, updating_arousal=1) - if(status_flags & GODMODE || !canbearoused) - return FALSE - arousalloss = CLAMP(arousalloss + amount, min_arousal, max_arousal) - if(updating_arousal) - updatearousal() - -/mob/living/proc/setArousalLoss(amount, updating_arousal=1) - if(status_flags & GODMODE || !canbearoused) - return FALSE - arousalloss = CLAMP(amount, min_arousal, max_arousal) - if(updating_arousal) - updatearousal() - -/mob/living/proc/getPercentAroused() - var/percentage = ((100 / max_arousal) * arousalloss) - return percentage - -/mob/living/proc/isPercentAroused(percentage)//returns true if the mob's arousal (measured in a percent of 100) is greater than the arg percentage. - if(!isnum(percentage) || percentage > 100 || percentage < 0) - CRASH("Provided percentage is invalid") - if(getPercentAroused() >= percentage) - return TRUE - return FALSE - -//H U D// -/mob/living/proc/updatearousal() - update_arousal_hud() - -/mob/living/carbon/updatearousal() - . = ..() - for(var/obj/item/organ/genital/G in internal_organs) - if(istype(G)) - var/datum/sprite_accessory/S - switch(G.type) - if(/obj/item/organ/genital/penis) - S = GLOB.cock_shapes_list[G.shape] - if(/obj/item/organ/genital/testicles) - S = GLOB.balls_shapes_list[G.shape] - if(/obj/item/organ/genital/vagina) - S = GLOB.vagina_shapes_list[G.shape] - if(/obj/item/organ/genital/breasts) - S = GLOB.breasts_shapes_list[G.shape] - if(S?.alt_aroused) - G.aroused_state = isPercentAroused(G.aroused_amount) - else - G.aroused_state = FALSE - G.update_appearance() - -/mob/living/proc/update_arousal_hud() - return FALSE - -/mob/living/carbon/human/update_arousal_hud() - if(!client || !(hud_used?.arousal)) - return FALSE - if(!canbearoused) - hud_used.arousal.icon_state = "" - return FALSE - else - var/value = FLOOR(getPercentAroused(), 10) - hud_used.arousal.icon_state = "arousal[value]" - return TRUE - -/obj/screen/arousal - name = "arousal" - icon_state = "arousal0" - icon = 'modular_citadel/icons/obj/genitals/hud.dmi' - screen_loc = ui_arousal - -/obj/screen/arousal/Click() - if(!isliving(usr)) - return FALSE - var/mob/living/M = usr - if(M.canbearoused) - M.mob_climax() - return TRUE - else - to_chat(M, "Arousal is disabled. Feature is unavailable.") - - -/mob/living/proc/mob_climax(forced_climax = FALSE)//This is just so I can test this shit without being forced to add actual content to get rid of arousal. Will be a very basic proc for a while. - set name = "Masturbate" - set category = "IC" - if(canbearoused && !restrained() && !stat) - if(mb_cd_timer <= world.time) - //start the cooldown even if it fails - mb_cd_timer = world.time + mb_cd_length - if(getArousalLoss() >= 33)//one third of average max_arousal or greater required - visible_message("[src] starts masturbating!", \ - "You start masturbating.") - if(do_after(src, 30, target = src)) - visible_message("[src] relieves [p_them()]self!", \ - "You have relieved yourself.") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - setArousalLoss(min_arousal) - else - to_chat(src, "You aren't aroused enough for that.") - /obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found. if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) . = reagents @@ -189,97 +53,38 @@ /mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE) if(!G) return - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - setArousalLoss(min_arousal) if(!target || !R) return var/turfing = isturf(target) - if(spill & R.total_volume >= 5) + if(spill && R.total_volume >= 5) R.reaction(turfing ? target : target.loc, TOUCH, 1, 0) if(!turfing) R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1)) R.clear_reagents() -//These are various procs that we'll use later, split up for readability instead of having one, huge proc. -//For all of these, we assume the arguments given are proper and have been checked beforehand. -/mob/living/carbon/human/proc/mob_masturbate(obj/item/organ/genital/G, mb_time = 30) //Masturbation, keep it gender-neutral - var/datum/reagents/fluid_source = G.climaxable(src) - if(!fluid_source) - return - var/obj/item/organ/genital/PP = CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) ? G.linked_organ : G - if(!PP) - to_chat(src, "You shudder, unable to cum with your [name].") - if(mb_time) - visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \ - "You start to [G.masturbation_verb] your [G.name].") - if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) - return - visible_message("[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with [p_their()] [PP.name]!", \ - "You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with your [PP.name].") - do_climax(fluid_source, loc, G) - /mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes var/datum/reagents/fluid_source = G.climaxable(src, TRUE) if(!fluid_source) - visible_message("[src] shudders, their [G.name] unable to cum.", \ - "Your [G.name] cannot cum, giving no relief.") + to_chat(src,"Your [G.name] cannot cum.") return if(mb_time) //as long as it's not instant, give a warning - visible_message("[src] looks like they're about to cum.", \ - "You feel yourself about to orgasm.") + to_chat(src,"You feel yourself about to orgasm.") if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) return - visible_message("[src] orgasms[isturf(loc) ? " onto [loc]" : ""], using [p_their()] [G.name]!", \ - "You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].") + to_chat(src,"You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].") do_climax(fluid_source, loc, G) -/mob/living/carbon/human/proc/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, mb_time = 30) //Used for climaxing with any living thing - var/datum/reagents/fluid_source = G.climaxable(src) - if(!fluid_source) - return - if(mb_time) //Skip warning if this is an instant climax. - visible_message("[src] is about to climax with [L]!", \ - "You're about to climax with [L]!") - if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE)) - return - if(spillage) - visible_message("[src] climaxes with [L], overflowing and spilling, using [p_their()] [G.name]!", \ - "You orgasm with [L], spilling out of them, using your [G.name].") - else //knots and other non-spilling orgasms - visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \ - "You ejaculate with [L], your [G.name] spilling nothing.") - SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - do_climax(fluid_source, spillage ? loc : L, G, spillage) - - /mob/living/carbon/human/proc/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time = 30) //For beaker-filling, beware the bartender var/datum/reagents/fluid_source = G.climaxable(src) if(!fluid_source) return if(mb_time) - visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \ - "You start to [G.masturbation_verb] your [G.name] over [container].") + to_chat(src,"You start to [G.masturbation_verb] your [G.name] over [container].") if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE)) return - visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \ - "You used your [G.name] to fill [container].") + to_chat(src,"You used your [G.name] to fill [container].") do_climax(fluid_source, container, G, FALSE) -/mob/living/carbon/human/proc/pick_masturbate_genitals(silent = FALSE) - var/list/genitals_list - var/list/worn_stuff = get_equipped_items() - - for(var/obj/item/organ/genital/G in internal_organs) - if(CHECK_BITFIELD(G.genital_flags, CAN_MASTURBATE_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with - if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ) - continue - LAZYADD(genitals_list, G) - if(LAZYLEN(genitals_list)) - var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list - return ret_organ - else if(!silent) - to_chat(src, "You cannot masturbate without available genitals.") - /mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE) var/list/genitals_list var/list/worn_stuff = get_equipped_items() @@ -293,27 +98,6 @@ else if(!silent) to_chat(src, "You cannot climax without available genitals.") -/mob/living/carbon/human/proc/pick_partner(silent = FALSE) - var/list/partners = list() - if(pulling) - partners += pulling - if(pulledby) - partners += pulledby - //Now we got both of them, let's check if they're proper - for(var/mob/living/L in partners) - if(iscarbon(L)) - var/mob/living/carbon/C = L - if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed()) //Nothing through_clothing, no proper partner. - partners -= C - //NOW the list should only contain correct partners - if(!partners.len) - if(!silent) - to_chat(src, "You cannot do this alone.") - return //No one left. - var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null - if(target && in_range(src, target)) - return target - /mob/living/carbon/human/proc/pick_climax_container(silent = FALSE) var/list/containers_list = list() @@ -349,13 +133,13 @@ return TRUE //Here's the main proc itself -/mob/living/carbon/human/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints +/mob/living/carbon/human/proc/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints if(mb_cd_timer > world.time) if(!forced_climax) //Don't spam the message to the victim if forced to come too fast to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!") return - if(!canbearoused || !has_dna()) + if(!client?.prefs.arousable || !has_dna()) return if(stat == DEAD) if(!forced_climax) @@ -363,31 +147,6 @@ return if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks for(var/obj/item/organ/genital/G in internal_organs) - if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles - continue - var/mob/living/partner - var/check_target - var/list/worn_stuff = get_equipped_items() - - if(G.is_exposed(worn_stuff)) - if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick - if(isliving(pulling)) //Don't fuck objects - check_target = pulling - if(pulledby && !check_target) //prioritise pulled over pulledby - if(isliving(pulledby)) - check_target = pulledby - //Now we should have a partner, or else we have to come alone - if(check_target) - if(iscarbon(check_target)) //carbons can have clothes - var/mob/living/carbon/C = check_target - if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough? - partner = C - else //A cat is fine too - partner = check_target - if(partner) //Did they pass the clothing checks? - mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced - continue //You've climaxed once with this organ, continue on - //not exposed OR if no partner was found while exposed, climax alone mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms //Now all genitals that could climax, have. //Since this was a forced climax, we do not need to continue with the other stuff @@ -398,42 +157,20 @@ if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious. to_chat(src, "You must be conscious to do that!") return - if(getArousalLoss() < 33) //flat number instead of percentage - to_chat(src, "You aren't aroused enough for that!") - return //Ok, now we check what they want to do. - var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container") + var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax", "Fill container") if(!choice) return switch(choice) - if("Masturbate") - if(!available_rosie_palms()) - return - //We got hands, let's pick an organ - var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals() - if(picked_organ && available_rosie_palms(TRUE)) - mob_masturbate(picked_organ) - return - - if("Climax alone") + if("Climax") if(!available_rosie_palms()) return var/obj/item/organ/genital/picked_organ = pick_climax_genitals() if(picked_organ && available_rosie_palms(TRUE)) mob_climax_outside(picked_organ) - if("Climax with partner") - //We need no hands, we can be restrained and so on, so let's pick an organ - var/obj/item/organ/genital/picked_organ = pick_climax_genitals() - if(picked_organ) - var/mob/living/partner = pick_partner() //Get someone - if(partner) - var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as null|anything in list("Yes", "No") - if(spillage && in_range(src, partner)) - mob_climax_partner(picked_organ, partner, spillage == "Yes" ? TRUE : FALSE) - if("Fill container") //We'll need hands and no restraints. if(!available_rosie_palms(FALSE, /obj/item/reagent_containers)) @@ -447,4 +184,10 @@ if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers)) mob_fill_container(picked_organ, fluid_container) - mb_cd_timer = world.time + mb_cd_length \ No newline at end of file + mb_cd_timer = world.time + mb_cd_length + +/mob/living/carbon/human/verb/climax_verb() + set category = "Arousal" + set name = "Climax" + set desc = "Lets you choose a couple ways to ejaculate." + mob_climax() diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 8d70464a2d..af9646fa51 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -2,10 +2,11 @@ color = "#fcccb3" w_class = WEIGHT_CLASS_NORMAL var/shape = "human" - var/sensitivity = AROUSAL_START_VALUE + var/sensitivity = 1 // wow if this were ever used that'd be cool but it's not but i'm keeping it for my unshit code var/genital_flags //see citadel_defines.dm var/masturbation_verb = "masturbate" var/orgasm_verb = "cumming" //present continous + var/arousal_verb = "feel aroused" var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? var/size = 2 //can vary between num or text, just used in icon_state strings var/fluid_id = null @@ -14,7 +15,6 @@ var/fluid_rate = CUM_RATE var/fluid_mult = 1 var/aroused_state = FALSE //Boolean used in icon_state strings - var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link(). var/layer_index = GENITAL_LAYER_INDEX //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in. @@ -85,16 +85,14 @@ H.update_genitals() /mob/living/carbon/verb/toggle_genitals() - set category = "IC" + set category = "Arousal" set name = "Expose/Hide genitals" set desc = "Allows you to toggle which genitals should show through clothes or not." var/list/genital_list = list() - for(var/obj/item/organ/O in internal_organs) - if(isgenital(O)) - var/obj/item/organ/genital/G = O - if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL)) - genital_list += G + for(var/obj/item/organ/genital/G in internal_organs) + if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL)) + genital_list += G if(!genital_list.len) //There is nothing to expose return //Full list of exposable genitals created @@ -105,6 +103,35 @@ picked_organ.toggle_visibility(picked_visibility) return +/mob/living/carbon/verb/toggle_arousal_state() + set category = "Arousal" + set name = "Toggle genital arousal" + set desc = "Allows you to toggle which genitals are showing signs of arousal." + var/list/genital_list = list() + for(var/obj/item/organ/genital/G in internal_organs) + var/datum/sprite_accessory/S + switch(G.type) + if(/obj/item/organ/genital/penis) + S = GLOB.cock_shapes_list[G.shape] + if(/obj/item/organ/genital/testicles) + S = GLOB.balls_shapes_list[G.shape] + if(/obj/item/organ/genital/vagina) + S = GLOB.vagina_shapes_list[G.shape] + if(/obj/item/organ/genital/breasts) + S = GLOB.breasts_shapes_list[G.shape] + if(S?.alt_aroused) + genital_list += G + if(!genital_list.len) //There's nothing that can show arousal + return + var/obj/item/organ/genital/picked_organ + picked_organ = input(src, "Choose which genitalia to toggle arousal on", "Set genital arousal", null) in genital_list + if(picked_organ) + picked_organ.aroused_state = !picked_organ.aroused_state + to_chat(src,"You [picked_organ.arousal_verb].") + picked_organ.update_appearance() + return + + /obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY) fluid_max_volume += modifier*2.5 fluid_rate += modifier/10 @@ -233,7 +260,7 @@ //Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours. /mob/living/carbon/human/proc/emergent_genital_call() - if(!canbearoused) + if(!client.prefs.arousable) return FALSE var/organCheck = locate(/obj/item/organ/genital) in internal_organs diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 105f5e157d..19c3ff80a9 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -11,6 +11,7 @@ shape = "pair" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION masturbation_verb = "massage" + arousal_verb = "feel very sensitive in your breasts" orgasm_verb = "leaking" fluid_transfer_factor = 0.5 var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0) diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 408d6521d0..d2d827e66d 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -6,6 +6,7 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS masturbation_verb = "stroke" + arousal_verb = "pop a boner" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH linked_organ_slot = ORGAN_SLOT_TESTICLES fluid_transfer_factor = 0.5 @@ -26,7 +27,7 @@ ..() /obj/item/organ/genital/penis/update_size(modified = FALSE) - if(length < 0)//I don't actually know what round() does to negative numbers, so to be safe!! + if(length <= 0)//I don't actually know what round() does to negative numbers, so to be safe!! if(owner) to_chat(owner, "You feel your tallywacker shrinking away from your body as your groin flattens out!") QDEL_IN(src, 1) diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index 0df954fd79..7ecc0c155c 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -8,6 +8,7 @@ size = 1 //There is only 1 size right now genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH masturbation_verb = "finger" + arousal_verb = "feel wet" fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS layer_index = VAGINA_LAYER_INDEX var/cap_length = 8//D E P T H (cap = capacity) diff --git a/modular_citadel/code/modules/arousal/toys/dildos.dm b/modular_citadel/code/modules/arousal/toys/dildos.dm index 964c9964ad..58245c0c5f 100644 --- a/modular_citadel/code/modules/arousal/toys/dildos.dm +++ b/modular_citadel/code/modules/arousal/toys/dildos.dm @@ -5,8 +5,7 @@ name = "dildo" desc = "Floppy!" icon = 'modular_citadel/icons/obj/genitals/dildo.dmi' - damtype = AROUSAL - force = 5 + force = 0 hitsound = 'sound/weapons/tap.ogg' throwforce = 0 icon_state = "dildo_knotted_2" diff --git a/modular_citadel/code/modules/client/preferences.dm b/modular_citadel/code/modules/client/preferences.dm index eef8664fbb..4e7cb2972f 100644 --- a/modular_citadel/code/modules/client/preferences.dm +++ b/modular_citadel/code/modules/client/preferences.dm @@ -49,10 +49,9 @@ if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT) return TRUE -datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1) +/datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1) ..() character.give_genitals(TRUE) character.flavor_text = features["flavor_text"] //Let's update their flavor_text at least initially - character.canbearoused = arousable if(icon_updates) character.update_genitals() diff --git a/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm b/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm deleted file mode 100644 index 547c1a5768..0000000000 --- a/modular_citadel/code/modules/integrated_electronics/subtypes/manipulation.dm +++ /dev/null @@ -1,53 +0,0 @@ -/obj/item/integrated_circuit/manipulation/electric_stimulator - name = "electronic stimulation module" - desc = "Used to induce sexual stimulation in a target via electricity." - icon_state = "power_relay" - extended_desc = "The circuit accepts a reference to a person, as well as a number representing the strength of the shock, and upon activation, attempts to stimulate them to orgasm. The number ranges from -35 to 35, with negative numbers reducing arousal and positive numbers increasing it by that amount." - complexity = 15 - size = 2 - inputs = list("target" = IC_PINTYPE_REF, "strength" = IC_PINTYPE_NUMBER) - outputs = list("arousal gain"=IC_PINTYPE_NUMBER) - activators = list("fire" = IC_PINTYPE_PULSE_IN, "on success" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT, "on orgasm" = IC_PINTYPE_PULSE_OUT) - spawn_flags = IC_SPAWN_RESEARCH - power_draw_per_use = 500 - cooldown_per_use = 50 - ext_cooldown = 25 - -/obj/item/integrated_circuit/manipulation/electric_stimulator/do_work() - set_pin_data(IC_OUTPUT, 1, 0) - var/mob/living/M = get_pin_data_as_type(IC_INPUT, 1, /mob/living) - if(!check_target(M)) - return - - var/arousal_gain = CLAMP(get_pin_data(IC_INPUT, 2),-35,35) - set_pin_data(IC_OUTPUT, 1, arousal_gain) - - if(ismob(M) && M.canbearoused && arousal_gain != 0) - var/orgasm = FALSE - if(arousal_gain > 0) - if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna()) - var/mob/living/carbon/human/H = M - var/orgasm_message = pick("A sharp pulse of electricity pushes you to orgasm!", "You feel a jolt of electricity force you into orgasm!") - H.visible_message("\The [assembly] electrodes shock [H]!", "[orgasm_message]") - playsound(src, "sound/effects/light_flicker.ogg", 30, 1) - H.mob_climax(forced_climax=TRUE) - orgasm = TRUE - else - M.adjustArousalLoss(arousal_gain) - var/stimulate_message = pick("You feel a sharp warming tingle of electricity through your body!", "A burst of arousing electricity flows through your body!") - M.visible_message("\The [assembly] electrodes shock [M]!", "[stimulate_message]") - - else - var/stimulate_message = pick("You feel a dull prickle of electricity through your body!", "A burst of dull electricity flows through your body!") - M.visible_message("\The [assembly] electrodes shock [M]!", "[stimulate_message]") - M.adjustArousalLoss(arousal_gain) - - playsound(src, "sound/effects/light_flicker.ogg", 30, 1) - push_data() - activate_pin(2) - if(orgasm) activate_pin(4) - - else - visible_message("\The [assembly] electrodes fail to shock [M]!") - push_data() - activate_pin(3) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index 65c652434b..66f0908a8e 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -312,8 +312,6 @@ Creating a chem with a low purity will make you permanently fall in love with so SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded") else if(get_dist(M, love) < 8) - if(HAS_TRAIT(M, TRAIT_NYMPHO)) //Add this back when merged/updated. - M.adjustArousalLoss(5) var/message = "[(lewd?"I'm next to my crush..! Eee!":"I'm making friends with [love]!")]" SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "InLove", /datum/mood_event/InLove, message) SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove") diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index f6b70eb7b6..b9619805c6 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -100,14 +100,18 @@ color = "#FFADFF"//PINK, rgb(255, 173, 255) /datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M) - if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if(prob(33)) - M.adjustArousalLoss(2) - if(prob(5)) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) + if((prob(min(current_cycle/2,5)))) M.emote(pick("moan","blush")) - if(prob(5)) + if(prob(min(current_cycle/4,10))) var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.") to_chat(M, "[aroused_message]") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/genital/G in H.internal_organs) + if(!G.aroused_state && prob(current_cycle)) + G.aroused_state = TRUE + to_chat(M, "You suddenly [G.arousal_verb]!") ..() /datum/reagent/drug/aphrodisiacplus @@ -122,21 +126,26 @@ overdose_threshold = 20 /datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO)) - if(prob(33)) - M.adjustArousalLoss(6)//not quite six times as powerful, but still considerably more powerful. + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO)) if(prob(5)) - if(M.getArousalLoss() > 75) + if(prob(current_cycle)) M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn...")) else M.emote(pick("moan","blush")) if(prob(5)) var/aroused_message - if(M.getArousalLoss() > 90) + if(current_cycle>25) aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!") else aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.") to_chat(M, "[aroused_message]") + REMOVE_TRAIT(M,TRAIT_NEVERBONER,"aphro") + if(ishuman(M)) + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/genital/G in H.internal_organs) + if(!G.aroused_state) + G.aroused_state = TRUE + to_chat(M, "You suddenly [G.arousal_verb]!") ..() /datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M) @@ -154,15 +163,11 @@ ..() /datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M) - if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) - if(prob(5) && M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna()) + if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33)) + if(prob(5) && ishuman(M) && M.has_dna()) if(prob(5)) //Less spam to_chat(M, "Your libido is going haywire!") - if(M.min_arousal < 50) - M.min_arousal += 1 - if(M.min_arousal < M.max_arousal) - M.min_arousal += 1 - M.adjustArousalLoss(2) + ADD_TRAIT(M,TRAIT_PERMABONER,"aphro") ..() /datum/reagent/drug/anaphrodisiac @@ -176,8 +181,16 @@ reagent_state = SOLID /datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M) - if(M && M.canbearoused && prob(33)) - M.adjustArousalLoss(-2) + if(M && M.client?.prefs.arousable && prob(16)) + if(ishuman(M)) + var/unboner = FALSE + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/genital/G in H.internal_organs) + if(G.aroused_state) + G.aroused_state = FALSE + unboner = TRUE + if(unboner) + to_chat(M, "You no longer feel aroused.") ..() /datum/reagent/drug/anaphrodisiacplus @@ -190,17 +203,22 @@ overdose_threshold = 20 /datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M) - if(M && M.canbearoused && prob(33)) - M.adjustArousalLoss(-4) + if(M && M.client?.prefs.arousable) + REMOVE_TRAIT(M,TRAIT_PERMABONER,"aphro") + if(ishuman(M)) + var/unboner = FALSE + var/mob/living/carbon/human/H = M + for(var/obj/item/organ/genital/G in H.internal_organs) + if(G.aroused_state) + G.aroused_state = FALSE + unboner = TRUE + if(unboner) + to_chat(M, "You no longer feel aroused.") ..() /datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M) - if(M && M.canbearoused && prob(33)) - if(M.min_arousal > 0) - M.min_arousal -= 1 - if(M.min_arousal > 50) - M.min_arousal -= 1 - M.adjustArousalLoss(-2) + if(M && M.client?.prefs.arousable && prob(5)) + ADD_TRAIT(M,TRAIT_NEVERBONER,"aphro") ..() //recipes diff --git a/tgstation.dme b/tgstation.dme index 30fcc602ce..4cfc15af8d 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -3126,7 +3126,6 @@ #include "modular_citadel\code\modules\custom_loadout\custom_items.dm" #include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm" #include "modular_citadel\code\modules\custom_loadout\read_from_file.dm" -#include "modular_citadel\code\modules\integrated_electronics\subtypes\manipulation.dm" #include "modular_citadel\code\modules\mentor\follow.dm" #include "modular_citadel\code\modules\mentor\mentor.dm" #include "modular_citadel\code\modules\mentor\mentor_memo.dm" From e7684f5df7f426a49cdab83576c7d69798af23f9 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 5 Jan 2020 19:29:23 -0800 Subject: [PATCH 050/409] whoops forgot to use sensitivity --- code/modules/reagents/chemistry/reagents/drink_reagents.dm | 2 +- code/modules/reagents/chemistry/reagents/other_reagents.dm | 2 +- modular_citadel/code/modules/reagents/reagents/cit_reagents.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 07d4b13b14..33eee92a31 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -968,7 +968,7 @@ to_chat(M, "[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]") if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(5)) for(var/obj/item/organ/genital/G in M.internal_organs) - if(!G.aroused_state && prob(5)) + if(!G.aroused_state && prob(5*G.sensitivity)) G.aroused_state = TRUE to_chat(M, "You feel like playing with your [G.name]!") diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 60ef8053b1..b50f424a6c 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2283,7 +2283,7 @@ if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO && ishuman(M))) var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) - if(!G.aroused_state && prob(2)) + if(!G.aroused_state && prob(2*G.sensitivity)) G.aroused_state = TRUE to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index b9619805c6..a44075079e 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -109,7 +109,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M for(var/obj/item/organ/genital/G in H.internal_organs) - if(!G.aroused_state && prob(current_cycle)) + if(!G.aroused_state && prob(current_cycle*G.sensitivity)) G.aroused_state = TRUE to_chat(M, "You suddenly [G.arousal_verb]!") ..() From 218e701fa9925df5603a7e4b2e6b15af3f883620 Mon Sep 17 00:00:00 2001 From: Putnam Date: Sun, 5 Jan 2020 21:48:04 -0800 Subject: [PATCH 051/409] whoops forgot update appearance --- code/modules/reagents/chemistry/reagents/drink_reagents.dm | 1 + code/modules/reagents/chemistry/reagents/other_reagents.dm | 1 + .../code/modules/reagents/reagents/cit_reagents.dm | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 33eee92a31..2fa012ae87 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -970,6 +970,7 @@ for(var/obj/item/organ/genital/G in M.internal_organs) if(!G.aroused_state && prob(5*G.sensitivity)) G.aroused_state = TRUE + G.update_appearance() to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index b50f424a6c..dc39c433eb 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2285,5 +2285,6 @@ for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state && prob(2*G.sensitivity)) G.aroused_state = TRUE + G.update_appearance() to_chat(M, "You feel like playing with your [G.name]!") ..() diff --git a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm index a44075079e..50dee539e3 100644 --- a/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm +++ b/modular_citadel/code/modules/reagents/reagents/cit_reagents.dm @@ -111,6 +111,7 @@ for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state && prob(current_cycle*G.sensitivity)) G.aroused_state = TRUE + G.update_appearance() to_chat(M, "You suddenly [G.arousal_verb]!") ..() @@ -145,6 +146,7 @@ for(var/obj/item/organ/genital/G in H.internal_organs) if(!G.aroused_state) G.aroused_state = TRUE + G.update_appearance() to_chat(M, "You suddenly [G.arousal_verb]!") ..() @@ -188,6 +190,7 @@ for(var/obj/item/organ/genital/G in H.internal_organs) if(G.aroused_state) G.aroused_state = FALSE + G.update_appearance() unboner = TRUE if(unboner) to_chat(M, "You no longer feel aroused.") @@ -211,6 +214,7 @@ for(var/obj/item/organ/genital/G in H.internal_organs) if(G.aroused_state) G.aroused_state = FALSE + G.update_appearance() unboner = TRUE if(unboner) to_chat(M, "You no longer feel aroused.") From 32043a9062ef3b36bc2bd826b7f199d54d10380f Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 6 Jan 2020 01:14:00 -0800 Subject: [PATCH 052/409] whoops forgot permaboner --- code/__DEFINES/citadel_defines.dm | 1 + code/modules/client/preferences.dm | 5 ++++ .../chemistry/reagents/drink_reagents.dm | 5 ++-- .../chemistry/reagents/other_reagents.dm | 5 ++-- .../code/modules/arousal/genitals.dm | 16 ++++++++++--- .../code/modules/arousal/organs/breasts.dm | 3 ++- .../code/modules/arousal/organs/penis.dm | 3 ++- .../code/modules/arousal/organs/testicles.dm | 2 ++ .../code/modules/arousal/organs/vagina.dm | 3 ++- .../modules/reagents/reagents/cit_reagents.dm | 24 ++++++++++--------- 10 files changed, 46 insertions(+), 21 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index c3bf3d2891..2b19610040 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -111,6 +111,7 @@ #define NEVER_HYPNO (1<<8) #define NO_APHRO (1<<9) #define NO_ASS_SLAP (1<<10) +#define BIMBOFICATION (1<<11) #define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 7b7cf3413e..546268b5c7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1007,6 +1007,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Forced Feminization: [(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]
    " dat += "Forced Masculinization: [(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]
    " dat += "Lewd Hypno: [(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]
    " + dat += "Bimbofication: [(cit_toggles & BIMBOFICATION) ? "Allowed" : "Disallowed"]
    " dat += "" dat +="" dat += "