diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml
index d22c6be2de5..81d435a4056 100644
--- a/.github/workflows/ci_suite.yml
+++ b/.github/workflows/ci_suite.yml
@@ -10,7 +10,7 @@ jobs:
run_linters:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Run Linters
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
concurrency:
group: run_linters-${{ github.ref }}
cancel-in-progress: true
@@ -56,7 +56,7 @@ jobs:
compile_all_maps:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Compile Maps
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
concurrency:
group: compile_all_maps-${{ github.ref }}
cancel-in-progress: true
@@ -76,7 +76,7 @@ jobs:
run_all_tests:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Integration Tests
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
services:
mysql:
image: mysql:latest
@@ -127,7 +127,7 @@ jobs:
if: "!contains(github.event.head_commit.message, '[ci skip]') && always()"
needs: [run_all_tests]
name: Compare Screenshot Tests
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3
# If we ever add more artifacts, this is going to break, but it'll be obvious.
diff --git a/cev_eris.dme b/cev_eris.dme
index 232ffbd9467..95a6ad58348 100644
--- a/cev_eris.dme
+++ b/cev_eris.dme
@@ -171,6 +171,7 @@
#include "code\ATMOSPHERICS\he_pipes.dm"
#include "code\ATMOSPHERICS\mainspipe.dm"
#include "code\ATMOSPHERICS\pipes.dm"
+#include "code\ATMOSPHERICS\tanks.dm"
#include "code\ATMOSPHERICS\components\portables_connector.dm"
#include "code\ATMOSPHERICS\components\tvalve.dm"
#include "code\ATMOSPHERICS\components\valve.dm"
@@ -280,7 +281,6 @@
#include "code\datums\callback.dm"
#include "code\datums\category.dm"
#include "code\datums\contract.dm"
-#include "code\datums\datacore.dm"
#include "code\datums\datum.dm"
#include "code\datums\datum_click_handlers.dm"
#include "code\datums\datum_hud.dm"
@@ -750,14 +750,12 @@
#include "code\game\machinery\computer\computer.dm"
#include "code\game\machinery\computer\guestpass.dm"
#include "code\game\machinery\computer\law.dm"
-#include "code\game\machinery\computer\medical.dm"
#include "code\game\machinery\computer\message.dm"
#include "code\game\machinery\computer\Operating.dm"
#include "code\game\machinery\computer\pod.dm"
#include "code\game\machinery\computer\prisoner.dm"
#include "code\game\machinery\computer\prisonshuttle.dm"
#include "code\game\machinery\computer\robot.dm"
-#include "code\game\machinery\computer\security.dm"
#include "code\game\machinery\computer\station_alert.dm"
#include "code\game\machinery\doors\airlock.dm"
#include "code\game\machinery\doors\airlock_control.dm"
@@ -1457,6 +1455,7 @@
#include "code\modules\asset_cache\asset_cache_item.dm"
#include "code\modules\asset_cache\asset_list.dm"
#include "code\modules\asset_cache\asset_list_items.dm"
+#include "code\modules\asset_cache\assets\legacyuiicons.dm"
#include "code\modules\asset_cache\assets\sanity.dm"
#include "code\modules\asset_cache\assets\sheetmaterials.dm"
#include "code\modules\asset_cache\assets\stats.dm"
@@ -2276,6 +2275,7 @@
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"
#include "code\modules\nano\modules\nano_module.dm"
+#include "code\modules\nano\modules\tgui_type.dm"
#include "code\modules\onestar\generator.dm"
#include "code\modules\onestar\os_cash.dm"
#include "code\modules\onestar\os_turret.dm"
@@ -2465,7 +2465,9 @@
#include "code\modules\projectiles\guns\projectile\battle_rifle\boltgun.dm"
#include "code\modules\projectiles\guns\projectile\battle_rifle\kovacs.dm"
#include "code\modules\projectiles\guns\projectile\battle_rifle\levergun.dm"
+#include "code\modules\projectiles\guns\projectile\modular\interactions.dm"
#include "code\modules\projectiles\guns\projectile\modular\modular_AK.dm"
+#include "code\modules\projectiles\guns\projectile\modular\modular_bolt.dm"
#include "code\modules\projectiles\guns\projectile\modular\modular_MK58.dm"
#include "code\modules\projectiles\guns\projectile\modular\modular_wintermute.dm"
#include "code\modules\projectiles\guns\projectile\other\RPG.dm"
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 317e27d4d4c..d9467989c30 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -48,7 +48,7 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/Destroy()
GLOB.atmos_machinery -= src
- ..()
+ . = ..()
/obj/machinery/atmospherics/proc/atmos_init()
return
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index 96d914be2ab..f6cd55f77cb 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -56,7 +56,7 @@
node2.disconnect(src)
QDEL_NULL(network2)
node2 = null
- ..()
+ . = ..()
/obj/machinery/atmospherics/binary/atmos_init()
diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm
index aa62e93caea..3c5508530ae 100644
--- a/code/ATMOSPHERICS/components/unary/unary_base.dm
+++ b/code/ATMOSPHERICS/components/unary/unary_base.dm
@@ -28,7 +28,7 @@
node1.disconnect(src)
QDEL_NULL(network)
node1 = null
- ..()
+ . = ..()
/obj/machinery/atmospherics/unary/atmos_init()
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
index ae48ca0d338..f86def37c21 100644
--- a/code/ATMOSPHERICS/pipes.dm
+++ b/code/ATMOSPHERICS/pipes.dm
@@ -72,8 +72,6 @@
return QDEL_HINT_QUEUE
/obj/machinery/atmospherics/pipe/attackby(obj/item/I, mob/user)
- if (istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
if (istype(src, /obj/machinery/atmospherics/pipe/vent))
return ..()
@@ -130,8 +128,6 @@
*/
/obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node)
- if(istype(src, /obj/machinery/atmospherics/pipe/tank))
- return ..()
if(istype(node, /obj/machinery/atmospherics/pipe/manifold) || istype(node, /obj/machinery/atmospherics/pipe/manifold4w))
if(pipe_color == node.pipe_color)
@@ -1034,166 +1030,6 @@
icon_connect_type = "-supply"
color = PIPE_COLOR_BLUE
-
-/obj/machinery/atmospherics/pipe/tank
- icon = 'icons/atmos/tank.dmi'
- icon_state = "air_map"
-
- name = "Pressure Tank"
- desc = "A large vessel containing pressurized gas."
-
- volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
- var/start_pressure = 25*ONE_ATMOSPHERE
-
- level = BELOW_PLATING_LEVEL
- dir = SOUTH
- initialize_directions = SOUTH
- density = TRUE
- layer = ABOVE_WINDOW_LAYER
-
-/obj/machinery/atmospherics/pipe/tank/LateInitialize()
- icon_state = "air"
- initialize_directions = dir
- ..()
-
-/obj/machinery/atmospherics/pipe/tank/Process()
- if(!parent)
- ..()
- else
- . = PROCESS_KILL
-
-/obj/machinery/atmospherics/pipe/tank/Destroy()
- if(node1)
- node1.disconnect(src)
-
- . = ..()
-
-/obj/machinery/atmospherics/pipe/tank/pipeline_expansion()
- return list(node1)
-
-/obj/machinery/atmospherics/pipe/tank/update_underlays()
- if(..())
- underlays.Cut()
- var/turf/T = get_turf(src)
- if(!istype(T))
- return
- add_underlay(T, node1, dir)
-
-/obj/machinery/atmospherics/pipe/tank/hide()
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/atmos_init()
- var/connect_direction = dir
-
- for(var/obj/machinery/atmospherics/target in get_step(src, connect_direction))
- if(target.initialize_directions & get_dir(target, src))
- if (check_connect_types(target, src))
- node1 = target
- break
-
- update_underlays()
-
-/obj/machinery/atmospherics/pipe/tank/disconnect(obj/machinery/atmospherics/reference)
- if(reference == node1)
- if(istype(node1, /obj/machinery/atmospherics/pipe))
- QDEL_NULL(parent)
- node1 = null
-
- update_underlays()
-
- return null
-
-/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
- if(istype(W, /obj/item/device/pipe_painter))
- return
-
-/obj/machinery/atmospherics/pipe/tank/air
- name = "Pressure Tank (Air)"
- icon_state = "air_map"
-
-/obj/machinery/atmospherics/pipe/tank/air/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
- "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
-
- ..()
- icon_state = "air"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen
- name = "Pressure Tank (Oxygen)"
- icon_state = "o2_map"
-
-/obj/machinery/atmospherics/pipe/tank/oxygen/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "o2"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen
- name = "Pressure Tank (Nitrogen)"
- icon_state = "n2_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrogen/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "n2"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
- name = "Pressure Tank (Carbon Dioxide)"
- icon_state = "co2_map"
-
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "co2"
-
-/obj/machinery/atmospherics/pipe/tank/plasma
- name = "Pressure Tank (Plasma)"
- description_antag = "Will blind people if they do not wear face-covering gear"
- icon_state = "plasma_map"
-
-/obj/machinery/atmospherics/pipe/tank/plasma/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T20C
-
- air_temporary.adjust_gas("plasma", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "plasma"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
- name = "Pressure Tank (Nitrous Oxide)"
- icon_state = "n2o_map"
-
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/LateInitialize()
- air_temporary = new
- air_temporary.volume = volume
- air_temporary.temperature = T0C
-
- air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
-
- ..()
- icon_state = "n2o"
-
/obj/machinery/atmospherics/pipe/vent
icon = 'icons/obj/atmospherics/pipe_vent.dmi'
icon_state = "intact"
diff --git a/code/ATMOSPHERICS/tanks.dm b/code/ATMOSPHERICS/tanks.dm
new file mode 100644
index 00000000000..21c30552bfb
--- /dev/null
+++ b/code/ATMOSPHERICS/tanks.dm
@@ -0,0 +1,221 @@
+/obj/machinery/atmospherics/tank
+ icon = 'icons/atmos/tank.dmi'
+ icon_state = "air_map"
+
+ name = "Pressure Tank"
+ desc = "A large vessel containing pressurized gas."
+
+ var/volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
+ var/start_pressure = 25*ONE_ATMOSPHERE
+
+ level = BELOW_PLATING_LEVEL
+ dir = SOUTH
+ initialize_directions = SOUTH
+ density = TRUE
+ layer = ABOVE_WINDOW_LAYER
+ var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke
+
+ var/obj/machinery/atmospherics/node
+
+ var/datum/pipe_network/network
+
+ use_power = NO_POWER_USE
+
+ can_buckle = TRUE
+ buckle_require_restraints = 1
+ buckle_lying = -1
+
+/obj/machinery/atmospherics/tank/drain_power()
+ return -1
+
+/obj/machinery/atmospherics/tank/LateInitialize()
+ icon_state = "air"
+ initialize_directions = dir
+ ..()
+
+/obj/machinery/atmospherics/tank/hides_under_flooring()
+ return level != 2
+
+/obj/machinery/atmospherics/tank/return_air()
+ return air_temporary
+
+/obj/machinery/atmospherics/tank/build_network()
+ if(!network && node)
+ network = new /datum/pipe_network()
+ network.normal_members += src
+ network.build_network(node, src)
+
+/obj/machinery/atmospherics/tank/return_network(obj/machinery/atmospherics/reference)
+ build_network()
+
+ if(reference==node)
+ return network
+
+ return null
+
+/obj/machinery/atmospherics/tank/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
+ if(network == old_network)
+ network = new_network
+
+ return TRUE
+
+/obj/machinery/atmospherics/tank/return_network_air(datum/pipe_network/reference)
+ var/list/results = list()
+
+ if(air_temporary)
+ results += air_temporary
+
+ return results
+
+
+/obj/machinery/atmospherics/tank/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
+ if(reference == node)
+ network = new_network
+
+ if(new_network.normal_members.Find(src))
+ return 0
+
+ new_network.normal_members += src
+
+ return null
+
+/obj/machinery/atmospherics/tank/Process()
+ if(!network)
+ ..()
+ network?.update = 1
+ else
+ . = PROCESS_KILL
+
+/obj/machinery/atmospherics/tank/Destroy()
+ if(node)
+ node.disconnect(src)
+ QDEL_NULL(network)
+
+ if(air_temporary)
+ loc.assume_air(air_temporary)
+ QDEL_NULL(air_temporary)
+
+ loc = null
+ node = null
+
+ . = ..()
+ return QDEL_HINT_QUEUE
+
+/obj/machinery/atmospherics/tank/update_underlays()
+ if(..())
+ underlays.Cut()
+ var/turf/T = get_turf(src)
+ if(!istype(T))
+ return
+ add_underlay(T, node, dir)
+
+/obj/machinery/atmospherics/tank/hide()
+ update_underlays()
+
+/obj/machinery/atmospherics/tank/atmos_init()
+ if(node) return
+ var/connect_direction = dir
+
+ for(var/obj/machinery/atmospherics/target in get_step(src, connect_direction))
+ if(target.initialize_directions & get_dir(target, src))
+ if (check_connect_types(target, src))
+ node = target
+ break
+
+ update_underlays()
+
+/obj/machinery/atmospherics/tank/disconnect(obj/machinery/atmospherics/reference)
+ if(reference==node)
+ QDEL_NULL(network)
+ node = null
+
+ update_underlays()
+
+ return null
+
+/obj/machinery/atmospherics/tank/air
+ name = "Pressure Tank (Air)"
+ icon_state = "air_map"
+
+/obj/machinery/atmospherics/tank/air/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
+ "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+
+ ..()
+ icon_state = "air"
+
+/obj/machinery/atmospherics/tank/oxygen
+ name = "Pressure Tank (Oxygen)"
+ icon_state = "o2_map"
+
+/obj/machinery/atmospherics/tank/oxygen/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "o2"
+
+/obj/machinery/atmospherics/tank/nitrogen
+ name = "Pressure Tank (Nitrogen)"
+ icon_state = "n2_map"
+
+/obj/machinery/atmospherics/tank/nitrogen/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "n2"
+
+/obj/machinery/atmospherics/tank/carbon_dioxide
+ name = "Pressure Tank (Carbon Dioxide)"
+ icon_state = "co2_map"
+
+/obj/machinery/atmospherics/tank/carbon_dioxide/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "co2"
+
+/obj/machinery/atmospherics/tank/plasma
+ name = "Pressure Tank (Plasma)"
+ description_antag = "Will blind people if they do not wear face-covering gear"
+ icon_state = "plasma_map"
+
+/obj/machinery/atmospherics/tank/plasma/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T20C
+
+ air_temporary.adjust_gas("plasma", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "plasma"
+
+/obj/machinery/atmospherics/tank/nitrous_oxide
+ name = "Pressure Tank (Nitrous Oxide)"
+ icon_state = "n2o_map"
+
+/obj/machinery/atmospherics/tank/nitrous_oxide/LateInitialize()
+ air_temporary = new
+ air_temporary.volume = volume
+ air_temporary.temperature = T0C
+
+ air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+
+ ..()
+ icon_state = "n2o"
\ No newline at end of file
diff --git a/code/__DEFINES/items.dm b/code/__DEFINES/items.dm
index e288b79ab3d..4f682d97fa1 100644
--- a/code/__DEFINES/items.dm
+++ b/code/__DEFINES/items.dm
@@ -63,6 +63,9 @@
#define GUN_UPGRADE_OVERCHARGE_MAX "overcharge_max_mult"
#define GUN_UPGRADE_OVERCHARGE_RATE "overcharge_rate_mult"
#define GUN_UPGRADE_ONEHANDPENALTY "onehandpenalty_mult"
+#define GUN_UPGRADE_MOVEPENALTY "movementpenalty_mult"
+#define GUN_UPGRADE_RECOILBUILDUP "recoilbuildup_mult"
+#define GUN_UPGRADE_BASESLOW "slowdown_base_add"
//Int additive
#define GUN_UPGRADE_DAMAGEMOD_PLUS "damage_plus"
@@ -81,14 +84,29 @@
#define GUN_UPGRADE_OFFSET "offset" //Constant offset, in degrees
#define GUN_UPGRADE_ZOOM "zoom"
+#define GUN_UPGRADE_SCOPEVISION "scopeseeinvis"
+#define GUN_UPGRADE_SCOPECORRECTION "scopeoffset"
+#define GUN_UPGRADE_DARKSCOPE "scopedarksight"
//Type configuration
+#define GUN_UPGRADE_REPLACE_INTERACTIONS "interactions"
#define GUN_UPGRADE_DEFINE_OK_CALIBERS "ok_calibers"
#define GUN_UPGRADE_DEFINE_CALIBER "caliber"
#define GUN_UPGRADE_DEFINE_MAG_WELL "mag_well"
#define GUN_UPGRADE_DEFINE_STOCK "stock"
#define GUN_UPGRADE_FIREMODES "firemodes"
#define GUN_UPGRADE_DEFINE_GRIP "grip"
+#define GUN_UPGRADE_DEFINE_LOADER "loadtype"
+#define GUN_UPGRADE_DENY_MAG "no_mag"
+#define GUN_UPGRADE_DEFINE_WCLASS "add_wclass"
+#define GUN_UPGRADE_SCOPE_POWER "scope_power"
+
+//Gun Interaction flags
+#define GI_ATTACKSELF 1
+#define GI_LOAD 2
+#define GI_UNLOAD 4
+#define GI_SPIN 8
+#define GI_SPECIAL 16
//boolean
#define GUN_UPGRADE_SILENCER "silencable"
diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm
index 18a82d9b01c..2bebcf467e3 100644
--- a/code/__DEFINES/jobs.dm
+++ b/code/__DEFINES/jobs.dm
@@ -8,10 +8,10 @@
#define JOBS_MEDICAL "Moebius Biolab Officer","Moebius Doctor","Moebius Psychiatrist","Moebius Chemist","Moebius Paramedic","Moebius Bio-Engineer"
#define JOBS_SCIENCE "Moebius Expedition Overseer","Moebius Scientist","Moebius Roboticist"
#define JOBS_MOEBIUS "Moebius Biolab Officer","Moebius Doctor","Moebius Psychiatrist","Moebius Chemist","Moebius Paramedic","Moebius Bio-Engineer","Moebius Expedition Overseer","Moebius Scientist","Moebius Roboticist"
-#define JOBS_CARGO "Guild Merchant","Guild Technician","Guild Miner",
+#define JOBS_GUILD "Guild Merchant","Guild Technician","Guild Miner",
#define JOBS_CIVILIAN "Club Manager","Club Worker","Club Artist",ASSISTANT_TITLE
#define JOBS_CHURCH "NeoTheology Preacher","NeoTheology Acolyte","NeoTheology Agrolyte","NeoTheology Custodian"
-#define JOBS_NONHUMAN "AI","Robot","pAI"
+#define JOBS_SILICON "AI","Robot","pAI"
#define CREDITS "¢"
#define CREDS "¢"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 81457891953..7ed87bd3a0d 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -106,10 +106,10 @@
#define COIN_GOLD "Gold coin"
#define COIN_SILVER "Silver coin"
#define COIN_DIAMOND "Diamond coin"
-#define COIN_IRON "Iron coin"
+#define COIN_PLASTEEL "Plasteel coin"
#define COIN_PLASMA "Solid plasma coin"
#define COIN_URANIUM "Uranium coin"
-#define COIN_PLATINUM "Platunum coin"
+#define COIN_PLATINUM "Platinum coin"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"
diff --git a/code/__DEFINES/perks.dm b/code/__DEFINES/perks.dm
index 210eaa70c3e..d6571683e42 100644
--- a/code/__DEFINES/perks.dm
+++ b/code/__DEFINES/perks.dm
@@ -1,6 +1,6 @@
//fate perks
#define PERK_PAPER_WORM /datum/perk/fate/paper_worm
-#define PERK_FREELACER /datum/perk/fate/freelancer
+#define PERK_FREELANCER /datum/perk/fate/freelancer
#define PERK_NIHILIST /datum/perk/fate/nihilist
#define PERK_MORALIST /datum/perk/fate/moralist
#define PERK_ALCOHOLIC /datum/perk/fate/alcoholic
@@ -49,6 +49,8 @@
#define PERK_CODESPEAK_COP /datum/perk/codespeak
#define PERK_CODESPEAK_SERB /datum/perk/codespeak/serbian
#define PERK_TECHNOMANCER /datum/perk/inspiration
+#define PERK_NEAT /datum/perk/neat
+#define PERK_GREEN_THUMB /datum/perk/greenthumb
#define PERK_CLUB /datum/perk/job/club
#define PERK_CHANNELING /datum/perk/channeling
diff --git a/code/__DEFINES/weapons.dm b/code/__DEFINES/weapons.dm
index c737c7ce3e1..ea223064507 100644
--- a/code/__DEFINES/weapons.dm
+++ b/code/__DEFINES/weapons.dm
@@ -107,3 +107,4 @@
#define RIFLE_RECOIL(x) list(0.8 *x, 5, 2.4*x )
#define LMG_RECOIL(x) list(0.7 *x, 8, 3*x )
#define HMG_RECOIL(x) list(0.6 *x, 12, 3.6*x )
+#define SLATE_RECOIL(x) list(1 *x, 1, 1 *x)
diff --git a/code/__HELPERS/manifest.dm b/code/__HELPERS/manifest.dm
index 334e07960d3..2215f1bbb96 100644
--- a/code/__HELPERS/manifest.dm
+++ b/code/__HELPERS/manifest.dm
@@ -142,13 +142,13 @@
"sec" = filtered_nano_crew_manifest(security_positions),\
"eng" = filtered_nano_crew_manifest(engineering_positions),\
"med" = filtered_nano_crew_manifest(medical_positions),\
- "sup" = filtered_nano_crew_manifest(cargo_positions),\
+ "sup" = filtered_nano_crew_manifest(guild_positions),\
"chr" = filtered_nano_crew_manifest(church_positions),\
- "bot" = silicon_nano_crew_manifest(nonhuman_positions),\
+ "bot" = silicon_nano_crew_manifest(silicon_positions),\
"civ" = filtered_nano_crew_manifest(civilian_positions)\
)
/proc/flat_nano_crew_manifest()
. = list()
. += filtered_nano_crew_manifest(null, TRUE)
- . += silicon_nano_crew_manifest(nonhuman_positions)
\ No newline at end of file
+ . += silicon_nano_crew_manifest(silicon_positions)
\ No newline at end of file
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index c87268b454f..2c8a171b4e2 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -94,8 +94,8 @@ var/syndicate_code_response//Code response for contractors.
var/locations[] = LAZYLEN(SSmapping.main_ship_areas_by_name) ? SSmapping.main_ship_areas_by_name : drinks // If null, defaults to drinks instead.
var/names[] = list()
- for(var/datum/data/record/t in data_core.general)//Picks from crew manifest.
- names += t.fields["name"]
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)//Picks from crew manifest.
+ names += t.get_name()
var/maxwords = words//Extra var to check for duplicates.
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 0785b29e9fc..7a6bf8d5007 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -276,26 +276,21 @@ Turf and target are seperate in case you want to teleport some distance from a t
mind.name = newname
if(oldname)
- //update the datacore records! This is goig to be a bit costly.
- for(var/list/L in list(data_core.general, data_core.medical, data_core.security, data_core.locked))
- for(var/datum/data/record/R in L)
- if(R.fields["name"] == oldname)
- R.fields["name"] = newname
- break
+ for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
+ if(R.get_name() == oldname)
+ R.set_name(newname)
//update our pda and id if we have them on our person
- var/list/searching = GetAllContents(searchDepth = 3)
- var/search_id = 1
- var/search_pda = 1
-
- for(var/A in searching)
- if( search_id && istype(A,/obj/item/card/id) )
+ for(var/obj/A in GetAllContents(searchDepth = 3))
+ if(istype(A,/obj/item/card/id))
var/obj/item/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
ID.name = "[newname]'s ID Card ([ID.assignment])"
- if(!search_pda) break
- search_id = 0
+ if(istype(A.loc, /obj/item/modular_computer))
+ var/obj/item/modular_computer/tolabel = A.loc
+ tolabel.update_label()
+ break
return 1
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index 1777bd31dcf..1fe7dfc2abc 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -241,7 +241,6 @@ SUBSYSTEM_DEF(ticker)
if(!H.mind || player_is_antag(H.mind, only_offstation_roles = 1) || !SSjob.ShouldCreateRecords(H.mind.assigned_role))
continue
CreateModularRecord(H)
- data_core.manifest()
CHECK_TICK
diff --git a/code/controllers/subsystems/trade.dm b/code/controllers/subsystems/trade.dm
index 764d7bd4bb3..a14e2fc89a7 100644
--- a/code/controllers/subsystems/trade.dm
+++ b/code/controllers/subsystems/trade.dm
@@ -541,7 +541,7 @@ SUBSYSTEM_DEF(trade)
create_log_entry("Export", guild_account.get_name(), invoice_contents_info, cost, FALSE, get_turf(senderBeacon))
/datum/controller/subsystem/trade/proc/get_export_price_multiplier(atom/movable/target)
- if(!target || target.anchored)
+ if(!target || isturf(target) || target.anchored)
return NONEXPORTABLE
. = EXPORTABLE
diff --git a/code/datums/craft/gun_parts.dm b/code/datums/craft/gun_parts.dm
index e98868bd083..95bca9de5af 100644
--- a/code/datums/craft/gun_parts.dm
+++ b/code/datums/craft/gun_parts.dm
@@ -67,7 +67,7 @@ semi accepts weird caliber - +1 points
w_class = ITEM_SIZE_SMALL
matter = list(MATERIAL_PLASTEEL = 5)
generic = TRUE
- var/part_overlay
+ var/part_overlay = ""
var/part_itemstring
var/needs_grip_type
generic = FALSE
@@ -75,6 +75,7 @@ semi accepts weird caliber - +1 points
var/datum/component/item_upgrade/I // For changing stats when needed
var/old_quality = 0
var/max_quality = 2
+ var/interactions
// Bonuses from forging/type or maluses from printing
var/cheap = FALSE // Set this to true for cheap variants
@@ -82,8 +83,11 @@ semi accepts weird caliber - +1 points
/obj/item/part/gun/modular/New(location)
..()
I = AddComponent(/datum/component/item_upgrade)
+ if(interactions)
+ interactions = new interactions(src)
I.weapon_upgrades = list(
- UPGRADE_MAXUPGRADES = 1 // Since this takes an upgrade slot, we want to give it back
+ UPGRADE_MAXUPGRADES = 1, // Since this takes an upgrade slot, we want to give it back
+ GUN_UPGRADE_REPLACE_INTERACTIONS = interactions // used for overriding gun behavior
)
I.req_gun_tags = list(GUN_MODULAR)
I.removable = MOD_INTEGRAL // Will get unique removal handling when we get there, until then works by disassembling the frame
@@ -374,21 +378,34 @@ semi accepts weird caliber - +1 points
price_tag = 100
rarity_value = 6
var/list/accepted_calibers = list(CAL_PISTOL, CAL_MAGNUM, CAL_SRIFLE, CAL_CLRIFLE, CAL_LRIFLE, CAL_SHOTGUN)
+ var/loader = MAGAZINE
var/mag_well = MAG_WELL_GENERIC
var/divisor_bonus = 0
var/recoil_bonus = 0
var/damage_bonus = 0
+ var/onehandpenalty = 0
+ var/max_shells = 0
var/list/bonus_firemodes = list()
+ var/no_internal_mag = FALSE
+
+
/obj/item/part/gun/modular/mechanism/New(location, var/quality = 0)
..(quality)
I.weapon_upgrades[GUN_UPGRADE_FIREMODES] = bonus_firemodes
I.weapon_upgrades[GUN_UPGRADE_DEFINE_MAG_WELL] = mag_well
I.weapon_upgrades[GUN_UPGRADE_DEFINE_OK_CALIBERS] = accepted_calibers
+ I.weapon_upgrades[GUN_UPGRADE_DEFINE_LOADER] = loader
+
if(divisor_bonus)
I.weapon_upgrades[GUN_UPGRADE_PEN_MULT] = divisor_bonus
if(recoil_bonus)
I.weapon_upgrades[GUN_UPGRADE_RECOIL] = recoil_bonus
+ if(max_shells)
+ I.weapon_upgrades[GUN_UPGRADE_MAGUP] = max_shells
+ if(no_internal_mag)
+ I.weapon_upgrades[GUN_UPGRADE_DENY_MAG] = TRUE
+
I.gun_loc_tag = PART_MECHANISM
/obj/item/part/gun/modular/mechanism/set_quality(var/quality = 0)
@@ -419,6 +436,10 @@ semi accepts weird caliber - +1 points
name = "revolver mechanism"
desc = "All the bits that makes the bullet go bang, rolling round and round."
icon_state = "mechanism_revolver"
+ max_shells = 6
+
+/obj/item/part/gun/modular/mechanism/revolver/seven
+ max_shells = 7
/obj/item/part/gun/modular/mechanism/shotgun
name = "shotgun mechanism"
@@ -565,6 +586,43 @@ semi accepts weird caliber - +1 points
desc = "All the bits that makes the bullet go bang, slow and methodical."
icon_state = "mechanism_boltaction"
matter = list(MATERIAL_STEEL = 3)
+ accepted_calibers = list(CAL_LRIFLE, CAL_SRIFLE, CAL_PISTOL, CAL_MAGNUM) // used by boltrifles
+ loader = SINGLE_CASING|SPEEDLOADER
+ interactions = /datum/guninteraction/bolted
+ max_shells = 10
+ divisor_bonus = 0.3
+ damage_bonus = 0.4
+
+/obj/item/part/gun/modular/mechanism/boltgun/power
+ accepted_calibers = list(CAL_SRIFLE, CAL_MAGNUM)
+ max_shells = 6
+ divisor_bonus = 1
+ damage_bonus = 0.8
+
+/obj/item/part/gun/modular/mechanism/boltgun/heavy
+ name = "heavy manual-action mechanism"
+ desc = "All the bits that makes the bullet go bang, slow and methodical; for larger calibers."
+ matter = list(MATERIAL_STEEL = 4)
+ accepted_calibers = list(CAL_SHOTGUN, CAL_MAGNUM, CAL_FLARE, CAL_ANTIM) // used by AMRs
+ part_overlay = "big_" // the full entry is handled by the guninteraction
+ loader = SINGLE_CASING
+ max_shells = 1
+ divisor_bonus = 0
+ damage_bonus = 1
+
+/obj/item/part/gun/modular/mechanism/boltgun/junk
+ name = "handmade manual-action mechanism"
+ max_shells = 5
+ divisor_bonus = -0.3
+ damage_bonus = 0.5
+
+/obj/item/part/gun/modular/mechanism/levergun
+ name = "break-action mechanism"
+ desc = "This one breaks in half!"
+ // no icon state available
+ matter = list(MATERIAL_STEEL = 4)
+ accepted_calibers = list(CAL_MAGNUM, CAL_SHOTGUN) // used by leverguns only
+ max_shells = 7
/obj/item/part/gun/modular/mechanism/autorifle/steel
name = "cheap self-loading mechanism"
@@ -583,10 +641,25 @@ semi accepts weird caliber - +1 points
price_tag = 200
rarity_value = 15
var/caliber = CAL_357
+ var/speed
+ var/onehandpenalty
+ var/recoilbuildup
+ var/pierce
+ var/basemove
/obj/item/part/gun/modular/barrel/New(location, var/quality = 0)
..(quality)
I.weapon_upgrades[GUN_UPGRADE_DEFINE_CALIBER] = caliber
+ if(!isnull(speed))
+ I.weapon_upgrades[GUN_UPGRADE_STEPDELAY_MULT] = speed
+ if(onehandpenalty)
+ I.weapon_upgrades[GUN_UPGRADE_ONEHANDPENALTY] = onehandpenalty
+ if(recoilbuildup)
+ I.weapon_upgrades[GUN_UPGRADE_RECOILBUILDUP] = recoilbuildup
+ if(pierce)
+ I.weapon_upgrades[GUN_UPGRADE_PIERC_MULT] = pierce
+ if(basemove)
+ I.weapon_upgrades[GUN_UPGRADE_BASESLOW] = basemove
I.gun_loc_tag = PART_BARREL
@@ -632,6 +705,13 @@ semi accepts weird caliber - +1 points
caliber = CAL_SRIFLE
part_overlay = "well_srifle"
+/obj/item/part/gun/modular/barrel/srifle/long
+ name = "long .20 barrel"
+ desc = "A gun barrel, which keeps the bullet going in the right direction efficiently. Chambered in .20 caliber."
+ onehandpenalty = 1.2
+ recoilbuildup = 1.2
+ speed = 0.8
+
/obj/item/part/gun/modular/barrel/clrifle
name = ".25 barrel"
desc = "A gun barrel, which keeps the bullet going in the right direction. Chambered in .25 caliber."
@@ -671,10 +751,21 @@ semi accepts weird caliber - +1 points
name = ".60 barrel"
desc = "A gun barrel, which keeps the bullet going in the right direction. Chambered in .60 caliber."
icon_state = "barrel_60"
- matter = list(MATERIAL_PLASTEEL = 16)
+ matter = list(MATERIAL_PLASTEEL = 10)
caliber = CAL_ANTIM
part_overlay = "well_amr"
+/obj/item/part/gun/modular/barrel/antim/long
+ name = "long .60 barrel"
+ desc = "A long gun barrel, which keeps the bullet moving in the right direction efficiently. Chambered in .60 caliber."
+ matter = list(MATERIAL_PLASTEEL = 15)
+ speed = 0
+ part_overlay = "well_amr_long"
+ onehandpenalty = 2
+ recoilbuildup = 2
+ pierce = 6
+ basemove = 3
+
// steel barrels
/obj/item/part/gun/modular/barrel/pistol/steel
name = "cheap .35 barrel"
@@ -720,8 +811,124 @@ semi accepts weird caliber - +1 points
generic = FALSE
part_overlay = "stock"
needs_grip_type = TRUE
+ var/brace = 0
+ var/recoilbuildup
+ var/movementcost
+ var/onehandpenalty
+ var/wclassmod = 1
/obj/item/part/gun/modular/stock/New(location, var/quality = 0)
..() // No stat change, so no need for price change either
I.weapon_upgrades[GUN_UPGRADE_DEFINE_STOCK] = TRUE
I.gun_loc_tag = PART_STOCK
+
+ if(movementcost)
+ I.weapon_upgrades[GUN_UPGRADE_MOVEPENALTY] = movementcost
+ if(recoilbuildup)
+ I.weapon_upgrades[GUN_UPGRADE_RECOILBUILDUP] = recoilbuildup
+ if(onehandpenalty)
+ I.weapon_upgrades[GUN_UPGRADE_ONEHANDPENALTY] = onehandpenalty
+ I.weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS] = wclassmod
+
+/obj/item/part/gun/modular/stock/heavy
+ recoilbuildup = 0.7
+ movementcost = 8
+ onehandpenalty = 3
+
+/obj/item/part/gun/modular/stock/longrifle
+ recoilbuildup = 0.8
+ movementcost = 5
+ onehandpenalty = 2.4
+
+/obj/item/part/gun/modular/sights
+ name = "ironsights"
+ desc = "A set of sights for aiming through."
+ var/list/scopes = list()
+ interactions = /datum/guninteraction/zoomed
+ var/scopeaccuracy
+ var/scopeseeinvis
+ var/darksight
+ var/list/powerboost
+
+/obj/item/part/gun/modular/sights/New(location, var/quality = 0)
+ ..(quality)
+ I.weapon_upgrades[GUN_UPGRADE_ZOOM] = scopes
+ if(scopeseeinvis)
+ I.weapon_upgrades[GUN_UPGRADE_SCOPEVISION] = scopeseeinvis
+ if(scopeaccuracy)
+ I.weapon_upgrades[GUN_UPGRADE_SCOPECORRECTION] = scopeaccuracy
+ if(darksight)
+ I.weapon_upgrades[GUN_UPGRADE_DARKSCOPE] = darksight
+ if(powerboost)
+ I.weapon_upgrades[GUN_UPGRADE_SCOPE_POWER] = powerboost
+ I.gun_loc_tag = GUN_SCOPE
+
+/obj/item/part/gun/modular/sights/scopesmall // Arasaka boltgun
+ name = "small scope"
+ desc = "A sight for aiming through. This one is on the smaller side."
+ icon_state = "scope_small"
+ scopes = list(0.5)
+ part_overlay = "scope_small"
+
+/obj/item/part/gun/modular/sights/scopebig // Kadmin
+ name = "medium scope"
+ desc = "A sight for aiming through. This one is medium."
+ icon_state = "scope_big"
+ scopes = list(0.8)
+ part_overlay = "scope_big"
+
+/obj/item/part/gun/modular/sights/customizable
+
+/obj/item/part/gun/modular/sights/customizable/attackby(obj/item/Item, mob/living/user)
+ if(istype(Item, /obj/item/clothing/glasses/powered/thermal))
+ user.visible_message(SPAN_NOTICE("[user] inserts \a [Item] into [src]."), SPAN_NOTICE("You insert [Item] into \the [src]."), "You hear a faint click.", 5)
+ I.weapon_upgrades[GUN_UPGRADE_THERMAL] = TRUE
+ user.drop_from_inventory(Item, src)
+ else if(Item.has_quality(QUALITY_SCREW_DRIVING))
+ var/list/choices = contents.Copy()
+ choices += "Cancel"
+ var/obj/toremove = input("Which upgrade would you like to try to remove?","Removing Upgrades") in choices
+ if(toremove == "Cancel")
+ return TRUE
+ else if(!isnull(toremove))
+ toremove.forceMove(get_turf(src))
+ if(istype(toremove, /obj/item/clothing/glasses/powered/thermal))
+ I.weapon_upgrades[GUN_UPGRADE_THERMAL] = FALSE
+ to_chat(user, SPAN_NOTICE("You successfully remove [toremove] from \the [src]!"))
+
+
+/obj/item/part/gun/modular/sights/customizable/scopeheavy // AMR
+ name = "sniper scope"
+ desc = "A large adjustable sight for aiming through. Provides night vision. Can add advanced lenses to improve vision."
+ icon_state = "scope_heavy"
+ scopes = list(1,2)
+ part_overlay = "scope_heavy"
+ darksight = 7
+ scopeseeinvis = SEE_INVISIBLE_NOLIGHTING
+ scopeaccuracy = 8
+ powerboost = list(0.2, 0.4)
+ interactions = /datum/guninteraction/zoomed/multizoom
+
+/obj/item/part/gun/modular/bayonet
+ name = "integrated bayonet"
+ desc = "A bayonet designed for a firmer attachment, applied during assembly."
+ matter = list(MATERIAL_PLASTEEL = 3, MATERIAL_STEEL = 2)
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "dagger"
+ part_overlay = "bayonet"
+ var/damagedone = 6
+
+/obj/item/part/gun/modular/bayonet/New(location, var/quality = 0)
+ ..(quality)
+ I.weapon_upgrades = list(
+ GUN_UPGRADE_BAYONET = TRUE,
+ GUN_UPGRADE_MELEEDAMAGE = damagedone,
+ GUN_UPGRADE_MELEEPENETRATION = ARMOR_PEN_MODERATE,
+ GUN_UPGRADE_OFFSET = 4
+ )
+
+/obj/item/part/gun/modular/bayonet/steel
+ name = "cheap integrated bayonet"
+ desc = "A bayonet designed for a firmer attachment, applied during assembly. This one's made from cheap steel."
+ matter = list(MATERIAL_STEEL = 2)
+ damagedone = 3
diff --git a/code/datums/craft/recipes/guns.dm b/code/datums/craft/recipes/guns.dm
index 86d2824ac06..439cb6ee0a4 100644
--- a/code/datums/craft/recipes/guns.dm
+++ b/code/datums/craft/recipes/guns.dm
@@ -27,8 +27,8 @@
name = "HM BR \"Riose\""
result = /obj/item/gun/projectile/boltgun/handmade
steps = list(
- list(CRAFT_MATERIAL, 10, MATERIAL_STEEL),
- list(CRAFT_MATERIAL, 10, MATERIAL_WOOD),
+ list(CRAFT_MATERIAL, 13, MATERIAL_STEEL),
+ list(CRAFT_MATERIAL, 5, MATERIAL_WOOD),
list(QUALITY_HAMMERING, 10),
list(QUALITY_ADHESIVE, 15, 70)
)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
deleted file mode 100644
index 5fbabd76693..00000000000
--- a/code/datums/datacore.dm
+++ /dev/null
@@ -1,454 +0,0 @@
-var/global/list/PDA_Manifest = list()
-var/global/ManifestJSON
-
-/hook/startup/proc/createDatacore()
- data_core = new /datum/datacore()
- return 1
-
-/datum/datacore
- var/name = "datacore"
- var/medical[] = list()
- var/general[] = list()
- var/security[] = list()
- //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
- var/locked[] = list()
-
-
-/datum/datacore/proc/get_manifest(monochrome, OOC)
- var/list/heads = new()
- var/list/sec = new()
- var/list/eng = new()
- var/list/med = new()
- var/list/sci = new()
- var/list/car = new()
- var/list/chr = new()
- var/list/civ = new()
- var/list/bot = new()
- var/list/misc = new()
- var/list/isactive = new()
- var/dat = {"
-
-
- Name Rank Activity
- "}
- var/even = 0
- // sort mobs
- for(var/datum/data/record/t in data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- if(OOC)
- var/active = 0
- for(var/mob/M in GLOB.player_list)
- if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
- active = 1
- break
- isactive[name] = active ? "Active" : "Inactive"
- else
- isactive[name] = t.fields["p_stat"]
- //world << "[name]: [rank]"
- //cael - to prevent multiple appearances of a player/job combination, add a continue after each line
- var/department = 0
- if(real_rank in command_positions)
- heads[name] = rank
- department = 1
- if(real_rank in security_positions)
- sec[name] = rank
- department = 1
- if(real_rank in engineering_positions)
- eng[name] = rank
- department = 1
- if(real_rank in medical_positions)
- med[name] = rank
- department = 1
- if(real_rank in science_positions)
- sci[name] = rank
- department = 1
- if(real_rank in cargo_positions)
- car[name] = rank
- department = 1
- if(real_rank in church_positions)
- chr[name] = rank
- department = 1
- if(real_rank in civilian_positions)
- civ[name] = rank
- department = 1
- if(!department && !(name in heads))
- misc[name] = rank
-
- // Synthetics don't have actual records, so we will pull them from here.
-/* for(var/mob/living/silicon/ai/ai in SSmobs.mob_list)
- bot[ai.name] = "Artificial Intelligence"
-
- for(var/mob/living/silicon/robot/robot in SSmobs.mob_list)
- // No combat/syndicate cyborgs, no drones.
- if(robot.module && robot.module.hide_on_manifest)
- continue
-
- bot[robot.name] = "[robot.modtype] [robot.braintype]"*/
-
- if(bot.len > 0)
- dat += "Silicon "
- for(name in bot)
- dat += "[name] [bot[name]] [isactive[name]] "
- even = !even
-
- if(heads.len > 0)
- dat += "Heads "
- for(name in heads)
- dat += "[name] [heads[name]] [isactive[name]] "
- even = !even
- if(sec.len > 0)
- dat += "Security "
- for(name in sec)
- dat += "[name] [sec[name]] [isactive[name]] "
- even = !even
- if(eng.len > 0)
- dat += "Engineering "
- for(name in eng)
- dat += "[name] [eng[name]] [isactive[name]] "
- even = !even
- if(med.len > 0)
- dat += "Medical "
- for(name in med)
- dat += "[name] [med[name]] [isactive[name]] "
- even = !even
- if(sci.len > 0)
- dat += "Science "
- for(name in sci)
- dat += "[name] [sci[name]] [isactive[name]] "
- even = !even
- if(car.len > 0)
- dat += "Guild "
- for(name in car)
- dat += "[name] [car[name]] [isactive[name]] "
- even = !even
- if(chr.len > 0)
- dat += "Church "
- for(name in chr)
- dat += "[name] [chr[name]] [isactive[name]] "
- even = !even
- if(civ.len > 0)
- dat += "Civilian "
- for(name in civ)
- dat += "[name] [civ[name]] [isactive[name]] "
- even = !even
- if(misc.len > 0)
- dat += "Miscellaneous "
- for(name in misc)
- dat += "[name] [misc[name]] [isactive[name]] "
- even = !even
-
- dat += "
"
- dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
- dat = replacetext(dat, "\t", "")
- return dat
-
-/datum/datacore/proc/manifest()
- spawn()
- for(var/mob/living/carbon/human/H in GLOB.player_list)
- manifest_inject(H)
- return
-
-/datum/datacore/proc/manifest_modify(var/name, var/assignment)
- ResetPDAManifest()
- var/datum/data/record/foundrecord
- var/real_title = assignment
-
- for(var/datum/data/record/t in data_core.general)
- if (t)
- if(t.fields["name"] == name)
- foundrecord = t
- break
-
- if(foundrecord)
- foundrecord.fields["rank"] = assignment
- foundrecord.fields["real_rank"] = real_title
-
-/datum/datacore/proc/manifest_inject(var/mob/living/carbon/human/H)
- if(H.mind && !player_is_antag(H.mind, only_offstation_roles = 1) && H.job != ASSISTANT_TITLE)
- var/assignment = GetAssignment(H)
-
- var/id = generate_record_id()
- //General Record
- var/datum/data/record/G = CreateGeneralRecord(H, id)
- G.fields["name"] = H.real_name
- G.fields["real_rank"] = H.mind.assigned_role
- G.fields["rank"] = assignment
- G.fields["age"] = H.age
- G.fields["fingerprint"] = H.fingers_trace
- if(H.mind.initial_account)
- G.fields["pay_account"] = H.mind.initial_account.account_number ? H.mind.initial_account.account_number : "N/A"
- G.fields["email"] = H.mind.initial_email_login["login"]
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["sex"] = H.gender
- if(H.gen_record && !jobban_isbanned(H, "Records"))
- G.fields["notes"] = H.gen_record
-
- //Medical Record
- var/datum/data/record/M = CreateMedicalRecord(H.real_name, id)
- M.fields["b_type"] = H.b_type
- M.fields["b_dna"] = H.dna_trace
- //M.fields["id_gender"] = gender2text(H.identifying_gender)
- if(H.med_record && !jobban_isbanned(H, "Records"))
- M.fields["notes"] = H.med_record
-
- //Security Record
- var/datum/data/record/S = CreateSecurityRecord(H.real_name, id)
- if(H.sec_record && !jobban_isbanned(H, "Records"))
- S.fields["notes"] = H.sec_record
-
- //Locked Record
- var/datum/data/record/L = new()
- L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]")
- L.fields["name"] = H.real_name
- L.fields["rank"] = H.mind.assigned_role
- L.fields["age"] = H.age
- L.fields["fingerprint"] = H.fingers_trace
- L.fields["sex"] = H.gender
- L.fields["b_type"] = H.b_type
- L.fields["b_dna"] = H.dna_trace
- L.fields["image"] = getFlatIcon(H) //This is god-awful
- if(H.exploit_record && !jobban_isbanned(H, "Records"))
- L.fields["exploit_record"] = H.exploit_record
- else
- L.fields["exploit_record"] = "No additional information acquired."
- locked += L
- return
-
-/proc/generate_record_id()
- return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex
-
-/proc/get_id_photo(var/mob/living/carbon/human/H, var/assigned_role)
-
- var/icon/preview_icon = new(H.stand_icon)
- var/icon/temp
-
- var/datum/sprite_accessory/hair_style = GLOB.hair_styles_list[H.h_style]
- if(hair_style)
- temp = new/icon(hair_style.icon, hair_style.icon_state)
- temp.Blend(H.hair_color, ICON_ADD)
-
- hair_style = GLOB.facial_hair_styles_list[H.h_style]
- if(hair_style)
- var/icon/facial = new/icon(hair_style.icon, hair_style.icon_state)
- facial.Blend(H.facial_color, ICON_ADD)
- temp.Blend(facial, ICON_OVERLAY)
-
- preview_icon.Blend(temp, ICON_OVERLAY)
-
-
- var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
- if(J)
- var/t_state
- temp = new /icon('icons/inventory/uniform/mob.dmi', t_state)
-
- temp.Blend(new /icon('icons/inventory/feet/mob.dmi', t_state), ICON_OVERLAY)
- else
- temp = new /icon('icons/inventory/uniform/mob.dmi', "grey")
- temp.Blend(new /icon('icons/inventory/feet/mob.dmi', "black"), ICON_OVERLAY)
-
- preview_icon.Blend(temp, ICON_OVERLAY)
-
- qdel(temp)
-
- return preview_icon
-
-/datum/datacore/proc/CreateGeneralRecord(var/mob/living/carbon/human/H, var/id)
- ResetPDAManifest()
- var/icon/front
- var/icon/side
- if(H)
- front = getFlatIcon(H, SOUTH)
- side = getFlatIcon(H, WEST)
- else
- var/mob/living/carbon/human/dummy = new()
- front = new(get_id_photo(dummy), dir = SOUTH)
- side = new(get_id_photo(dummy), dir = WEST)
- qdel(dummy)
-
- if(!id) id = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
- var/datum/data/record/G = new /datum/data/record()
- G.name = "Employee Record #[id]"
- G.fields["name"] = "New Record"
- G.fields["id"] = id
- G.fields["rank"] = "Unassigned"
- G.fields["real_rank"] = "Unassigned"
- G.fields["sex"] = "Male"
- G.fields["age"] = "Unknown"
- G.fields["fingerprint"] = "Unknown"
- G.fields["p_stat"] = "Active"
- G.fields["m_stat"] = "Stable"
- G.fields["species"] = SPECIES_HUMAN
- G.fields["photo_front"] = front
- G.fields["photo_side"] = side
- G.fields["notes"] = "No notes found."
- general += G
-
- return G
-
-/datum/datacore/proc/CreateSecurityRecord(var/name, var/id)
- ResetPDAManifest()
- var/datum/data/record/R = new /datum/data/record()
- R.name = "Security Record #[id]"
- R.fields["name"] = name
- R.fields["id"] = id
- R.fields["criminal"] = "None"
- R.fields["mi_crim"] = "None"
- R.fields["mi_crim_d"] = "No minor crime convictions."
- R.fields["ma_crim"] = "None"
- R.fields["ma_crim_d"] = "No major crime convictions."
- R.fields["notes"] = "No notes."
- R.fields["notes"] = "No notes."
- data_core.security += R
-
- return R
-
-/datum/datacore/proc/CreateMedicalRecord(var/name, var/id)
- ResetPDAManifest()
- var/datum/data/record/M = new()
- M.name = "Medical Record #[id]"
- M.fields["id"] = id
- M.fields["name"] = name
- M.fields["b_type"] = "AB+"
- M.fields["b_dna"] = md5(name)
- 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 found."
- data_core.medical += M
-
- return M
-
-/datum/datacore/proc/ResetPDAManifest()
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
-
-/proc/find_general_record(field, value)
- return find_record(field, value, data_core.general)
-
-/proc/find_medical_record(field, value)
- return find_record(field, value, data_core.medical)
-
-/proc/find_security_record(field, value)
- return find_record(field, value, data_core.security)
-
-/proc/find_record(field, value, list/L)
- for(var/datum/data/record/R in L)
- if(R.fields[field] == value)
- return R
-
-/*/proc/GetAssignment(var/mob/living/carbon/human/H)
- if(H.mind.assigned_role)
- return H.mind.assigned_role
- else if(H.job)
- return H.job
- else
- return "Unassigned"
-*/
-/var/list/acting_rank_prefixes = list("acting", "temporary", "interim", "provisional")
-
-/proc/make_list_rank(rank)
- for(var/prefix in acting_rank_prefixes)
- if(findtext(rank, "[prefix] ", 1, 2+length(prefix)))
- return copytext(rank, 2+length(prefix))
- return rank
-
-/datum/datacore/proc/get_manifest_json()
- if(PDA_Manifest.len)
- return
- var/heads[0]
- var/sec[0]
- var/eng[0]
- var/med[0]
- var/sci[0]
- var/chr[0]
- var/civ[0]
- var/bot[0]
- var/misc[0]
- for(var/datum/data/record/t in data_core.general)
- var/name = sanitize(t.fields["name"])
- var/rank = sanitize(t.fields["rank"])
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- var/isactive = t.fields["p_stat"]
- var/department = 0
- var/depthead = 0 // Department Heads will be placed at the top of their lists.
- if(real_rank in command_positions)
- heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- depthead = 1
- if(rank=="Captain" && heads.len != 1)
- heads.Swap(1, heads.len)
-
- if(real_rank in security_positions)
- sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && sec.len != 1)
- sec.Swap(1, sec.len)
-
- if(real_rank in engineering_positions)
- eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && eng.len != 1)
- eng.Swap(1, eng.len)
-
- if(real_rank in medical_positions)
- med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && med.len != 1)
- med.Swap(1, med.len)
-
- if(real_rank in science_positions)
- sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && sci.len != 1)
- sci.Swap(1, sci.len)
-
- if(real_rank in church_positions)
- chr[++chr.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && chr.len != 1)
- chr.Swap(1, chr.len)
-
- if(real_rank in civilian_positions)
- civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
- if(depthead && civ.len != 1)
- civ.Swap(1, civ.len)
-
- if(real_rank in nonhuman_positions)
- bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
- department = 1
-
- if(!department && !(name in heads))
- misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
-
-
- PDA_Manifest = list(
- "heads" = heads,
- "sec" = sec,
- "eng" = eng,
- "med" = med,
- "sci" = sci,
- "chr" = chr,
- "civ" = civ,
- "bot" = bot,
- "misc" = misc
- )
- ManifestJSON = json_encode(PDA_Manifest)
- return
diff --git a/code/datums/setup_option/backgrounds/fate.dm b/code/datums/setup_option/backgrounds/fate.dm
index 8093c95bbc3..3cda4c9d8e7 100644
--- a/code/datums/setup_option/backgrounds/fate.dm
+++ b/code/datums/setup_option/backgrounds/fate.dm
@@ -26,7 +26,7 @@
You were always on the move, looking for a brighter future on the other side. \
And because of that you never specialised as much as you should, but have broader array of other skills."
- perks = list(PERK_FREELACER)
+ perks = list(PERK_FREELANCER)
/datum/category_item/setup_option/background/fate/nihilist
name = "Nihilist"
diff --git a/code/datums/topic/admin.dm b/code/datums/topic/admin.dm
index 8200320a178..f3af9e40f72 100644
--- a/code/datums/topic/admin.dm
+++ b/code/datums/topic/admin.dm
@@ -387,8 +387,8 @@
body += source.formatJobGroup(M, "Church Positions", "ecd37d", "churchdept", church_positions)
//Civilian (Grey)
body += source.formatJobGroup(M, "Civilian Positions", "dddddd", "civiliandept", civilian_positions)
- //Non-Human (Green)
- body += source.formatJobGroup(M, "Non-human Positions", "ccffcc", "nonhumandept", nonhuman_positions + "Antag HUD")
+ //Silicon (Green)
+ body += source.formatJobGroup(M, "Non-human Positions", "ccffcc", "silicondept", silicon_positions + "Antag HUD")
//Antagonist (Orange)
var/jobban_list = list()
@@ -459,9 +459,9 @@
var/datum/job/temp = SSjob.GetJob(jobPos)
if(!temp) continue
joblist += temp.title
- if("nonhumandept")
+ if("silicondept")
joblist += "pAI"
- for(var/jobPos in nonhuman_positions)
+ for(var/jobPos in silicon_positions)
if(!jobPos) continue
var/datum/job/temp = SSjob.GetJob(jobPos)
if(!temp) continue
diff --git a/code/datums/topic/world.dm b/code/datums/topic/world.dm
index f596fd2b7b5..0d9b2df53c0 100644
--- a/code/datums/topic/world.dm
+++ b/code/datums/topic/world.dm
@@ -94,31 +94,16 @@
/datum/world_topic/manifest/Run(list/input)
var/list/positions = list()
- var/list/set_names = list(
- "heads" = command_positions,
- "sec" = security_positions,
- "eng" = engineering_positions,
- "med" = medical_positions,
- "sci" = science_positions,
- "car" = cargo_positions,
- "civ" = civilian_positions,
- "chr" = church_positions,
- "bot" = nonhuman_positions
- )
-
- for(var/datum/data/record/t in data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/real_rank = make_list_rank(t.fields["real_rank"])
-
- var/department = FALSE
- for(var/k in set_names)
- if(real_rank in set_names[k])
- if(!positions[k])
- positions[k] = list()
- positions[k][name] = rank
- department = TRUE
- if(!department)
+
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)
+ var/name = t.get_name()
+ var/rank = t.get_job()
+
+ var/department = t.get_department()
+
+ if(department && department != "Unset")
+ positions[department][name] = rank
+ else
if(!positions["misc"])
positions["misc"] = list()
positions["misc"][name] = rank
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index ae51fc9b055..694d0563cb3 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -38,48 +38,42 @@
return 0
var/obj/item/card/id/I = user.GetIdCard()
- var/datum/data/record/random_general_record
- var/datum/data/record/random_medical_record
- if(data_core.general.len)
- random_general_record = pick(data_core.general)
- random_medical_record = find_medical_record("id", random_general_record.fields["id"])
+ var/datum/computer_file/report/crew_record/random_record
+ if(GLOB.all_crew_records.len)
+ random_record = pick(GLOB.all_crew_records)
- var/datum/data/record/general = data_core.CreateGeneralRecord(user)
+ var/datum/computer_file/report/crew_record/general = new()
if(I)
- general.fields["age"] = I.age
- general.fields["rank"] = I.assignment
- general.fields["real_rank"] = I.assignment
- general.fields["name"] = I.registered_name
- general.fields["sex"] = I.sex
+ general.set_age(I.age)
+ general.set_job(I.assignment)
+ general.set_name(I.registered_name)
+ general.set_sex(I.sex)
else
var/mob/living/carbon/human/H
if(ishuman(user))
H = user
- general.fields["age"] = H.age
+ general.set_age(H.age)
else
- general.fields["age"] = initial(H.age)
+ general.set_age(initial(H.age))
var/assignment = GetAssignment(user)
- general.fields["rank"] = assignment
- general.fields["real_rank"] = assignment
- general.fields["name"] = user.real_name
- general.fields["sex"] = capitalize(user.gender)
+ general.set_job(assignment)
+ general.set_department(args["department"])
+ general.set_name(user.real_name)
+ general.set_sex(capitalize(user.gender))
- general.fields["species"] = user.get_species()
- var/datum/data/record/medical = data_core.CreateMedicalRecord(general.fields["name"], general.fields["id"])
- data_core.CreateSecurityRecord(general.fields["name"], general.fields["id"])
+ general.set_species(user.get_species())
- if(!random_general_record)
- general.fields["fingerprint"] = random_general_record.fields["fingerprint"]
- if(random_medical_record)
- medical.fields["b_type"] = random_medical_record.fields["b_type"]
- medical.fields["b_dna"] = random_medical_record.fields["b_type"]
+ if(random_record)
+ general.set_fingerprint(random_record.get_fingerprint())
+ general.set_bloodtype(random_record.get_bloodtype())
+ general.set_dna(random_record.get_bloodtype())
if(I)
- general.fields["fingerprint"] = I.fingerprint_hash
- medical.fields["b_type"] = I.blood_type
- medical.fields["b_dna"] = I.dna_hash
+ general.set_fingerprint(I.fingerprint_hash)
+ general.set_bloodtype(I.blood_type)
+ general.set_dna(I.dna_hash)
- AnnounceArrival(general.fields["name"], general.fields["rank"], "has completed cryogenic revival")
+ AnnounceArrival(general.get_name(), general.get_job(), "has completed cryogenic revival")
return 1
/datum/uplink_item/abstract/announcements/fake_ion_storm
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 414f37d219f..8c30760d562 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -119,4 +119,7 @@ datum/announcement/proc/Log(message as text, message_title as text)
if(issilicon(character))
global_announcer.autosay("A new [rank] [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
else
- global_announcer.autosay("[character.real_name], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
+ if(istype(character))
+ global_announcer.autosay("[character.real_name], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE)
+ else if(istext(character))
+ global_announcer.autosay("[character], [rank], [join_message].", ANNOUNCER_NAME, use_text_to_speech = TRUE) // send the text
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 4fe53b73120..89df2e1fc66 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -78,7 +78,7 @@ var/list/science_positions = list(JOBS_SCIENCE)
var/list/moebius_positions = list(JOBS_MOEBIUS)
//BS12 EDIT
-var/list/cargo_positions = list(JOBS_CARGO)
+var/list/guild_positions = list(JOBS_GUILD)
var/list/church_positions = list(JOBS_CHURCH)
@@ -90,8 +90,8 @@ var/list/civilian_positions = list(JOBS_CIVILIAN)
var/list/security_positions = list(JOBS_SECURITY)
var/list/armory_positions = list(JOBS_ARMORY)
-var/list/nonhuman_positions = list(JOBS_NONHUMAN)
+var/list/silicon_positions = list(JOBS_SILICON)
/proc/guest_jobbans(var/job)
- return ((job in command_positions) || (job in nonhuman_positions) || (job in armory_positions))
+ return ((job in command_positions) || (job in silicon_positions) || (job in armory_positions))
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 12f408b42ef..622b5b938d9 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -1193,7 +1193,7 @@ FIRE ALARM
/obj/machinery/firealarm/Destroy()
GLOB.firealarm_list -= src
- ..()
+ . = ..()
/*
FIRE ALARM CIRCUIT
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 7e5e36a2e6b..c2da5fc236f 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -22,7 +22,7 @@
/obj/machinery/computer/Destroy()
GLOB.computer_list -= src
- ..()
+ . = ..()
/obj/machinery/computer/Process()
if(stat & (NOPOWER|BROKEN))
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
deleted file mode 100644
index c657a915e49..00000000000
--- a/code/game/machinery/computer/medical.dm
+++ /dev/null
@@ -1,519 +0,0 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
-/obj/machinery/computer/med_data//TODO:SANITY
- name = "medical records console"
- desc = "Used to view, edit and maintain medical records."
- icon_keyboard = "med_key"
- icon_screen = "medcomp"
- light_color = COLOR_LIGHTING_GREEN_MACHINERY
- req_one_access = list(access_moebius, access_forensics_lockers)
- circuit = /obj/item/electronics/circuitboard/med_data
- var/obj/item/card/id/scan
- var/authenticated
- var/rank
- var/screen
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/a_id
- var/temp
- var/printing
-
-/obj/machinery/computer/med_data/verb/eject_id()
- set category = "Object"
- set name = "Eject ID Card"
- set src in oview(1)
-
- if(!usr || usr.stat || usr.lying) return
-
- if(scan)
- to_chat(usr, "You remove \the [scan] from \the [src].")
- scan.loc = get_turf(src)
- if(!usr.get_active_hand() && ishuman(usr))
- usr.put_in_hands(scan)
- scan = null
- else
- to_chat(usr, "There is nothing to remove from the console.")
- return
-
-/obj/machinery/computer/med_data/attackby(var/obj/item/O, var/mob/user)
- if(istype(O, /obj/item/card/id) && !scan && user.unEquip(O))
- O.loc = src
- scan = O
- to_chat(user, "You insert \the [O].")
- else
- ..()
-
-/obj/machinery/computer/med_data/attack_hand(mob/user as mob)
- if(..())
- return
- nano_ui_interact(user)
-
-/obj/machinery/computer/med_data/nano_ui_interact(mob/user)
- var/dat
- if (src.temp)
- dat = text("[src.temp] Clear Screen ")
- else
- dat = text("Confirm Identity: [] ", src, (src.scan ? text("[]", src.scan.name) : "----------"))
- if (src.authenticated)
- switch(src.screen)
- if(1)
- dat += {"
-Search Records
-List Records
-Medbot Tracking
-
-Record Maintenance
-{Log Out}
-"}
- if(2)
- dat += "Record List : "
- if(!isnull(data_core.general))
- for(var/datum/data/record/R in sortRecord(data_core.general))
- dat += text("[]: [] ", src, R, R.fields["id"], R.fields["name"])
- //Foreach goto(132)
- dat += text(" Back ", src)
- if(3)
- dat += text("Records Maintenance \nBackup To Disk \nUpload From disk \nDelete All Records \n \nBack ", src, src, src, src)
- if(4)
- var/icon/front = active1.fields["photo_front"]
- var/icon/side = active1.fields["photo_side"]
- user << browse_rsc(front, "front.png")
- user << browse_rsc(side, "side.png")
- dat += "Medical Record "
- if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
- dat += ""
- else
- dat += "General Record Lost! "
- if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
- dat += text(" \nMedical 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 \nComments/Log ", src, src.active2.fields["b_type"], src, src.active2.fields["b_dna"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, decode(src.active2.fields["notes"]))
- var/counter = 1
- while(src.active2.fields[text("com_[]", counter)])
- dat += text("[]Delete Entry ", src.active2.fields[text("com_[]", counter)], src, counter)
- counter++
- dat += text("Add Entry ", src)
- dat += text("Delete Record (Medical Only) ", src)
- else
- dat += "Medical Record Lost! "
- dat += text("New Record ")
- dat += text("\nPrint Record \nBack ", src, src)
- if(6)
- dat += "Medical Robot Monitor "
- dat += "Back "
- dat += "Medical Robots: "
- var/bdat
- for(var/mob/living/bot/medbot/M in world)
-
- if(M.z != src.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 += text("{Log In} ", src)
- user << browse(text("Medical Records [] ", dat), "window=med_rec")
- onclose(user, "med_rec")
- return
-
-/obj/machinery/computer/med_data/Topic(href, href_list)
- if(..())
- return 1
-
- if (!( data_core.general.Find(src.active1) ))
- src.active1 = null
-
- if (!( data_core.medical.Find(src.active2) ))
- src.active2 = null
-
- if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (issilicon(usr)))
- usr.set_machine(src)
-
- if (href_list["temp"])
- src.temp = null
-
- if (href_list["scan"])
- if (src.scan)
-
- if(ishuman(usr))
- scan.loc = usr.loc
-
- if(!usr.get_active_hand())
- usr.put_in_hands(scan)
-
- scan = null
-
- else
- src.scan.loc = src.loc
- src.scan = null
-
- else
- var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/card/id))
- usr.drop_item()
- I.loc = src
- src.scan = I
-
- else if (href_list["logout"])
- src.authenticated = null
- src.screen = null
- src.active1 = null
- src.active2 = null
-
- else if (href_list["login"])
-
- if (isAI(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- src.rank = "AI"
- src.screen = 1
-
- else if (isrobot(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- var/mob/living/silicon/robot/R = usr
- src.rank = "[R.modtype] [R.braintype]"
- src.screen = 1
-
- else if (istype(src.scan, /obj/item/card/id))
- src.active1 = null
- src.active2 = null
-
- if (src.check_access(src.scan))
- src.authenticated = src.scan.registered_name
- src.rank = src.scan.assignment
- src.screen = 1
-
- if (src.authenticated)
-
- if(href_list["screen"])
- src.screen = text2num(href_list["screen"])
- if(src.screen < 1)
- src.screen = 1
-
- src.active1 = null
- src.active2 = null
-
- if (href_list["del_all"])
- src.temp = text("Are you sure you wish to delete all records? \n\tYes \n\tNo ", src, src)
-
- if (href_list["del_all2"])
- for(var/datum/data/record/R in data_core.medical)
- //R = null
- qdel(R)
- //Foreach goto(494)
- src.temp = "All records deleted."
-
- if (href_list["field"])
- var/a1 = src.active1
- var/a2 = src.active2
- switch(href_list["field"])
- if("fingerprint")
- if (istype(src.active1, /datum/data/record))
- var/t1 = sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active1 != a1))
- return
- src.active1.fields["fingerprint"] = t1
- if("sex")
- if (istype(src.active1, /datum/data/record))
- if (src.active1.fields["sex"] == "Male")
- src.active1.fields["sex"] = "Female"
- else
- src.active1.fields["sex"] = "Male"
- if("age")
- if (istype(src.active1, /datum/data/record))
- var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as num
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active1 != a1))
- return
- src.active1.fields["age"] = t1
- if("mi_dis")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["mi_dis"] = t1
- if("mi_dis_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["mi_dis_d"] = t1
- if("ma_dis")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["ma_dis"] = t1
- if("ma_dis_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["ma_dis_d"] = t1
- if("alg")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["alg"] = t1
- if("alg_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["alg_d"] = t1
- if("cdi")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["cdi"] = t1
- if("cdi_d")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["cdi_d"] = t1
- if("notes")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message, extra = 0)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["notes"] = t1
- if("p_stat")
- if (istype(src.active1, /datum/data/record))
- src.temp = text("Physical Condition: \n\t*Deceased* \n\t*SSD* \n\tActive \n\tPhysically Unfit \n\tDisabled ", src, src, src, src, src)
- if("m_stat")
- if (istype(src.active1, /datum/data/record))
- src.temp = text("Mental Condition: \n\t*Insane* \n\t*Unstable* \n\t*Watch* \n\tStable ", src, src, src, src)
- if("b_type")
- if (istype(src.active2, /datum/data/record))
- src.temp = text("Blood Type: \n\tA- A+ \n\tB- B+ \n\tAB- AB+ \n\tO- O+ ", src, src, src, src, src, src, src, src)
- if("b_dna")
- if (istype(src.active2, /datum/data/record))
- var/t1 = sanitize(input("Please input DNA hash:", "Med. records", src.active2.fields["b_dna"], null) as text)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- src.active2.fields["b_dna"] = t1
- else
-
- if (href_list["p_stat"])
- if (src.active1)
- switch(href_list["p_stat"])
- if("deceased")
- src.active1.fields["p_stat"] = "*Deceased*"
- if("ssd")
- src.active1.fields["p_stat"] = "*SSD*"
- if("active")
- src.active1.fields["p_stat"] = "Active"
- if("unfit")
- src.active1.fields["p_stat"] = "Physically Unfit"
- if("disabled")
- src.active1.fields["p_stat"] = "Disabled"
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
-
- if (href_list["m_stat"])
- if (src.active1)
- switch(href_list["m_stat"])
- if("insane")
- src.active1.fields["m_stat"] = "*Insane*"
- if("unstable")
- src.active1.fields["m_stat"] = "*Unstable*"
- if("watch")
- src.active1.fields["m_stat"] = "*Watch*"
- if("stable")
- src.active1.fields["m_stat"] = "Stable"
-
-
- if (href_list["b_type"])
- if (src.active2)
- switch(href_list["b_type"])
- if("an")
- src.active2.fields["b_type"] = "A-"
- if("bn")
- src.active2.fields["b_type"] = "B-"
- if("abn")
- src.active2.fields["b_type"] = "AB-"
- if("on")
- src.active2.fields["b_type"] = "O-"
- if("ap")
- src.active2.fields["b_type"] = "A+"
- if("bp")
- src.active2.fields["b_type"] = "B+"
- if("abp")
- src.active2.fields["b_type"] = "AB+"
- if("op")
- src.active2.fields["b_type"] = "O+"
-
-
- if (href_list["del_r"])
- if (src.active2)
- src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)? \n\tYes \n\tNo ", src, src)
-
- if (href_list["del_r2"])
- if (src.active2)
- //src.active2 = null
- qdel(src.active2)
-
- if (href_list["d_rec"])
- var/datum/data/record/R = locate(href_list["d_rec"])
- var/datum/data/record/M = locate(href_list["d_rec"])
- if (!( data_core.general.Find(R) ))
- src.temp = "Record Not Found!"
- return
- for(var/datum/data/record/E in data_core.medical)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- else
- //Foreach continue //goto(2540)
- src.active1 = R
- src.active2 = M
- src.screen = 4
-
- if (href_list["new"])
- if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) )))
- var/datum/data/record/R = new /datum/data/record( )
- R.fields["name"] = src.active1.fields["name"]
- R.fields["id"] = src.active1.fields["id"]
- R.name = text("Medical Record #[]", R.fields["id"])
- R.fields["b_type"] = "Unknown"
- R.fields["b_dna"] = "Unknown"
- R.fields["mi_dis"] = "None"
- R.fields["mi_dis_d"] = "No minor disabilities have been declared."
- 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."
- data_core.medical += R
- src.active2 = R
- src.screen = 4
-
- if (href_list["add_c"])
- if (!( istype(src.active2, /datum/data/record) ))
- return
- var/a2 = src.active2
- var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message)
- if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || src.active2 != a2))
- return
- var/counter = 1
- while(src.active2.fields[text("com_[]", counter)])
- counter++
- src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [game_year] [t1]")
-
- if (href_list["del_c"])
- if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
- src.active2.fields[text("com_[]", href_list["del_c"])] = "Deleted "
-
- if (href_list["search"])
- var/t1 = input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!in_range(src, usr)) && (!issilicon(usr)))))
- return
- src.active1 = null
- src.active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in data_core.medical)
- if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])))
- src.active2 = R
- else
- //Foreach continue //goto(3229)
- if (!( src.active2 ))
- src.temp = text("Could not locate record [].", t1)
- else
- for(var/datum/data/record/E in data_core.general)
- if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"]))
- src.active1 = E
- else
- //Foreach continue //goto(3334)
- src.screen = 4
-
- if (href_list["print_p"])
- if (!( src.printing ))
- src.printing = 1
- var/datum/data/record/record1
- var/datum/data/record/record2
- if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
- record1 = active1
- if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
- record2 = active2
- sleep(50)
- var/obj/item/paper/P = new /obj/item/paper( src.loc )
- P.info = "Medical Record "
- if (record1)
- P.info += text("Name: [] ID: [] \nSex: [] \nAge: [] \nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
- P.name = text("Medical Record ([])", record1.fields["name"])
- else
- P.info += "General Record Lost! "
- P.name = "Medical Record"
- if (record2)
- P.info += text(" \nMedical 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 \nComments/Log ", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"]))
- var/counter = 1
- while(record2.fields[text("com_[]", counter)])
- P.info += text("[] ", record2.fields[text("com_[]", counter)])
- counter++
- else
- P.info += "Medical Record Lost! "
- P.info += ""
- src.printing = null
-
- src.add_fingerprint(usr)
- src.updateUsrDialog()
- return
-
-/obj/machinery/computer/med_data/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
-
- for(var/datum/data/record/R in data_core.medical)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["sex"] = pick("Male", "Female")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["b_type"] = pick("A-", "B-", "AB-", "O-", "A+", "B+", "AB+", "O+")
- if(5)
- R.fields["p_stat"] = pick("*SSD*", "Active", "Physically Unfit", "Disabled")
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
- ..(severity)
-
-
-/obj/machinery/computer/med_data/laptop
- name = "Medical Laptop"
- desc = "A cheap laptop."
- icon_state = "laptop"
- icon_keyboard = "laptop_key"
- icon_screen = "medlaptop"
- CheckFaceFlag = 0
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
deleted file mode 100644
index 62cd2c4e956..00000000000
--- a/code/game/machinery/computer/security.dm
+++ /dev/null
@@ -1,658 +0,0 @@
-/obj/machinery/computer/secure_data
- name = "security records console"
- desc = "Used to view, edit and maintain security records"
- icon_keyboard = "security_key"
- icon_screen = "security"
- light_color = COLOR_LIGHTING_SCI_BRIGHT
- req_one_access = list(access_security)
- circuit = /obj/item/electronics/circuitboard/secure_data
- var/obj/item/card/id/scan
- var/authenticated
- var/rank
- var/screen
- var/datum/data/record/active1
- var/datum/data/record/active2
- var/a_id
- var/temp
- var/printing
- var/can_change_id = 0
- var/list/Perp
- var/tempname
- //Sorting Variables
- var/sortBy = "name"
- var/order = 1 // -1 = Descending - 1 = Ascending
-
-/obj/machinery/computer/secure_data/verb/eject_id()
- set category = "Object"
- set name = "Eject ID Card"
- set src in oview(1)
-
- if(!usr || usr.stat || usr.lying) return
-
- if(scan)
- to_chat(usr, "You remove \the [scan] from \the [src].")
- scan.loc = get_turf(src)
- if(!usr.get_active_hand() && ishuman(usr))
- usr.put_in_hands(scan)
- scan = null
- else
- to_chat(usr, "There is nothing to remove from the console.")
- return
-
-/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob)
- if(istype(O, /obj/item/card/id) && !scan)
- usr.drop_item()
- O.loc = src
- scan = O
- to_chat(user, "You insert [O].")
- ..()
-
-//Someone needs to break down the dat += into chunks instead of long ass lines.
-/obj/machinery/computer/secure_data/attack_hand(mob/user)
- if(..())
- return
- nano_ui_interact(user)
-
-/obj/machinery/computer/secure_data/nano_ui_interact(user)
- if (src.z > 6)
- to_chat(user, "Unable to establish a connection: You're too far away from the station!")
- return
-
- var/dat
- if (temp)
- dat = text("[] Clear Screen ", temp, src)
- else
- dat = text("Confirm Identity: [] ", src, (scan ? text("[]", scan.name) : "----------"))
- if (authenticated)
- switch(screen)
- if(1)
- dat += {""}
- dat += text("Search Records ", src)
- dat += text("New Record ", src)
- dat += {"
-
-
-
-
-Name
-ID
-Rank
-Fingerprints
-Criminal Status
- "}
- if(!isnull(data_core.general))
- for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order))
- var/crimstat = ""
- for(var/datum/data/record/E in 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:#DC143C;'"
- if("Incarcerated")
- background = "'background-color:#CD853F;'"
- if("Parolled")
- background = "'background-color:#CD853F;'"
- if("Released")
- background = "'background-color:#3BB9FF;'"
- if("None")
- background = "'background-color:#00FF7F;'"
- if("")
- background = "'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += text("[] ", background, src, R, R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += "
"
- dat += text("Record Maintenance ", src)
- dat += text("{Log Out} ",src)
- if(2)
- dat += "Records Maintenance "
- dat += "Delete All Records Back "
- if(3)
- dat += "Security Record "
- if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
- user << browse_rsc(active1.fields["photo_front"], "front.png")
- user << browse_rsc(active1.fields["photo_side"], "side.png")
- dat += {"
-
- "}
- else
- dat += "General Record Lost! "
- if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
- dat += " \nSecurity Data \nCriminal Status: \
- [active2.fields["criminal"]] \n \n \
- Minor Crimes: [active2.fields["mi_crim"]] \n \
- Details: [active2.fields["mi_crim_d"]] \n \n\
- Major Crimes: [active2.fields["ma_crim"]] \n \
- Details: [active2.fields["ma_crim_d"]] \n \n \
- Important Notes: \n\t[decode(active2.fields["notes"])] \n \n\
- Comments/Log "
- var/counter = 1
- while(active2.fields["com_[counter]"])
- dat += text("[]Delete Entry ", active2.fields["com_[counter]"], src, 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 "
- if(4)
- if(!Perp.len)
- dat += text("ERROR. String could not be located.Back ", src)
- else
- dat += {"
-
- Search Results for '[tempname]':
-
-
- Name
- ID
- Rank
- Fingerprints
- Criminal Status
-
- "}
- for(var/i=1, i<=Perp.len, i += 2)
- var/crimstat = ""
- var/datum/data/record/R = Perp[i]
- if(istype(Perp[i+1],/datum/data/record/))
- var/datum/data/record/E = Perp[i+1]
- crimstat = E.fields["criminal"]
- var/background
- switch(crimstat)
- if("*Arrest*")
- background = "'background-color:#DC143C;'"
- if("Incarcerated")
- background = "'background-color:#CD853F;'"
- if("Parolled")
- background = "'background-color:#CD853F;'"
- if("Released")
- background = "'background-color:#3BB9FF;'"
- if("None")
- background = "'background-color:#00FF7F;'"
- if("")
- background = "'background-color:#FFFFFF;'"
- crimstat = "No Record."
- dat += text("[] ", background, src, R, R.fields["name"])
- dat += text("[] ", R.fields["id"])
- dat += text("[] ", R.fields["rank"])
- dat += text("[] ", R.fields["fingerprint"])
- dat += text("[] ", crimstat)
- dat += "
"
- dat += text("Return to index. ", src)
- else
- else
- dat += text("{Log In} ", src)
- user << browse(text("Security Records [] ", dat), "window=secure_rec;size=600x400")
- onclose(user, "secure_rec")
- 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 1
- if (!( data_core.general.Find(active1) ))
- active1 = null
- if (!( data_core.security.Find(active2) ))
- active2 = null
- if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (issilicon(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("Confirm Identity")
- if (scan)
- if(ishuman(usr) && !usr.get_active_hand())
- usr.put_in_hands(scan)
- else
- scan.loc = get_turf(src)
- scan = null
- else
- var/obj/item/I = usr.get_active_hand()
- if (istype(I, /obj/item/card/id) && usr.unEquip(I))
- I.loc = src
- scan = I
-
- if("Log Out")
- authenticated = null
- screen = null
- active1 = null
- active2 = null
-
- if("Log In")
- if (isAI(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- src.rank = "AI"
- src.screen = 1
- else if (isrobot(usr))
- src.active1 = null
- src.active2 = null
- src.authenticated = usr.name
- var/mob/living/silicon/robot/R = usr
- src.rank = "[R.modtype] [R.braintype]"
- src.screen = 1
- else if (istype(scan, /obj/item/card/id))
- active1 = null
- active2 = null
- if(check_access(scan))
- authenticated = scan.registered_name
- rank = scan.assignment
- screen = 1
-//RECORD FUNCTIONS
- if("Search Records")
- var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr)))
- return
- Perp = new/list()
- t1 = lowertext(t1)
- var/list/components = splittext(t1, " ")
- if(components.len > 5)
- return //Lets not let them search too greedily.
- for(var/datum/data/record/R in data_core.general)
- var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"]
- for(var/i = 1, i<=components.len, i++)
- if(findtext(temptext,components[i]))
- var/prelist = new/list(2)
- prelist[1] = R
- Perp += prelist
- for(var/i = 1, i<=Perp.len, i+=2)
- for(var/datum/data/record/E in data_core.security)
- var/datum/data/record/R = Perp[i]
- if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
- Perp[i+1] = E
- tempname = t1
- screen = 4
-
- if("Record Maintenance")
- screen = 2
- active1 = null
- active2 = null
-
- if ("Browse Record")
- var/datum/data/record/R = locate(href_list["d_rec"])
- var/S = locate(href_list["d_rec"])
- if (!( data_core.general.Find(R) ))
- temp = "Record Not Found!"
- else
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- S = E
- active1 = R
- active2 = S
- screen = 3
-
-/* if ("Search Fingerprints")
- var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
- if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!issilicon(usr))))
- return
- active1 = null
- active2 = null
- t1 = lowertext(t1)
- for(var/datum/data/record/R in data_core.general)
- if (lowertext(R.fields["fingerprint"]) == t1)
- active1 = R
- if (!( active1 ))
- temp = text("Could not locate record [].", t1)
- else
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"]))
- active2 = E
- screen = 3 */
-
- if ("Print Record")
- if (!( printing ))
- printing = 1
- var/datum/data/record/record1 = null
- var/datum/data/record/record2 = null
- if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
- record1 = active1
- if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
- record2 = active2
- sleep(50)
- var/obj/item/paper/P = new /obj/item/paper( loc )
- P.info = "Security Record "
- if (record1)
- P.info += {"
- Name: [record1.fields["name"]] ID: [record1.fields["id"]]
- Sex: [record1.fields["sex"]]
- Age: [record1.fields["age"]]
- Fingerprint: [record1.fields["fingerprint"]]
- Physical Status: [record1.fields["p_stat"]]
- Mental Status: [record1.fields["m_stat"]]
- "}
- P.name = "Security Record ([record1.fields["name"]])"
- else
- P.info += "General Record Lost! "
- P.name = "Security Record"
- if (record2)
- P.info += {"
- Security Data
- Criminal Status: [record2.fields["criminal"]]
- Minor Crimes: [record2.fields["mi_crim"]]
- Details: [record2.fields["mi_crim_d"]]
- Major Crimes: [record2.fields["ma_crim"]]
- Details: [record2.fields["ma_crim_d"]]
- Important Notes:
- \t[decode(record2.fields["notes"])]
- Comments/Log
- "}
- var/counter = 1
- while(record2.fields[text("com_[]", counter)])
- P.info += text("[] ", record2.fields[text("com_[]", counter)])
- counter++
- else
- P.info += "Security Record Lost! "
- P.info += ""
- printing = null
- updateUsrDialog()
-
- if ("Print Poster")
- if(!printing)
- var/wanted_name = sanitizeName(input("Please enter an alias for the criminal:", "Print Wanted Poster", active1.fields["name"]) as text, MAX_NAME_LEN, 1)
- 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/major_crimes = active2.fields["ma_crim"]
- var/minor_crimes = active2.fields["mi_crim"]
- default_description += "\n[wanted_name] is wanted for the following crimes:\n"
- default_description += "\nMinor Crimes:\n[minor_crimes]\n[active2.fields["mi_crim_d"]]\n"
- default_description += "\nMajor Crimes:\n[major_crimes]\n[active2.fields["ma_crim_d"]]\n"
- printing = 1
- spawn(30)
- playsound(loc, 'sound/items/poster_being_created.ogg', 100, 1)
- if((istype(active1, /datum/data/record) && data_core.general.Find(active1)))//make sure the record still exists.
- new /obj/item/contraband/poster/wanted(src.loc, active1.fields["photo_front"], wanted_name, default_description)
- 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")
- for(var/datum/data/record/R in data_core.security)
- qdel(R)
- temp = "All Security records deleted."
-
- if ("Add Entry")
- if (!( istype(active2, /datum/data/record) ))
- return
- var/a2 = active2
- var/t1 = sanitize(input("Add Comment:", "Secure. records", null, null) as message)
- if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!issilicon(usr))) || active2 != a2))
- return
- var/counter = 1
- while(active2.fields[text("com_[]", counter)])
- counter++
- active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [stationtime2text()], [game_year] [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) )))
- active2 = data_core.CreateSecurityRecord(active1.fields["name"], active1.fields["id"])
- screen = 3
-
- if ("New Record (General)")
- active1 = data_core.CreateGeneralRecord()
- active2 = null
-
-//FIELD FUNCTIONS
- if ("Edit")
- if (is_not_allowed(usr))
- return
- var/a1 = active1
- var/a2 = active2
- switch(href_list["field"])
- if("name")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitizeName(input("Please input name:", "Secure. records", active1.fields["name"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["name"] = t1
- if("id")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["id"] = t1
- if("fingerprint")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text)
- if (!t1 || active1 != a1)
- return
- active1.fields["fingerprint"] = t1
- if("sex")
- if (istype(active1, /datum/data/record))
- if (active1.fields["sex"] == "Male")
- active1.fields["sex"] = "Female"
- else
- active1.fields["sex"] = "Male"
- if("age")
- if (istype(active1, /datum/data/record))
- var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
- if (!t1 || active1 != a1)
- return
- active1.fields["age"] = t1
- if("mi_crim")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text)
- if (!t1 || active2 != a2)
- return
- active2.fields["mi_crim"] = t1
- if("mi_crim_d")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message)
- if (!t1 || active2 != a2)
- return
- active2.fields["mi_crim_d"] = t1
- if("ma_crim")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text)
- if (!t1 || active2 != a2)
- return
- active2.fields["ma_crim"] = t1
- if("ma_crim_d")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message)
- if (!t1 || active2 != a2)
- return
- active2.fields["ma_crim_d"] = t1
- if("notes")
- if (istype(active2, /datum/data/record))
- var/t1 = sanitize(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message, extra = 0)
- if (!t1 || active2 != a2)
- return
- active2.fields["notes"] = t1
- if("criminal")
- if (istype(active2, /datum/data/record))
- temp = "Criminal Status: "
- temp += ""
- if("rank")
- var/list/L = list( "First Officer", "Captain", "AI" )
- //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 GLOB.joblist)
- temp += "[rank] "
- temp += " "
- else
- alert(usr, "You do not have the required rank to do this!")
- if("species")
- if (istype(active1, /datum/data/record))
- var/t1 = sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message)
- if (!t1 || active1 != a1)
- return
- active1.fields["species"] = t1
- if("photo front")
- var/icon/photo = get_photo(usr)
- if(photo)
- active1.fields["photo_front"] = photo
- if("photo side")
- var/icon/photo = get_photo(usr)
- if(photo)
- active1.fields["photo_side"] = photo
-
-
-//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 GLOB.joblist)
- active1.fields["real_rank"] = href_list["real_rank"]
-
- if ("Change Criminal Status")
- if (active2)
- for(var/mob/living/carbon/human/H in GLOB.player_list)
- BITSET(H.hud_updateflag, WANTED_HUD)
- switch(href_list["criminal2"])
- if("none")
- active2.fields["criminal"] = "None"
- if("arrest")
- active2.fields["criminal"] = "*Arrest*"
- if("incarcerated")
- active2.fields["criminal"] = "Incarcerated"
- if("parolled")
- active2.fields["criminal"] = "Parolled"
- if("released")
- active2.fields["criminal"] = "Released"
-
- if ("Delete Record (Security) Execute")
- if (active2)
- qdel(active2)
-
- if ("Delete Record (ALL) Execute")
- if (active1)
- for(var/datum/data/record/R in data_core.medical)
- if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
- qdel(R)
- else
- qdel(active1)
- if (active2)
- qdel(active2)
- 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/is_not_allowed(var/mob/user)
- return !src.authenticated || user.stat || user.restrained() || (!in_range(src, user) && (!issilicon(user)))
-
-/obj/machinery/computer/secure_data/proc/get_photo(var/mob/user)
- if(istype(user.get_active_hand(), /obj/item/photo))
- var/obj/item/photo/photo = user.get_active_hand()
- return photo.img
- if(issilicon(user))
- var/mob/living/silicon/tempAI = usr
- var/obj/item/photo/selection = tempAI.GetPicture()
- if (selection)
- return selection.img
-
-/obj/machinery/computer/secure_data/emp_act(severity)
- if(stat & (BROKEN|NOPOWER))
- ..(severity)
- return
-
- for(var/datum/data/record/R in data_core.security)
- if(prob(10/severity))
- switch(rand(1,6))
- if(1)
- R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
- if(2)
- R.fields["sex"] = pick("Male", "Female")
- if(3)
- R.fields["age"] = rand(5, 85)
- if(4)
- R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
- if(5)
- R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- if(6)
- R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
- continue
-
- else if(prob(1))
- qdel(R)
- continue
-
- ..(severity)
-
-/obj/machinery/computer/secure_data/detective_computer
- icon = 'icons/obj/computer.dmi'
- icon_state = "messyfiles"
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 5741b5f4dd3..030d1994869 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -51,7 +51,7 @@
/obj/machinery/door/Destroy()
GLOB.all_doors -= src
- ..()
+ . = ..()
/obj/machinery/door/can_prevent_fall(above)
return above ? density : null
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 84ef9938851..cf5b00ad86d 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -241,9 +241,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location.
if(caller_id)
var/icon/tempicon = new
- for(var/datum/data/record/t in data_core.locked)
- if(t.fields["name"]==caller_id.name)
- tempicon = t.fields["image"]
+ var/datum/computer_file/report/crew_record/t = get_crewmember_record(caller_id.name)
+ tempicon = t.photo_front
hologram.overlays += getHologramIcon(icon(tempicon)) // Add the callers image as an overlay to keep coloration!
else
hologram.overlays += A.holo_icon // Add the AI's configured holo Icon
diff --git a/code/game/objects/items/devices/lighting/toggleable/flashlight.dm b/code/game/objects/items/devices/lighting/toggleable/flashlight.dm
index 4287451346b..35293fa94ec 100644
--- a/code/game/objects/items/devices/lighting/toggleable/flashlight.dm
+++ b/code/game/objects/items/devices/lighting/toggleable/flashlight.dm
@@ -243,7 +243,7 @@
if(ismob(src.loc))
to_chat(src.loc, SPAN_WARNING("Your flashlight dies. You are alone now."))
turn_off()
- else if(cell.percent() <= 25)
+ else if(cell && (cell.percent() <= 25))
apply_power_deficiency()
/obj/item/device/lighting/toggleable/flashlight/attack(mob/living/M, mob/living/user)
diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm
index 386216bf09b..31d157d3bcd 100644
--- a/code/game/objects/items/devices/pipe_painter.dm
+++ b/code/game/objects/items/devices/pipe_painter.dm
@@ -17,7 +17,7 @@
if(!proximity)
return
- if(!istype(A,/obj/machinery/atmospherics/pipe) || istype(A,/obj/machinery/atmospherics/pipe/tank) || istype(A,/obj/machinery/atmospherics/pipe/vent) || istype(A,/obj/machinery/atmospherics/pipe/simple/heat_exchanging) || istype(A,/obj/machinery/atmospherics/pipe/simple/insulated) || !in_range(user, A))
+ if(!istype(A,/obj/machinery/atmospherics/pipe) || istype(A,/obj/machinery/atmospherics/pipe/vent) || istype(A,/obj/machinery/atmospherics/pipe/simple/heat_exchanging) || istype(A,/obj/machinery/atmospherics/pipe/simple/insulated) || !in_range(user, A))
return
var/obj/machinery/atmospherics/pipe/P = A
diff --git a/code/game/objects/items/devices/uplink.dm b/code/game/objects/items/devices/uplink.dm
index aa9da5de9d1..01cd5aaaf64 100644
--- a/code/game/objects/items/devices/uplink.dm
+++ b/code/game/objects/items/devices/uplink.dm
@@ -234,14 +234,14 @@ A list of items and costs is stored under the datum of every game mode, alongsid
nanoui_data["items"] = items
else if(nanoui_menu == 2)
var/permanentData[0]
- for(var/datum/data/record/L in sortRecord(data_core.locked))
- permanentData[++permanentData.len] = list(Name = L.fields["name"],"id" = L.fields["id"])
+ for(var/datum/computer_file/report/crew_record/L in GLOB.all_crew_records)
+ permanentData[++permanentData.len] = list(Name = L.get_name(), "id" = jointext(L.get_name(), L.get_job()))
nanoui_data["exploit_records"] = permanentData
else if(nanoui_menu == 21)
nanoui_data["exploit_exists"] = 0
- for(var/datum/data/record/L in data_core.locked)
- if(L.fields["id"] == exploit_id)
+ for(var/datum/computer_file/report/crew_record/L in GLOB.all_crew_records)
+ if(jointext(L.get_name(), L.get_job()) == exploit_id) // datacore used name and job to make their IDs, so this would be the same level of specificity as it was in datacore
nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value.
// We trade off being able to automatically add shit for more control over what gets passed to json
// and if it's sanitized for html.
diff --git a/code/game/objects/items/weapons/candle.dm b/code/game/objects/items/weapons/candle.dm
index d490e7e0c13..0a9a68243c2 100644
--- a/code/game/objects/items/weapons/candle.dm
+++ b/code/game/objects/items/weapons/candle.dm
@@ -55,7 +55,7 @@
if(!wax)
new/obj/item/trash/candle(src.loc)
if(ismob(loc))
- src.dropped(usr)
+ src.dropped(loc)
qdel(src)
update_icon()
if(istype(loc, /turf)) //start a fire if possible
diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
index f5be72a64bc..9717514e5d0 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
@@ -18,9 +18,6 @@
build_path = /obj/machinery/computer/borgupload
origin_tech = list(TECH_DATA = 4)
-/obj/item/electronics/circuitboard/med_data
- name = T_BOARD("medical records console")
- build_path = /obj/machinery/computer/med_data
/obj/item/electronics/circuitboard/communications
name = T_BOARD("command and communications console")
@@ -33,9 +30,6 @@
build_path = /obj/machinery/computer/teleporter
origin_tech = list(TECH_DATA = 2, TECH_BLUESPACE = 2)
-/obj/item/electronics/circuitboard/secure_data
- name = T_BOARD("security records console")
- build_path = /obj/machinery/computer/secure_data
/obj/item/electronics/circuitboard/atmos_alert
rarity_value = 13.3
diff --git a/code/game/objects/items/weapons/implant/implants/carrion/identity_spider.dm b/code/game/objects/items/weapons/implant/implants/carrion/identity_spider.dm
index 8be0c312aa4..5248bde7c36 100644
--- a/code/game/objects/items/weapons/implant/implants/carrion/identity_spider.dm
+++ b/code/game/objects/items/weapons/implant/implants/carrion/identity_spider.dm
@@ -8,7 +8,7 @@
if(!owner_mob)
return
if(wearer)
- if(wearer.type == /mob/living/carbon/human)
+ if(ishuman(wearer))
var/obj/item/organ/internal/carrion/core/C = owner_mob.random_organ_by_process(BP_SPCORE)
C.absorbed_dna |= wearer.real_name
to_chat(owner_mob, SPAN_NOTICE("You absorb [wearer]'s DNA"))
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index c08f5f1a525..ee19caa1e5d 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -245,10 +245,12 @@
/obj/item/storage/briefcase/antimaterial_rifle/populate_contents()
new /obj/item/ammo_casing/antim(src)
- new /obj/item/part/gun/frame/heavysniper(src)
+ new /obj/item/gun/projectile/automatic/modular/bolt/sniper(src)
new /obj/item/part/gun/modular/grip/serb(src)
- new /obj/item/part/gun/modular/mechanism/boltgun(src)
- new /obj/item/part/gun/modular/barrel/antim(src)
+ new /obj/item/part/gun/modular/mechanism/boltgun/heavy(src)
+ new /obj/item/part/gun/modular/barrel/antim/long(src)
+ new /obj/item/part/gun/modular/stock/heavy(src)
+ new /obj/item/part/gun/modular/sights/customizable/scopeheavy(src)
/obj/item/storage/box/syndie_kit/toxin
name = "toxin kit"
diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm
index 4fbe7fa18fe..e4794fea619 100644
--- a/code/game/objects/items/weapons/storage/wallets.dm
+++ b/code/game/objects/items/weapons/storage/wallets.dm
@@ -86,7 +86,7 @@
if(prob(50))
to_add = pick(/obj/item/spacecash/bundle/c10,/obj/item/spacecash/bundle/c100,/obj/item/spacecash/bundle/c1000,/obj/item/spacecash/bundle/c20,/obj/item/spacecash/bundle/c200,/obj/item/spacecash/bundle/c50,/obj/item/spacecash/bundle/c500)
new to_add(src)
- to_add = pick(/obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/gold, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron)
+ to_add = pick(/obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/gold, /obj/item/coin/plasteel, /obj/item/coin/plasteel, /obj/item/coin/plasteel)
new to_add(src)
if(prob(20))
new /obj/item/card/id/randomassistant(src)
diff --git a/code/game/objects/items/weapons/tools/_tools.dm b/code/game/objects/items/weapons/tools/_tools.dm
index 84553c2a515..be2bc5a2dfd 100644
--- a/code/game/objects/items/weapons/tools/_tools.dm
+++ b/code/game/objects/items/weapons/tools/_tools.dm
@@ -529,7 +529,7 @@
failtypes["damage"] = 2.5
// You can only fail with tools you are holding
- if(user && T.loc == user)
+ if(user && loc == user)
failtypes["slip"] = 2
failtypes["swing"] = 1
if(ishuman(user))
diff --git a/code/game/objects/items/weapons/tools/knives.dm b/code/game/objects/items/weapons/tools/knives.dm
index 9185df41241..ce70ea421b5 100644
--- a/code/game/objects/items/weapons/tools/knives.dm
+++ b/code/game/objects/items/weapons/tools/knives.dm
@@ -32,7 +32,7 @@
I.weapon_upgrades = list(
GUN_UPGRADE_BAYONET = TRUE,
GUN_UPGRADE_MELEEDAMAGE = 5,
- GUN_UPGRADE_MELEEPENETRATION = ARMOR_PEN_MODERATE,
+ GUN_UPGRADE_MELEEPENETRATION = (ARMOR_PEN_MODERATE-1),
GUN_UPGRADE_OFFSET = 4
)
I.gun_loc_tag = GUN_UNDERBARREL
diff --git a/code/game/objects/items/weapons/tools/mods/_upgrades.dm b/code/game/objects/items/weapons/tools/mods/_upgrades.dm
index de7453f9590..dee5b963e1f 100644
--- a/code/game/objects/items/weapons/tools/mods/_upgrades.dm
+++ b/code/game/objects/items/weapons/tools/mods/_upgrades.dm
@@ -255,6 +255,7 @@
P.forceMove(get_turf(I))
UnregisterSignal(I, COMSIG_ADDVAL)
UnregisterSignal(I, COMSIG_APPVAL)
+ reset_owner()
/datum/component/item_upgrade/proc/apply_values(atom/holder)
//SIGNAL_HANDLER
@@ -327,7 +328,7 @@
G.pierce_multiplier += weapon_upgrades[GUN_UPGRADE_PIERC_MULT]
if(weapon_upgrades[GUN_UPGRADE_RICO_MULT])
G.ricochet_multiplier += weapon_upgrades[GUN_UPGRADE_RICO_MULT]
- if(weapon_upgrades[GUN_UPGRADE_STEPDELAY_MULT])
+ if(!isnull(weapon_upgrades[GUN_UPGRADE_STEPDELAY_MULT])) // so AMR barrel can 0x
G.proj_step_multiplier *= weapon_upgrades[GUN_UPGRADE_STEPDELAY_MULT]
if(weapon_upgrades[GUN_UPGRADE_FIRE_DELAY_MULT])
G.fire_delay *= weapon_upgrades[GUN_UPGRADE_FIRE_DELAY_MULT]
@@ -375,6 +376,12 @@
if(ismob(G.loc))
var/mob/user = G.loc
user.update_action_buttons()
+ if(weapon_upgrades[GUN_UPGRADE_SCOPEVISION])
+ G.see_invisible_gun = max(G.see_invisible_gun, weapon_upgrades[GUN_UPGRADE_SCOPEVISION]) // scope stats should take best of class
+ if(weapon_upgrades[GUN_UPGRADE_SCOPECORRECTION])
+ G.scoped_offset_reduction = max(G.scoped_offset_reduction, weapon_upgrades[GUN_UPGRADE_SCOPECORRECTION])
+ if(weapon_upgrades[GUN_UPGRADE_DARKSCOPE])
+ G.darkness_view = max(G.darkness_view, weapon_upgrades[GUN_UPGRADE_DARKSCOPE])
if(weapon_upgrades[GUN_UPGRADE_THERMAL])
G.vision_flags = SEE_MOBS
if(weapon_upgrades[GUN_UPGRADE_GILDED])
@@ -388,6 +395,11 @@
G.armor_divisor += weapon_upgrades[GUN_UPGRADE_MELEEPENETRATION]
if(weapon_upgrades[GUN_UPGRADE_ONEHANDPENALTY])
G.recoil = G.recoil.modifyRating(_one_hand_penalty = weapon_upgrades[GUN_UPGRADE_ONEHANDPENALTY])
+ if(weapon_upgrades[GUN_UPGRADE_MOVEPENALTY])
+ G.recoil = G.recoil.modifyRating(_brace_penalty = weapon_upgrades[GUN_UPGRADE_MOVEPENALTY])
+ if(weapon_upgrades[GUN_UPGRADE_RECOILBUILDUP])
+ G.recoil = G.recoil.modifyRating(_recoil_buildup = weapon_upgrades[GUN_UPGRADE_RECOILBUILDUP])
+
if(weapon_upgrades[GUN_UPGRADE_DNALOCK])
G.dna_compare_samples = TRUE
@@ -430,6 +442,14 @@
M.verbs += /obj/item/gun/projectile/automatic/modular/proc/quick_fold // Grant the verb for folding stocks
if(weapon_upgrades[GUN_UPGRADE_DEFINE_GRIP])
M.grip_type = weapon_upgrades[GUN_UPGRADE_DEFINE_GRIP]
+ if(weapon_upgrades[GUN_UPGRADE_DEFINE_LOADER])
+ M.load_method = weapon_upgrades[GUN_UPGRADE_DEFINE_LOADER]
+ if(weapon_upgrades[GUN_UPGRADE_DENY_MAG])
+ M.no_internal_mag = TRUE
+ if(weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS])
+ M.w_class += weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS]
+ if(weapon_upgrades[GUN_UPGRADE_SCOPE_POWER])
+ M.scope_damage_adds.Add(weapon_upgrades[GUN_UPGRADE_SCOPE_POWER])
for(var/datum/firemode/F in G.firemodes)
apply_values_firemode(F)
@@ -440,6 +460,29 @@
if(weapon_upgrades[GUN_UPGRADE_FIREMODES])
for(var/FM in weapon_upgrades[GUN_UPGRADE_FIREMODES])
G.add_firemode(FM)
+ if(istype(G, /obj/item/gun/projectile/automatic/modular))
+ if(weapon_upgrades[GUN_UPGRADE_REPLACE_INTERACTIONS])
+ var/obj/item/gun/projectile/automatic/modular/interactive = G
+ var/datum/gunoverrides/overrided = interactive.overridedatum
+ if(overrided)
+ var/datum/guninteraction/interaction = weapon_upgrades[GUN_UPGRADE_REPLACE_INTERACTIONS]
+ interaction.parentgun = G
+ if(islist(overrided.priorities["[interaction.priority]"]))
+ var/list/currentpriority = overrided.priorities["[interaction.priority]"]
+ currentpriority.Add(interaction)
+ else
+ overrided.priorities["[interaction.priority]"] = list(interaction)
+
+/datum/component/item_upgrade/proc/reset_owner()
+ if(weapon_upgrades[GUN_UPGRADE_REPLACE_INTERACTIONS])
+ var/datum/guninteraction/interaction = weapon_upgrades[GUN_UPGRADE_REPLACE_INTERACTIONS]
+ if(istype(interaction))
+ interaction.parentgun = null
+ if(weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS])
+ if(istype(parent, /obj/item/part/gun/modular/stock))
+ var/obj/item/part/gun/modular/stock/base = parent
+ weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS] = base.wclassmod
+
/datum/component/item_upgrade/proc/apply_values_firemode(datum/firemode/F)
for(var/i in F.settings)
diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm
index e365e0b9081..fafb07e083f 100644
--- a/code/game/turfs/simulated/floor_attackby.dm
+++ b/code/game/turfs/simulated/floor_attackby.dm
@@ -128,7 +128,7 @@
if(is_damaged())
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_VERY_EASY, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You remove the broken [flooring.descriptor]."))
- make_plating()
+ make_plating(TRUE, null, TRUE)
return
else if(flooring.flags & TURF_IS_FRAGILE)
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_VERY_EASY, required_stat = STAT_MEC))
@@ -138,7 +138,7 @@
else if(flooring.flags & TURF_REMOVE_CROWBAR)
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_VERY_EASY, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You lever off the [flooring.descriptor]."))
- make_plating(1)
+ make_plating(TRUE)
return
return
@@ -146,21 +146,21 @@
if((!(is_damaged()) && !is_plating()) || flooring.flags & TURF_REMOVE_SCREWDRIVER)
if(I.use_tool(user, src, flooring.removal_time*1.5, tool_type, FAILCHANCE_VERY_EASY, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You unscrew and remove the [flooring.descriptor]."))
- make_plating(1)
+ make_plating(TRUE)
return
if(QUALITY_BOLT_TURNING)
if(flooring.flags & TURF_REMOVE_WRENCH)
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_NORMAL, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You unwrench and remove the [flooring.descriptor]."))
- make_plating(1)
+ make_plating(TRUE)
return
if(QUALITY_SHOVELING)
if(flooring.flags & TURF_REMOVE_SHOVEL)
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_VERY_EASY, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You shovel off the [flooring.descriptor]."))
- make_plating(1)
+ make_plating(TRUE)
return
if(QUALITY_WELDING)
@@ -179,7 +179,7 @@
to_chat(user, SPAN_NOTICE("You start cutting through the [flooring.descriptor]."))
if(I.use_tool(user, src, flooring.removal_time, tool_type, FAILCHANCE_NORMAL, required_stat = STAT_MEC))
to_chat(user, SPAN_NOTICE("You cut through and remove the [flooring.descriptor]."))
- make_plating(1)
+ make_plating(TRUE)
if(ABORT_CHECK)
return
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index a9c97abf497..5adc512afab 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -69,7 +69,9 @@
girder.is_low = is_low_wall
girder.is_reinforced = is_reinforced
girder.update_icon()
- qdel(src)
+ remove_neighbour_connections()
+ ChangeTurf(/turf/floor/plating)
+ updateVisibility(src)
/turf/wall/get_matter()
return list(MATERIAL_STEEL = 5)
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index 9bfa1824162..2cfe8bb1ec2 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -341,7 +341,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += "-- "
for(var/j in get_all_jobs())
output += "[j] "
- for(var/j in nonhuman_positions)
+ for(var/j in silicon_positions)
output += "[j] "
var/list/bantypes = list("contractor","carrion","operative","revolutionary","cultist","wizard") //For legacy bans.
for(var/ban_type in GLOB.antag_bantypes) // Grab other bans.
diff --git a/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
index 3cbe5062e71..e2c57b04d1e 100644
--- a/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
+++ b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm
@@ -7,6 +7,6 @@
return
var/dat
dat += "Crew Manifest "
- dat += data_core.get_manifest()
+ dat += html_crew_manifest(TRUE)
user << browse(dat, "window=manifest;size=370x420;can_close=1")
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 6231512f112..03737d21e38 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -321,23 +321,8 @@ Contractors and the like can also be revived with the previous role mostly intac
var/mob/living/carbon/human/new_character = new()//The mob being spawned.
- var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character.
- if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something
- /*Try and locate a record for the person being respawned through data_core.
- This isn't an exact science but it does the trick more often than not.*/
- var/id = md5("[G_found.real_name][G_found.mind.assigned_role]")
- for(var/datum/data/record/t in data_core.locked)
- if(t.fields["id"]==id)
- record_found = t//We shall now reference the record.
- break
-
- if(record_found)//If they have a record we can determine a few things.
- new_character.real_name = record_found.fields["name"]
- new_character.gender = record_found.fields["sex"]
- new_character.age = record_found.fields["age"]
- new_character.b_type = record_found.fields["b_type"]
- new_character.dna_trace = record_found.fields["b_dna"]
- new_character.fingers_trace = record_found.fields["fingerprint"]
+ if(G_found.client?.prefs)//If they have a record we can determine a few things.
+ G_found.client?.prefs.copy_to(new_character)
else
new_character.gender = pick(MALE,FEMALE)
var/datum/preferences/A = new()
@@ -378,12 +363,13 @@ Contractors and the like can also be revived with the previous role mostly intac
//Now for special roles and equipment.
SSjob.EquipRank(new_character, new_character.mind.assigned_role)
+ var/datum/computer_file/report/crew_record/record_found = get_crewmember_record(new_character.name)
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
if(!record_found && !player_is_antag(new_character.mind, only_offstation_roles = 1)) //If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
//Power to the user!
- if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
- data_core.manifest_inject(new_character)
+ if(alert(new_character,"Warning: No record entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
+ CreateModularRecord(new_character)
if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes")
call(/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role)
diff --git a/code/modules/asset_cache/assets/legacyuiicons.dm b/code/modules/asset_cache/assets/legacyuiicons.dm
new file mode 100644
index 00000000000..5051a76d70a
--- /dev/null
+++ b/code/modules/asset_cache/assets/legacyuiicons.dm
@@ -0,0 +1,5 @@
+/datum/asset/spritesheet/legacyicons
+ name = "oldicons"
+
+/datum/asset/spritesheet/legacyicons/create_spritesheets()
+ InsertAll("", 'icons/ui_icons/dmis/uiicons16.dmi')
diff --git a/code/modules/client/preference_setup/background/03_records.dm b/code/modules/client/preference_setup/background/03_records.dm
index f65d4407d45..59d34b28a9b 100644
--- a/code/modules/client/preference_setup/background/03_records.dm
+++ b/code/modules/client/preference_setup/background/03_records.dm
@@ -15,9 +15,6 @@
from_file(S["memory"],pref.memory)
/datum/category_item/player_setup_item/background/records/save_character(var/savefile/S)
- to_file(S["med_record"],pref.med_record)
- to_file(S["sec_record"],pref.sec_record)
- to_file(S["gen_record"],pref.gen_record)
to_file(S["memory"],pref.memory)
/datum/category_item/player_setup_item/background/records/content(var/mob/user)
@@ -26,33 +23,30 @@
if(jobban_isbanned(user, "Records"))
. += "You are banned from using character records. "
else
- . += "Medical Records: "
- . += "[TextPreview(pref.med_record,40)] "
- . += "Employment Records: "
- . += "[TextPreview(pref.gen_record,40)] "
- . += "Security Records: "
- . += "[TextPreview(pref.sec_record,40)] "
+ if(pref.med_record)
+ . += "Medical Records: "
+ . += "[TextPreview(pref.med_record,40)] "
+ if(pref.gen_record)
+ . += "Employment Records: "
+ . += "[TextPreview(pref.gen_record,40)] "
+ if(pref.sec_record)
+ . += "Security Records: "
+ . += "[TextPreview(pref.sec_record,40)] "
. += "Memory: "
. += "[TextPreview(pref.memory,40)] "
. = jointext(.,null)
/datum/category_item/player_setup_item/background/records/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["set_medical_records"])
- var/new_medical = sanitize(input(user,"Enter medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.med_record = new_medical
+ input(user,"Read medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_general_records"])
- var/new_general = sanitize(input(user,"Enter employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.gen_record = new_general
+ input(user,"Read employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_security_records"])
- var/sec_medical = sanitize(input(user,"Enter security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.sec_record = sec_medical
+ input(user,"Read security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null
return TOPIC_REFRESH
else if(href_list["set_memory"])
@@ -62,3 +56,82 @@
return TOPIC_REFRESH
. = ..()
+
+/datum/category_item/player_setup_item/background/records/proc/load_record(savefile/S, recordtype)
+ var/recordgiven = S["[recordtype]"]
+ if(S["version"] >= 19)
+ if(!recordgiven || !(recordtype in pref.vars))
+ return FALSE
+
+ if(istype(recordgiven, /datum/storedrecord))
+ pref.vars[recordtype] = recordgiven
+ else
+ if(istext(recordgiven) && (recordtype in pref.vars))
+ pref.vars[recordtype] = recordgiven
+
+
+
+/datum/storedrecord
+
+/datum/storedrecord/proc/transfertocomputer(datum/report_field/tofile)
+ // nobody here.
+/datum/storedrecord/security
+ var/list/crimes = list()
+ var/list/evidence = list()
+ var/list/locations = list()
+
+
+/datum/storedrecord/security/transfertocomputer(datum/report_field/tofile)
+ if(!istype(tofile, /datum/report_field/arraylinkage))
+ return FALSE
+ var/datum/report_field/arraylinkage/toset = tofile
+ toset.arrays = list()
+ toset.arrays["crimes"] = crimes // edit these appropriately on any changes
+ toset.arrays["evidence"] = evidence // don't forget to synch these indexes
+ toset.arrays["locations"] = locations
+
+/datum/storedrecord/security/default // used by default
+ crimes = list("No crimes on record.")
+ evidence = list("N/A.")
+ locations = list("N/A.")
+
+
+/datum/storedrecord/medical
+ var/list/prosthetics = list()
+ var/list/wounds = list()
+ var/list/bodystate = list()
+ var/list/chemhistory = list()
+ var/list/psychological = list()
+
+
+/datum/storedrecord/medical/transfertocomputer(datum/report_field/tofile)
+ if(!istype(tofile, /datum/report_field/arrayclump))
+ return FALSE
+ var/datum/report_field/arrayclump/toset = tofile
+ var/list/tochange = toset.value
+ tochange["prosthetics"] = prosthetics // change these appropriately as well
+ tochange["wounds"] = wounds // but as an arrayclump, they don't need synchronized indexing
+ tochange["Body state"] = bodystate
+ tochange["chemhistory"] = chemhistory
+ tochange["psychological"] = psychological
+
+
+/datum/storedrecord/medical/default // used by default
+ prosthetics = list("No prosthetics on record.")
+ wounds = list("No wounds on record.")
+ bodystate = list("Alive at time of writing.")
+ chemhistory = list("Chemical record is clean.")
+ psychological = list("No psychological profiling has been done at time of writing.")
+
+
+/datum/storedrecord/general
+ var/background // background is defined by fates
+ var/origin // origin is defined by origin
+
+
+
+
+/datum/storedrecord/general/default // used by default
+ background = list("Unremarkable.")
+ origin = list("Origin unknown.")
+
diff --git a/code/modules/client/preference_setup/general/05_records.dm b/code/modules/client/preference_setup/general/05_records.dm
deleted file mode 100644
index 28767cd3fa4..00000000000
--- a/code/modules/client/preference_setup/general/05_records.dm
+++ /dev/null
@@ -1,64 +0,0 @@
-/datum/preferences
- var/med_record = ""
- var/sec_record = ""
- var/gen_record = ""
- var/memory = ""
-
-/datum/category_item/player_setup_item/physical/records
- name = "Records"
- sort_order = 5
-
-/datum/category_item/player_setup_item/physical/records/load_character(var/savefile/S)
- from_file(S["med_record"],pref.med_record)
- from_file(S["sec_record"],pref.sec_record)
- from_file(S["gen_record"],pref.gen_record)
- from_file(S["memory"],pref.memory)
-
-/datum/category_item/player_setup_item/physical/records/save_character(var/savefile/S)
- to_file(S["med_record"],pref.med_record)
- to_file(S["sec_record"],pref.sec_record)
- to_file(S["gen_record"],pref.gen_record)
- to_file(S["memory"],pref.memory)
-
-/datum/category_item/player_setup_item/physical/records/content(var/mob/user)
- . = list()
- . += "Records : "
- if(jobban_isbanned(user, "Records"))
- . += "You are banned from using character records. "
- else
- . += "Medical Records: "
- . += "[TextPreview(pref.med_record,40)] "
- . += "Employment Records: "
- . += "[TextPreview(pref.gen_record,40)] "
- . += "Security Records: "
- . += "[TextPreview(pref.sec_record,40)] "
- . += "Memory: "
- . += "[TextPreview(pref.memory,40)] "
- . = jointext(.,null)
-
-/datum/category_item/player_setup_item/physical/records/OnTopic(var/href,var/list/href_list, var/mob/user)
- if(href_list["set_medical_records"])
- var/new_medical = sanitize(input(user,"Enter medical information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.med_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.med_record = new_medical
- return TOPIC_REFRESH
-
- else if(href_list["set_general_records"])
- var/new_general = sanitize(input(user,"Enter employment information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.gen_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(new_general) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.gen_record = new_general
- return TOPIC_REFRESH
-
- else if(href_list["set_security_records"])
- var/sec_medical = sanitize(input(user,"Enter security information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.sec_record)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(sec_medical) && !jobban_isbanned(user, "Records") && CanUseTopic(user))
- pref.sec_record = sec_medical
- return TOPIC_REFRESH
-
- else if(href_list["set_memory"])
- var/memes = sanitize(input(user,"Enter memorized information here.",CHARACTER_PREFERENCE_INPUT_TITLE, html_decode(pref.memory)) as message|null, MAX_PAPER_MESSAGE_LEN, extra = 0)
- if(!isnull(memes) && CanUseTopic(user))
- pref.memory = memes
- return TOPIC_REFRESH
-
- . = ..()
diff --git a/code/modules/client/preference_setup/loadout/lists/accessories.dm b/code/modules/client/preference_setup/loadout/lists/accessories.dm
index 8ef7c68fba2..939ae4b7dae 100644
--- a/code/modules/client/preference_setup/loadout/lists/accessories.dm
+++ b/code/modules/client/preference_setup/loadout/lists/accessories.dm
@@ -43,7 +43,7 @@
/datum/gear/accessory/guild
display_name = "armband, Aster's Guild"
path = /obj/item/clothing/accessory/armband/cargo
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
/datum/gear/accessory/engineering
display_name = "armband, Technomancer League"
diff --git a/code/modules/client/preference_setup/loadout/lists/suits.dm b/code/modules/client/preference_setup/loadout/lists/suits.dm
index aae61f2a909..2915bdfa18f 100644
--- a/code/modules/client/preference_setup/loadout/lists/suits.dm
+++ b/code/modules/client/preference_setup/loadout/lists/suits.dm
@@ -137,10 +137,10 @@
/datum/gear/suit/guild/black
display_name = "black guild coat"
path = /obj/item/clothing/suit/storage/cargo_jacket/black
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
/datum/gear/suit/guild/black/old
display_name = "old black guild coat"
path = /obj/item/clothing/suit/storage/cargo_jacket/black/old
- allowed_roles = list(JOBS_CARGO)
+ allowed_roles = list(JOBS_GUILD)
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index d147644c094..1c99753d81d 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -239,10 +239,7 @@
for(var/lang in alternate_languages)
character.add_language(lang)
-
- character.med_record = med_record
- character.sec_record = sec_record
- character.gen_record = gen_record
+
character.exploit_record = exploit_record
if(!character.isSynthetic())
character.nutrition = rand(250, 450)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 3868750180a..c60ce12189c 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -1,5 +1,5 @@
#define SAVEFILE_VERSION_MIN 8
-#define SAVEFILE_VERSION_MAX 18
+#define SAVEFILE_VERSION_MAX 19
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
diff --git a/code/modules/economy/Accounts.dm b/code/modules/economy/Accounts.dm
index 9bd0818e2bf..56100ca2687 100644
--- a/code/modules/economy/Accounts.dm
+++ b/code/modules/economy/Accounts.dm
@@ -37,8 +37,12 @@
return owner_name
//Attempts to return the associated data record for this account
+// expensive to run, store the result from this.
/datum/money_account/proc/get_record()
- return find_general_record("pay_account", account_number)
+ for(var/datum/computer_file/report/crew_record/CR in GLOB.all_crew_records)
+ var/accountnum = CR.get_account()
+ if(account_number == accountnum)
+ return CR
/datum/transaction
var/target_name = ""
diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index 882dfea2999..632fed74e37 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -68,7 +68,7 @@
if(63 to 64)
var/t = rand(4,7)
for(var/i = 0, i < t, ++i)
- var/newcoin = pick(/obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/iron, /obj/item/coin/gold, /obj/item/coin/diamond, /obj/item/coin/plasma, /obj/item/coin/uranium, /obj/item/coin/platinum)
+ var/newcoin = pick(/obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/silver, /obj/item/coin/plasteel, /obj/item/coin/plasteel, /obj/item/coin/plasteel, /obj/item/coin/gold, /obj/item/coin/diamond, /obj/item/coin/plasma, /obj/item/coin/uranium, /obj/item/coin/platinum)
new newcoin(src)
if(65 to 68)
var/t = rand(4,7)
diff --git a/code/modules/mining/coins.dm b/code/modules/mining/coins.dm
index 1a1b318014c..434638d6e99 100644
--- a/code/modules/mining/coins.dm
+++ b/code/modules/mining/coins.dm
@@ -20,30 +20,44 @@
/obj/item/coin/gold
name = COIN_GOLD
icon_state = "coin_gold"
+ matter = list(MATERIAL_GOLD = 0.2)
+ price_tag = 10
/obj/item/coin/silver
name = COIN_SILVER
icon_state = "coin_silver"
+ matter = list(MATERIAL_SILVER = 0.2)
+ price_tag = 8
/obj/item/coin/diamond
name = COIN_DIAMOND
icon_state = "coin_diamond"
+ matter = list(MATERIAL_DIAMOND = 0.2)
+ price_tag = 20
-/obj/item/coin/iron
- name = COIN_IRON
+/obj/item/coin/plasteel
+ name = COIN_PLASTEEL
icon_state = "coin_iron"
+ matter = list(MATERIAL_PLASTEEL = 0.2)
+ price_tag = 6
/obj/item/coin/plasma
name = COIN_PLASMA
icon_state = "coin_plasma"
+ matter = list(MATERIAL_PLASMA = 0.2)
+ price_tag = 6
/obj/item/coin/uranium
name = COIN_URANIUM
icon_state = "coin_uranium"
+ matter = list(MATERIAL_URANIUM = 0.2)
+ price_tag = 10
/obj/item/coin/platinum
name = COIN_PLATINUM
icon_state = "coin_adamantine"
+ matter = list(MATERIAL_PLATINUM = 0.2)
+ price_tag = 16
/obj/item/coin/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/stack/cable_coil))
diff --git a/code/modules/mining/drilling/deep_drill.dm b/code/modules/mining/drilling/deep_drill.dm
index 0c4f10389a2..f496ec8dda5 100644
--- a/code/modules/mining/drilling/deep_drill.dm
+++ b/code/modules/mining/drilling/deep_drill.dm
@@ -43,7 +43,7 @@
MATERIAL_PLASTIC = /obj/item/ore/coal
)
-/obj/machinery/mining/deep_drill/Initialize()
+/obj/machinery/mining/deep_drill/LateInitialize()
. = ..()
cave_gen = locate(/obj/cave_generator)
update_icon()
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index fdbdc12c46b..de862f2b8ff 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -149,8 +149,9 @@
for(var/oretype in typesof(/ore)-/ore)
var/ore/OD = new oretype()
ore_data[OD.name] = OD
- ores_processing[OD.name] = 0
- ores_stored[OD.name] = 0
+ for(var/ore/OD in ore_data)
+ ores_processing[OD.name] = 0
+ ores_stored[OD.name] = 0
spawn()
//Locate our output and input machinery.
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
index 03690ad9128..bfa17850c02 100644
--- a/code/modules/mining/money_bag.dm
+++ b/code/modules/mining/money_bag.dm
@@ -15,7 +15,7 @@
var/amt_gold = 0
var/amt_silver = 0
var/amt_diamond = 0
- var/amt_iron = 0
+ var/amt_plasteel = 0
var/amt_plasma = 0
var/amt_uranium = 0
@@ -24,8 +24,8 @@
amt_diamond++;
if (istype(C,/obj/item/coin/plasma))
amt_plasma++;
- if (istype(C,/obj/item/coin/iron))
- amt_iron++;
+ if (istype(C,/obj/item/coin/plasteel))
+ amt_plasteel++;
if (istype(C,/obj/item/coin/silver))
amt_silver++;
if (istype(C,/obj/item/coin/gold))
@@ -38,8 +38,8 @@
dat += text("Gold coins: [amt_gold] Remove one ")
if (amt_silver)
dat += text("Silver coins: [amt_silver] Remove one ")
- if (amt_iron)
- dat += text("Metal coins: [amt_iron] Remove one ")
+ if (amt_plasteel)
+ dat += text("Plasteel coins: [amt_plasteel] Remove one ")
if (amt_diamond)
dat += text("Diamond coins: [amt_diamond] Remove one ")
if (amt_plasma)
@@ -73,17 +73,17 @@
COIN = locate(/obj/item/coin/gold,src.contents)
if(MATERIAL_SILVER)
COIN = locate(/obj/item/coin/silver,src.contents)
- if("iron")
- COIN = locate(/obj/item/coin/iron,src.contents)
+ if(MATERIAL_PLASTEEL)
+ COIN = locate(/obj/item/coin/plasteel,src.contents)
if(MATERIAL_DIAMOND)
COIN = locate(/obj/item/coin/diamond,src.contents)
- if("plasma")
+ if(MATERIAL_PLASMA)
COIN = locate(/obj/item/coin/plasma,src.contents)
if(MATERIAL_URANIUM)
COIN = locate(/obj/item/coin/uranium,src.contents)
if(!COIN)
return
- COIN.loc = src.loc
+ COIN.forceMove(get_turf(src))
return
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index a2c889b6124..f35152a5ca2 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -108,9 +108,8 @@
var/mob/living/carbon/human/H = speaker
if(H.voice)
speaker_name = H.voice
- for(var/datum/data/record/G in data_core.general)
- if(G.fields["name"] == speaker_name)
- return H.rank_prefix_name(speaker_name)
+ if(get_crewmember_record(speaker_name))
+ return H.rank_prefix_name(speaker_name)
return voice_name ? voice_name : speaker_name
diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm
index bf61af693ba..6cf3d470d69 100755
--- a/code/modules/mob/holder.dm
+++ b/code/modules/mob/holder.dm
@@ -136,10 +136,8 @@ var/list/holder_mob_icon_cache = list()
//Repeat this check
//If we're still on the turf a few frames later, then we have actually been dropped or thrown
//Release the mob accordingly
- //addtimer(CALLBACK(src, PROC_REF(post_drop)), 3)
+ addtimer(CALLBACK(src, PROC_REF(post_drop)), 3)
//TODO: Uncomment the above once addtimer is ported
- spawn(3)
- post_drop()
return
if (istype(loc, /obj/item/storage)) //The second drop reads the container its placed into as the location
@@ -581,6 +579,18 @@ var/list/holder_mob_icon_cache = list()
return I
return null
+//Holders for mice
+/obj/item/holder/carrion
+ name = "spider core"
+ desc = "A horrifying face on spider-like legs."
+ desc_dead = "A dead bio-weapon, it probably tastes horrible."
+ icon = 'icons/mob/animal.dmi'
+ icon_state = "spider_core"
+ slot_flags = SLOT_HEAD
+ origin_tech = list(TECH_BIO = 5)
+ w_class = ITEM_SIZE_NORMAL
+
+
/*
//Lizards
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index c647f21637c..26b9b9510bd 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -44,7 +44,7 @@
W.forceMove(get_turf(src))
W.layer = initial(W.layer)
W.set_plane(initial(W.plane))
- W.dropped(usr)
+ W.dropped(src)
// Removes an item from inventory and places it in the target atom.
// If canremove or other conditions need to be checked then use unEquip instead.
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 74137ba2483..76fbc1a113e 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -294,7 +294,8 @@
criminal = R ? R.get_criminalStatus() : "None"
msg += "Criminal status: \[[criminal]\] \n"
- msg += "Security records: \[View\] \[Add comment\] \n"
+ msg += {"Security records: \[View\] \[View Brief\]
+ \[Add Note\] \n"}
if(hasHUD(user, "medical"))
var/perpname = "wot"
@@ -306,15 +307,11 @@
perpname = id_card.registered_name
else
perpname = src.name
-
- for (var/datum/data/record/E in data_core.general)
- if (E.fields["name"] == perpname)
- for (var/datum/data/record/R in data_core.general)
- if (R.fields["id"] == E.fields["id"])
- medical = R.fields["p_stat"]
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ medical = E.get_status()
msg += "Physical status: \[[medical]\] \n"
- msg += "Medical records: \[View\] \[Add comment\] \n"
+ msg += "Medical records: \[View\] \n"
var/obj/item/clothing/under/U = w_uniform
if(U && istype(U) && U.sensor_mode >= 2)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index e4a204b26bc..7103825d880 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -425,21 +425,20 @@ var/list/rank_prefix = list(\
if(perpname)
var/datum/computer_file/report/crew_record/R = get_crewmember_record(perpname)
if(R)
+ modified = TRUE
var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.get_criminalStatus()) in GLOB.security_statuses + "Cancel"
- if(hasHUD(usr, "security"))
- if(setcriminal != "Cancel")
- R.set_criminalStatus(setcriminal)
- modified = TRUE
- BITSET(hud_updateflag, WANTED_HUD)
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- U.handle_regular_hud_updates()
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- U.handle_regular_hud_updates()
+ if(setcriminal != "Cancel")
+ R.set_criminalStatus(setcriminal)
+ BITSET(hud_updateflag, WANTED_HUD)
+ if(ishuman(usr))
+ var/mob/living/carbon/human/U = usr
+ U.handle_regular_hud_updates()
+ if(isrobot(usr))
+ var/mob/living/silicon/robot/U = usr
+ U.handle_regular_hud_updates()
if(!modified)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
+ to_chat(usr, "\red Unable to locate a criminal record for this person.")
if(href_list["secrecord"])
if(hasHUD(usr,"security"))
@@ -452,52 +451,50 @@ var/list/rank_prefix = list(\
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]")
- to_chat(usr, "Minor Crimes: [R.fields["mi_crim"]]")
- to_chat(usr, "Details: [R.fields["mi_crim_d"]]")
- to_chat(usr, "Major Crimes: [R.fields["ma_crim"]]")
- to_chat(usr, "Details: [R.fields["ma_crim_d"]]")
- to_chat(usr, "Notes: [R.fields["notes"]]")
- to_chat(usr, "\[View Comment Log\] ")
- read = 1
+ var/datum/computer_file/report/crew_record/CR = get_crewmember_record(perpname)
+ if(CR)
+ to_chat(usr, "Name: [CR.get_name()] Criminal Status: [CR.get_criminalStatus()]")
+ var/datum/report_field/array/tofetch = CR.get_linkage_secNotes()
+ var/list/Briefing = tofetch.value_list
+ if(Briefing.len > 0)
+ var/list/combined = list()
+ for(var/iterator = min(Briefing.len-1, 3), iterator > -1, iterator -= 1)
+ combined.Add(Briefing[Briefing.len - iterator])
+ to_chat(usr, "Briefing latest: "+combined.Join(", "))
+ to_chat(usr, "\[Add to Brief\] ")
+ to_chat(usr, "\[View Full Brief\] ")
+ read = 1
if(!read)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
+ to_chat(usr, "\red Unable to locate a criminal record for this person.")
- if(href_list["secrecordComment"])
+ if(href_list["viewbrief"])
if(hasHUD(usr,"security"))
var/perpname = "wot"
- var/read = 0
- var/obj/item/card/id/id = GetIdCard()
- if(istype(id))
- perpname = id.registered_name
+ if(wear_id)
+ var/obj/item/card/id/id
+ if(istype(wear_id, /obj/item/modular_computer/pda))
+ id = wear_id.GetIdCard()
+ if(!id)
+ id = get_idcard()
+ if(id)
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- read = 1
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
- counter++
- if(counter == 1)
- to_chat(usr, "No comment found")
- to_chat(usr, "\[Add comment\] ")
-
- if(!read)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(!E)
+ to_chat(usr, SPAN_DANGER("Unable to locate a record for this person."))
+ return
+ var/datum/report_field/array/tofetch = E.get_linkage_secNotes()
+ var/list/Briefing = tofetch.value_list
+ if(Briefing.len > 0)
+ to_chat(usr, SPAN_NOTICE("Brief: " + Briefing.Join(", ")))
+ else
+ to_chat(usr, SPAN_NOTICE("[perpname] does not have a brief."))
- if(href_list["secrecordadd"])
+ if(href_list["secnoteadd"])
if(hasHUD(usr,"security"))
var/perpname = "wot"
if(wear_id)
@@ -506,32 +503,27 @@ var/list/rank_prefix = list(\
id = wear_id.GetIdCard()
if(!id)
id = get_idcard()
- if(id)
- perpname = id.registered_name
+ if(id)
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.security)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"security"))
- var/t1 = sanitize(input("Add Comment:", "Sec. records", null, null) as message)
- if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) )
- return
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- counter++
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year] [t1]")
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year] [t1]")
+
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(!E)
+ to_chat(usr, SPAN_WARNING("Record for [perpname] not found!"))
+ return
+ var/t1 = sanitize(input("Add to Brief:", "Sec. records", null, null) as text)
+ if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"security")) )
+ return
+
+ var/datum/report_field/array/recordnote = E.get_linkage_secNotes()
+
+ if(recordnote)
+ recordnote.add_value(t1)
if(href_list["medical"])
if(hasHUD(usr,"medical"))
var/perpname = "wot"
- var/modified = 0
var/obj/item/card/id/id = GetIdCard()
if(istype(id))
@@ -539,126 +531,49 @@ var/list/rank_prefix = list(\
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.general)
- if(R.fields["id"] == E.fields["id"])
-
- var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("*SSD*", "*Deceased*", "Physically Unfit", "Active", "Disabled", "Cancel")
-
- if(hasHUD(usr,"medical"))
- if(setmedical != "Cancel")
- R.fields["p_stat"] = setmedical
- modified = 1
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ if(E)
+ var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", E.get_status()) in GLOB.physical_statuses
- spawn()
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- U.handle_regular_hud_updates()
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- U.handle_regular_hud_updates()
+ if(hasHUD(usr,"medical"))
+ if(setmedical != "Cancel")
+ E.set_status(setmedical)
- if(!modified)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
-
- if(href_list["medrecord"])
- if(hasHUD(usr,"medical"))
- var/perpname = "wot"
- var/read = 0
+ spawn()
+ if(ishuman(usr))
+ var/mob/living/carbon/human/U = usr
+ U.handle_regular_hud_updates()
+ if(isrobot(usr))
+ var/mob/living/silicon/robot/U = usr
+ U.handle_regular_hud_updates()
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
else
- perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- to_chat(usr, "Name: [R.fields["name"]] Blood Type: [R.fields["b_type"]]")
- to_chat(usr, "DNA: [R.fields["b_dna"]]")
- to_chat(usr, "Minor Disabilities: [R.fields["mi_dis"]]")
- to_chat(usr, "Details: [R.fields["mi_dis_d"]]")
- to_chat(usr, "Major Disabilities: [R.fields["ma_dis"]]")
- to_chat(usr, "Details: [R.fields["ma_dis_d"]]")
- to_chat(usr, "Notes: [R.fields["notes"]]")
- to_chat(usr, "\[View Comment Log\] ")
- read = 1
-
- if(!read)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
+ to_chat(usr, "\red Unable to locate a medical record for this person.")
- if(href_list["medrecordComment"])
+ if(href_list["medrecord"])
if(hasHUD(usr,"medical"))
var/perpname = "wot"
var/read = 0
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
+ var/obj/item/card/id/id = GetIdCard()
+ if(istype(id))
+ perpname = id.registered_name
else
perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- read = 1
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- to_chat(usr, text("[]", R.fields[text("com_[]", counter)]))
- counter++
- if(counter == 1)
- to_chat(usr, "No comment found")
- to_chat(usr, "\[Add comment\] ")
+ var/datum/computer_file/report/crew_record/E = get_crewmember_record(perpname)
+ var/datum/report_field/arrayclump/M = E.get_linkage_medRecord()
+ if(E)
+ to_chat(usr, "Name: [E.get_name()] Blood Type: [E.get_bloodtype()]")
+ to_chat(usr, "DNA: [E.get_dna()]")
+ to_chat(usr, "Prosthetics: [M.value["prosthetics"]]")
+ to_chat(usr, "Recorded Wounds: [M.value["wounds"]]")
+ to_chat(usr, "Autopsy: [M.value["Body state"]]")
+ to_chat(usr, "Psychological Profile: [M.value["psychological"]]")
+ to_chat(usr, "Chemical History: [M.value["chemhistory"]]")
+ read = 1
if(!read)
- to_chat(usr, "\red Unable to locate a data core entry for this person.")
-
- if(href_list["medrecordadd"])
- if(hasHUD(usr,"medical"))
- var/perpname = "wot"
- if(wear_id)
- var/obj/item/card/id/id
- if(istype(wear_id, /obj/item/modular_computer/pda))
- id = wear_id.GetIdCard()
- if(!id)
- id = get_idcard()
- if(id)
- perpname = id.registered_name
- else
- perpname = src.name
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == perpname)
- for(var/datum/data/record/R in data_core.medical)
- if(R.fields["id"] == E.fields["id"])
- if(hasHUD(usr,"medical"))
- var/t1 = sanitize(input("Add Comment:", "Med. records", null, null) as message)
- if( !(t1) || usr.stat || usr.restrained() || !(hasHUD(usr,"medical")) )
- return
- var/counter = 1
- while(R.fields[text("com_[]", counter)])
- counter++
- if(ishuman(usr))
- var/mob/living/carbon/human/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.get_authentification_name()] ([U.get_assignment()]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year] [t1]")
- if(isrobot(usr))
- var/mob/living/silicon/robot/U = usr
- R.fields[text("com_[counter]")] = text("Made by [U.name] ([U.modtype] [U.braintype]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year] [t1]")
+ to_chat(usr, "\red Unable to locate a medical record for this person.")
if(href_list["lookitem"])
var/obj/item/I = locate(href_list["lookitem"])
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index d38ef6b67fb..5ac925a2773 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -345,7 +345,7 @@ This function restores all organs.
organ = def_zone
else
if(!def_zone)
- if(!damagetype == TOX) // global application
+ if(!(damagetype == TOX)) // global application
def_zone = ran_zone(def_zone)
organ = get_organ(check_zone(def_zone))
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 771b32d155c..8cc45281e7d 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -37,7 +37,7 @@ meteor_act
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."
SP.loc = organ
if(length(P.matter))
- SP.material = P.matter[1]
+ SP.material = get_material_by_name(P.matter[1])
SP.amount = P.matter[SP.material] // amount no longer randomized
organ.embed(SP)
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index f10fe52c7a6..de1bf065ae6 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -84,9 +84,6 @@
var/equipment_prescription // Eye prescription granted by equipped items
var/list/equipment_overlays = list() // Extra overlays from equipped items
- var/med_record = ""
- var/sec_record = ""
- var/gen_record = ""
var/exploit_record = ""
var/stance_damage = 0 //Whether this mob's ability to stand has been affected
diff --git a/code/modules/mob/living/carbon/superior_animal/roach/roach.dm b/code/modules/mob/living/carbon/superior_animal/roach/roach.dm
index 5de1e56f001..771cb0e171d 100644
--- a/code/modules/mob/living/carbon/superior_animal/roach/roach.dm
+++ b/code/modules/mob/living/carbon/superior_animal/roach/roach.dm
@@ -120,7 +120,7 @@
comrade.joinOvermind(overseer)
overseer.leader = comrade
else if(!overseer && comrade.overseer) // or if they have an overmind and we don't, we join
- joinOvermind(overseer)
+ joinOvermind(comrade.overseer)
if(/mob/living/carbon/superior_animal/roach/kaiser) // only one possibility requires code with kaiser
if(istype(comrade, /mob/living/carbon/superior_animal/roach/fuhrer))
if(overseer && comrade.overseer)
@@ -131,5 +131,5 @@
else if(overseer && !comrade.overseer)
comrade.joinOvermind(overseer)
else
- if(!overseer && istype(comrade, /mob/living/carbon/superior_animal/roach/fuhrer) || istype(comrade, /mob/living/carbon/superior_animal/roach/kaiser) && comrade.overseer)
+ if(!overseer && (istype(comrade, /mob/living/carbon/superior_animal/roach/fuhrer) || istype(comrade, /mob/living/carbon/superior_animal/roach/kaiser)) && comrade.overseer)
joinOvermind(comrade.overseer)
diff --git a/code/modules/mob/living/carbon/superior_animal/roach/roachmind.dm b/code/modules/mob/living/carbon/superior_animal/roach/roachmind.dm
index 5709077ab16..4df847b22bc 100644
--- a/code/modules/mob/living/carbon/superior_animal/roach/roachmind.dm
+++ b/code/modules/mob/living/carbon/superior_animal/roach/roachmind.dm
@@ -33,7 +33,7 @@
var/list/highest[] // an overmind ruled by a fuhrer is subordinate to one ruled by a kaiser.
if(istype(leader, /mob/living/carbon/superior_animal/roach/kaiser))
highest += src
- if(!istype(collatewith.leader, /mob/living/carbon/superior_animal/roach/kaiser))
+ if(istype(collatewith.leader, /mob/living/carbon/superior_animal/roach/kaiser))
highest += collatewith
if(length(highest) == 1)
if(highest[1] == src)
diff --git a/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm b/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm
index 37951ccf651..45c8c8adb7e 100644
--- a/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm
+++ b/code/modules/mob/living/carbon/superior_animal/roach/types/kaiser.dm
@@ -106,6 +106,25 @@ Has ability of every roach.
gas_sac.clear_reagents()
return TRUE
+/mob/living/carbon/superior_animal/roach/kaiser/leaveOvermind()
+ var/mob/living/carbon/superior_animal/roach/backup
+ overseer.removeHarrier(src)
+ for(var/mob/living/carbon/superior_animal/roach/tocheck in overseer.members)
+ if(istype(tocheck, /mob/living/carbon/superior_animal/roach/kaiser))
+ overseer.leader = tocheck
+ overseer?.casualties.Remove(src)
+ overseer = null
+ return
+ else if(istype(tocheck, /mob/living/carbon/superior_animal/roach/fuhrer))
+ backup = tocheck
+ for(var/datum/overmind/roachmind/subordinate in overseer.subordinates) //by this point if there even is a new leader, it is a "mere fuhrer".
+ subordinate.superior = null
+ overseer.subordinates.Cut()
+ overseer.leader = backup
+ if(!backup && !QDELETED(overseer)) // kaiser is always the leader
+ qdel(overseer) // disband
+ overseer = null
+
/mob/living/carbon/superior_animal/roach/kaiser/findTarget()
. = ..()
if(. && gas_attack())
diff --git a/code/modules/mob/living/carbon/taste.dm b/code/modules/mob/living/carbon/taste.dm
index e723e0b9ff3..39a4a498c85 100644
--- a/code/modules/mob/living/carbon/taste.dm
+++ b/code/modules/mob/living/carbon/taste.dm
@@ -23,6 +23,8 @@ calculate text size per text.
continue
if(R.id == "nutriment")
var/list/t = R.get_data()
+ if(!t) // no data, nutriment made from no source?
+ continue
for(var/i in 1 to t.len)
var/A = t[i]
if(!(A in tastes))
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 50684da1ed4..cd8fa61de9d 100755
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -500,17 +500,8 @@ default behaviour is:
// Delete them from datacore.
- if(PDA_Manifest.len)
- PDA_Manifest.Cut()
- for(var/datum/data/record/R in data_core.medical)
- if ((R.fields["name"] == src.real_name))
- qdel(R)
- for(var/datum/data/record/T in data_core.security)
- if ((T.fields["name"] == src.real_name))
- qdel(T)
- for(var/datum/data/record/G in data_core.general)
- if ((G.fields["name"] == src.real_name))
- qdel(G)
+ var/datum/todelete = get_crewmember_record(name)
+ qdel(todelete)
//This should guarantee that ghosts don't spawn.
src.ckey = null
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index a4387a8c287..711932dc7b6 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -550,8 +550,8 @@ var/list/ai_verbs_default = list(
var/personnel_list[] = list()
- for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
- personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
+ for(var/datum/computer_file/report/crew_record/t in GLOB.all_crew_records)
+ personnel_list["[t.get_name()]: [t.get_job()]"] = t.photo_front//Pull names, rank, and image.
if(personnel_list.len)
input = input("Select a crew member:") as null|anything in personnel_list
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index adb433f583e..eec8f2cf1fd 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -58,12 +58,10 @@
var/medHUD = FALSE // Toggles whether the Medical HUD is active or not
var/medical_cannotfind = 0
- var/datum/data/record/medicalActive1 // Datacore record declarations for record software
- var/datum/data/record/medicalActive2
+ var/datum/data/record/medicalActive // Datacore record declarations for record software
var/security_cannotfind = 0
- var/datum/data/record/securityActive1 // Could probably just combine all these into one
- var/datum/data/record/securityActive2
+ var/datum/data/record/securityActive
var/obj/machinery/door/hackdoor // The airlock being hacked
var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check
@@ -158,11 +156,9 @@
set category = "pAI Commands"
set name = "Reset Records Software"
- securityActive1 = null
- securityActive2 = null
+ securityActive = null
security_cannotfind = 0
- medicalActive1 = null
- medicalActive2 = null
+ medicalActive = null
medical_cannotfind = 0
SSnano.update_uis(src)
to_chat(usr, SPAN_NOTICE("You reset your record-viewing software."))
diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm
index 7855c6da1a5..7e9f4306c97 100644
--- a/code/modules/mob/living/silicon/pai/software_modules.dm
+++ b/code/modules/mob/living/silicon/pai/software_modules.dm
@@ -118,21 +118,19 @@
ram_cost = 5
id = "manifest"
toggle = 0
+ var/datum/nano_module/crew_manifest/manifestmodule
+ var/datum/topic_manager/program/mandatorymanager
- on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
- data_core.get_manifest_json()
-
- var/data[0]
- // This is dumb, but NanoUI breaks if it has no data to send
- data["manifest"] = list("__json_cache" = ManifestJSON)
+ New()
+ mandatorymanager = new()
+ manifestmodule = new(src, mandatorymanager)
+
+ Destroy()
+ . = ..()
+ QDEL_NULL(manifestmodule)
- ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
- if(!ui)
- // Don't copy-paste this unless you're making a pAI software module!
- ui = new(user, user, id, "pai_manifest.tmpl", "Crew Manifest", 450, 600)
- ui.set_initial_data(data)
- ui.open()
- ui.set_auto_update(1)
+ on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=NANOUI_REINITIALIZE)
+ manifestmodule.nano_ui_interact(user, ui, "main", force_open) // transfers applicable vars to manifestmodule
/datum/pai_software/med_records
name = "Medical Records"
@@ -144,18 +142,23 @@
var/data[0]
var/records[0]
- for(var/datum/data/record/general in sortRecord(data_core.general))
+ for(var/datum/computer_file/report/crew_record/general in GLOB.all_crew_records)
var/record[0]
- record["name"] = general.fields["name"]
+ record["name"] = general.get_name()
record["ref"] = "\ref[general]"
records[++records.len] = record
data["records"] = records
- var/datum/data/record/G = user.medicalActive1
- var/datum/data/record/M = user.medicalActive2
- data["general"] = G ? G.fields : null
- data["medical"] = M ? M.fields : null
+ var/datum/computer_file/report/crew_record/G = user.securityActive
+ var/datum/report_field/arrayclump/M = G?.get_linkage_medRecord()
+ data["general"] = G ? list("name" = G.get_name(), "sex" = G.get_sex(), "species" = G.get_species(), "age" = G.get_age(), \
+ "job" = G.get_job(), "fingerprint" = G.get_fingerprint(), "status" = G.get_status(), "bloodtype" = G.get_bloodtype()) : null
+ data["prosthetics"] = M ? M.value["prosthetics"] : null
+ data["wounds"] = M ? M.value["wounds"] : null
+ data["Body state"] = M ? M.value["body state"] : null
+ data["chemhistory"] = M ? M.value["chemhistory"] : null
+ data["psychological"] = M ? M.value["psychological"] : null
data["could_not_find"] = user.medical_cannotfind
ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
@@ -169,24 +172,15 @@
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P)) return
-
+
if(href_list["select"])
- var/datum/data/record/record = locate(href_list["select"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/M = null
- if (!( data_core.general.Find(R) ))
- P.medical_cannotfind = 1
- else
- P.medical_cannotfind = 0
- for(var/datum/data/record/E in data_core.medical)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- M = E
- P.medicalActive1 = R
- P.medicalActive2 = M
+ var/datum/computer_file/report/crew_record/record = locate(href_list["select"])
+ if(istype(record))
+ P.medical_cannotfind = 0
+ P.medicalActive = record
else
P.medical_cannotfind = 1
- return 1
+ return TRUE
/datum/pai_software/sec_records
name = "Security Records"
@@ -198,18 +192,18 @@
var/data[0]
var/records[0]
- for(var/datum/data/record/general in sortRecord(data_core.general))
+ for(var/datum/computer_file/report/crew_record/general in GLOB.all_crew_records)
var/record[0]
- record["name"] = general.fields["name"]
+ record["name"] = general.get_name()
record["ref"] = "\ref[general]"
records[++records.len] = record
data["records"] = records
- var/datum/data/record/G = user.securityActive1
- var/datum/data/record/S = user.securityActive2
- data["general"] = G ? G.fields : null
- data["security"] = S ? S.fields : null
+ var/datum/computer_file/report/crew_record/G = user.securityActive
+ data["general"] = G ? list("name" = G.get_name(), "sex" = G.get_sex(), "species" = G.get_species(), "age" = G.get_age(), \
+ "job" = G.get_job(), "fingerprint" = G.get_fingerprint(), "status" = G.get_status(), "criminalStatus" = G.get_criminalStatus(), \
+ "secNotes" = G.get_linkage_secNotes()) : null
data["could_not_find"] = user.security_cannotfind
ui = SSnano.try_update_ui(user, user, id, ui, data, force_open)
@@ -225,26 +219,14 @@
if(!istype(P)) return
if(href_list["select"])
- var/datum/data/record/record = locate(href_list["select"])
- if(record)
- var/datum/data/record/R = record
- var/datum/data/record/S = null
- if (!( data_core.general.Find(R) ))
- P.securityActive1 = null
- P.securityActive2 = null
- P.security_cannotfind = 1
- else
- P.security_cannotfind = 0
- for(var/datum/data/record/E in data_core.security)
- if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- S = E
- P.securityActive1 = R
- P.securityActive2 = S
+ var/datum/computer_file/report/crew_record/record = locate(href_list["select"])
+ if(istype(record))
+ P.security_cannotfind = 0
+ P.securityActive = record
else
- P.securityActive1 = null
- P.securityActive2 = null
+ P.securityActive = null
P.security_cannotfind = 1
- return 1
+ return TRUE
/datum/pai_software/door_jack
name = "Door Jack"
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index cc3da5e05aa..e4680aebb17 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -86,9 +86,6 @@
squeals++
last_squealgain = world.time
- else
- if ((world.time - timeofdeath) > decompose_time)
- dust()
//Pixel offsetting as they scamper around
diff --git a/code/modules/mob/living/simple_animal/spider_core.dm b/code/modules/mob/living/simple_animal/spider_core.dm
index 4f2a0cc6204..0359f5a965a 100644
--- a/code/modules/mob/living/simple_animal/spider_core.dm
+++ b/code/modules/mob/living/simple_animal/spider_core.dm
@@ -24,6 +24,7 @@
hunger_enabled = FALSE
pass_flags = PASSTABLE
universal_understand = 1
+ holder_type = /obj/item/holder/carrion
density = TRUE //Should be 0, but then these things would be a nightmare to kill.
faction = "spiders"
@@ -35,7 +36,12 @@
/mob/living/simple_animal/spider_core/proc/generate_body))
/mob/living/simple_animal/spider_core/death()
- gibs(loc, null, /obj/effect/gibspawner/generic, "#666600", "#666600")
+ var/obj/item/organ/internal/core = locate(/obj/item/organ/internal/carrion/core) in contents
+ if(core)
+ core.forceMove(loc)
+ core.status |= ORGAN_DEAD // todo: make wound somehow
+ core.refresh_damage()
+ playsound(loc, 'sound/voice/shriek1.ogg', 50)
qdel(src)
diff --git a/code/modules/mob/mob_grab_specials.dm b/code/modules/mob/mob_grab_specials.dm
index 027cb9ce6e3..29b394e0ebc 100644
--- a/code/modules/mob/mob_grab_specials.dm
+++ b/code/modules/mob/mob_grab_specials.dm
@@ -74,8 +74,8 @@
else
visible_message(SPAN_NOTICE("[user] finishes putting pressure on [H]'s wounds."))
for(var/datum/wound/W in bodypart.wounds)
- W.current_stage++
- W.bleed_timer -= 5
+ W.clamped = TRUE
+ bodypart.stopBleeding()
//do not kill the grab
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index ea7c4bebbf3..bce2ea9e511 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -490,11 +490,11 @@ proc/is_blind(A)
if(id)
perpname = id.registered_name
- var/datum/data/record/R = find_security_record("name", perpname)
- if(check_records && !R)
+ var/datum/computer_file/report/crew_record/CR = get_crewmember_record(perpname)
+ if(check_records && !CR)
threatcount += 4
- if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
+ if(check_arrest && CR && (CR?.get_criminalStatus() == "*Arrest*")) // why is paperwork's folly being translated to electronic format?
threatcount += 4
return threatcount
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index cee4bf2988a..4fae2968ad0 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -318,7 +318,6 @@
if(SSjob.ShouldCreateRecords(job.title))
if(character.mind.assigned_role != "Robot")
CreateModularRecord(character)
- data_core.manifest_inject(character)
matchmaker.do_matchmaking()
SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm
index 1a01fb8f1d1..22c3b472a3f 100644
--- a/code/modules/modular_computers/computers/modular_computer/core.dm
+++ b/code/modules/modular_computers/computers/modular_computer/core.dm
@@ -308,6 +308,8 @@
SetName(initial(name))
/obj/item/modular_computer/proc/update_uis()
+ if(active_program && istype(active_program?.nanomodule_path, /datum/nano_module/tgui))
+ return FALSE
if(active_program) //Should we update program ui or computer ui?
SSnano.update_uis(active_program)
if(active_program.NM)
diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm
index 6e3a4dd9015..04407afb0f1 100644
--- a/code/modules/modular_computers/file_system/program.dm
+++ b/code/modules/modular_computers/file_system/program.dm
@@ -195,7 +195,10 @@
if(ui)
ui.close()
return computer.nano_ui_interact(user)
- if(istype(NM))
+ if(istype(NM, /datum/nano_module/tgui))
+ NM.ui_interact(user)
+ return FALSE
+ else if(istype(NM))
NM.nano_ui_interact(user, ui_key, null, force_open)
return 0
return 1
diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm
index 4835caca081..3fc804a66de 100644
--- a/code/modules/modular_computers/file_system/programs/command/card.dm
+++ b/code/modules/modular_computers/file_system/programs/command/card.dm
@@ -62,7 +62,7 @@
data["security_jobs"] = format_jobs(security_positions)
//data["exploration_jobs"] = format_jobs(exploration_positions)
data["service_jobs"] = format_jobs(civilian_positions)
- data["supply_jobs"] = format_jobs(cargo_positions)
+ data["supply_jobs"] = format_jobs(guild_positions)
data["church_jobs"] = format_jobs(church_positions)
//data["civilian_jobs"] = format_jobs(civilian_positions)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
diff --git a/code/modules/modular_computers/file_system/programs/generic/records.dm b/code/modules/modular_computers/file_system/programs/generic/records.dm
index 2836b1a741b..01fb6a442d1 100644
--- a/code/modules/modular_computers/file_system/programs/generic/records.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/records.dm
@@ -1,3 +1,5 @@
+
+#define NULL_RECORD list("name" = null, "uid" = null, "creator" = null, "file_time" = null, "fields" = null, "access" = null, "access_edit" = null)
/datum/computer_file/program/records
filename = "crewrecords"
filedesc = "Crew Records"
@@ -7,22 +9,22 @@
size = 14
requires_ntnet = TRUE
available_on_ntnet = TRUE
- nanomodule_path = /datum/nano_module/records
+ nanomodule_path = /datum/nano_module/tgui/records
usage_flags = PROGRAM_ALL
-/datum/nano_module/records
+/datum/nano_module/tgui/records
name = "Crew Records"
var/datum/computer_file/report/crew_record/active_record
var/message = null
-/datum/nano_module/records/nano_ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = NANOUI_FOCUS, state = GLOB.default_state)
+/datum/nano_module/tgui/records/ui_data(mob/user)
var/list/data = host.initial_data()
var/list/user_access = get_record_access(user)
data["message"] = message
if(active_record)
- user << browse_rsc(active_record.photo_front, "front_[active_record.uid].png")
- user << browse_rsc(active_record.photo_side, "side_[active_record.uid].png")
+ data["front_pic"] = icon2base64html(active_record.photo_front)
+ data["side_pic"] = icon2base64html(active_record.photo_side)
data["pic_edit"] = check_access(user, access_heads) || check_access(user, access_security)
data += active_record.generate_nano_data(user_access)
else
@@ -38,16 +40,20 @@
data["creation"] = check_access(user, access_heads)
data["dnasearch"] = check_access(user, access_moebius) || check_access(user, access_forensics_lockers)
data["fingersearch"] = check_access(user, access_security)
+ data += NULL_RECORD
+ return data
+#undef NULL_RECORD
+
+
- ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open)
+/datum/nano_module/tgui/records/ui_interact(mob/user, datum/tgui/ui = null)
+ ui = SStgui.try_update_ui(user, src, ui || currentui)
if (!ui)
- ui = new(user, src, ui_key, "crew_records.tmpl", name, 700, 540, state = state)
- ui.auto_update_layout = 1
- ui.set_initial_data(data)
- ui.open()
+ currentui = new(user, src, "CrewRecords", name)
+ currentui.open()
-/datum/nano_module/records/proc/get_record_access(var/mob/user)
+/datum/nano_module/tgui/records/proc/get_record_access(var/mob/user)
var/list/user_access = using_access || user.GetAccess()
var/obj/item/modular_computer/PC = nano_host()
@@ -57,7 +63,7 @@
return user_access
-/datum/nano_module/records/proc/edit_field(var/mob/user, var/field_ID)
+/datum/nano_module/tgui/records/proc/edit_field(var/mob/user, var/field_ID)
var/datum/computer_file/report/crew_record/R = active_record
if(!R)
return
@@ -69,67 +75,68 @@
return
F.ask_value(user)
-/datum/nano_module/records/Topic(href, href_list)
+/datum/nano_module/tgui/records/ui_act(action, params)
if(..())
return 1
- if(href_list["clear_active"])
- active_record = null
- return 1
- if(href_list["clear_message"])
- message = null
- return 1
- if(href_list["set_active"])
- var/ID = text2num(href_list["set_active"])
- for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
- if(R.uid == ID)
- active_record = R
- break
- return 1
- if(href_list["new_record"])
- if(!check_access(usr, access_heads))
- to_chat(usr, "Access Denied.")
- return
- active_record = new/datum/computer_file/report/crew_record()
- GLOB.all_crew_records.Add(active_record)
- return 1
- if(href_list["print_active"])
- if(!active_record)
- return
- print_text(record_to_html(active_record, get_record_access(usr)), usr)
- return 1
- if(href_list["search"])
- var/field_name = href_list["search"]
- var/search = sanitize(input("Enter the value for search for.") as null|text)
- if(!search)
+ switch(action)
+
+ if("clear_active")
+ active_record = null
return 1
- for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
- var/datum/report_field/field = R.field_from_name(field_name)
- if(lowertext(field.get_value()) == lowertext(search))
- active_record = R
+ if("clear_message")
+ message = null
+ return 1
+ if("set_active")
+ var/ID = text2num(params["set_active"])
+ for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
+ if(R.uid == ID)
+ active_record = R
+ break
+ return 1
+ if("new_record")
+ if(!check_access(usr, access_heads))
+ to_chat(usr, "Access Denied.")
+ return
+ active_record = new/datum/computer_file/report/crew_record()
+ GLOB.all_crew_records.Add(active_record)
+ return 1
+ if("print_active")
+ if(!active_record)
+ return
+ print_text(record_to_html(active_record, get_record_access(usr)), usr)
+ return 1
+ if("search")
+ var/field_name = params["search"]
+ var/search = sanitize(input("Enter the value for search for.") as null|text)
+ if(!search)
return 1
- message = "Unable to find record containing '[search]'"
- return 1
+ for(var/datum/computer_file/report/crew_record/R in GLOB.all_crew_records)
+ var/datum/report_field/field = R.field_from_name(field_name)
+ if(lowertext(field.get_value()) == lowertext(search))
+ active_record = R
+ return 1
+ message = "Unable to find record containing '[search]'"
+ return 1
var/datum/computer_file/report/crew_record/R = active_record
if(!istype(R))
return 1
- if(href_list["edit_photo_front"])
- var/photo = get_photo(usr)
- if(photo && active_record)
- active_record.photo_front = photo
- nano_ui_interact(usr)
- return 1
- if(href_list["edit_photo_side"])
- var/photo = get_photo(usr)
- if(photo && active_record)
- active_record.photo_side = photo
- nano_ui_interact(usr)
- return 1
- if(href_list["edit_field"])
- edit_field(usr, text2num(href_list["edit_field"]))
- return 1
+ switch(action)
+ if("edit_photo_front")
+ var/photo = get_photo(usr)
+ if(photo && active_record)
+ active_record.photo_front = photo
+ return 1
+ if("edit_photo_side")
+ var/photo = get_photo(usr)
+ if(photo && active_record)
+ active_record.photo_side = photo
+ return 1
+ if("edit_field")
+ edit_field(usr, text2num(params["edit_field"]))
+ return 1
-/datum/nano_module/records/proc/get_photo(var/mob/user)
+/datum/nano_module/tgui/records/proc/get_photo(var/mob/user)
if(istype(user.get_active_hand(), /obj/item/photo))
var/obj/item/photo/photo = user.get_active_hand()
return photo.img
diff --git a/code/modules/modular_computers/file_system/reports/crew_record.dm b/code/modules/modular_computers/file_system/reports/crew_record.dm
index dda21f39149..1a058588995 100644
--- a/code/modules/modular_computers/file_system/reports/crew_record.dm
+++ b/code/modules/modular_computers/file_system/reports/crew_record.dm
@@ -53,34 +53,131 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
// Medical record
set_bloodtype(H ? H.b_type : "Unset")
- set_medRecord((H && H.med_record && !jobban_isbanned(H, "Records") ? html_decode(H.med_record) : "No record supplied"))
+ var/datum/preferences/loadedprefs = H?.client?.prefs
+ var/datum/report_field/arrayclump/medRecord = get_linkage_medRecord()
+ if(H)
+ var/list/wounds = list()
+ var/list/prosthetics = list()
+ var/list/scannedlimbs = list()
+ for(var/datum/organ_description/OD in H.species.has_limbs) // default limbs for species
+ if(H.organs_by_name[OD.organ_tag])
+ if(istype(H.organs_by_name[OD.organ_tag], OD.default_type)) // these lists contain abnormalilities, so normalities are skipped.
+ continue
+ else
+ var/obj/item/organ/external/organthing = H.organs_by_name[OD.organ_tag]
+ if(organthing.is_stump())
+ wounds.Add("[organthing.name] instead of [OD.name]")
+ else
+ prosthetics.Add(organthing.name)
+
+ scannedlimbs.Add(organthing)
+ // TODO: add organ checks once FBPs are better coded
+ else
+ wounds.Add("Missing [OD.name]")
+ var/list/addictions = list()
+ for(var/datum/reagent/addicted in H.metabolism_effects.addiction_list)
+ addictions.Add("Observed addicted to [addicted.name]")
+
+ var/bodystate
+ switch(H.stat)
+ if(DEAD)
+ bodystate = list("Dead at time of writing")
+ if(UNCONSCIOUS)
+ if(H.getOxyLoss() > H.species.total_health/2)
+ bodystate = list("Comatose at time of writing")
+ else
+ bodystate = list("Alive at time of writing")
+ if(CONSCIOUS)
+ bodystate = list("Alive at time of writing")
+
+ medRecord.value["wounds"] = wounds.len ? wounds : list("No wounds on record.")
+ medRecord.value["prosthetics"] = prosthetics.len ? prosthetics : list("No prosthetics on record.")
+ medRecord.value["Body state"] = bodystate ? bodystate : list("\[Data Missing\]")
+ medRecord.value["chemhistory"] = addictions.len ? addictions : list("Chemical record is clean.")
+
+ var/list/psychological = list()
+ for(var/datum/perk/profile in H.stats.perks)
+ switch(profile.type)
+ if(PERK_NIHILIST)
+ psychological.Add("Has an empty outlook on life.")
+ if(PERK_MORALIST)
+ psychological.Add("High morale in groups.")
+ if(PERK_DRUG_ADDICT)
+ psychological.Add("Easily addicted, remains addicted indefinitely.")
+ if(PERK_ALCOHOLIC)
+ psychological.Add("Psychologically dependent on alcohol.")
+ if(PERK_REJECTED_GENIUS, PERK_NOBLE)
+ psychological.Add("Mentally destabilized by minor stressing factors.")
+ if(PERK_RAT)
+ psychological.Add("Innately stressed by environments, to some degree.")
+ if(PERK_PAPER_WORM)
+ psychological.Add("Accustomed to over-stress.")
+ if(PERK_OBORIN_SYNDROME)
+ psychological.Add("Innately resilient to mental harm.")
+ if(PERK_LOWBORN, PERK_VAGABOND)
+ psychological |= "Accustomed to bad living conditions."
+ if(PERK_SURVIVOR)
+ psychological.Add("Accustomed to the presence of death.")
+ if(PERK_NEAT)
+ psychological.Add("Accustomed to the presence of grime, and comforted by its removal.")
+ if(PERK_GREEN_THUMB)
+ psychological.Add("Comforted by gardening.")
+ if(PERK_CLUB)
+ psychological.Add("Provides a comfortingly professional presence.")
+ if(PERK_CHAINGUN_SMOKER)
+ psychological.Add("Invigorated by smoking.")
+ if(PERK_CHARMING_PERSONALITY)
+ psychological.Add("Provides a comfortingly charming presence.")
+ if(PERK_HORRIBLE_DEEDS)
+ psychological.Add("UNSETTLING.")
+ if(PERK_TERRIBLE_FATE)
+ psychological.Add("More afraid of death than usual.")
+ if(PERK_BALLS_OF_PLASTEEL)
+ psychological.Add("Higher pain tolerance than otherwise indicated.")
+ if(PERK_ARTIST)
+ psychological.Add("Looks at life as art.")
+
+ medRecord.value["psychological"] = psychological.len ? psychological : list("No psychological abnormality at time of writing.")
+ else // if there isn't a human
+ var/datum/storedrecord/medical/default/medrecord = new() // just use the defaults
+ medrecord.transfertocomputer(medRecord)
+ qdel(medrecord)
// Security record
set_criminalStatus(GLOB.default_security_status)
set_dna(H ? H.dna_trace : "")
set_fingerprint(H ? H.fingers_trace : "")
- set_secRecord(H && H.sec_record && !jobban_isbanned(H, "Records") ? html_decode(H.sec_record) : "No record supplied")
- // Employment record
- var/employment_record = "No record supplied"
if(H)
- if(H.gen_record && !jobban_isbanned(H, "Records"))
- employment_record = html_decode(H.gen_record)
- if(H.client && H.client.prefs)
- var/list/qualifications
- if(LAZYLEN(qualifications))
- employment_record = "[employment_record ? "[employment_record]\[br\]" : ""][jointext(qualifications, "\[br\]>")]"
- set_emplRecord(employment_record)
-
-
- if(H)
- var/stats = list()
- for(var/statName in ALL_STATS)
- var/points = H.stats.getStat(statName,pure = TRUE)
- if(points > STAT_LEVEL_NONE)
- stats += "[statName]: [points] ([statPointsToLevel(points)])"
+ for(var/datum/perk/fate/profile in H.stats.perks)
+ switch(profile)
+ if(PERK_PAPER_WORM)
+ set_emplRecord("Experienced in bureacracy.")
+ if(PERK_FREELANCER)
+ set_emplRecord("Wide variety of employments.")
+ if(PERK_DRUG_ADDICT)
+ set_emplRecord("Has a history of drug addiction.")
+ if(PERK_ALCOHOLIC)
+ set_emplRecord("Is an alcoholic.")
+ if(PERK_NOBLE)
+ set_emplRecord("Is of noble origin.")
+ if(PERK_LOWBORN)
+ set_emplRecord("Was hired from poverty.")
+ if(!get_emplRecord())
+ set_emplRecord("Standard background.")
+ else
+ set_emplRecord("No record supplied.")
- set_skillset(jointext(stats,"\n"))
+ if(loadedprefs)
+ var/originfound
+ for(var/datum/category_group/setup_option_category/background/origin/OriginBG in loadedprefs.setup_options)
+ if(loadedprefs.loaded_character[OriginBG.name])
+ originfound = OriginBG.name
+ break
+ if(originfound)
+ set_origin(originfound)
+ else
+ set_origin("Origin not on record.")
// Antag record
set_antagRecord(H && H.exploit_record && !jobban_isbanned(H, "Records") ? html_decode(H.exploit_record) : "")
@@ -96,16 +193,16 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
/proc/SortModularRecords()
// improved bubble sort
- if(GLOB.all_crew_records.len > 1)
- for(var/i = 1, i <= GLOB.all_crew_records.len, i++)
- var/flag = FALSE
- for(var/j = 1, j <= GLOB.all_crew_records.len - 1, j++)
- var/datum/computer_file/report/crew_record/CR = GLOB.all_crew_records[j]
- var/datum/computer_file/report/crew_record/CR_NEXT = GLOB.all_crew_records[j+1]
- if(sorttext(CR.get_name(), CR_NEXT.get_name()) == -1)
- flag = TRUE
- GLOB.all_crew_records.Swap(j,j+1)
- if(!flag)
+ if(GLOB.all_crew_records.len > 1) // if list is big enough to sort
+ for(var/i = 1, i <= GLOB.all_crew_records.len, i++) // for each entry in list
+ var/flag = FALSE // define a var as false
+ for(var/j = GLOB.all_crew_records.len-1, j >= 1, j--) // cycle through all entries,
+ var/datum/computer_file/report/crew_record/CR = GLOB.all_crew_records[j] // starting from the one before the last
+ var/datum/computer_file/report/crew_record/CR_NEXT = GLOB.all_crew_records[j+1] // and the last
+ if(sorttext(CR.get_name(), CR_NEXT.get_name()) == 1) // if the one before the last is bigger than the last
+ flag = TRUE // reset the var to true
+ GLOB.all_crew_records.Swap(j,j+1) // and swap the last and the one before the last
+ if(!flag) // if no work was done, stop
break
// Gets crew records filtered by set of positions
@@ -161,9 +258,13 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest")
#define GETTER_SETTER(PATH, KEY) /datum/computer_file/report/crew_record/proc/get_##KEY(){var/datum/report_field/F = locate(/datum/report_field/##PATH/##KEY) in fields; if(F) return F.get_value()} \
/datum/computer_file/report/crew_record/proc/set_##KEY(given_value){var/datum/report_field/F = locate(/datum/report_field/##PATH/##KEY) in fields; if(F) F.set_value(given_value)}
+#define SELF_GETTER(PATH, KEY) /datum/computer_file/report/crew_record/proc/get_linkage_##KEY(){return locate(/datum/report_field/##PATH/##KEY) in fields}
#define SETUP_FIELD(NAME, KEY, PATH, ACCESS, ACCESS_EDIT) GETTER_SETTER(PATH, KEY); /datum/report_field/##PATH/##KEY;\
/datum/computer_file/report/crew_record/generate_fields(){..(); var/datum/report_field/##KEY = add_field(/datum/report_field/##PATH/##KEY, ##NAME);\
KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
+#define SETUP_ARRAYFIELD(NAME, KEY, PATH, ACCESS, ACCESS_EDIT) SELF_GETTER(PATH, KEY); /datum/report_field/##PATH/##KEY;\
+/datum/computer_file/report/crew_record/generate_fields(){..(); var/datum/report_field/##KEY = add_field(/datum/report_field/##PATH/##KEY, ##NAME);\
+KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
// Fear not the preprocessor, for it is a friend. To add a field, use one of these, depending on value type and if you need special access to see it.
// It will also create getter/setter procs for record datum, named like /get_[key here]() /set_[key_here](value) e.g. get_name() set_name(value)
@@ -174,6 +275,8 @@ KEY.set_access(ACCESS, ACCESS_EDIT || ACCESS || access_heads)}
#define FIELD_LIST(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT) FIELD_LIST_EDIT(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT)
#define FIELD_LIST_EDIT(NAME, KEY, OPTIONS, ACCESS, ACCESS_EDIT) SETUP_FIELD(NAME, KEY, options/crew_record, ACCESS, ACCESS_EDIT);\
/datum/report_field/options/crew_record/##KEY/get_options(){return OPTIONS}
+#define ARRAYFIELD_SINGLE(NAME, KEY, ACCESS, ACCESS_EDIT) SETUP_ARRAYFIELD(NAME, KEY, array/crew_record, ACCESS, ACCESS_EDIT)
+#define ARRAYFIELD_CLUMP(NAME, KEY, ACCESS, ACCESS_EDIT) SETUP_ARRAYFIELD(NAME, KEY, arrayclump/crew_record, ACCESS, ACCESS_EDIT)
// GENERIC RECORDS
FIELD_SHORT("Name", name, null, access_change_ids)
@@ -189,17 +292,17 @@ FIELD_NUM("Account",account, null, access_change_ids)
// MEDICAL RECORDS
FIELD_LIST("Blood Type", bloodtype, GLOB.blood_types, access_moebius, access_moebius)
-FIELD_LONG("Medical Record", medRecord, access_moebius, access_moebius)
+ARRAYFIELD_CLUMP("Medical Record", medRecord, access_moebius, access_moebius)
// SECURITY RECORDS
FIELD_LIST("Criminal Status", criminalStatus, GLOB.security_statuses, access_security, access_security)
-FIELD_LONG("Security Record", secRecord, access_security, access_security)
+ARRAYFIELD_SINGLE("Brief", secNotes, access_security, access_security)
FIELD_SHORT("DNA", dna, access_security, access_security)
FIELD_SHORT("Fingerprint", fingerprint, access_security, access_security)
// EMPLOYMENT RECORDS
FIELD_LONG("Employment Record", emplRecord, access_heads, access_heads)
-FIELD_LONG("Qualifications", skillset, access_heads, access_heads)
+FIELD_LONG("Place of origin", origin, access_heads, access_heads)
// ANTAG RECORDS
FIELD_LONG("Exploitable Information", antagRecord, access_syndicate, access_syndicate)
@@ -240,9 +343,13 @@ FIELD_LONG("Exploitable Information", antagRecord, access_syndicate, access_synd
. |= BR.name
*/
#undef GETTER_SETTER
+#undef SELF_GETTER
#undef SETUP_FIELD
+#undef SETUP_ARRAYFIELD
#undef FIELD_SHORT
#undef FIELD_LONG
#undef FIELD_NUM
#undef FIELD_LIST
#undef FIELD_LIST_EDIT
+#undef ARRAYFIELD_SINGLE
+#undef ARRAYFIELD_CLUMP
diff --git a/code/modules/modular_computers/file_system/reports/report.dm b/code/modules/modular_computers/file_system/reports/report.dm
index 9df7d118d09..739c004893f 100644
--- a/code/modules/modular_computers/file_system/reports/report.dm
+++ b/code/modules/modular_computers/file_system/reports/report.dm
@@ -133,7 +133,22 @@ If the override option is set to 0, the access supplied will instead be added as
dat["access"] = field.verify_access(given_access)
dat["access_edit"] = field.verify_access_edit(given_access)
dat["name"] = field.display_name()
- dat["value"] = field.get_value()
+
+ if(istype(field, /datum/report_field/array))
+ var/datum/report_field/array/arrayfield = field
+ dat["list_value"] = arrayfield.value_list.Copy()
+ dat["list_clumps"] = null // must override with null values or else react gets weird
+ dat["value"] = null
+ else if(istype(field, /datum/report_field/arrayclump))
+ var/datum/report_field/arrayclump/clumpfield = field
+ dat["list_value"] = null
+ dat["list_clumps"] = clumpfield.value
+ dat["value"] = null
+ else
+ dat["list_value"] = null
+ dat["list_clumps"] = null
+ dat["value"] = field.get_value()
+
dat["can_edit"] = field.can_edit
dat["needs_big_box"] = field.needs_big_box
dat["ignore_value"] = field.ignore_value
diff --git a/code/modules/modular_computers/file_system/reports/report_field.dm b/code/modules/modular_computers/file_system/reports/report_field.dm
index b36c199e1d9..df2e78a1327 100644
--- a/code/modules/modular_computers/file_system/reports/report_field.dm
+++ b/code/modules/modular_computers/file_system/reports/report_field.dm
@@ -211,4 +211,151 @@ Basic field subtypes.
value_list.Remove(given_value)
/datum/report_field/array/ask_value(mob/user)
- add_value(input(user, "Add value", "") as null|text)
+ var/inputchoice = input(user, "Add or Remove value", "Field Edit", "Add") in list("Add", "Remove")
+ if(inputchoice == "Add")
+ var/toadd = input(user, "Add value", "Field Input") as null|text
+ if(!isnull(toadd))
+ add_value(toadd)
+ else if(inputchoice == "Remove")
+ remove_value(input(user, "Choose value to remove", "Field Reduce") as null|anything in value_list )
+
+
+
+/datum/report_field/arraylinkage
+ var/list/arrays = list()
+ ignore_value = TRUE // value is too generic to use
+
+// retrieves index of key
+// can retrieve additional entries of same index using additionalarrays param
+/datum/report_field/arraylinkage/proc/retrieve_index_of_array(key, index = 0, additionalarrays = list())
+ if(!(key && (arrays.len > 0) && index > 0)) // can we access?
+ return FALSE
+ var/primeretrieved = arrays[key] // key's array
+ if(!(index && primeretrieved && length(primeretrieved) >= index)) // can we access the index asked for using the key?
+ return FALSE
+ var/list/toreturn = list(primeretrieved[index])
+ for(var/arrayexists in additionalarrays) // all linked arrays we also want index of
+ if((arrayexists in arrays) && length(arrays[arrayexists]) >= index)
+ var/list/toadd = arrays[arrayexists]
+ toreturn.Add(toadd[index])
+ else
+ return FALSE // we really don't want input from bad sources.
+ . = toreturn // succeeded all the checks? caller's will be done.
+
+// adds one index to the end of each list
+// sets the contents of each list for the created index on demand using either keys or arrangement of any given input of proper size
+/datum/report_field/arraylinkage/proc/add_index(list/new_entries, keyed = FALSE)
+ if(!new_entries || new_entries.len > arrays.len)
+ return FALSE
+ if(new_entries.len != arrays.len) // only accept using list-order based indexing when it has a 1 to 1 ratio
+ keyed = TRUE
+ var/count = 1
+ if(keyed)
+ for(var/key in arrays) // unfitting keys are discarded, but can still disqualify a list.
+ var/list/currentarray = arrays[key]
+ if(new_entries[key])
+ currentarray.Add(new_entries[key])
+ else
+ currentarray.Add(null) // all arrays must have the same indexing for the linkage to work.
+ . = TRUE
+ else
+ for(var/entry in new_entries) // sanitize before it's t oo late
+ if(new_entries[entry])
+ CRASH("keyed outside of key mode in add_index")
+ for(var/entry in new_entries)
+ var/list/currentarray = arrays?[count]
+ if(!currentarray) // in case a check breaks
+ return
+ count ++
+ currentarray.Add(entry)
+ . = TRUE
+
+// set one entry in one list
+/datum/report_field/arraylinkage/proc/edit_index(key, setto, index)
+ if(!arrays[key] || length(arrays[key]) < index || !islist(arrays[key]))
+ return FALSE
+ var/list/accessed = arrays[key]
+ if(accessed)
+ accessed[index] = setto
+ . = TRUE
+
+// delete one index of all lists in arraylinkage
+/datum/report_field/arraylinkage/proc/remove_index(index)
+ if(!length(arrays) || length(arrays[1]) < index) // check if there are arrays and the first one is long enough
+ return FALSE // hopefully all arrays have the same length as the first one
+ for(var/list/arraytocut in arrays)
+ arraytocut.Cut(index, index+1)
+ . = TRUE
+
+/datum/report_field/arraylinkage/ask_value(mob/user)
+
+/datum/report_field/arrayclump // these arrays are explicitly unlinked and are stored here for categorization
+ value = list() // only input key=array as entry
+
+/datum/report_field/arrayclump/set_value(given_value)
+ if(!islist(given_value))
+ return FALSE
+ . = ..()
+
+/datum/report_field/arrayclump/ask_value(mob/user)
+ . = TRUE
+ var/list/clumpvalue = value
+ if(!istype(clumpvalue))
+ return FALSE
+ var/list/entries = clumpvalue.Copy()
+ entries.Add("")
+
+ var/entrychoice = input(user, "Choose Entry Category", "Entry Category") as null | anything in entries
+ if(entrychoice == "" )
+ var/entryname = input(user, "Choose Entry Name", "Entry Name") as text | null
+ entryname = sanitizeSafe(entryname)
+ if(!istext(entryname))
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ if(clumpvalue[entryname]) // only replace entry with alert
+ if(alert(user, "Replace old entry?", "Entry Replacement", "Yes", "No") == "No")
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ var/startingvalue = input(user, "Create Entry", "Entry Creation") as text | null
+ startingvalue = sanitizeSafe(startingvalue)
+ if(!istext(startingvalue))
+ to_chat(user, SPAN_NOTICE("Edit canceled successfully."))
+ return FALSE
+ to_chat(user, SPAN_NOTICE("You have successfully added an entry to [name]."))
+ value[entryname] = list(startingvalue)
+
+ else if(entrychoice)
+ var/list/selections = clumpvalue[entrychoice]
+ selections = selections.Copy() // don't edit the original list
+ selections.Add("")
+ var/selectionchoice = input(user, "Select Entry", "Entry") as null | anything in selections
+ if(!istext(selectionchoice))
+ return FALSE
+ if(selectionchoice == "")
+ var/nextvalue = input(user, "Add Value", "Value") as text | null
+ nextvalue = sanitizeSafe(nextvalue)
+ if(!istext(nextvalue))
+ to_chat(user, SPAN_NOTICE("Addition canceled successfully."))
+ return FALSE
+ else
+ var/list/entrytoaddto = clumpvalue[entrychoice]
+ if(istype(entrytoaddto))
+ entrytoaddto.Add(nextvalue)
+ else
+ CRASH("Type Mismatch in clump list")
+
+ else
+ var/newvalue = input(user, "New Value", "Value") as text | null
+ newvalue = sanitizeSafe(newvalue)
+ if(!istext(newvalue))
+ to_chat(user, SPAN_NOTICE("Replacement canceled successfully."))
+ return FALSE
+ var/list/intermediaryvalue = clumpvalue[entrychoice]
+ if(istype(intermediaryvalue))
+ var/indexhound = clumpvalue.Find(intermediaryvalue) // the Hound finds the value we splice
+ intermediaryvalue.Splice(indexhound, indexhound+1, newvalue)
+ else
+ CRASH("Type Mismatch in clump list")
+
+
+
diff --git a/code/modules/nano/modules/tgui_type.dm b/code/modules/nano/modules/tgui_type.dm
new file mode 100644
index 00000000000..e605715301b
--- /dev/null
+++ b/code/modules/nano/modules/tgui_type.dm
@@ -0,0 +1,92 @@
+/datum/nano_module/tgui
+ var/datum/tgui/currentui // gotta save it, we can't get it any other way
+ var/show_map ; var/map_z_level // the sins of our predecessors, brought to the present by the sins of our own
+
+/datum/nano_module/tgui/ui_host(mob/user)
+ return nano_host()
+
+/datum/nano_module/tgui/ui_close(mob/user)
+ . = ..()
+ currentui = null // must clear reference to ui
+
+/datum/nano_module/tgui/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/spritesheet/legacyicons)
+ )
+
+
+/datum/nano_module/tgui/ui_act(action, params)
+ . = ..()
+
+ if(istype(host, /datum/computer_file/program))
+ var/datum/computer_file/program/program = host
+ switch(action)
+ if("PC_exit")
+ program.computer.kill_program()
+ return TRUE
+ if("PC_enable_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H) && !H.enabled)
+ H.enabled = TRUE
+ H.enabled()
+ . = TRUE
+ if("PC_disable_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H) && H.enabled)
+ H.enabled = FALSE
+ H.disabled()
+ . = TRUE
+ if("PC_toggle_component")
+ var/obj/item/computer_hardware/H = program.computer.find_hardware_by_name(params["component"])
+ if(istype(H))
+ H.enabled = !H.enabled
+ if(H.enabled)
+ H.enabled()
+ else
+ H.disabled()
+ . = TRUE
+ if("PC_shutdown")
+ program.computer.shutdown_computer()
+ return TRUE
+ if("PC_minimize")
+ var/mob/user = usr
+ program.computer.minimize_program(user)
+
+ if("PC_killprogram")
+ var/prog_name = params["PC_killprogram"]
+ var/obj/item/computer_hardware/hard_drive/prog_disk = locate(params["disk"]) in program.computer
+ if(!prog_disk)
+ return TRUE
+
+ for(var/p in program.computer.all_threads)
+ var/datum/computer_file/program/PRG = p
+ if(PRG.program_state == PROGRAM_STATE_KILLED)
+ continue
+
+ if(PRG.filename == prog_name && (PRG in prog_disk.stored_files))
+ PRG.kill_program(forced=TRUE)
+ to_chat(usr, SPAN_NOTICE("Program [PRG.filename].[PRG.filetype] has been killed."))
+ . = TRUE
+
+ if("PC_runprogram")
+ var/obj/item/computer_hardware/hard_drive/prog_disk = locate(params["disk"]) in program.computer
+ return program.computer.run_program(params["PC_runprogram"], prog_disk)
+
+ if("PC_setautorun")
+ if(!program.computer.hard_drive)
+ return
+ program.computer.set_autorun(params["PC_setautorun"])
+ if("PC_terminal")
+ program.computer.open_terminal(usr)
+ return TRUE
+
+/datum/nano_module/tgui/ui_status(mob/user, datum/ui_state/state)
+ . = ..(user, state ? state : GLOB.default_state)
+ if(. > UI_DISABLED && istype(host, /datum/computer_file/program))
+ var/datum/computer_file/program/relevant = host
+ if(relevant.program_state == PROGRAM_STATE_KILLED)
+ . = UI_CLOSE
+ else if(relevant.program_state == PROGRAM_STATE_BACKGROUND)
+ . = min(., UI_UPDATE) // theoretically might be necessary with a new system, if redundant just collapse this with the killing check.
+
+
diff --git a/code/modules/organs/internal/_internal.dm b/code/modules/organs/internal/_internal.dm
index 069c688417f..447f0bea084 100644
--- a/code/modules/organs/internal/_internal.dm
+++ b/code/modules/organs/internal/_internal.dm
@@ -56,7 +56,7 @@
UnregisterSignal(src, COMSIG_IORGAN_ADD_WOUND)
UnregisterSignal(src, COMSIG_IORGAN_REMOVE_WOUND)
UnregisterSignal(src, COMSIG_IORGAN_REFRESH_SELF)
- ..()
+ . = ..()
/obj/item/organ/internal/removed()
UnregisterSignal(parent, COMSIG_IORGAN_WOUND_COUNT)
@@ -405,6 +405,7 @@
/obj/item/organ/internal/rejuvenate()
status = null
+ current_blood = initial(current_blood)
for(var/woundtype in wounddatums)
remove_wound(wounddatums[woundtype])
diff --git a/code/modules/organs/internal/carrion.dm b/code/modules/organs/internal/carrion.dm
index 67fdc9aa3ab..2891cdc4219 100644
--- a/code/modules/organs/internal/carrion.dm
+++ b/code/modules/organs/internal/carrion.dm
@@ -32,6 +32,7 @@
/obj/item/organ/internal/carrion
max_damage = 15 //resilient
scanner_hidden = TRUE //sneaky
+ origin_tech = list(TECH_BIO = 5)
/obj/item/organ/internal/carrion/chemvessel
name = "chemical vessel"
@@ -376,12 +377,17 @@
to_chat(owner, SPAN_WARNING("You can't eat nothing."))
return
- if(istype(food, /obj/item/grab))
+ var/obj/item/holder/overcomplicated = istype(food, /obj/item/holder) ? food : null
+ if(istype(food, /obj/item/grab) || overcomplicated && ishuman(overcomplicated.contained))
var/obj/item/grab/grab = food
- var/mob/living/carbon/human/H = grab.affecting
- if (grab.state < GRAB_AGGRESSIVE)
- to_chat(owner, SPAN_WARNING("Your grip upon [H.name] is too weak."))
- return
+ var/mob/living/carbon/human/H
+ if(istype(grab))
+ H = grab.affecting
+ if (grab.state < GRAB_AGGRESSIVE)
+ to_chat(owner, SPAN_WARNING("Your grip upon [H.name] is too weak."))
+ return
+ else if(overcomplicated)
+ H = overcomplicated.contained
if(istype(H))
var/obj/item/organ/external/E = H.get_organ(owner.targeted_organ)
if (tearing) // one at a time, thank you.
@@ -401,8 +407,7 @@
for (var/obj/item/organ/internal/to_blacklist in E.internal_organs)
if (istype(to_blacklist, /obj/item/organ/internal/bone/))
blacklist += to_blacklist
- continue
- if (istype(to_blacklist, /obj/item/organ/internal/vital/brain/))
+ else if (istype(to_blacklist, /obj/item/organ/internal/vital/brain/))
blacklist += to_blacklist// removing bones from a valid_organs list based on
var/list/valid_organs = E.internal_organs - blacklist// E.internal_organs gibs the victim.
if (!valid_organs.len)
@@ -419,7 +424,7 @@
to_chat(owner, SPAN_WARNING("You can only tear flesh out of humanoids!"))
return
- if(istype(food, /obj/item/organ) || istype(food, /obj/item/reagent_containers/food/snacks/meat))
+ if(istype(food, /obj/item/organ) || istype(food, /obj/item/reagent_containers/food/snacks/meat) || istype(food, /obj/item/holder))
var/geneticpointgain = 0
var/chemgain = 0
var/taste_description = ""
@@ -437,11 +442,15 @@
var/obj/item/organ/internal/carrion/core/G = owner.random_organ_by_process(BP_SPCORE)
if(O in G.associated_carrion_organs)
taste_description = "albeit delicious, your own organs carry no new genetic material"
+ chemgain = 50
else
owner.carrion_hunger += 3
geneticpointgain = 4
chemgain = 50
taste_description = "carrion organs taste heavenly, you need more!"
+ if(istype(O, /obj/item/organ/internal/carrion/core))
+ var/obj/item/organ/internal/carrion/core/devoured = O
+ G.absorbed_dna |= devoured.absorbed_dna
else if(istype(O, /obj/item/organ/internal))
var/organ_rotten = FALSE
if (O.status & ORGAN_DEAD)
@@ -464,9 +473,25 @@
taste_description = "human meat is satisfying."
else
- chemgain = 5
- owner.carrion_hunger -= 1 //Prevents meat eating spam for infinate chems
- taste_description = "this meat is bland."
+ if(istype(food, /obj/item/holder/carrion))
+ owner.carrion_hunger += 9
+ geneticpointgain = 10
+ chemgain = 50
+ var/obj/item/holder/spiderholder = food
+ var/mob/living/simple_animal/spider_core/tastyspider = spiderholder.contained
+ var/obj/item/organ/internal/carrion/core/devoured = locate(/obj/item/organ/internal/carrion/core) in tastyspider.contents
+ var/obj/item/organ/internal/carrion/core/C = owner.random_organ_by_process(BP_SPCORE)
+ if(devoured && C)
+ C.absorbed_dna |= devoured.absorbed_dna
+ taste_description = "carrions taste heavenly, if only there was more!"
+ qdel(tastyspider)
+ else
+ if(istype(food, /obj/item/holder))
+ var/obj/item/holder/bland_animal = food
+ qdel(bland_animal.contained)
+ chemgain = 5
+ owner.carrion_hunger -= 1 //Prevents meat eating spam for infinate chems
+ taste_description = "this meat is bland."
var/obj/item/organ/internal/carrion/core/C = owner.random_organ_by_process(BP_SPCORE)
if(C)
@@ -477,7 +502,7 @@
var/chemvessel_efficiency = owner.get_organ_efficiency(OP_CHEMICALS)
if(chemvessel_efficiency > 1)
- owner.carrion_stored_chemicals = min(owner.carrion_stored_chemicals + 0.01 * chemvessel_efficiency , 0.5 * chemvessel_efficiency)
+ owner.carrion_stored_chemicals = min(owner.carrion_stored_chemicals + 0.01 * chemvessel_efficiency * chemgain , 0.5 * chemvessel_efficiency)
to_chat(owner, SPAN_NOTICE("You consume \the [food], [taste_description]."))
visible_message(SPAN_DANGER("[owner] devours \the [food]!"))
@@ -555,7 +580,7 @@
continue
toxin_attack(creature, rand(1, 3))
-/obj/effect/decal/cleanable/solid_biomass/attackby(var/obj/item/I, var/mob/user)
+/obj/effect/decal/cleanable/carrion_puddle/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/mop) || istype(I, /obj/item/soap))
to_chat(user, SPAN_NOTICE("You started cleaning this [src]."))
if(do_after(user, 3 SECONDS, src))
diff --git a/code/modules/organs/internal/internal_organ_processes.dm b/code/modules/organs/internal/internal_organ_processes.dm
index 1b9b97dd5b5..05590ed2015 100644
--- a/code/modules/organs/internal/internal_organ_processes.dm
+++ b/code/modules/organs/internal/internal_organ_processes.dm
@@ -259,6 +259,10 @@
if(carrion_hunger < max_hunger)
carrion_hunger = min(carrion_hunger + (round(1* (maw_efficiency / 100))), max_hunger)
else
+ if(ingested.has_reagent("nutriment", 1))
+ ingested.remove_reagent("nutriment", 1)
+ else
+ nutrition = max(0, nutrition - 20) // equivalent to a unit of nutriment
to_chat(src, SPAN_WARNING("Your hunger is restless!"))
carrion_last_hunger = world.time
diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm
index 3c0e65a0e9a..37d86a53b89 100644
--- a/code/modules/organs/wound.dm
+++ b/code/modules/organs/wound.dm
@@ -143,6 +143,7 @@
proc/open_wound(damage)
src.damage += damage
bleed_timer += damage
+ clamped = FALSE
while(src.current_stage > 1 && src.damage_list[current_stage-1] <= src.damage / src.amount)
src.current_stage--
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index db805e53355..481428103a6 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -107,22 +107,12 @@
/obj/structure/filingcabinet/security/populate()
if(virgin)
- for(var/datum/data/record/G in data_core.general)
- var/datum/data/record/S
- for(var/datum/data/record/R in data_core.security)
- if((R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]))
- S = R
- break
+ for(var/datum/computer_file/report/crew_record/G in GLOB.all_crew_records)
var/obj/item/paper/P = new /obj/item/paper(src)
P.info = "Security Record "
- P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]] \nSex: [G.fields["sex"]] \nAge: [G.fields["age"]] \nFingerprint: [G.fields["fingerprint"]] \nPhysical Status: [G.fields["p_stat"]] \nMental Status: [G.fields["m_stat"]] "
- P.info += " \nSecurity Data \nCriminal Status: [S.fields["criminal"]] \n \nMinor Crimes: [S.fields["mi_crim"]] \nDetails: [S.fields["mi_crim_d"]] \n \nMajor Crimes: [S.fields["ma_crim"]] \nDetails: [S.fields["ma_crim_d"]] \n \nImportant Notes: \n\t[S.fields["notes"]] \n \nComments/Log "
- var/counter = 1
- while(S.fields["com_[counter]"])
- P.info += "[S.fields["com_[counter]"]] "
- counter++
+ P.info += "Name: [G.get_name()] \nSex: [G.get_sex()] \nAge: [G.get_age()] \nFingerprint: [G.get_fingerprint()] "
P.info += ""
- P.name = "Security Record ([G.fields["name"]])"
+ P.name = "Security Record ([G.get_name()])"
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
@@ -142,24 +132,21 @@
/obj/structure/filingcabinet/medical/populate()
if(virgin)
- for(var/datum/data/record/G in data_core.general)
- var/datum/data/record/M
- for(var/datum/data/record/R in data_core.medical)
- if((R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]))
- M = R
- break
+ for(var/datum/computer_file/report/crew_record/G in GLOB.all_crew_records)
+ var/datum/report_field/arrayclump/M = G.get_linkage_medRecord()
if(M)
var/obj/item/paper/P = new /obj/item/paper(src)
- P.info = "Medical Record "
- P.info += "Name: [G.fields["name"]] ID: [G.fields["id"]] \nSex: [G.fields["sex"]] \nAge: [G.fields["age"]] \nFingerprint: [G.fields["fingerprint"]] \nPhysical Status: [G.fields["p_stat"]] \nMental Status: [G.fields["m_stat"]] "
-
- P.info += " \nMedical Data \nBlood Type: [M.fields["b_type"]] \nDNA: [M.fields["b_dna"]] \n \nMinor Disabilities: [M.fields["mi_dis"]] \nDetails: [M.fields["mi_dis_d"]] \n \nMajor Disabilities: [M.fields["ma_dis"]] \nDetails: [M.fields["ma_dis_d"]] \n \nAllergies: [M.fields["alg"]] \nDetails: [M.fields["alg_d"]] \n \nCurrent Diseases: [M.fields["cdi"]] (per disease info placed in log/comment section) \nDetails: [M.fields["cdi_d"]] \n \nImportant Notes: \n\t[M.fields["notes"]] \n \nComments/Log "
- var/counter = 1
- while(M.fields["com_[counter]"])
- P.info += "[M.fields["com_[counter]"]] "
- counter++
- P.info += ""
- P.name = "Medical Record ([G.fields["name"]])"
+ var/list/infostoadd = list()
+ infostoadd += "Medical Record "
+ infostoadd += "Name: [G.get_name()] \nSex: [G.get_sex()] \nAge: [G.get_age()] "
+
+ infostoadd += " \nMedical Data \nBlood Type: [G.get_bloodtype()] \nDNA: [G.get_dna()] "
+ infostoadd += " \nProsthetics: [M.value["prosthetics"]] \nWounds: [M.value["wounds"]] \n \nAutopsy: [M.value["Body state"]] "
+ infostoadd +=" \nChemical History: [M.value["chemhistory"]] \nPsychological Profile: [M.value["psychological"]] "
+
+ infostoadd += ""
+ P.name = "Medical Record ([G.get_name()])"
+ P.info = infostoadd.Join() // minor optimization
virgin = 0 //tabbing here is correct- it's possible for people to try and use it
//before the records have been generated, so we do this inside the loop.
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 68adc53e1f1..a846b75f986 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -230,7 +230,7 @@
if(flashlight_attachment)
flashlight_attachment.forceMove(get_turf(src))
flashlight_attachment = null
- ..()
+ . = ..()
/obj/item/gun/proc/set_item_state(state, hands = TRUE, back = FALSE, onsuit = FALSE)
var/wield_state
@@ -1017,6 +1017,7 @@
sharp = initial(sharp)
braceable = initial(braceable)
recoil = getRecoil(init_recoil[1], init_recoil[2], init_recoil[3])
+ w_class = initial(w_class)
attack_verb = list()
if(LAZYLEN(custom_default)) // this override is used by the artwork_revolver for RNG gun stats
diff --git a/code/modules/projectiles/guns/projectile/battle_rifle/boltgun.dm b/code/modules/projectiles/guns/projectile/battle_rifle/boltgun.dm
index 90694a08547..6630573aa64 100644
--- a/code/modules/projectiles/guns/projectile/battle_rifle/boltgun.dm
+++ b/code/modules/projectiles/guns/projectile/battle_rifle/boltgun.dm
@@ -77,14 +77,14 @@
playsound(src.loc, 'sound/weapons/guns/interact/rifle_boltback.ogg', 75, 1)
bolt_open = !bolt_open
if(bolt_open)
- if(contents.len)
+ if(length(loaded))
if(chambered)
to_chat(user, SPAN_NOTICE("You work the [message] open, ejecting [chambered]!"))
chambered.forceMove(get_turf(src))
loaded -= chambered
chambered = null
else
- var/obj/item/ammo_casing/B = loaded[loaded.len]
+ var/obj/item/ammo_casing/B = loaded[1]
if(!B.is_caseless)
to_chat(user, SPAN_NOTICE("You work the [message] open, ejecting [B]!"))
B.forceMove(get_turf(src))
@@ -196,7 +196,7 @@
icon = 'icons/obj/guns/projectile/riose.dmi'
icon_state = "boltgun_hand"
item_suffix = "_hand"
- matter = list(MATERIAL_STEEL = 10, MATERIAL_WOOD = 5)
+ matter = list(MATERIAL_STEEL = 13, MATERIAL_WOOD = 5)
wielded_item_state = "_doble_hand"
w_class = ITEM_SIZE_HUGE
slot_flags = SLOT_BACK
@@ -221,7 +221,7 @@
matter = list(MATERIAL_STEEL = 5)
resultvars = list(/obj/item/gun/projectile/boltgun/handmade)
gripvars = list(/obj/item/part/gun/modular/grip/wood)
- mechanismvar = /obj/item/part/gun/modular/mechanism/boltgun
+ mechanismvar = /obj/item/part/gun/modular/mechanism/boltgun/junk
barrelvars = list(/obj/item/part/gun/modular/barrel/lrifle/steel, /obj/item/part/gun/modular/barrel/srifle/steel, /obj/item/part/gun/modular/barrel/clrifle/steel)
//// OBREZ ////
diff --git a/code/modules/projectiles/guns/projectile/flaregun.dm b/code/modules/projectiles/guns/projectile/flaregun.dm
index bf1f285697b..5a2c1eea232 100644
--- a/code/modules/projectiles/guns/projectile/flaregun.dm
+++ b/code/modules/projectiles/guns/projectile/flaregun.dm
@@ -45,14 +45,14 @@
playsound(loc, 'sound/weapons/guns/interact/rev_cock.ogg', 75, 1)
bolt_open = !bolt_open
if(bolt_open)
- if(loaded.len)
+ if(length(loaded))
if(chambered)
to_chat(user, SPAN_NOTICE("You snap the barrel open, ejecting [chambered]!"))
chambered.forceMove(get_turf(src))
loaded -= chambered
chambered = null
else
- var/obj/item/ammo_casing/shell = loaded[loaded.len]
+ var/obj/item/ammo_casing/shell = loaded[1]
to_chat(user, SPAN_NOTICE("You snap the barrel open, ejecting [shell]!"))
shell.forceMove(get_turf(src))
loaded -= shell
diff --git a/code/modules/projectiles/guns/projectile/modular.dm b/code/modules/projectiles/guns/projectile/modular.dm
index f5ea3f514c0..0d230834c44 100644
--- a/code/modules/projectiles/guns/projectile/modular.dm
+++ b/code/modules/projectiles/guns/projectile/modular.dm
@@ -51,6 +51,9 @@
max_upgrades = 6
+ var/list/scope_damage_adds = list()
+ var/datum/gunoverrides/overridedatum
+
/obj/item/gun/projectile/automatic/modular/Initialize()
gun_tags += GUN_MODULAR
@@ -59,6 +62,7 @@
var/obj/item/part/gun/modular/new_part = new partPath(quality = gun_parts[partPath])
if(!new_part.I.rapid_apply(src))
visible_message(SPAN_WARNING("Something seems wrong... Maybe you should ask a professional for help?"))
+ overridedatum = new()
refresh_upgrades()
. = ..()
update_icon()
@@ -80,7 +84,12 @@
verbs -= MODULAR_VERBS // Removes all modularized verbs
grip_type = initial(grip_type)
good_calibers = list() // Won't ever be redefined, mechanism determines this, and when no mechanism is installed, we don't want anything here anyways
+ no_internal_mag = initial(no_internal_mag)
+ scope_damage_adds = list()
+ overridedatum?.reset() // clear first
..()
+ reset_action_buttons()
+ overridedatum?.cycle() // then use an assignment sort
name = get_initial_name()
/obj/item/gun/projectile/automatic/modular/update_icon() // V2
@@ -157,6 +166,75 @@
// Interactions
+/datum/gunoverrides
+ var/list/priorities = list()
+
+/datum/gunoverrides/proc/reset()
+ for(var/list/wiped in priorities)
+ wiped.Cut()
+ priorities.Cut()
+
+/datum/gunoverrides/proc/call_Flag(obj/item/load, user, flag)
+ for(var/key in priorities)
+ var/list/priority = priorities[key]
+ var/done = FALSE
+ for(var/datum/guninteraction/tocheck in priority) // highest numbers first.
+ if(tocheck.interactionflags & flag)
+ switch(flag)
+ if(GI_ATTACKSELF)
+ if(tocheck.attack_self(user))
+ done = TRUE
+ if(GI_LOAD)
+ if(tocheck.load_ammo(load, user))
+ done = TRUE
+ if(GI_UNLOAD)
+ if(tocheck.unload_ammo(user))
+ done = TRUE
+ if(GI_SPECIAL)
+ if(tocheck.special_check(user))
+ done = TRUE
+ if(done)
+ return TRUE
+
+/datum/gunoverrides/proc/cycle()
+ var/list/slate = list()
+ for(var/number = 4, number >= 0, number -= 1)
+ slate["[number]"] = priorities["[number]"] ? priorities["[number]"] : null
+ priorities = slate.Copy()
+
+/obj/item/gun/projectile/automatic/modular/attack_self(mob/user)
+ if(!overridedatum.call_Flag(user = user, flag = GI_ATTACKSELF))
+ . = ..()
+
+/obj/item/gun/projectile/automatic/modular/load_ammo(obj/item/A, mob/user)
+ if(!overridedatum.call_Flag(load = A, user = user, flag = GI_LOAD))
+ . = ..()
+
+
+/obj/item/gun/projectile/automatic/modular/unload_ammo(mob/user, allow_dump)
+ if(!overridedatum.call_Flag(user = user, flag = GI_UNLOAD))
+ . = ..()
+
+/obj/item/gun/projectile/automatic/modular/special_check(mob/user)
+ if(!overridedatum.call_Flag(user = user, flag = GI_SPECIAL))
+ . = ..()
+
+/obj/item/gun/projectile/automatic/modular/hand_spin(mob/living/carbon/caller)
+ overridedatum.call_Flag(user = caller, flag = GI_SPIN)
+
+/obj/item/gun/projectile/automatic/modular/proc/reset_action_buttons()
+ for(var/key in overridedatum.priorities)
+ var/list/priority = overridedatum.priorities[key]
+ for(var/datum/guninteraction/tocheck in priority) // highest numbers first.
+ if(tocheck.action_button_name && tocheck.action_button_proc)
+ action_button_name = tocheck.action_button_name
+ action_button_proc = tocheck.action_button_proc
+ return TRUE // can only have one button
+ // if we didn't override them
+ action_button_name = initial(action_button_name)
+ action_button_proc = initial(action_button_proc)
+ qdel(action)
+
/obj/item/gun/projectile/automatic/modular/can_interact(mob/user)
if((!ishuman(user) && (loc != user)) || user.stat || user.restrained())
return 1
@@ -194,16 +272,19 @@
/obj/item/gun/projectile/automatic/modular/proc/fold(user)
if(PARTMOD_FOLDING_STOCK & spriteTags)
- if(PARTMOD_FOLDING_STOCK & statusTags)
- to_chat(user, SPAN_NOTICE("You fold the stock on \the [src]."))
- statusTags -= PARTMOD_FOLDING_STOCK
- w_class = initial(w_class)
- else
- to_chat(user, SPAN_NOTICE("You unfold the stock on \the [src]."))
- statusTags |= PARTMOD_FOLDING_STOCK
- w_class = initial(w_class) + 1
-
+ for(var/obj/item/part/gun/modular/stock/toedit in gun_parts) // only gonna edit one, doing this to find it
+ if(PARTMOD_FOLDING_STOCK & statusTags)
+ to_chat(user, SPAN_NOTICE("You fold the stock on \the [src]."))
+ statusTags -= PARTMOD_FOLDING_STOCK
+ toedit.I.weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS] = 0
+ else
+ to_chat(user, SPAN_NOTICE("You unfold the stock on \the [src]."))
+ statusTags |= PARTMOD_FOLDING_STOCK
+ toedit.I.weapon_upgrades[GUN_UPGRADE_DEFINE_WCLASS] = toedit.wclassmod
+ break
+
refresh_upgrades()
+
playsound(loc, 'sound/weapons/guns/interact/selector.ogg', 100, 1)
update_icon()
@@ -218,3 +299,14 @@
return FALSE
load_ammo(I, user)
update_held_icon()
+
+/obj/item/gun/projectile/automatic/modular/zoom(tileoffset, viewsize, stayzoomed)
+ ..()
+ refresh_upgrades()
+ if(zoom)
+ var/currentzoom = zoom_factors.Find(active_zoom_factor)
+ var/extra_damage
+ if(scope_damage_adds[currentzoom])
+ extra_damage = scope_damage_adds[currentzoom]
+ damage_multiplier += extra_damage
+
diff --git a/code/modules/projectiles/guns/projectile/modular/interactions.dm b/code/modules/projectiles/guns/projectile/modular/interactions.dm
new file mode 100644
index 00000000000..92cc43349c8
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/modular/interactions.dm
@@ -0,0 +1,99 @@
+/datum/guninteraction
+ var/obj/item/gun/projectile/automatic/modular/parentgun
+ var/obj/item/part/gun/modular/parentpart
+ var/priority = 0
+ var/interactionflags
+ var/action_button_name = ""
+ var/action_button_proc = ""
+
+/datum/guninteraction/proc/attack_self(mob/user)
+
+/datum/guninteraction/proc/update_icon()
+
+/datum/guninteraction/proc/load_ammo(var/obj/item/A, mob/user)
+
+/datum/guninteraction/proc/unload_ammo(mob/user, var/allow_dump=1)
+
+/datum/guninteraction/proc/special_check(mob/user)
+
+/datum/guninteraction/New(newparent)
+ parentpart = newparent
+
+/datum/guninteraction/bolted
+ var/bolt_open = FALSE
+ var/message = "bolt"
+ interactionflags = GI_ATTACKSELF|GI_LOAD|GI_UNLOAD|GI_SPECIAL
+
+
+/datum/guninteraction/bolted/New(newparent)
+ ..()
+ parentpart.part_overlay = jointext(list(initial(parentpart.part_overlay),"bolt_closed"), "")
+
+/datum/guninteraction/bolted/attack_self(mob/user)
+ bolt_act(user)
+ . = TRUE
+
+/datum/guninteraction/bolted/update_icon()
+ if(bolt_open)
+ parentpart.part_overlay = jointext(list(initial(parentpart.part_overlay),"bolt_open"), "")
+ else
+ parentpart.part_overlay = jointext(list(initial(parentpart.part_overlay),"bolt_closed"), "")
+ parentgun.update_icon()
+
+/datum/guninteraction/bolted/load_ammo(var/obj/item/A, mob/user)
+ if(!bolt_open)
+ return TRUE // disable operations
+
+/datum/guninteraction/bolted/unload_ammo(mob/user, var/allow_dump=1)
+ if(!bolt_open)
+ return TRUE // disable operations
+
+
+/datum/guninteraction/bolted/special_check(mob/user)
+ if(bolt_open)
+ to_chat(user, SPAN_WARNING("You can't fire [parentgun] while the [message] is open!"))
+ return TRUE
+
+/datum/guninteraction/bolted/proc/bolt_act(mob/living/user)
+
+ playsound(parentgun.loc, 'sound/weapons/guns/interact/rifle_boltback.ogg', 75, 1)
+ bolt_open = !bolt_open
+ if(bolt_open)
+ if(length(parentgun.loaded)||parentgun.chambered)
+ if(parentgun.chambered)
+ to_chat(user, SPAN_NOTICE("You work the [message] open, ejecting [parentgun.chambered]!"))
+ parentgun.chambered.forceMove(get_turf(parentgun))
+ parentgun.loaded -= parentgun.chambered
+ parentgun.chambered = null
+ else
+ var/obj/item/ammo_casing/B = parentgun.loaded[1]
+ if(!B.is_caseless)
+ to_chat(user, SPAN_NOTICE("You work the [message] open, ejecting [B]!"))
+ B.forceMove(get_turf(parentgun))
+ parentgun.loaded -= B
+ else
+ to_chat(user, SPAN_NOTICE("You work the [message] open."))
+ B = parentgun.loaded[1]
+ parentgun.loaded -= B
+ qdel(B)
+ else
+ to_chat(user, SPAN_NOTICE("You work the [message] open."))
+ else
+ to_chat(user, SPAN_NOTICE("You work the [message] closed."))
+ playsound(parentgun.loc, 'sound/weapons/guns/interact/rifle_boltforward.ogg', 75, 1)
+ bolt_open = 0
+ parentgun.add_fingerprint(user)
+ update_icon()
+
+/datum/guninteraction/zoomed
+ priority = 1
+ interactionflags = GI_ATTACKSELF
+
+/datum/guninteraction/zoomed/attack_self(mob/user)
+ if(parentgun?.zoom)
+ parentgun.toggle_scope(user)
+ return TRUE
+
+/datum/guninteraction/zoomed/multizoom
+ action_button_name = "Switch zoom level"
+ action_button_proc = "switch_zoom"
diff --git a/code/modules/projectiles/guns/projectile/modular/modular_bolt.dm b/code/modules/projectiles/guns/projectile/modular/modular_bolt.dm
new file mode 100644
index 00000000000..ab1bb03f566
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/modular/modular_bolt.dm
@@ -0,0 +1,83 @@
+/obj/item/gun/projectile/automatic/modular/bolt // frame
+ name = "Excelsior BR .30 \"Kardashev-Mosin\""
+ desc = "Weapon for hunting, or endless trench warfare. \
+ If you’re on a budget, it’s a darn good rifle for just about everything."
+ icon = 'icons/obj/guns/projectile/modular/bolt.dmi'
+ slot_flags = SLOT_BACK
+ origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
+ w_class = ITEM_SIZE_BULKY
+ force = WEAPON_FORCE_ROBUST
+ handle_casings = HOLD_CASINGS
+ load_method = SINGLE_CASING|SPEEDLOADER
+ matter = list(MATERIAL_PLASTEEL = 5, MATERIAL_PLASTIC = 4)
+ price_tag = 900
+ spawn_blacklisted = TRUE
+ twohanded = TRUE
+ spriteTagBans = PARTMOD_FOLDING_STOCK
+ init_recoil = SLATE_RECOIL(1.5)
+ required_parts = list(/obj/item/part/gun/modular/barrel = 0, /obj/item/part/gun/modular/grip = 0, /obj/item/part/gun/modular/stock = 0,\
+ /obj/item/part/gun/modular/mechanism/boltgun = 0, /obj/item/part/gun/modular/sights = -1, /obj/item/part/gun/modular/bayonet = -1)
+ init_firemodes = list() // boltguns don't have firemodes!
+
+/obj/item/gun/projectile/automatic/modular/bolt/get_initial_name()
+ if(grip_type)
+ switch(grip_type)
+ if("wood")
+ if(caliber == CAL_SRIFLE)
+ return "FS SR .20 \"Arasaka\"" // or small
+ else
+ return "SA SR [caliber] \"Novakovic\"" // we love/fear them all
+ if("black")
+ return "NT SR [caliber] \"Eradicator\""
+ if("rubber")
+ return "FS SR [caliber] \"Kadmin\""
+ if("excelsior")
+ return "Excelsior SR [caliber] \"Kardashev-Mosin\""
+ if("serbian")
+ return "SA AMR [caliber] \"Hristov\"" // big
+ if("makeshift")
+ return "HM SR [caliber] \"Riose\""
+ else
+ return "SR [caliber] \"Boltie\""
+
+/obj/item/gun/projectile/automatic/modular/bolt/excel
+ gun_parts = list(/obj/item/part/gun/modular/grip/excel = 0, /obj/item/part/gun/modular/mechanism/boltgun = 0, /obj/item/part/gun/modular/barrel/lrifle/steel = 0, \
+ /obj/item/part/gun/modular/stock/longrifle = 0, /obj/item/part/gun/modular/bayonet = 0)
+
+/obj/item/gun/projectile/automatic/modular/bolt/serbian
+ desc = "Weapon for hunting, or endless trench warfare. \
+ If you’re on a budget, it’s a darn good rifle for just about everything. \
+ This copy, in fact, is a reverse-engineered poor-quality copy of a more perfect copy of an ancient rifle"
+ init_recoil = SLATE_RECOIL(1.7)
+ spawn_blacklisted = FALSE
+
+/obj/item/gun/projectile/automatic/modular/bolt/serbian/finished
+ gun_parts = list(/obj/item/part/gun/modular/grip/wood = 1, /obj/item/part/gun/modular/mechanism/boltgun = 0,\
+ /obj/item/part/gun/modular/barrel/lrifle/steel = 0, /obj/item/part/gun/modular/stock/longrifle = 0, /obj/item/part/gun/modular/bayonet/steel = 0)
+
+/obj/item/gun/projectile/automatic/modular/bolt/fs
+ gun_parts = list(/obj/item/part/gun/modular/grip/rubber = 0, /obj/item/part/gun/modular/mechanism/boltgun = 0, /obj/item/part/gun/modular/barrel/srifle/long = 0,\
+ /obj/item/part/gun/modular/stock/longrifle = 0, /obj/item/part/gun/modular/sights/scopebig = 0)
+
+/obj/item/gun/projectile/automatic/modular/bolt/fs/civilian
+ gun_parts = list(/obj/item/part/gun/modular/grip/wood = -1, /obj/item/part/gun/modular/mechanism/boltgun = 0, /obj/item/part/gun/modular/barrel/srifle/long = 0,\
+ /obj/item/part/gun/modular/stock/longrifle = 0, /obj/item/part/gun/modular/sights/scopesmall = 0) // nerfed the stock to simulate civilian shittyness that apparently increases recoil by 1/9th
+ spawn_blacklisted = FALSE
+
+/obj/item/gun/projectile/automatic/modular/bolt/handmade
+ desc = "A handmade bolt action rifle, made from junk and some spare parts."
+ spawn_blacklisted = FALSE
+ matter = list(MATERIAL_STEEL = 4)
+ init_recoil = SLATE_RECOIL(2) // lower quality frame
+ price_tag = 800
+
+/obj/item/gun/projectile/automatic/modular/bolt/handmade/finished
+ gun_parts = list(/obj/item/part/gun/modular/grip/makeshift = 0, /obj/item/part/gun/modular/mechanism/boltgun/junk = 0, /obj/item/part/gun/modular/barrel/lrifle/steel = 0,\
+ /obj/item/part/gun/modular/stock/longrifle = 0, /obj/item/part/gun/modular/bayonet = 0)
+
+/obj/item/gun/projectile/automatic/modular/bolt/sniper
+ desc = "A portable anti-armour rifle, it was originally designed for use against armoured exosuits. It is capable of punching through windows and non-reinforced walls with ease, but suffers from overpenetration at close range. Fires armor piercing .60 shells."
+
+/obj/item/gun/projectile/automatic/modular/bolt/sniper/finished
+ gun_parts = list(/obj/item/part/gun/modular/grip/serb = 0, /obj/item/part/gun/modular/mechanism/boltgun/heavy = 0, /obj/item/part/gun/modular/barrel/antim/long = 0,\
+ /obj/item/part/gun/modular/stock/heavy = 0, /obj/item/part/gun/modular/sights/customizable/scopeheavy = 0)
diff --git a/code/modules/projectiles/guns/projectile/shotgun/doublebarrel.dm b/code/modules/projectiles/guns/projectile/shotgun/doublebarrel.dm
index 55441bf8449..e1e211f294c 100644
--- a/code/modules/projectiles/guns/projectile/shotgun/doublebarrel.dm
+++ b/code/modules/projectiles/guns/projectile/shotgun/doublebarrel.dm
@@ -64,7 +64,6 @@
else
playsound(src.loc, 'sound/weapons/guns/interact/shotgun_close.ogg', 75, 1)
to_chat(user, SPAN_NOTICE("You snap the barrel closed"))
- bolt_open = 0
add_fingerprint(user)
update_icon()
diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm
index 6e3a79cf5e6..66bd2daa097 100644
--- a/code/modules/projectiles/guns/projectile/sniper.dm
+++ b/code/modules/projectiles/guns/projectile/sniper.dm
@@ -83,14 +83,14 @@
playsound(src.loc, 'sound/weapons/guns/interact/rifle_boltback.ogg', 75, 1)
bolt_open = !bolt_open
if(bolt_open)
- if(contents.len)
+ if(length(loaded))
if(chambered)
to_chat(user, SPAN_NOTICE("You work the bolt open, ejecting [chambered]!"))
chambered.forceMove(get_turf(src))
loaded -= chambered
chambered = null
else
- var/obj/item/ammo_casing/B = loaded[loaded.len]
+ var/obj/item/ammo_casing/B = loaded[1]
to_chat(user, SPAN_NOTICE("You work the bolt open, ejecting [B]!"))
B.forceMove(get_turf(src))
loaded -= B
diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm
index 5dac23f32e5..1695af497ea 100644
--- a/code/modules/random_map/automata/caves.dm
+++ b/code/modules/random_map/automata/caves.dm
@@ -40,6 +40,10 @@
// Create ore turfs.
/datum/random_map/automata/cave_system/cleanup()
+ if(!ore_data || !ore_data.len)
+ for(var/oretype in typesof(/ore)-/ore)
+ var/ore/OD = new oretype()
+ ore_data[OD.name] = OD
var/ore_count = round(map.len/20)
while((ore_count>0) && (ore_turfs.len>0))
if(!priority_process) sleep(-1)
diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm
index deb9e45fa08..69cc3f6a172 100644
--- a/code/modules/reagents/reagent_containers/food/snacks.dm
+++ b/code/modules/reagents/reagent_containers/food/snacks.dm
@@ -3489,7 +3489,9 @@
slice_path = /obj/item/reagent_containers/food/snacks/doughslice
slices_num = 3
center_of_mass = list("x"=16, "y"=16)
- preloaded_reagents = list("protein" = 1, "nutriment" = 3)
+ nutriment_desc = list("dough" = 3)
+ nutriment_amt = 3
+ preloaded_reagents = list("protein" = 1)
taste_tag = list(BLAND_FOOD,FLOURY_FOOD)
/obj/item/reagent_containers/food/snacks/doughslice
diff --git a/code/modules/reagents/reagents/core.dm b/code/modules/reagents/reagents/core.dm
index b3e3c62df42..e907e0945f7 100644
--- a/code/modules/reagents/reagents/core.dm
+++ b/code/modules/reagents/reagents/core.dm
@@ -79,7 +79,7 @@
if (prob(5))
T.visible_message(SPAN_WARNING("The water sizzles as it lands on \the [T]!"))
- else if(volume >= 10)
+ else if(volume >= 10 && !QDELING(T))
T.wet_floor(1)
return TRUE
diff --git a/code/modules/reagents/reagents/toxins.dm b/code/modules/reagents/reagents/toxins.dm
index 9183eb1161f..1a76b18968a 100644
--- a/code/modules/reagents/reagents/toxins.dm
+++ b/code/modules/reagents/reagents/toxins.dm
@@ -564,7 +564,7 @@
to_chat(M, SPAN_DANGER("Your flesh rapidly mutates!"))
for(var/obj/item/W in H) //Check all items on the person
if(istype(W, /obj/item/organ/external/robotic) || istype(W, /obj/item/implant)) //drop prosthetic limbs and implants, you are a slime now.
- W.dropped()
+ W.dropped(M)
H.set_species(SPECIES_SLIME)
/datum/reagent/toxin/aslimetoxin
@@ -595,7 +595,7 @@
if(istype(W, /obj/item/implant) || istype(W, /obj/item/organ/external/robotic)) //Check if item is implant or prosthetic
if(istype(W, /obj/item/implant/core_implant/cruciform)) //If cruciform is present victim is gibbed instead of transformed
cruciformed = TRUE
- W.dropped() //use the baseline dropped()
+ W.dropped(M) //use the baseline dropped()
continue
W.layer = initial(W.layer)
W.loc = M.loc
diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm
index f5c38fe0f0e..d424223f6d9 100644
--- a/code/modules/research/designs/circuits.dm
+++ b/code/modules/research/designs/circuits.dm
@@ -36,11 +36,6 @@
sort_string = "MABBA"
category = CAT_MISC
-/datum/design/research/circuit/secdata
- name = "security records console"
- build_path = /obj/item/electronics/circuitboard/secure_data
- sort_string = "DABAA"
- category = CAT_COMP
/datum/design/research/circuit/prisonmanage
name = "prisoner management console"
@@ -48,11 +43,6 @@
sort_string = "DACAA"
category = CAT_COMP
-/datum/design/research/circuit/med_data
- name = "medical records console"
- build_path = /obj/item/electronics/circuitboard/med_data
- sort_string = "FAAAA"
- category = CAT_COMP
/datum/design/research/circuit/operating
name = "patient monitoring console"
diff --git a/code/modules/research/nodes/biotech.dm b/code/modules/research/nodes/biotech.dm
index 609699af18e..b0c65c29102 100644
--- a/code/modules/research/nodes/biotech.dm
+++ b/code/modules/research/nodes/biotech.dm
@@ -17,7 +17,7 @@
/datum/technology/basic_med_machines
name = "Basic Medical Machines"
- desc = "Basic medical databases and surgical monitoring."
+ desc = "Basic surgical monitoring."
tech_type = RESEARCH_BIOTECH
x = 0.25
@@ -28,9 +28,7 @@
required_tech_levels = list()
cost = 200
- unlocks_designs = list( /datum/design/research/circuit/med_data,
- /datum/design/research/circuit/operating
- )
+ unlocks_designs = list(/datum/design/research/circuit/operating)
/*
/datum/technology/virology
name = "Virology"
diff --git a/code/modules/sanity/breakdowns.dm b/code/modules/sanity/breakdowns.dm
index 0d4a81d8745..ea95d2ac83c 100644
--- a/code/modules/sanity/breakdowns.dm
+++ b/code/modules/sanity/breakdowns.dm
@@ -201,7 +201,7 @@
/datum/breakdown/negative/selfharm/occur()
spawn(delay)
- ++holder.owner.suppress_communication
+ ++holder?.owner.suppress_communication
return ..()
/datum/breakdown/negative/selfharm/conclude()
@@ -240,9 +240,9 @@
/datum/breakdown/negative/hysteric/occur()
spawn(delay)
- holder.owner.SetWeakened(4)
- holder.owner.SetStunned(4)
- ++holder.owner.suppress_communication
+ holder?.owner.SetWeakened(4)
+ holder?.owner.SetStunned(4)
+ ++holder?.owner.suppress_communication
return ..()
/datum/breakdown/negative/hysteric/conclude()
diff --git a/code/modules/surgery/autodoc.dm b/code/modules/surgery/autodoc.dm
index 821ad4939e5..cb80d952e44 100644
--- a/code/modules/surgery/autodoc.dm
+++ b/code/modules/surgery/autodoc.dm
@@ -116,6 +116,7 @@
if(patchnote.surgery_operations & AUTODOC_TOXIN)
to_chat(patient, SPAN_NOTICE("Administering anti-toxin to patient."))
patient.adjustToxLoss(-damage_heal_amount)
+ patient.add_chemical_effect(CE_ANTITOX, damage_heal_amount/10)
if(!patient.getToxLoss())
patchnote.surgery_operations &= ~AUTODOC_TOXIN
@@ -132,8 +133,8 @@
else if (patchnote.surgery_operations & AUTODOC_BLOOD)
to_chat(patient, SPAN_NOTICE("Administering blood IV to patient."))
var/datum/reagent/organic/blood/blood = patient.vessel.reagent_list[1]
- blood.volume += damage_heal_amount
- if(blood.volume >= patient.vessel.total_volume)
+ blood.volume = min(blood.volume + damage_heal_amount, patient.vessel.maximum_volume)
+ if(blood.volume == patient.vessel.maximum_volume)
patchnote.surgery_operations &= ~AUTODOC_BLOOD
else if(patchnote.surgery_operations & AUTODOC_DAMAGE)
@@ -164,30 +165,31 @@
if(istype(patchnote.organ, /obj/item/organ/internal))
var/obj/item/organ/internal/I = patchnote.organ
to_chat(patient, SPAN_NOTICE("Treating internal wounds in the patient's [I.name]."))
- SEND_SIGNAL_OLD(I, COMSIG_IWOUND_TREAT, TRUE, TRUE)
- patchnote.surgery_operations &= ~AUTODOC_INTERNAL_WOUNDS
+ var/datum/internal_wound/wound = I.wounddatums[pick(I.wounddatums)]
+ if(istype(wound))
+ wound.treatment(TRUE, TRUE)
+ if(!length(I.wounddatums)) patchnote.surgery_operations &= ~AUTODOC_INTERNAL_WOUNDS
/datum/autodoc/Process()
if(!patient)
stop()
+ else if(current_step > picked_patchnotes.len)
+ stop()
+ scan_user(patient)
+ return
while(!(picked_patchnotes[current_step].surgery_operations))
- if(current_step + 1 > picked_patchnotes.len)
+ current_step++
+ if(current_step > picked_patchnotes.len)
stop()
scan_user(patient)
return
- else
- current_step++
if(world.time > (start_op_time + processing_speed))
start_op_time = world.time
patient.updatehealth()
if(process_note(picked_patchnotes[current_step]))
- if(current_step + 1 > picked_patchnotes.len)
- stop()
- scan_user(patient)
- else
- current_step++
+ current_step++
/datum/autodoc/proc/fail()
current_step++
diff --git a/html/changelogs/AutoChangeLog-pr-8570.yml b/html/changelogs/AutoChangeLog-pr-8570.yml
new file mode 100644
index 00000000000..5fd14d077a1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8570.yml
@@ -0,0 +1,7 @@
+author: chickenish, bobob
+delete-after: true
+changes:
+ - rscadd: Added modular bolt-gun config
+ - tweak: tweaked Riose cost
+ - bugfix: fixed clrifle bolt action ammo choice discrepancy
+ - imageadd: added modular boltgun parts
diff --git a/html/changelogs/AutoChangeLog-pr-8586.yml b/html/changelogs/AutoChangeLog-pr-8586.yml
new file mode 100644
index 00000000000..db1ee805e87
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8586.yml
@@ -0,0 +1,9 @@
+author: Chickenish
+delete-after: true
+changes:
+ - rscadd: Added Plasteel Coin
+ - rscdel: Removed Iron Coin
+ - bugfix: Coins now moderately valuable for use and trade.
+ - spellcheck: Platinum coin no longer spelled as Platunum coin.
+ - code_imp: Moneybag no longer shoves coins in the person holding the
+ moneybag.
diff --git a/html/changelogs/AutoChangeLog-pr-8590.yml b/html/changelogs/AutoChangeLog-pr-8590.yml
new file mode 100644
index 00000000000..3905262bbaf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8590.yml
@@ -0,0 +1,5 @@
+author: Chickenish
+delete-after: true
+changes:
+ - tweak: 'balance: Prying damaged flooring now produces scrap metal instead of deleting
+ the floor with no returns.'
diff --git a/html/changelogs/AutoChangeLog-pr-8594.yml b/html/changelogs/AutoChangeLog-pr-8594.yml
new file mode 100644
index 00000000000..9bee9b16fb8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8594.yml
@@ -0,0 +1,9 @@
+author: Chickenish
+delete-after: true
+changes:
+ - rscadd: Character records are now automatically defined based on the
+ character they are associated with.
+ - rscdel: Destroyed Data Core
+ - tweak: Sechud interface reworked
+ - bugfix: Security records now accessible via computer
+ - admin: fully_replace_character_name proc now fully functional
diff --git a/html/changelogs/AutoChangeLog-pr-8595.yml b/html/changelogs/AutoChangeLog-pr-8595.yml
new file mode 100644
index 00000000000..29a9194ce41
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8595.yml
@@ -0,0 +1,4 @@
+author: Chickenish
+delete-after: true
+changes:
+ - refactor: stationary Tanks refactored to unique type
diff --git a/html/changelogs/AutoChangeLog-pr-8596.yml b/html/changelogs/AutoChangeLog-pr-8596.yml
new file mode 100644
index 00000000000..a275c006c75
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8596.yml
@@ -0,0 +1,4 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: fixed Autodoc
diff --git a/html/changelogs/AutoChangeLog-pr-8610.yml b/html/changelogs/AutoChangeLog-pr-8610.yml
new file mode 100644
index 00000000000..f81c629263e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8610.yml
@@ -0,0 +1,4 @@
+author: Chickenish
+delete-after: true
+changes:
+ - rscadd: Mice can now live.
diff --git a/html/changelogs/AutoChangeLog-pr-8612.yml b/html/changelogs/AutoChangeLog-pr-8612.yml
new file mode 100644
index 00000000000..d3e8bac789c
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8612.yml
@@ -0,0 +1,4 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: Holding a candle as it runs out of wax now functions properly.
diff --git a/html/changelogs/AutoChangeLog-pr-8613.yml b/html/changelogs/AutoChangeLog-pr-8613.yml
new file mode 100644
index 00000000000..04d1924f576
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8613.yml
@@ -0,0 +1,5 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: self-harm and hysteric breakdowns no longer cause a runtime when
+ they begin shortly before the associated human is obliterated.
diff --git a/html/changelogs/AutoChangeLog-pr-8615.yml b/html/changelogs/AutoChangeLog-pr-8615.yml
new file mode 100644
index 00000000000..02eafbaaede
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8615.yml
@@ -0,0 +1,5 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: nutriment made via roach chem decay is now fully drinkable.
+ - bugfix: Flat Dough and derivatives are now more edible.
diff --git a/html/changelogs/AutoChangeLog-pr-8617.yml b/html/changelogs/AutoChangeLog-pr-8617.yml
new file mode 100644
index 00000000000..688c64b11bf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8617.yml
@@ -0,0 +1,5 @@
+author: Chickenish
+delete-after: true
+changes:
+ - balance: Clamped wounds do not stay clamped when re-opened.
+ - balance: Pressuring wounds now clamps the wound until re-opened.
diff --git a/html/changelogs/AutoChangeLog-pr-8621.yml b/html/changelogs/AutoChangeLog-pr-8621.yml
new file mode 100644
index 00000000000..9961f8f1c58
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8621.yml
@@ -0,0 +1,10 @@
+author: Chickenish
+delete-after: true
+changes:
+ - rscadd: Eating another carrion's core with your maw gives you the other
+ carrion's disguises
+ - balance: carrion over-hunger is now punished by making your human form
+ hungry
+ - tweak: carrion maw now works with holders.
+ - tweak: carrions now drop as an inert item if the core is killed.
+ - bugfix: eating with carrion maw provides proper chem value
diff --git a/html/changelogs/AutoChangeLog-pr-8625.yml b/html/changelogs/AutoChangeLog-pr-8625.yml
new file mode 100644
index 00000000000..a7f91c96f66
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8625.yml
@@ -0,0 +1,5 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: dismantling walls no longer results in GC errors.
+ - code_imp: Qdel hints are now better
diff --git a/html/changelogs/AutoChangeLog-pr-8626.yml b/html/changelogs/AutoChangeLog-pr-8626.yml
new file mode 100644
index 00000000000..21592f367e8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-8626.yml
@@ -0,0 +1,4 @@
+author: Chickenish
+delete-after: true
+changes:
+ - bugfix: fixed a mistake with vague attack logic
diff --git a/icons/obj/crafts.dmi b/icons/obj/crafts.dmi
index 7f510b84c7e..80c310ea350 100644
Binary files a/icons/obj/crafts.dmi and b/icons/obj/crafts.dmi differ
diff --git a/icons/obj/guns/projectile/modular/bolt.dmi b/icons/obj/guns/projectile/modular/bolt.dmi
new file mode 100644
index 00000000000..bbbfef4d598
Binary files /dev/null and b/icons/obj/guns/projectile/modular/bolt.dmi differ
diff --git a/icons/ui_icons/dmis/uiicons16.dmi b/icons/ui_icons/dmis/uiicons16.dmi
new file mode 100644
index 00000000000..7b5d90ace41
Binary files /dev/null and b/icons/ui_icons/dmis/uiicons16.dmi differ
diff --git a/maps/main_ship/eris_classic.dmm b/maps/main_ship/eris_classic.dmm
index 0f321fdc1e8..f9f6358a91a 100644
--- a/maps/main_ship/eris_classic.dmm
+++ b/maps/main_ship/eris_classic.dmm
@@ -398,7 +398,7 @@
/turf/floor/tiled/techmaint_panels,
/area/eris/maintenance/section1deck5central)
"abm" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section2deck5starboard)
"abn" = (
@@ -1014,7 +1014,7 @@
/turf/floor/tiled/dark,
/area/eris/security/prison)
"acE" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/obj/machinery/camera/network/security{
dir = 8
},
@@ -6302,7 +6302,7 @@
/turf/floor/tiled/steel,
/area/eris/hallway/side/eschangarb)
"apa" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -6865,7 +6865,7 @@
/turf/floor/tiled/dark,
/area/eris/rnd/podbay)
"aqs" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/tiled/dark,
/area/eris/rnd/podbay)
"aqt" = (
@@ -7554,7 +7554,7 @@
/turf/wall/low/with_glass/smart,
/area/eris/hallway/side/section3starboard)
"arR" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/tiled/techmaint,
@@ -10595,7 +10595,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section4deck5port)
"azX" = (
-/obj/machinery/atmospherics/pipe/tank/oxygen{
+/obj/machinery/atmospherics/tank/oxygen{
dir = 4
},
/turf/floor/tiled/steel/brown_platform,
@@ -11043,7 +11043,7 @@
/turf/floor/tiled/steel/cargo,
/area/eris/maintenance/section3deck2starboard)
"aAW" = (
-/obj/machinery/atmospherics/pipe/tank/plasma{
+/obj/machinery/atmospherics/tank/plasma{
dir = 4
},
/turf/floor/tiled/steel/brown_platform,
@@ -14625,7 +14625,7 @@
/turf/floor/tiled/steel,
/area/eris/hallway/side/eschangarb)
"aLw" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/plating/under,
/area/eris/maintenance/section3deck1central)
"aLx" = (
@@ -15834,7 +15834,7 @@
/turf/floor/tiled/steel/bluecorner,
/area/eris/security/prisoncells)
"aPv" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/tiled/dark/gray_platform,
@@ -16436,7 +16436,7 @@
/turf/wall,
/area/eris/maintenance/section4deck5port)
"aQw" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/plating,
@@ -19232,7 +19232,7 @@
/turf/open,
/area/eris/security/prisoncells)
"aXa" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/turf/floor/plating/under,
@@ -19313,7 +19313,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section1deck4central)
"aXm" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/plating/under,
@@ -23081,7 +23081,7 @@
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section2deck4central)
"beN" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/plating/under,
/area/eris/maintenance/section2deck4central)
"beO" = (
@@ -23090,7 +23090,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section2deck4starboard)
"beP" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section3deck1central)
"beQ" = (
@@ -30376,7 +30376,7 @@
/turf/floor/tiled/steel,
/area/eris/hallway/main/section1)
"bwC" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/obj/structure/railing,
@@ -31242,7 +31242,7 @@
/turf/floor/tiled/steel,
/area/eris/hallway/main/section2)
"byA" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/obj/structure/railing,
@@ -33830,7 +33830,7 @@
/turf/floor/plating,
/area/eris/maintenance/section4deck4port)
"bFc" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/obj/structure/railing{
@@ -34134,7 +34134,7 @@
},
/area/eris/command/tcommsat/chamber)
"bFH" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/obj/structure/railing{
@@ -34869,7 +34869,7 @@
/turf/floor/wood,
/area/eris/crew_quarters/hydroponics)
"bHr" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/turf/floor/tiled/steel,
@@ -58029,7 +58029,7 @@
/turf/floor/tiled/steel/techfloor_grid,
/area/eris/engineering/breakroom)
"cNa" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/turf/floor/plating/under,
@@ -58918,13 +58918,13 @@
},
/area/shuttle/mining/station)
"cPO" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/mining{
icon_state = "12,21"
},
/area/shuttle/mining/station)
"cPP" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/mining{
icon_state = "13,21"
},
@@ -61159,7 +61159,7 @@
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section4deck3port)
"cWa" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -74419,7 +74419,7 @@
/turf/floor/plating/under,
/area/eris/medical/medbay)
"dBk" = (
-/obj/machinery/atmospherics/pipe/tank/oxygen{
+/obj/machinery/atmospherics/tank/oxygen{
dir = 8
},
/turf/floor/tiled/white/brown_platform,
@@ -76993,7 +76993,7 @@
/area/eris/maintenance/section4deck2port)
"dHx" = (
/obj/effect/floor_decal/rust,
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -81558,7 +81558,7 @@
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section2deck1starboard)
"dUS" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/tiled/techmaint,
/area/eris/maintenance/section2deck1port)
"dUT" = (
@@ -82964,7 +82964,7 @@
/turf/wall/low/with_glass/reinforced,
/area/eris/quartermaster/office)
"dYk" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/obj/structure/railing{
@@ -88887,7 +88887,7 @@
},
/area/shuttle/research/station)
"enr" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/science{
icon_state = "5,5"
},
@@ -92886,7 +92886,7 @@
/turf/floor/tiled/steel,
/area/eris/hallway/side/section3starboard)
"exh" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/obj/machinery/alarm{
@@ -95710,7 +95710,7 @@
/turf/floor/tiled/white,
/area/eris/rnd/xenobiology/xenoflora)
"eDP" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/obj/structure/sign/atmos_air{
pixel_y = 32
},
@@ -102856,6 +102856,14 @@
},
/turf/floor/plating/under,
/area/eris/maintenance/sorter)
+"qmi" = (
+/obj/item/cell/medium,
+/obj/item/cell/medium,
+/obj/item/computer_hardware/processor_unit,
+/obj/item/computer_hardware/tesla_link,
+/obj/item/computer_hardware/tesla_link,
+/turf/floor/hull,
+/area/space)
"qmJ" = (
/obj/machinery/door/blast/shutters{
dir = 4;
@@ -104952,6 +104960,13 @@
},
/turf/floor/plating/under,
/area/eris/maintenance/section3deck5port)
+"tZv" = (
+/obj/item/computer_hardware/network_card/wired,
+/obj/item/computer_hardware/network_card/wired,
+/obj/item/computer_hardware/scanner/paper,
+/obj/item/computer_hardware/scanner/paper,
+/turf/floor/hull,
+/area/space)
"tZw" = (
/obj/structure/cable/green{
d1 = 4;
@@ -205242,7 +205257,7 @@ iEk
cBO
cwU
abF
-abF
+qmi
abF
cwU
cwU
@@ -205444,7 +205459,7 @@ cBO
cos
cwU
abF
-abF
+tZv
abF
abF
cwU
diff --git a/maps/main_ship/eris_smol.dmm b/maps/main_ship/eris_smol.dmm
index c5cfdf7338e..0ef1e18d883 100644
--- a/maps/main_ship/eris_smol.dmm
+++ b/maps/main_ship/eris_smol.dmm
@@ -1035,7 +1035,7 @@
/turf/floor/tiled/dark/panels,
/area/eris/crew_quarters/firing_range)
"acF" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/turf/floor/plating/under,
@@ -1170,7 +1170,7 @@
/turf/floor/plating/under,
/area/eris/neotheology/bioreactor)
"acV" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/plating/under,
@@ -13403,7 +13403,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section2deck3port)
"aGf" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/plating/under,
@@ -20903,7 +20903,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section2deck3port)
"aYq" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/obj/structure/railing{
@@ -39583,7 +39583,7 @@
/turf/floor/tiled/steel/bar_dance,
/area/eris/command/tcommsat/chamber)
"bQs" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -42835,7 +42835,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section1deck1central)
"bYe" = (
-/obj/machinery/atmospherics/pipe/tank/plasma{
+/obj/machinery/atmospherics/tank/plasma{
dir = 8
},
/turf/floor/tiled/techmaint_cargo,
@@ -44844,7 +44844,7 @@
/turf/floor/tiled/steel,
/area/eris/crew_quarters/fitness)
"cdj" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -50458,7 +50458,7 @@
/turf/floor/tiled/dark/cargo,
/area/eris/crew_quarters/hydroponics)
"crf" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/floor/plating/under,
/area/eris/maintenance/section2deck4port)
"crg" = (
@@ -51700,7 +51700,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/disposal)
"cum" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4;
start_pressure = 740.5
},
@@ -55477,7 +55477,7 @@
/turf/floor/grass,
/area/eris/crew_quarters/hydroponics/garden)
"cDv" = (
-/obj/machinery/atmospherics/pipe/tank/oxygen,
+/obj/machinery/atmospherics/tank/oxygen,
/turf/floor/plating/under,
/area/eris/crew_quarters/sleep/cryo)
"cDw" = (
@@ -58144,13 +58144,13 @@
},
/area/shuttle/mining/station)
"cJE" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/mining{
icon_state = "12,21"
},
/area/shuttle/mining/station)
"cJF" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/mining{
icon_state = "13,21"
},
@@ -58184,7 +58184,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section2deck1starboard)
"cJL" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 1;
initialize_directions = 0
},
@@ -60188,7 +60188,7 @@
},
/area/shuttle/research/station)
"cPi" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/turf/shuttle/floor/science{
icon_state = "5,5"
},
@@ -60767,7 +60767,7 @@
/turf/floor/tiled/steel/gray_platform,
/area/eris/crew_quarters/pubeva)
"cQM" = (
-/obj/machinery/atmospherics/pipe/tank/oxygen{
+/obj/machinery/atmospherics/tank/oxygen{
dir = 4
},
/turf/floor/tiled/steel/brown_perforated,
@@ -61041,7 +61041,7 @@
/turf/floor/plating/under,
/area/eris/storage/tech)
"cRy" = (
-/obj/machinery/atmospherics/pipe/tank/plasma{
+/obj/machinery/atmospherics/tank/plasma{
dir = 4
},
/turf/floor/tiled/steel/brown_perforated,
@@ -63034,7 +63034,7 @@
/turf/floor/tiled/steel/monofloor,
/area/eris/hallway/side/docks)
"cXh" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/obj/structure/railing{
@@ -63082,7 +63082,7 @@
/turf/floor/plating/under,
/area/eris/maintenance/section2deck2port)
"cXl" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4
},
/obj/structure/railing,
@@ -63820,7 +63820,7 @@
/turf/floor/tiled/white/brown_perforated,
/area/eris/medical/medbreak)
"cYR" = (
-/obj/machinery/atmospherics/pipe/tank/oxygen{
+/obj/machinery/atmospherics/tank/oxygen{
dir = 8
},
/obj/structure/railing,
@@ -68339,7 +68339,7 @@
/turf/floor/tiled/steel/brown_perforated,
/area/eris/quartermaster/miningdock)
"djx" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/obj/structure/railing,
/turf/floor/plating/under,
/area/eris/maintenance/section2deck1starboard)
@@ -73992,7 +73992,7 @@
/turf/floor/tiled/steel/cargo,
/area/eris/engineering/foyer)
"dwN" = (
-/obj/machinery/atmospherics/pipe/tank/air,
+/obj/machinery/atmospherics/tank/air,
/obj/machinery/alarm{
pixel_y = 26
},
diff --git a/maps/shuttle/hulk.dmm b/maps/shuttle/hulk.dmm
index b98edd87c54..f5aace8a896 100644
--- a/maps/shuttle/hulk.dmm
+++ b/maps/shuttle/hulk.dmm
@@ -117,7 +117,7 @@
"sL" = (/turf/shuttle/wall/mining{icon_state = "1,19"},/area/space)
"te" = (/obj/structure/shuttle_part/mining{icon_state = "5,1"},/turf/space,/area/space)
"tf" = (/obj/machinery/atmospherics/unary/vent_pump/on{dir = 8},/turf/shuttle/floor/mining{icon_state = "10,14"},/area/space)
-"tC" = (/obj/machinery/atmospherics/pipe/tank/air,/turf/shuttle/floor/mining{icon_state = "12,21"},/area/space)
+"tC" = (/obj/machinery/atmospherics/tank/air,/turf/shuttle/floor/mining{icon_state = "12,21"},/area/space)
"tW" = (/turf/shuttle/wall/mining{icon_state = "15,6"; opacity = 0},/area/space)
"tZ" = (/obj/structure/table/standard,/obj/item/device/lighting/toggleable/lamp,/turf/shuttle/floor/mining{icon_state = "5,16"},/area/space)
"ud" = (/obj/structure/shuttle_part/mining{icon_state = "10,0"},/turf/template_noop,/area/space)
@@ -369,7 +369,7 @@
"Yf" = (/obj/structure/shuttle_part/mining{icon_state = "12,0"},/turf/template_noop,/area/space)
"Yg" = (/obj/structure/shuttle_part/mining{icon_state = "3,14"},/turf/space,/area/space)
"Yk" = (/turf/shuttle/wall/mining{icon_state = "7,18"},/area/space)
-"Yq" = (/obj/machinery/atmospherics/pipe/tank/air,/turf/shuttle/floor/mining{icon_state = "13,21"},/area/space)
+"Yq" = (/obj/machinery/atmospherics/tank/air,/turf/shuttle/floor/mining{icon_state = "13,21"},/area/space)
"Yu" = (/turf/shuttle/wall/mining{icon_state = "11,22"},/area/space)
"YK" = (/turf/shuttle/floor/mining{icon_state = "12,13"},/area/space)
"YN" = (/obj/structure/cable/yellow{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/light/small,/turf/shuttle/floor/mining{icon_state = "4,4"},/area/space)
diff --git a/maps/shuttle/nerd.dmm b/maps/shuttle/nerd.dmm
index 5e12ce90452..f9fa15dcf67 100644
--- a/maps/shuttle/nerd.dmm
+++ b/maps/shuttle/nerd.dmm
@@ -10,7 +10,7 @@
"bz" = (/turf/shuttle/wall/science{icon_state = "10,13"},/area/space)
"bI" = (/obj/structure/shuttle_part/science{icon_state = "11,0"},/turf/template_noop,/area/space)
"bK" = (/obj/machinery/light/small{dir = 1},/turf/shuttle/floor/science{icon_state = "10,12"},/area/space)
-"cl" = (/obj/machinery/atmospherics/pipe/tank/air,/turf/shuttle/floor/science{icon_state = "5,5"},/area/space)
+"cl" = (/obj/machinery/atmospherics/tank/air,/turf/shuttle/floor/science{icon_state = "5,5"},/area/space)
"co" = (/turf/shuttle/wall/science{icon_state = "8,0"},/area/space)
"cI" = (/obj/structure/table/standard,/obj/machinery/camera/network/research_outpost{dir = 1},/obj/machinery/recharger,/turf/shuttle/floor/science{icon_state = "7,17"},/area/space)
"cM" = (/obj/machinery/atmospherics/pipe/simple/hidden/universal,/turf/shuttle/floor/science{icon_state = "5,4"},/area/space)
diff --git a/maps/submaps/centcomm.dmm b/maps/submaps/centcomm.dmm
index 40c1ed3fbd0..a4adab0ae35 100644
--- a/maps/submaps/centcomm.dmm
+++ b/maps/submaps/centcomm.dmm
@@ -2983,7 +2983,7 @@
/turf/space,
/area/space)
"oz" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 4;
start_pressure = 740.5
},
diff --git a/maps/submaps/pulsar.dmm b/maps/submaps/pulsar.dmm
index 3a8846416dc..9afa0f086a7 100644
--- a/maps/submaps/pulsar.dmm
+++ b/maps/submaps/pulsar.dmm
@@ -1141,7 +1141,7 @@
/turf/floor/plating/under,
/area/outpost/pulsar/maintenance)
"LT" = (
-/obj/machinery/atmospherics/pipe/tank/air{
+/obj/machinery/atmospherics/tank/air{
dir = 8
},
/turf/floor/tiled/steel/brown_platform,
diff --git a/nano/templates/crew_records.tmpl b/nano/templates/crew_records.tmpl
index 543879ebe0d..009496403e1 100644
--- a/nano/templates/crew_records.tmpl
+++ b/nano/templates/crew_records.tmpl
@@ -28,6 +28,27 @@
{{if value.needs_big_box}}
{{:value.value}}
+ {{else}}
+ {{if value.list_value}}
+ {{for value.list_value}}
+ {{:value}}
+ {{/for}}
+ {{else}}
+ {{if value.list_clumps}}
+ {{for value.list_clumps}}
+ {{for value}}
+ {{:value}}
+ {{/for}}
+ {{/for}}
+ {{else}}
+ {{if value.links}}
+ {{for 1 to value.links.len}}
+ {{for value.links}}
+
+ {{/if}}
+ {{/if}}
+ {{/if}}
+ {{/if}}
{{else}}
{{:value.value}}
diff --git a/nano/templates/pai_medrecords.tmpl b/nano/templates/pai_medrecords.tmpl
index 37b1d7061ca..b45d66cd2c9 100644
--- a/nano/templates/pai_medrecords.tmpl
+++ b/nano/templates/pai_medrecords.tmpl
@@ -15,10 +15,6 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Name
{{:data.general.name}}
-
-
Record ID
-
{{:data.general.id}}
-
Sex
{{:data.general.sex}}
@@ -32,50 +28,52 @@ code/modules/mob/living/silicon/pai/software_modules.dm
{{:data.general.age}}
-
Rank
-
{{:data.general.rank}}
+
Job Title
+
{{:data.general.job}}
Fingerprint
{{:data.general.fingerprint}}
-
Physical Status
-
{{:data.general.p_stat}}
+
=Status
+
{{:data.general.status}}
-
Mental Status
-
{{:data.general.m_stat}}
+
Blood Type
+
{{:data.general.bloodtype}}
{{/if}}
{{if data.medical}}
-
Blood Type
-
{{:data.medical.b_type}}
-
-
-
Minor Disabilities
-
{{:data.medical.mi_dis}}
-
{{:data.medical.mi_dis_d}}
+
Prosthetics
+ {{for data.medical.value.prosthetics}}
+
{{:value}}
+ {{/for}}
-
Major Disabilities
-
{{:data.medical.ma_dis}}
-
{{:data.medical.ma_dis_d}}
+
Wounds
+ {{for data.medical.value.wounds}}
+
{{:value}}
+ {{/for}}
-
Allergies
-
{{:data.medical.alg}}
-
{{:data.medical.alg_d}}
+
Body State
+ {{for data.medical.value.body state}}
+
{{:value}}
+ {{/for}}
-
Current Diseases
-
{{:data.medical.cdi}}
-
{{:data.medical.cdi_d}}
+
Chemical History
+ {{for data.medical.value.chemhistory}}
+
{{:value}}
+ {{/for}}
-
Important Notes
-
{{:data.medical.notes}}
+
Psychological Profile
+ {{for data.medical.value.psychological}}
+
{{:value}}
+ {{/for}}
{{/if}}
diff --git a/nano/templates/pai_secrecords.tmpl b/nano/templates/pai_secrecords.tmpl
index e139034c0de..cdb3321a07c 100644
--- a/nano/templates/pai_secrecords.tmpl
+++ b/nano/templates/pai_secrecords.tmpl
@@ -15,10 +15,6 @@ code/modules/mob/living/silicon/pai/software_modules.dm
Name
{{:data.general.name}}
-
-
Record ID
-
{{:data.general.id}}
-
Sex
{{:data.general.sex}}
@@ -32,40 +28,24 @@ code/modules/mob/living/silicon/pai/software_modules.dm
{{:data.general.age}}
-
Rank
-
{{:data.general.rank}}
+
Job Title
+
{{:data.general.job}}
Fingerprint
{{:data.general.fingerprint}}
-
Physical Status
-
{{:data.general.p_stat}}
+
Status
+
{{:data.general.status}}
-
-
Mental Status
-
{{:data.general.m_stat}}
-
-{{/if}}
-{{if data.security}}
Criminal Status
-
{{:data.security.criminal}}
-
-
-
Minor Crimes
-
{{:data.security.mi_crim}}
-
{{:data.security.mi_crim_d}}
-
-
-
Major Crimes
-
{{:data.security.ma_crim}}
-
{{:data.security.ma_crim_d}}
-
+ {{:data.general.criminalStatus }}
+
Important Notes
-
{{:data.security.notes}}
+
{{:data.general.secNotes}}
{{/if}}
diff --git a/tgui/packages/tgui/interfaces/Computer.tsx b/tgui/packages/tgui/interfaces/Computer.tsx
new file mode 100644
index 00000000000..cd4fa1f534f
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/Computer.tsx
@@ -0,0 +1,169 @@
+import { BooleanLike } from 'common/react';
+import { Button, Box, Table } from '../components';
+import { TableCell, TableRow } from '../components/Table';
+import { sendAct } from '../backend';
+
+export interface ComputerInterface {
+ PC_batteryicon: string;
+ PC_batterypercent: string;
+ PC_showbatteryicon: BooleanLike;
+ PC_light_name: string;
+ PC_light_on: BooleanLike;
+ PC_apclinkicon: string;
+ PC_ntneticon: string;
+ has_gps: BooleanLike;
+ gps_icon: string;
+ gps_data: string;
+ PC_programheaders: Programheader[];
+ PC_stationtime: string;
+ PC_hasheader: BooleanLike;
+ PC_showexitprogram: BooleanLike;
+ mapZLevels: number[];
+ mapZLevel: number;
+}
+
+type Programheader = {
+ icon: string;
+};
+
+export const ProgramShell = (props, context) => {
+ const {
+ PC_batteryicon,
+ PC_batterypercent,
+ PC_showbatteryicon,
+ PC_light_name,
+ PC_light_on,
+ PC_apclinkicon,
+ PC_ntneticon,
+ has_gps,
+ gps_icon,
+ gps_data,
+ PC_programheaders,
+ PC_stationtime,
+ PC_hasheader,
+ PC_showexitprogram,
+ mapZLevels,
+ mapZLevel,
+ } = props;
+ const act = sendAct;
+ return (
+ <>
+
+
+
+
+ {PC_showexitprogram && (
+
+
+
+
+ act('PC_exit')}
+ />
+
+
+ act('PC_minimize')}
+ />
+
+
+
+
+ )}
+ {PC_showexitprogram || }
+
+
+ Initiating...
+
+ >
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/CrewRecords.tsx b/tgui/packages/tgui/interfaces/CrewRecords.tsx
new file mode 100644
index 00000000000..3cb3f0bc944
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/CrewRecords.tsx
@@ -0,0 +1,332 @@
+import { BooleanLike } from 'common/react';
+import { useBackend, sendAct } from '../backend';
+import { Button, Box, Divider, Table } from '../components';
+import { GameIcon } from '../components/GameIcon';
+import { Window } from '../layouts';
+import { ComputerInterface, ProgramShell } from './Computer';
+import { classes } from 'common/react';
+
+interface CrewRecordsInterface extends RecordConcrete, ComputerInterface {
+ message: string;
+ front_pic: string;
+ side_pic: string;
+ pic_edit: BooleanLike;
+ all_records: RecordAbstract[];
+ creation: BooleanLike;
+ dnasearch: BooleanLike;
+ fingersearch: BooleanLike;
+}
+
+interface RecordConcrete {
+ name: string;
+ uid: number;
+ creator: string;
+ filetime: string;
+ fields: RecordField[];
+ access: BooleanLike;
+ access_edit: BooleanLike;
+}
+type RecordField = {
+ access: BooleanLike;
+ access_edit: BooleanLike;
+ name: string;
+ value: string | number | object;
+ list_value: any[];
+ list_clumps: object[];
+ can_edit: BooleanLike;
+ needs_big_box: BooleanLike;
+ ignore_value: BooleanLike;
+ ID: number;
+};
+
+type RecordAbstract = {
+ name: string;
+ rank: string;
+ id: number;
+};
+
+export const CrewRecords = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ message,
+ uid,
+ fields,
+ front_pic,
+ side_pic,
+ pic_edit,
+ all_records,
+ creation,
+ dnasearch,
+ fingersearch,
+ } = data;
+ return (
+
+
+ {ProgramShell(props, context)}
+ {message && act('clear_message')} />}
+ {message}
+
+ {uid &&
+ currentrecord(
+ { uid, fields, front_pic, side_pic, pic_edit },
+ context,
+ )}
+ {Boolean(uid) || (
+ <>
+ {Boolean(creation) && (
+ <>
+
+ act('new_record')}
+ />
+ >
+ )}
+ <>
+
+ act('search', { search: 'Name' })}
+ />
+ >
+ {Boolean(dnasearch) && (
+ <>
+
+ act('search', { search: 'DNA' })}
+ />
+ >
+ )}
+ {Boolean(fingersearch) && (
+ <>
+
+ act('search', { search: 'Fingerprint' })}
+ />
+ >
+ )}
+
+
+ Available records:
+
+
+
+ NamePosition
+
+
+ {all_records.map((mapped) => {
+ return (
+ <>
+
+
+
+ act('set_active', { set_active: mapped.id })
+ }
+ />
+
+
+ {mapped.rank}
+ >
+ );
+ })}
+
+ >
+ )}
+
+
+ );
+};
+
+const currentrecord = (props, context) => {
+ const act = sendAct;
+ const { uid, fields, front_pic, side_pic, pic_edit } = props;
+ return (
+ <>
+ act('clear_active')} />
+ act('print_active')} />
+
+
+ GENERIC INFORMATION
+
+
+
+
+
+
+ {Boolean(pic_edit) && (
+
+
+
+ act('edit_photo_front')}
+ />
+
+ act('edit_photo_side')} />
+
+ )}
+ {fields &&
+ fields.map((mapped) => {
+ return displayfield(mapped, context);
+ })}
+ >
+ );
+};
+const displayfield = (props, context) => {
+ const act = sendAct;
+ const {
+ access,
+ access_edit,
+ name,
+ value,
+ list_value,
+ list_clumps,
+ can_edit,
+ needs_big_box,
+ ignore_value,
+ ID,
+ } = props;
+ return (
+ <>
+ {access && access_edit && (
+
+
+ act('edit_field', { edit_field: ID })}
+ />
+
+ )}
+ {access && (Boolean(access_edit) || name)}
+ {access && (
+
+ {value}
+ {list_value &&
+ (Object.values(list_value).length
+ ? list_value.join(', ')
+ : 'Unset')}
+ {list_clumps &&
+ (Object.keys(list_clumps)
+ ? Object.keys(list_clumps).map((mapped, count) => {
+ return (
+ <>
+ {mapped}
+ {': '}
+ {returnlist(
+ { origin: list_clumps, whichlist: count },
+ context,
+ )}
+
+ >
+ );
+ })
+ : 'Unset')}
+
+ )}
+ >
+ );
+};
+
+const returnlist = (props, context) => {
+ const { origin, whichlist } = props;
+ let toreturn: any;
+ if (
+ Object.values(origin) &&
+ typeof Object.values(origin)[whichlist] !== 'undefined' &&
+ Array.isArray(Object.values(origin)[whichlist])
+ ) {
+ let unfoldthis1: any = Object.values(origin)[whichlist];
+ let unfoldthis2: any[] = unfoldthis1;
+ toreturn = unfoldthis2.toString();
+ } else toreturn = 'Sadness';
+ return toreturn;
+};
+
+/**/
+/*
+{{if data.message}}
+{{:helper.link('X', null, {'clear_message' : 1})}}{{:data.message}}
+{{/if}}
+{{if data.uid}}
+{{:helper.link('BACK', '', {'clear_active' : 1})}}{{:helper.link('PRINT', '', {'print_active' : 1})}}
+
+
+
GENERIC INFORMATION
+
+
+
+
+
+ {{if data.pic_edit}}
+
+
 
+
{{:helper.link('Edit Front', 'pencil', {'edit_photo_front' : 1}, null)}}{{:helper.link('Edit Side', 'pencil', {'edit_photo_side' : 1}, null)}}
+
+ {{/if}}
+ {{for data.fields}}
+ {{if value.access}}
+
+ {{if value.access_edit}}
+
{{:helper.link(value.name, 'pencil', {'edit_field' : value.ID}, null)}}
+ {{else}}
+
{{:value.name}}:
+ {{/if}}
+ {{if value.needs_big_box}}
+
+ {{if value.value}}
+ {{:value.value}}
+ {{else}}
+ {{if value.list_value}}
+ {{for value.list_value}}
+ {{:value}}
+ {{/for}}
+ {{else}}
+ {{if value.list_clumps}}
+ {{for value.list_clumps}}
+ {{for value}}
+ {{:value}}
+ {{/for}}
+ {{/for}}
+ {{else}}
+ {{if value.links}}
+ {{for 1 to value.links.len}}
+ {{for value.links}}
+
+ {{/if}}
+ {{/if}}
+ {{/if}}
+ {{/if}}
+
+ {{else}}
+
{{:value.value}}
+ {{/if}}
+
+ {{/if}}
+ {{/for}}
+
+{{else}}
+{{if data.creation}}
+ {{:helper.link('New Record', 'document', {'new_record' : 1}, null)}}
+{{/if}}
+{{:helper.link('Name Search', 'search', {'search' : 'Name'}, null)}}
+{{if data.dnasearch}}
+ {{:helper.link('DNA Search', 'search', {'search' : 'DNA'}, null)}}
+{{/if}}
+{{if data.fingersearch}}
+ {{:helper.link('Fingerprint Search', 'search', {'search' : 'Fingerprint'}, null)}}
+{{/if}}
+
+Available records:
+
+Name Position
+{{for data.all_records}}
+ {{:helper.link(value.name, '', {'set_active' : value.id})}}
+ {{:value.rank}}
+{{/for}}
+
+{{/if}}
+*/
diff --git a/tgui/public/tgui.bundle.js b/tgui/public/tgui.bundle.js
index e083ff52000..ab10866babe 100644
--- a/tgui/public/tgui.bundle.js
+++ b/tgui/public/tgui.bundle.js
@@ -1 +1 @@
-!function(){var e={52078:function(e,t,n){"use strict";t.__esModule=!0,t.popperGenerator=f,t.createPopper=void 0;var o=p(n(21743)),r=p(n(90389)),a=p(n(62931)),i=p(n(84704)),c=(p(n(37601)),p(n(40032))),l=p(n(67213)),d=(p(n(30948)),p(n(66125)),p(n(17048)),p(n(27491))),s=p(n(16550));t.detectOverflow=s["default"];var u=n(89075);n(28558);function p(e){return e&&e.__esModule?e:{"default":e}}var m={placement:"bottom",modifiers:[],strategy:"absolute"};function h(){for(var e=arguments.length,t=new Array(e),n=0;n=0&&(0,s.isHTMLElement)(e)?(0,c["default"])(e):e;if(!(0,s.isElement)(n))return[];return t.filter((function(e){return(0,s.isElement)(e)&&(0,m["default"])(e,n)&&"body"!==(0,h["default"])(e)}))}(e):[].concat(t),r=[].concat(o,[n]),a=r[0],l=r.reduce((function(t,n){var o=N(e,n);return t.top=(0,C.max)(o.top,t.top),t.right=(0,C.min)(o.right,t.right),t.bottom=(0,C.min)(o.bottom,t.bottom),t.left=(0,C.max)(o.left,t.left),t}),N(e,a));return l.width=l.right-l.left,l.height=l.bottom-l.top,l.x=l.left,l.y=l.top,l};var o=n(28558),r=g(n(94947)),a=g(n(18059)),i=g(n(62931)),c=g(n(84704)),l=g(n(43730)),d=g(n(37601)),s=n(89075),u=g(n(57462)),p=g(n(57298)),m=g(n(46372)),h=g(n(37623)),f=g(n(52726)),C=n(4179);function g(e){return e&&e.__esModule?e:{"default":e}}function N(e,t){return t===o.viewport?(0,f["default"])((0,r["default"])(e)):(0,s.isHTMLElement)(t)?function(e){var t=(0,u["default"])(e);return t.top=t.top+e.clientTop,t.left=t.left+e.clientLeft,t.bottom=t.top+e.clientHeight,t.right=t.left+e.clientWidth,t.width=e.clientWidth,t.height=e.clientHeight,t.x=t.left,t.y=t.top,t}(t):(0,f["default"])((0,a["default"])((0,l["default"])(e)))}},21743:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t,n){void 0===n&&(n=!1);var s=(0,i.isHTMLElement)(t),u=(0,i.isHTMLElement)(t)&&function(e){var t=e.getBoundingClientRect(),n=t.width/e.offsetWidth||1,o=t.height/e.offsetHeight||1;return 1!==n||1!==o}(t),p=(0,l["default"])(t),m=(0,o["default"])(e,u),h={scrollLeft:0,scrollTop:0},f={x:0,y:0};(s||!s&&!n)&&(("body"!==(0,a["default"])(t)||(0,d["default"])(p))&&(h=(0,r["default"])(t)),(0,i.isHTMLElement)(t)?((f=(0,o["default"])(t,!0)).x+=t.clientLeft,f.y+=t.clientTop):p&&(f.x=(0,c["default"])(p)));return{x:m.left+h.scrollLeft-f.x,y:m.top+h.scrollTop-f.y,width:m.width,height:m.height}};var o=s(n(57462)),r=s(n(31781)),a=s(n(37623)),i=n(89075),c=s(n(97240)),l=s(n(43730)),d=s(n(73918));function s(e){return e&&e.__esModule?e:{"default":e}}},37601:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(0,r["default"])(e).getComputedStyle(e)};var o,r=(o=n(81104))&&o.__esModule?o:{"default":o}},43730:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(((0,o.isElement)(e)?e.ownerDocument:e.document)||window.document).documentElement};var o=n(89075)},18059:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t,n=(0,o["default"])(e),l=(0,i["default"])(e),d=null==(t=e.ownerDocument)?void 0:t.body,s=(0,c.max)(n.scrollWidth,n.clientWidth,d?d.scrollWidth:0,d?d.clientWidth:0),u=(0,c.max)(n.scrollHeight,n.clientHeight,d?d.scrollHeight:0,d?d.clientHeight:0),p=-l.scrollLeft+(0,a["default"])(e),m=-l.scrollTop;"rtl"===(0,r["default"])(d||n).direction&&(p+=(0,c.max)(n.clientWidth,d?d.clientWidth:0)-s);return{width:s,height:u,x:p,y:m}};var o=l(n(43730)),r=l(n(37601)),a=l(n(97240)),i=l(n(37365)),c=n(4179);function l(e){return e&&e.__esModule?e:{"default":e}}},20041:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}}},90389:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,r["default"])(e),n=e.offsetWidth,o=e.offsetHeight;Math.abs(t.width-n)<=1&&(n=t.width);Math.abs(t.height-o)<=1&&(o=t.height);return{x:e.offsetLeft,y:e.offsetTop,width:n,height:o}};var o,r=(o=n(57462))&&o.__esModule?o:{"default":o}},37623:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e?(e.nodeName||"").toLowerCase():null}},31781:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return e!==(0,r["default"])(e)&&(0,a.isHTMLElement)(e)?(0,i["default"])(e):(0,o["default"])(e)};var o=c(n(37365)),r=c(n(81104)),a=n(89075),i=c(n(20041));function c(e){return e&&e.__esModule?e:{"default":e}}},84704:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,o["default"])(e),n=s(e);for(;n&&(0,c["default"])(n)&&"static"===(0,a["default"])(n).position;)n=s(n);if(n&&("html"===(0,r["default"])(n)||"body"===(0,r["default"])(n)&&"static"===(0,a["default"])(n).position))return t;return n||function(e){var t=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&(0,i.isHTMLElement)(e)){if("fixed"===(0,a["default"])(e).position)return null}var n=(0,l["default"])(e);for(;(0,i.isHTMLElement)(n)&&["html","body"].indexOf((0,r["default"])(n))<0;){var o=(0,a["default"])(n);if("none"!==o.transform||"none"!==o.perspective||"paint"===o.contain||-1!==["transform","perspective"].indexOf(o.willChange)||t&&"filter"===o.willChange||t&&o.filter&&"none"!==o.filter)return n;n=n.parentNode}return null}(e)||t};var o=d(n(81104)),r=d(n(37623)),a=d(n(37601)),i=n(89075),c=d(n(79449)),l=d(n(57298));function d(e){return e&&e.__esModule?e:{"default":e}}function s(e){return(0,i.isHTMLElement)(e)&&"fixed"!==(0,a["default"])(e).position?e.offsetParent:null}},57298:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){if("html"===(0,o["default"])(e))return e;return e.assignedSlot||e.parentNode||((0,a.isShadowRoot)(e)?e.host:null)||(0,r["default"])(e)};var o=i(n(37623)),r=i(n(43730)),a=n(89075);function i(e){return e&&e.__esModule?e:{"default":e}}},22460:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function l(e){if(["html","body","#document"].indexOf((0,a["default"])(e))>=0)return e.ownerDocument.body;if((0,i.isHTMLElement)(e)&&(0,r["default"])(e))return e;return l((0,o["default"])(e))};var o=c(n(57298)),r=c(n(73918)),a=c(n(37623)),i=n(89075);function c(e){return e&&e.__esModule?e:{"default":e}}},94947:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,o["default"])(e),n=(0,r["default"])(e),i=t.visualViewport,c=n.clientWidth,l=n.clientHeight,d=0,s=0;i&&(c=i.width,l=i.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(d=i.offsetLeft,s=i.offsetTop));return{width:c,height:l,x:d+(0,a["default"])(e),y:s}};var o=i(n(81104)),r=i(n(43730)),a=i(n(97240));function i(e){return e&&e.__esModule?e:{"default":e}}},81104:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){if(null==e)return window;if("[object Window]"!==e.toString()){var t=e.ownerDocument;return t&&t.defaultView||window}return e}},37365:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,r["default"])(e),n=t.pageXOffset,o=t.pageYOffset;return{scrollLeft:n,scrollTop:o}};var o,r=(o=n(81104))&&o.__esModule?o:{"default":o}},97240:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return(0,o["default"])((0,r["default"])(e)).left+(0,a["default"])(e).scrollLeft};var o=i(n(57462)),r=i(n(43730)),a=i(n(37365));function i(e){return e&&e.__esModule?e:{"default":e}}},89075:function(e,t,n){"use strict";t.__esModule=!0,t.isElement=function(e){var t=(0,r["default"])(e).Element;return e instanceof t||e instanceof Element},t.isHTMLElement=function(e){var t=(0,r["default"])(e).HTMLElement;return e instanceof t||e instanceof HTMLElement},t.isShadowRoot=function(e){if("undefined"==typeof ShadowRoot)return!1;var t=(0,r["default"])(e).ShadowRoot;return e instanceof t||e instanceof ShadowRoot};var o,r=(o=n(81104))&&o.__esModule?o:{"default":o}},73918:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=(0,r["default"])(e),n=t.overflow,o=t.overflowX,a=t.overflowY;return/auto|scroll|overlay|hidden/.test(n+a+o)};var o,r=(o=n(37601))&&o.__esModule?o:{"default":o}},79449:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return["table","td","th"].indexOf((0,r["default"])(e))>=0};var o,r=(o=n(37623))&&o.__esModule?o:{"default":o}},62931:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function l(e,t){var n;void 0===t&&(t=[]);var c=(0,o["default"])(e),d=c===(null==(n=e.ownerDocument)?void 0:n.body),s=(0,a["default"])(c),u=d?[s].concat(s.visualViewport||[],(0,i["default"])(c)?c:[]):c,p=t.concat(u);return d?p:p.concat(l((0,r["default"])(u)))};var o=c(n(22460)),r=c(n(57298)),a=c(n(81104)),i=c(n(73918));function c(e){return e&&e.__esModule?e:{"default":e}}},28558:function(e,t){"use strict";t.__esModule=!0,t.modifierPhases=t.afterWrite=t.write=t.beforeWrite=t.afterMain=t.main=t.beforeMain=t.afterRead=t.read=t.beforeRead=t.placements=t.variationPlacements=t.reference=t.popper=t.viewport=t.clippingParents=t.end=t.start=t.basePlacements=t.auto=t.left=t.right=t.bottom=t.top=void 0;t.top="top";var n="bottom";t.bottom=n;var o="right";t.right=o;var r="left";t.left=r;var a="auto";t.auto=a;var i=["top",n,o,r];t.basePlacements=i;var c="start";t.start=c;var l="end";t.end=l;t.clippingParents="clippingParents";t.viewport="viewport";t.popper="popper";t.reference="reference";var d=i.reduce((function(e,t){return e.concat([t+"-"+c,t+"-"+l])}),[]);t.variationPlacements=d;var s=[].concat(i,[a]).reduce((function(e,t){return e.concat([t,t+"-"+c,t+"-"+l])}),[]);t.placements=s;var u="beforeRead";t.beforeRead=u;var p="read";t.read=p;var m="afterRead";t.afterRead=m;var h="beforeMain";t.beforeMain=h;var f="main";t.main=f;var C="afterMain";t.afterMain=C;var g="beforeWrite";t.beforeWrite=g;var N="write";t.write=N;var b="afterWrite";t.afterWrite=b;var V=[u,p,m,h,f,C,g,N,b];t.modifierPhases=V},67326:function(e,t,n){"use strict";t.__esModule=!0;var o={popperGenerator:!0,detectOverflow:!0,createPopperBase:!0,createPopper:!0,createPopperLite:!0};t.createPopperLite=t.createPopper=t.createPopperBase=t.detectOverflow=t.popperGenerator=void 0;var r=n(28558);Object.keys(r).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(o,e)||e in t&&t[e]===r[e]||(t[e]=r[e]))}));var a=n(70810);Object.keys(a).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(o,e)||e in t&&t[e]===a[e]||(t[e]=a[e]))}));var i=n(52078);t.popperGenerator=i.popperGenerator,t.detectOverflow=i.detectOverflow,t.createPopperBase=i.createPopper;var c=n(50081);t.createPopper=c.createPopper;var l=n(54488);t.createPopperLite=l.createPopper},68503:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o,r=(o=n(37623))&&o.__esModule?o:{"default":o},a=n(89075);var i={name:"applyStyles",enabled:!0,phase:"write",fn:function(e){var t=e.state;Object.keys(t.elements).forEach((function(e){var n=t.styles[e]||{},o=t.attributes[e]||{},i=t.elements[e];(0,a.isHTMLElement)(i)&&(0,r["default"])(i)&&(Object.assign(i.style,n),Object.keys(o).forEach((function(e){var t=o[e];!1===t?i.removeAttribute(e):i.setAttribute(e,!0===t?"":t)})))}))},effect:function(e){var t=e.state,n={popper:{position:t.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(t.elements.popper.style,n.popper),t.styles=n,t.elements.arrow&&Object.assign(t.elements.arrow.style,n.arrow),function(){Object.keys(t.elements).forEach((function(e){var o=t.elements[e],i=t.attributes[e]||{},c=Object.keys(t.styles.hasOwnProperty(e)?t.styles[e]:n[e]).reduce((function(e,t){return e[t]="",e}),{});(0,a.isHTMLElement)(o)&&(0,r["default"])(o)&&(Object.assign(o.style,c),Object.keys(i).forEach((function(e){o.removeAttribute(e)})))}))}},requires:["computeStyles"]};t["default"]=i},44145:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o=p(n(17048)),r=p(n(90389)),a=p(n(46372)),i=p(n(84704)),c=p(n(84656)),l=p(n(18203)),d=p(n(30281)),s=p(n(97341)),u=n(28558);n(89075);function p(e){return e&&e.__esModule?e:{"default":e}}var m=function(e,t){return e="function"==typeof e?e(Object.assign({},t.rects,{placement:t.placement})):e,(0,d["default"])("number"!=typeof e?e:(0,s["default"])(e,u.basePlacements))};var h={name:"arrow",enabled:!0,phase:"main",fn:function(e){var t,n=e.state,a=e.name,d=e.options,s=n.elements.arrow,p=n.modifiersData.popperOffsets,h=(0,o["default"])(n.placement),f=(0,c["default"])(h),C=[u.left,u.right].indexOf(h)>=0?"height":"width";if(s&&p){var g=m(d.padding,n),N=(0,r["default"])(s),b="y"===f?u.top:u.left,V="y"===f?u.bottom:u.right,v=n.rects.reference[C]+n.rects.reference[f]-p[f]-n.rects.popper[C],k=p[f]-n.rects.reference[f],y=(0,i["default"])(s),_=y?"y"===f?y.clientHeight||0:y.clientWidth||0:0,S=v/2-k/2,w=g[b],x=_-N[C]-g[V],I=_/2-N[C]/2+S,B=(0,l["default"])(w,I,x),L=f;n.modifiersData[a]=((t={})[L]=B,t.centerOffset=B-I,t)}},effect:function(e){var t=e.state,n=e.options.element,o=void 0===n?"[data-popper-arrow]":n;null!=o&&("string"!=typeof o||(o=t.elements.popper.querySelector(o)))&&(0,a["default"])(t.elements.popper,o)&&(t.elements.arrow=o)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};t["default"]=h},84288:function(e,t,n){"use strict";t.__esModule=!0,t.mapToStyles=p,t["default"]=void 0;var o=n(28558),r=s(n(84704)),a=s(n(81104)),i=s(n(43730)),c=s(n(37601)),l=s(n(17048)),d=n(4179);function s(e){return e&&e.__esModule?e:{"default":e}}var u={top:"auto",right:"auto",bottom:"auto",left:"auto"};function p(e){var t,n=e.popper,l=e.popperRect,s=e.placement,p=e.offsets,m=e.position,h=e.gpuAcceleration,f=e.adaptive,C=e.roundOffsets,g=!0===C?function(e){var t=e.x,n=e.y,o=window.devicePixelRatio||1;return{x:(0,d.round)((0,d.round)(t*o)/o)||0,y:(0,d.round)((0,d.round)(n*o)/o)||0}}(p):"function"==typeof C?C(p):p,N=g.x,b=void 0===N?0:N,V=g.y,v=void 0===V?0:V,k=p.hasOwnProperty("x"),y=p.hasOwnProperty("y"),_=o.left,S=o.top,w=window;if(f){var x=(0,r["default"])(n),I="clientHeight",B="clientWidth";x===(0,a["default"])(n)&&(x=(0,i["default"])(n),"static"!==(0,c["default"])(x).position&&(I="scrollHeight",B="scrollWidth")),x=x,s===o.top&&(S=o.bottom,v-=x[I]-l.height,v*=h?1:-1),s===o.left&&(_=o.right,b-=x[B]-l.width,b*=h?1:-1)}var L,A=Object.assign({position:m},f&&u);return h?Object.assign({},A,((L={})[S]=y?"0":"",L[_]=k?"0":"",L.transform=(w.devicePixelRatio||1)<2?"translate("+b+"px, "+v+"px)":"translate3d("+b+"px, "+v+"px, 0)",L)):Object.assign({},A,((t={})[S]=y?v+"px":"",t[_]=k?b+"px":"",t.transform="",t))}var m={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(e){var t=e.state,n=e.options,o=n.gpuAcceleration,r=void 0===o||o,a=n.adaptive,i=void 0===a||a,c=n.roundOffsets,d=void 0===c||c,s={placement:(0,l["default"])(t.placement),popper:t.elements.popper,popperRect:t.rects.popper,gpuAcceleration:r};null!=t.modifiersData.popperOffsets&&(t.styles.popper=Object.assign({},t.styles.popper,p(Object.assign({},s,{offsets:t.modifiersData.popperOffsets,position:t.options.strategy,adaptive:i,roundOffsets:d})))),null!=t.modifiersData.arrow&&(t.styles.arrow=Object.assign({},t.styles.arrow,p(Object.assign({},s,{offsets:t.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:d})))),t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-placement":t.placement})},data:{}};t["default"]=m},8646:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o,r=(o=n(81104))&&o.__esModule?o:{"default":o};var a={passive:!0};var i={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(e){var t=e.state,n=e.instance,o=e.options,i=o.scroll,c=void 0===i||i,l=o.resize,d=void 0===l||l,s=(0,r["default"])(t.elements.popper),u=[].concat(t.scrollParents.reference,t.scrollParents.popper);return c&&u.forEach((function(e){e.addEventListener("scroll",n.update,a)})),d&&s.addEventListener("resize",n.update,a),function(){c&&u.forEach((function(e){e.removeEventListener("scroll",n.update,a)})),d&&s.removeEventListener("resize",n.update,a)}},data:{}};t["default"]=i},81628:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o=s(n(8095)),r=s(n(17048)),a=s(n(1637)),i=s(n(16550)),c=s(n(87825)),l=n(28558),d=s(n(95817));function s(e){return e&&e.__esModule?e:{"default":e}}var u={name:"flip",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,s=e.name;if(!t.modifiersData[s]._skip){for(var u=n.mainAxis,p=void 0===u||u,m=n.altAxis,h=void 0===m||m,f=n.fallbackPlacements,C=n.padding,g=n.boundary,N=n.rootBoundary,b=n.altBoundary,V=n.flipVariations,v=void 0===V||V,k=n.allowedAutoPlacements,y=t.options.placement,_=(0,r["default"])(y),S=f||(_===y||!v?[(0,o["default"])(y)]:function(e){if((0,r["default"])(e)===l.auto)return[];var t=(0,o["default"])(e);return[(0,a["default"])(e),t,(0,a["default"])(t)]}(y)),w=[y].concat(S).reduce((function(e,n){return e.concat((0,r["default"])(n)===l.auto?(0,c["default"])(t,{placement:n,boundary:g,rootBoundary:N,padding:C,flipVariations:v,allowedAutoPlacements:k}):n)}),[]),x=t.rects.reference,I=t.rects.popper,B=new Map,L=!0,A=w[0],T=0;T=0,O=P?"width":"height",F=(0,i["default"])(t,{placement:D,boundary:g,rootBoundary:N,altBoundary:b,padding:C}),R=P?E?l.right:l.left:E?l.bottom:l.top;x[O]>I[O]&&(R=(0,o["default"])(R));var j=(0,o["default"])(R),z=[];if(p&&z.push(F[M]<=0),h&&z.push(F[R]<=0,F[j]<=0),z.every((function(e){return e}))){A=D,L=!1;break}B.set(D,z)}if(L)for(var W=function(e){var t=w.find((function(t){var n=B.get(t);if(n)return n.slice(0,e).every((function(e){return e}))}));if(t)return A=t,"break"},H=v?3:1;H>0;H--){if("break"===W(H))break}t.placement!==A&&(t.modifiersData[s]._skip=!0,t.placement=A,t.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};t["default"]=u},84723:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o,r=n(28558),a=(o=n(16550))&&o.__esModule?o:{"default":o};function i(e,t,n){return void 0===n&&(n={x:0,y:0}),{top:e.top-t.height-n.y,right:e.right-t.width+n.x,bottom:e.bottom-t.height+n.y,left:e.left-t.width-n.x}}function c(e){return[r.top,r.right,r.bottom,r.left].some((function(t){return e[t]>=0}))}var l={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(e){var t=e.state,n=e.name,o=t.rects.reference,r=t.rects.popper,l=t.modifiersData.preventOverflow,d=(0,a["default"])(t,{elementContext:"reference"}),s=(0,a["default"])(t,{altBoundary:!0}),u=i(d,o),p=i(s,r,l),m=c(u),h=c(p);t.modifiersData[n]={referenceClippingOffsets:u,popperEscapeOffsets:p,isReferenceHidden:m,hasPopperEscaped:h},t.attributes.popper=Object.assign({},t.attributes.popper,{"data-popper-reference-hidden":m,"data-popper-escaped":h})}};t["default"]=l},70810:function(e,t,n){"use strict";t.__esModule=!0,t.preventOverflow=t.popperOffsets=t.offset=t.hide=t.flip=t.eventListeners=t.computeStyles=t.arrow=t.applyStyles=void 0;var o=p(n(68503));t.applyStyles=o["default"];var r=p(n(44145));t.arrow=r["default"];var a=p(n(84288));t.computeStyles=a["default"];var i=p(n(8646));t.eventListeners=i["default"];var c=p(n(81628));t.flip=c["default"];var l=p(n(84723));t.hide=l["default"];var d=p(n(44409));t.offset=d["default"];var s=p(n(29323));t.popperOffsets=s["default"];var u=p(n(52559));function p(e){return e&&e.__esModule?e:{"default":e}}t.preventOverflow=u["default"]},44409:function(e,t,n){"use strict";t.__esModule=!0,t.distanceAndSkiddingToXY=i,t["default"]=void 0;var o,r=(o=n(17048))&&o.__esModule?o:{"default":o},a=n(28558);function i(e,t,n){var o=(0,r["default"])(e),i=[a.left,a.top].indexOf(o)>=0?-1:1,c="function"==typeof n?n(Object.assign({},t,{placement:e})):n,l=c[0],d=c[1];return l=l||0,d=(d||0)*i,[a.left,a.right].indexOf(o)>=0?{x:d,y:l}:{x:l,y:d}}var c={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(e){var t=e.state,n=e.options,o=e.name,r=n.offset,c=void 0===r?[0,0]:r,l=a.placements.reduce((function(e,n){return e[n]=i(n,t.rects,c),e}),{}),d=l[t.placement],s=d.x,u=d.y;null!=t.modifiersData.popperOffsets&&(t.modifiersData.popperOffsets.x+=s,t.modifiersData.popperOffsets.y+=u),t.modifiersData[o]=l}};t["default"]=c},29323:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o,r=(o=n(63979))&&o.__esModule?o:{"default":o};var a={name:"popperOffsets",enabled:!0,phase:"read",fn:function(e){var t=e.state,n=e.name;t.modifiersData[n]=(0,r["default"])({reference:t.rects.reference,element:t.rects.popper,strategy:"absolute",placement:t.placement})},data:{}};t["default"]=a},52559:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=void 0;var o=n(28558),r=h(n(17048)),a=h(n(84656)),i=h(n(72366)),c=h(n(18203)),l=h(n(90389)),d=h(n(84704)),s=h(n(16550)),u=h(n(95817)),p=h(n(58464)),m=n(4179);function h(e){return e&&e.__esModule?e:{"default":e}}var f={name:"preventOverflow",enabled:!0,phase:"main",fn:function(e){var t=e.state,n=e.options,h=e.name,f=n.mainAxis,C=void 0===f||f,g=n.altAxis,N=void 0!==g&&g,b=n.boundary,V=n.rootBoundary,v=n.altBoundary,k=n.padding,y=n.tether,_=void 0===y||y,S=n.tetherOffset,w=void 0===S?0:S,x=(0,s["default"])(t,{boundary:b,rootBoundary:V,padding:k,altBoundary:v}),I=(0,r["default"])(t.placement),B=(0,u["default"])(t.placement),L=!B,A=(0,a["default"])(I),T=(0,i["default"])(A),D=t.modifiersData.popperOffsets,M=t.rects.reference,E=t.rects.popper,P="function"==typeof w?w(Object.assign({},t.rects,{placement:t.placement})):w,O={x:0,y:0};if(D){if(C||N){var F="y"===A?o.top:o.left,R="y"===A?o.bottom:o.right,j="y"===A?"height":"width",z=D[A],W=D[A]+x[F],H=D[A]-x[R],U=_?-E[j]/2:0,G=B===o.start?M[j]:E[j],Y=B===o.start?-E[j]:-M[j],q=t.elements.arrow,K=_&&q?(0,l["default"])(q):{width:0,height:0},$=t.modifiersData["arrow#persistent"]?t.modifiersData["arrow#persistent"].padding:(0,p["default"])(),Q=$[F],J=$[R],Z=(0,c["default"])(0,M[j],K[j]),X=L?M[j]/2-U-Z-Q-P:G-Z-Q-P,ee=L?-M[j]/2+U+Z+J+P:Y+Z+J+P,te=t.elements.arrow&&(0,d["default"])(t.elements.arrow),ne=te?"y"===A?te.clientTop||0:te.clientLeft||0:0,oe=t.modifiersData.offset?t.modifiersData.offset[t.placement][A]:0,re=D[A]+X-oe-ne,ae=D[A]+ee-oe;if(C){var ie=(0,c["default"])(_?(0,m.min)(W,re):W,z,_?(0,m.max)(H,ae):H);D[A]=ie,O[A]=ie-z}if(N){var ce="x"===A?o.top:o.left,le="x"===A?o.bottom:o.right,de=D[T],se=de+x[ce],ue=de-x[le],pe=(0,c["default"])(_?(0,m.min)(se,re):se,de,_?(0,m.max)(ue,ae):ue);D[T]=pe,O[T]=pe-de}}t.modifiersData[h]=O}},requiresIfExists:["offset"]};t["default"]=f},54488:function(e,t,n){"use strict";t.__esModule=!0,t.defaultModifiers=t.createPopper=void 0;var o=n(52078);t.popperGenerator=o.popperGenerator,t.detectOverflow=o.detectOverflow;var r=l(n(8646)),a=l(n(29323)),i=l(n(84288)),c=l(n(68503));function l(e){return e&&e.__esModule?e:{"default":e}}var d=[r["default"],a["default"],i["default"],c["default"]];t.defaultModifiers=d;var s=(0,o.popperGenerator)({defaultModifiers:d});t.createPopper=s},50081:function(e,t,n){"use strict";t.__esModule=!0;var o={createPopper:!0,createPopperLite:!0,defaultModifiers:!0,popperGenerator:!0,detectOverflow:!0};t.defaultModifiers=t.createPopperLite=t.createPopper=void 0;var r=n(52078);t.popperGenerator=r.popperGenerator,t.detectOverflow=r.detectOverflow;var a=C(n(8646)),i=C(n(29323)),c=C(n(84288)),l=C(n(68503)),d=C(n(44409)),s=C(n(81628)),u=C(n(52559)),p=C(n(44145)),m=C(n(84723)),h=n(54488);t.createPopperLite=h.createPopper;var f=n(70810);function C(e){return e&&e.__esModule?e:{"default":e}}Object.keys(f).forEach((function(e){"default"!==e&&"__esModule"!==e&&(Object.prototype.hasOwnProperty.call(o,e)||e in t&&t[e]===f[e]||(t[e]=f[e]))}));var g=[a["default"],i["default"],c["default"],l["default"],d["default"],s["default"],u["default"],p["default"],m["default"]];t.defaultModifiers=g;var N=(0,r.popperGenerator)({defaultModifiers:g});t.createPopperLite=t.createPopper=N},87825:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t){void 0===t&&(t={});var n=t,c=n.placement,l=n.boundary,d=n.rootBoundary,s=n.padding,u=n.flipVariations,p=n.allowedAutoPlacements,m=void 0===p?r.placements:p,h=(0,o["default"])(c),f=h?u?r.variationPlacements:r.variationPlacements.filter((function(e){return(0,o["default"])(e)===h})):r.basePlacements,C=f.filter((function(e){return m.indexOf(e)>=0}));0===C.length&&(C=f);var g=C.reduce((function(t,n){return t[n]=(0,a["default"])(e,{placement:n,boundary:l,rootBoundary:d,padding:s})[(0,i["default"])(n)],t}),{});return Object.keys(g).sort((function(e,t){return g[e]-g[t]}))};var o=c(n(95817)),r=n(28558),a=c(n(16550)),i=c(n(17048));function c(e){return e&&e.__esModule?e:{"default":e}}},63979:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t,n=e.reference,c=e.element,l=e.placement,d=l?(0,o["default"])(l):null,s=l?(0,r["default"])(l):null,u=n.x+n.width/2-c.width/2,p=n.y+n.height/2-c.height/2;switch(d){case i.top:t={x:u,y:n.y-c.height};break;case i.bottom:t={x:u,y:n.y+n.height};break;case i.right:t={x:n.x+n.width,y:p};break;case i.left:t={x:n.x-c.width,y:p};break;default:t={x:n.x,y:n.y}}var m=d?(0,a["default"])(d):null;if(null!=m){var h="y"===m?"height":"width";switch(s){case i.start:t[m]=t[m]-(n[h]/2-c[h]/2);break;case i.end:t[m]=t[m]+(n[h]/2-c[h]/2)}}return t};var o=c(n(17048)),r=c(n(95817)),a=c(n(84656)),i=n(28558);function c(e){return e&&e.__esModule?e:{"default":e}}},67213:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){var t;return function(){return t||(t=new Promise((function(n){Promise.resolve().then((function(){t=undefined,n(e())}))}))),t}}},16550:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t){void 0===t&&(t={});var n=t,p=n.placement,m=void 0===p?e.placement:p,h=n.boundary,f=void 0===h?l.clippingParents:h,C=n.rootBoundary,g=void 0===C?l.viewport:C,N=n.elementContext,b=void 0===N?l.popper:N,V=n.altBoundary,v=void 0!==V&&V,k=n.padding,y=void 0===k?0:k,_=(0,s["default"])("number"!=typeof y?y:(0,u["default"])(y,l.basePlacements)),S=b===l.popper?l.reference:l.popper,w=e.elements.reference,x=e.rects.popper,I=e.elements[v?S:b],B=(0,r["default"])((0,d.isElement)(I)?I:I.contextElement||(0,a["default"])(e.elements.popper),f,g),L=(0,o["default"])(w),A=(0,i["default"])({reference:L,element:x,strategy:"absolute",placement:m}),T=(0,c["default"])(Object.assign({},x,A)),D=b===l.popper?T:L,M={top:B.top-D.top+_.top,bottom:D.bottom-B.bottom+_.bottom,left:B.left-D.left+_.left,right:D.right-B.right+_.right},E=e.modifiersData.offset;if(b===l.popper&&E){var P=E[m];Object.keys(M).forEach((function(e){var t=[l.right,l.bottom].indexOf(e)>=0?1:-1,n=[l.top,l.bottom].indexOf(e)>=0?"y":"x";M[e]+=P[n]*t}))}return M};var o=p(n(57462)),r=p(n(64133)),a=p(n(43730)),i=p(n(63979)),c=p(n(52726)),l=n(28558),d=n(89075),s=p(n(30281)),u=p(n(97341));function p(e){return e&&e.__esModule?e:{"default":e}}},97341:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e,t){return t.reduce((function(t,n){return t[n]=e,t}),{})}},52015:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o=0?"x":"y"}},8095:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.replace(/left|right|bottom|top/g,(function(e){return n[e]}))};var n={left:"right",right:"left",bottom:"top",top:"bottom"}},1637:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.replace(/start|end/g,(function(e){return n[e]}))};var n={start:"end",end:"start"}},95817:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return e.split("-")[1]}},4179:function(e,t){"use strict";t.__esModule=!0,t.round=t.min=t.max=void 0;var n=Math.max;t.max=n;var o=Math.min;t.min=o;var r=Math.round;t.round=r},27491:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){var t=e.reduce((function(e,t){var n=e[t.name];return e[t.name]=n?Object.assign({},n,t,{options:Object.assign({},n.options,t.options),data:Object.assign({},n.data,t.data)}):t,e}),{});return Object.keys(t).map((function(e){return t[e]}))}},30281:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){return Object.assign({},(0,r["default"])(),e)};var o,r=(o=n(58464))&&o.__esModule?o:{"default":o}},40032:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){var t=function(e){var t=new Map,n=new Set,o=[];function r(e){n.add(e.name),[].concat(e.requires||[],e.requiresIfExists||[]).forEach((function(e){if(!n.has(e)){var o=t.get(e);o&&r(o)}})),o.push(e)}return e.forEach((function(e){t.set(e.name,e)})),e.forEach((function(e){n.has(e.name)||r(e)})),o}(e);return o.modifierPhases.reduce((function(e,n){return e.concat(t.filter((function(e){return e.phase===n})))}),[])};var o=n(28558)},52726:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e){return Object.assign({},e,{left:e.x,top:e.y,right:e.x+e.width,bottom:e.y+e.height})}},66125:function(e,t){"use strict";t.__esModule=!0,t["default"]=function(e,t){var n=new Set;return e.filter((function(e){var o=t(e);if(!n.has(o))return n.add(o),!0}))}},30948:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e){e.forEach((function(t){Object.keys(t).forEach((function(n){switch(n){case"name":t.name;break;case"enabled":t.enabled;case"phase":r.modifierPhases.indexOf(t.phase);break;case"fn":t.fn;break;case"effect":t.effect;break;case"requires":Array.isArray(t.requires);break;case"requiresIfExists":Array.isArray(t.requiresIfExists)}t.requires&&t.requires.forEach((function(t){e.find((function(e){return e.name===t}))}))}))}))};(o=n(52015))&&o.__esModule;var o,r=n(28558)},18203:function(e,t,n){"use strict";t.__esModule=!0,t["default"]=function(e,t,n){return(0,o.max)(e,(0,o.min)(t,n))};var o=n(4179)},3728:function(e){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},81145:function(e,t,n){"use strict";var o=n(94053);e.exports=function(e){if(!o(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},30648:function(e,t,n){"use strict";var o=n(96646),r=n(37541),a=n(75808),i=o("unscopables"),c=Array.prototype;c[i]==undefined&&a.f(c,i,{configurable:!0,value:r(null)}),e.exports=function(e){c[i][e]=!0}},76053:function(e,t,n){"use strict";var o=n(14967).charAt;e.exports=function(e,t,n){return t+(n?o(e,t).length:1)}},19169:function(e){"use strict";e.exports=function(e,t,n){if(!(e instanceof t))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation");return e}},40140:function(e,t,n){"use strict";var o=n(94053);e.exports=function(e){if(!o(e))throw TypeError(String(e)+" is not an object");return e}},12227:function(e){"use strict";e.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},47222:function(e,t,n){"use strict";var o,r,a,i=n(12227),c=n(82711),l=n(27576),d=n(94053),s=n(51800),u=n(82895),p=n(79421),m=n(63130),h=n(75808).f,f=n(77754),C=n(56226),g=n(96646),N=n(79285),b=l.Int8Array,V=b&&b.prototype,v=l.Uint8ClampedArray,k=v&&v.prototype,y=b&&f(b),_=V&&f(V),S=Object.prototype,w=S.isPrototypeOf,x=g("toStringTag"),I=N("TYPED_ARRAY_TAG"),B=N("TYPED_ARRAY_CONSTRUCTOR"),L=i&&!!C&&"Opera"!==u(l.opera),A=!1,T={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},D={BigInt64Array:8,BigUint64Array:8},M=function(e){if(!d(e))return!1;var t=u(e);return"DataView"===t||s(T,t)||s(D,t)},E=function(e){if(!d(e))return!1;var t=u(e);return s(T,t)||s(D,t)};for(o in T)(a=(r=l[o])&&r.prototype)?p(a,B,r):L=!1;for(o in D)(a=(r=l[o])&&r.prototype)&&p(a,B,r);if((!L||"function"!=typeof y||y===Function.prototype)&&(y=function(){throw TypeError("Incorrect invocation")},L))for(o in T)l[o]&&C(l[o],y);if((!L||!_||_===S)&&(_=y.prototype,L))for(o in T)l[o]&&C(l[o].prototype,_);if(L&&f(k)!==_&&C(k,_),c&&!s(_,x))for(o in A=!0,h(_,x,{get:function(){return d(this)?this[I]:undefined}}),T)l[o]&&p(l[o],I,o);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:L,TYPED_ARRAY_CONSTRUCTOR:B,TYPED_ARRAY_TAG:A&&I,aTypedArray:function(e){if(E(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(C&&!w.call(y,e))throw TypeError("Target is not a typed array constructor");return e},exportTypedArrayMethod:function(e,t,n){if(c){if(n)for(var o in T){var r=l[o];if(r&&s(r.prototype,e))try{delete r.prototype[e]}catch(a){}}_[e]&&!n||m(_,e,n?t:L&&V[e]||t)}},exportTypedArrayStaticMethod:function(e,t,n){var o,r;if(c){if(C){if(n)for(o in T)if((r=l[o])&&s(r,e))try{delete r[e]}catch(a){}if(y[e]&&!n)return;try{return m(y,e,n?t:L&&y[e]||t)}catch(a){}}for(o in T)!(r=l[o])||r[e]&&!n||m(r,e,t)}},isView:M,isTypedArray:E,TypedArray:y,TypedArrayPrototype:_}},85585:function(e,t,n){"use strict";var o=n(27576),r=n(82711),a=n(12227),i=n(79421),c=n(87378),l=n(60219),d=n(19169),s=n(39929),u=n(25269),p=n(39327),m=n(46743),h=n(77754),f=n(56226),C=n(14889).f,g=n(75808).f,N=n(57474),b=n(39201),V=n(70901),v=V.get,k=V.set,y="ArrayBuffer",_="DataView",S="Wrong index",w=o.ArrayBuffer,x=w,I=o.DataView,B=I&&I.prototype,L=Object.prototype,A=o.RangeError,T=m.pack,D=m.unpack,M=function(e){return[255&e]},E=function(e){return[255&e,e>>8&255]},P=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},O=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},F=function(e){return T(e,23,4)},R=function(e){return T(e,52,8)},j=function(e,t){g(e.prototype,t,{get:function(){return v(this)[t]}})},z=function(e,t,n,o){var r=p(n),a=v(e);if(r+t>a.byteLength)throw A(S);var i=v(a.buffer).bytes,c=r+a.byteOffset,l=i.slice(c,c+t);return o?l:l.reverse()},W=function(e,t,n,o,r,a){var i=p(n),c=v(e);if(i+t>c.byteLength)throw A(S);for(var l=v(c.buffer).bytes,d=i+c.byteOffset,s=o(+r),u=0;uY;)(H=G[Y++])in x||i(x,H,w[H]);U.constructor=x}f&&h(B)!==L&&f(B,L);var q=new I(new x(2)),K=B.setInt8;q.setInt8(0,2147483648),q.setInt8(1,2147483649),!q.getInt8(0)&&q.getInt8(1)||c(B,{setInt8:function(e,t){K.call(this,e,t<<24>>24)},setUint8:function(e,t){K.call(this,e,t<<24>>24)}},{unsafe:!0})}else x=function(e){d(this,x,y);var t=p(e);k(this,{bytes:N.call(new Array(t),0),byteLength:t}),r||(this.byteLength=t)},I=function(e,t,n){d(this,I,_),d(e,x,_);var o=v(e).byteLength,a=s(t);if(a<0||a>o)throw A("Wrong offset");if(a+(n=n===undefined?o-a:u(n))>o)throw A("Wrong length");k(this,{buffer:e,byteLength:n,byteOffset:a}),r||(this.buffer=e,this.byteLength=n,this.byteOffset=a)},r&&(j(x,"byteLength"),j(I,"buffer"),j(I,"byteLength"),j(I,"byteOffset")),c(I.prototype,{getInt8:function(e){return z(this,1,e)[0]<<24>>24},getUint8:function(e){return z(this,1,e)[0]},getInt16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=z(this,2,e,arguments.length>1?arguments[1]:undefined);return t[1]<<8|t[0]},getInt32:function(e){return O(z(this,4,e,arguments.length>1?arguments[1]:undefined))},getUint32:function(e){return O(z(this,4,e,arguments.length>1?arguments[1]:undefined))>>>0},getFloat32:function(e){return D(z(this,4,e,arguments.length>1?arguments[1]:undefined),23)},getFloat64:function(e){return D(z(this,8,e,arguments.length>1?arguments[1]:undefined),52)},setInt8:function(e,t){W(this,1,e,M,t)},setUint8:function(e,t){W(this,1,e,M,t)},setInt16:function(e,t){W(this,2,e,E,t,arguments.length>2?arguments[2]:undefined)},setUint16:function(e,t){W(this,2,e,E,t,arguments.length>2?arguments[2]:undefined)},setInt32:function(e,t){W(this,4,e,P,t,arguments.length>2?arguments[2]:undefined)},setUint32:function(e,t){W(this,4,e,P,t,arguments.length>2?arguments[2]:undefined)},setFloat32:function(e,t){W(this,4,e,F,t,arguments.length>2?arguments[2]:undefined)},setFloat64:function(e,t){W(this,8,e,R,t,arguments.length>2?arguments[2]:undefined)}});b(x,y),b(I,_),e.exports={ArrayBuffer:x,DataView:I}},16048:function(e,t,n){"use strict";var o=n(46850),r=n(68476),a=n(25269),i=Math.min;e.exports=[].copyWithin||function(e,t){var n=o(this),c=a(n.length),l=r(e,c),d=r(t,c),s=arguments.length>2?arguments[2]:undefined,u=i((s===undefined?c:r(s,c))-d,c-l),p=1;for(d0;)d in n?n[l]=n[d]:delete n[l],l+=p,d+=p;return n}},57474:function(e,t,n){"use strict";var o=n(46850),r=n(68476),a=n(25269);e.exports=function(e){for(var t=o(this),n=a(t.length),i=arguments.length,c=r(i>1?arguments[1]:undefined,n),l=i>2?arguments[2]:undefined,d=l===undefined?n:r(l,n);d>c;)t[c++]=e;return t}},12933:function(e,t,n){"use strict";var o=n(46712).forEach,r=n(69310)("forEach");e.exports=r?[].forEach:function(e){return o(this,e,arguments.length>1?arguments[1]:undefined)}},4379:function(e){"use strict";e.exports=function(e,t){for(var n=0,o=t.length,r=new e(o);o>n;)r[n]=t[n++];return r}},50682:function(e,t,n){"use strict";var o=n(69184),r=n(46850),a=n(18372),i=n(14453),c=n(25269),l=n(48286),d=n(61931);e.exports=function(e){var t,n,s,u,p,m,h=r(e),f="function"==typeof this?this:Array,C=arguments.length,g=C>1?arguments[1]:undefined,N=g!==undefined,b=d(h),V=0;if(N&&(g=o(g,C>2?arguments[2]:undefined,2)),b==undefined||f==Array&&i(b))for(n=new f(t=c(h.length));t>V;V++)m=N?g(h[V],V):h[V],l(n,V,m);else for(p=(u=b.call(h)).next,n=new f;!(s=p.call(u)).done;V++)m=N?a(u,g,[s.value,V],!0):s.value,l(n,V,m);return n.length=V,n}},44100:function(e,t,n){"use strict";var o=n(25333),r=n(25269),a=n(68476),i=function(e){return function(t,n,i){var c,l=o(t),d=r(l.length),s=a(i,d);if(e&&n!=n){for(;d>s;)if((c=l[s++])!=c)return!0}else for(;d>s;s++)if((e||s in l)&&l[s]===n)return e||s||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},46712:function(e,t,n){"use strict";var o=n(69184),r=n(19286),a=n(46850),i=n(25269),c=n(50171),l=[].push,d=function(e){var t=1==e,n=2==e,d=3==e,s=4==e,u=6==e,p=7==e,m=5==e||u;return function(h,f,C,g){for(var N,b,V=a(h),v=r(V),k=o(f,C,3),y=i(v.length),_=0,S=g||c,w=t?S(h,y):n||p?S(h,0):undefined;y>_;_++)if((m||_ in v)&&(b=k(N=v[_],_,V),e))if(t)w[_]=b;else if(b)switch(e){case 3:return!0;case 5:return N;case 6:return _;case 2:l.call(w,N)}else switch(e){case 4:return!1;case 7:l.call(w,N)}return u?-1:d||s?s:w}};e.exports={forEach:d(0),map:d(1),filter:d(2),some:d(3),every:d(4),find:d(5),findIndex:d(6),filterReject:d(7)}},51445:function(e,t,n){"use strict";var o=n(25333),r=n(39929),a=n(25269),i=n(69310),c=Math.min,l=[].lastIndexOf,d=!!l&&1/[1].lastIndexOf(1,-0)<0,s=i("lastIndexOf"),u=d||!s;e.exports=u?function(e){if(d)return l.apply(this,arguments)||0;var t=o(this),n=a(t.length),i=n-1;for(arguments.length>1&&(i=c(i,r(arguments[1]))),i<0&&(i=n+i);i>=0;i--)if(i in t&&t[i]===e)return i||0;return-1}:l},87176:function(e,t,n){"use strict";var o=n(60219),r=n(96646),a=n(12709),i=r("species");e.exports=function(e){return a>=51||!o((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},69310:function(e,t,n){"use strict";var o=n(60219);e.exports=function(e,t){var n=[][e];return!!n&&o((function(){n.call(null,t||function(){throw 1},1)}))}},86240:function(e,t,n){"use strict";var o=n(3728),r=n(46850),a=n(19286),i=n(25269),c=function(e){return function(t,n,c,l){o(n);var d=r(t),s=a(d),u=i(d.length),p=e?u-1:0,m=e?-1:1;if(c<2)for(;;){if(p in s){l=s[p],p+=m;break}if(p+=m,e?p<0:u<=p)throw TypeError("Reduce of empty array with no initial value")}for(;e?p>=0:u>p;p+=m)p in s&&(l=n(l,s[p],p,d));return l}};e.exports={left:c(!1),right:c(!0)}},96276:function(e){"use strict";var t=Math.floor,n=function(e,t){for(var n,o,r=e.length,a=1;a0;)e[o]=e[--o];o!==a++&&(e[o]=n)}return e},o=function(e,t,n){for(var o=e.length,r=t.length,a=0,i=0,c=[];a1?arguments[1]:undefined,3);t=t?t.next:n.first;)for(o(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!g(this,e)}}),a(s.prototype,n?{get:function(e){var t=g(this,e);return t&&t.value},set:function(e,t){return C(this,0===e?0:e,t)}}:{add:function(e){return C(this,e=0===e?0:e,e)}}),u&&o(s.prototype,"size",{get:function(){return m(this).size}}),s},setStrong:function(e,t,n){var o=t+" Iterator",r=f(t),a=f(o);d(e,t,(function(e,t){h(this,{type:o,target:e,state:r(e),kind:t,last:undefined})}),(function(){for(var e=a(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=undefined,{value:undefined,done:!0})}),n?"entries":"values",!n,!0),s(t)}}},4293:function(e,t,n){"use strict";var o=n(87378),r=n(59916).getWeakData,a=n(40140),i=n(94053),c=n(19169),l=n(66075),d=n(46712),s=n(51800),u=n(70901),p=u.set,m=u.getterFor,h=d.find,f=d.findIndex,C=0,g=function(e){return e.frozen||(e.frozen=new N)},N=function(){this.entries=[]},b=function(e,t){return h(e.entries,(function(e){return e[0]===t}))};N.prototype={get:function(e){var t=b(this,e);if(t)return t[1]},has:function(e){return!!b(this,e)},set:function(e,t){var n=b(this,e);n?n[1]=t:this.entries.push([e,t])},"delete":function(e){var t=f(this.entries,(function(t){return t[0]===e}));return~t&&this.entries.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,d){var u=e((function(e,o){c(e,u,t),p(e,{type:t,id:C++,frozen:undefined}),o!=undefined&&l(o,e[d],{that:e,AS_ENTRIES:n})})),h=m(t),f=function(e,t,n){var o=h(e),i=r(a(t),!0);return!0===i?g(o).set(t,n):i[o.id]=n,e};return o(u.prototype,{"delete":function(e){var t=h(this);if(!i(e))return!1;var n=r(e);return!0===n?g(t)["delete"](e):n&&s(n,t.id)&&delete n[t.id]},has:function(e){var t=h(this);if(!i(e))return!1;var n=r(e);return!0===n?g(t).has(e):n&&s(n,t.id)}}),o(u.prototype,n?{get:function(e){var t=h(this);if(i(e)){var n=r(e);return!0===n?g(t).get(e):n?n[t.id]:undefined}},set:function(e,t){return f(this,e,t)}}:{add:function(e){return f(this,e,!0)}}),u}}},21484:function(e,t,n){"use strict";var o=n(19651),r=n(27576),a=n(41356),i=n(63130),c=n(59916),l=n(66075),d=n(19169),s=n(94053),u=n(60219),p=n(57102),m=n(39201),h=n(20361);e.exports=function(e,t,n){var f=-1!==e.indexOf("Map"),C=-1!==e.indexOf("Weak"),g=f?"set":"add",N=r[e],b=N&&N.prototype,V=N,v={},k=function(e){var t=b[e];i(b,e,"add"==e?function(e){return t.call(this,0===e?0:e),this}:"delete"==e?function(e){return!(C&&!s(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return C&&!s(e)?undefined:t.call(this,0===e?0:e)}:"has"==e?function(e){return!(C&&!s(e))&&t.call(this,0===e?0:e)}:function(e,n){return t.call(this,0===e?0:e,n),this})};if(a(e,"function"!=typeof N||!(C||b.forEach&&!u((function(){(new N).entries().next()})))))V=n.getConstructor(t,e,f,g),c.enable();else if(a(e,!0)){var y=new V,_=y[g](C?{}:-0,1)!=y,S=u((function(){y.has(1)})),w=p((function(e){new N(e)})),x=!C&&u((function(){for(var e=new N,t=5;t--;)e[g](t,t);return!e.has(-0)}));w||((V=t((function(t,n){d(t,V,e);var o=h(new N,t,V);return n!=undefined&&l(n,o[g],{that:o,AS_ENTRIES:f}),o}))).prototype=b,b.constructor=V),(S||x)&&(k("delete"),k("has"),f&&k("get")),(x||_)&&k(g),C&&b.clear&&delete b.clear}return v[e]=V,o({global:!0,forced:V!=N},v),m(V,e),C||n.setStrong(V,e,f),V}},52040:function(e,t,n){"use strict";var o=n(51800),r=n(92652),a=n(47409),i=n(75808);e.exports=function(e,t){for(var n=r(t),c=i.f,l=a.f,d=0;d"+c+""+t+">"}},10790:function(e,t,n){"use strict";var o=n(30579).IteratorPrototype,r=n(37541),a=n(74258),i=n(39201),c=n(62530),l=function(){return this};e.exports=function(e,t,n){var d=t+" Iterator";return e.prototype=r(o,{next:a(1,n)}),i(e,d,!1,!0),c[d]=l,e}},79421:function(e,t,n){"use strict";var o=n(82711),r=n(75808),a=n(74258);e.exports=o?function(e,t,n){return r.f(e,t,a(1,n))}:function(e,t,n){return e[t]=n,e}},74258:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},48286:function(e,t,n){"use strict";var o=n(76593),r=n(75808),a=n(74258);e.exports=function(e,t,n){var i=o(t);i in e?r.f(e,i,a(0,n)):e[i]=n}},86822:function(e,t,n){"use strict";var o=n(60219),r=n(84004).start,a=Math.abs,i=Date.prototype,c=i.getTime,l=i.toISOString;e.exports=o((function(){return"0385-07-25T07:06:39.999Z"!=l.call(new Date(-50000000000001))}))||!o((function(){l.call(new Date(NaN))}))?function(){if(!isFinite(c.call(this)))throw RangeError("Invalid time value");var e=this,t=e.getUTCFullYear(),n=e.getUTCMilliseconds(),o=t<0?"-":t>9999?"+":"";return o+r(a(t),o?6:4,0)+"-"+r(e.getUTCMonth()+1,2,0)+"-"+r(e.getUTCDate(),2,0)+"T"+r(e.getUTCHours(),2,0)+":"+r(e.getUTCMinutes(),2,0)+":"+r(e.getUTCSeconds(),2,0)+"."+r(n,3,0)+"Z"}:l},61309:function(e,t,n){"use strict";var o=n(40140),r=n(76782);e.exports=function(e){if(o(this),"string"===e||"default"===e)e="string";else if("number"!==e)throw TypeError("Incorrect hint");return r(this,e)}},26946:function(e,t,n){"use strict";var o=n(19651),r=n(10790),a=n(77754),i=n(56226),c=n(39201),l=n(79421),d=n(63130),s=n(96646),u=n(93739),p=n(62530),m=n(30579),h=m.IteratorPrototype,f=m.BUGGY_SAFARI_ITERATORS,C=s("iterator"),g="keys",N="values",b="entries",V=function(){return this};e.exports=function(e,t,n,s,m,v,k){r(n,t,s);var y,_,S,w=function(e){if(e===m&&A)return A;if(!f&&e in B)return B[e];switch(e){case g:case N:case b:return function(){return new n(this,e)}}return function(){return new n(this)}},x=t+" Iterator",I=!1,B=e.prototype,L=B[C]||B["@@iterator"]||m&&B[m],A=!f&&L||w(m),T="Array"==t&&B.entries||L;if(T&&(y=a(T.call(new e)),h!==Object.prototype&&y.next&&(u||a(y)===h||(i?i(y,h):"function"!=typeof y[C]&&l(y,C,V)),c(y,x,!0,!0),u&&(p[x]=V))),m==N&&L&&L.name!==N&&(I=!0,A=function(){return L.call(this)}),u&&!k||B[C]===A||l(B,C,A),p[t]=A,m)if(_={values:w(N),keys:v?A:w(g),entries:w(b)},k)for(S in _)(f||I||!(S in B))&&d(B,S,_[S]);else o({target:t,proto:!0,forced:f||I},_);return _}},23805:function(e,t,n){"use strict";var o=n(99581),r=n(51800),a=n(42472),i=n(75808).f;e.exports=function(e){var t=o.Symbol||(o.Symbol={});r(t,e)||i(t,e,{value:a.f(e)})}},82711:function(e,t,n){"use strict";var o=n(60219);e.exports=!o((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},43725:function(e,t,n){"use strict";var o=n(27576),r=n(94053),a=o.document,i=r(a)&&r(a.createElement);e.exports=function(e){return i?a.createElement(e):{}}},23346:function(e,t,n){"use strict";var o=n(84785).match(/firefox\/(\d+)/i);e.exports=!!o&&+o[1]},86745:function(e){"use strict";e.exports="object"==typeof window},11151:function(e,t,n){"use strict";var o=n(84785);e.exports=/MSIE|Trident/.test(o)},83603:function(e,t,n){"use strict";var o=n(84785),r=n(27576);e.exports=/iphone|ipod|ipad/i.test(o)&&r.Pebble!==undefined},38969:function(e,t,n){"use strict";var o=n(84785);e.exports=/(?:iphone|ipod|ipad).*applewebkit/i.test(o)},85621:function(e,t,n){"use strict";var o=n(87585),r=n(27576);e.exports="process"==o(r.process)},53812:function(e,t,n){"use strict";var o=n(84785);e.exports=/web0s(?!.*chrome)/i.test(o)},84785:function(e,t,n){"use strict";var o=n(77990);e.exports=o("navigator","userAgent")||""},12709:function(e,t,n){"use strict";var o,r,a=n(27576),i=n(84785),c=a.process,l=a.Deno,d=c&&c.versions||l&&l.version,s=d&&d.v8;s?r=(o=s.split("."))[0]<4?1:o[0]+o[1]:i&&(!(o=i.match(/Edge\/(\d+)/))||o[1]>=74)&&(o=i.match(/Chrome\/(\d+)/))&&(r=o[1]),e.exports=r&&+r},18822:function(e,t,n){"use strict";var o=n(84785).match(/AppleWebKit\/(\d+)\./);e.exports=!!o&&+o[1]},61289:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},19651:function(e,t,n){"use strict";var o=n(27576),r=n(47409).f,a=n(79421),i=n(63130),c=n(91034),l=n(52040),d=n(41356);e.exports=function(e,t){var n,s,u,p,m,h=e.target,f=e.global,C=e.stat;if(n=f?o:C?o[h]||c(h,{}):(o[h]||{}).prototype)for(s in t){if(p=t[s],u=e.noTargetGet?(m=r(n,s))&&m.value:n[s],!d(f?s:h+(C?".":"#")+s,e.forced)&&u!==undefined){if(typeof p==typeof u)continue;l(p,u)}(e.sham||u&&u.sham)&&a(p,"sham",!0),i(n,s,p,e)}}},60219:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},49248:function(e,t,n){"use strict";n(36100);var o=n(63130),r=n(57625),a=n(60219),i=n(96646),c=n(79421),l=i("species"),d=RegExp.prototype;e.exports=function(e,t,n,s){var u=i(e),p=!a((function(){var t={};return t[u]=function(){return 7},7!=""[e](t)})),m=p&&!a((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[l]=function(){return n},n.flags="",n[u]=/./[u]),n.exec=function(){return t=!0,null},n[u](""),!t}));if(!p||!m||n){var h=/./[u],f=t(u,""[e],(function(e,t,n,o,a){var i=t.exec;return i===r||i===d.exec?p&&!a?{done:!0,value:h.call(t,n,o)}:{done:!0,value:e.call(n,t,o)}:{done:!1}}));o(String.prototype,e,f[0]),o(d,u,f[1])}s&&c(d[u],"sham",!0)}},99802:function(e,t,n){"use strict";var o=n(84419),r=n(25269),a=n(69184);e.exports=function i(e,t,n,c,l,d,s,u){for(var p,m=l,h=0,f=!!s&&a(s,u,3);h0&&o(p))m=i(e,t,p,r(p.length),m,d-1)-1;else{if(m>=9007199254740991)throw TypeError("Exceed the acceptable array length");e[m]=p}m++}h++}return m}},64687:function(e,t,n){"use strict";var o=n(60219);e.exports=!o((function(){return Object.isExtensible(Object.preventExtensions({}))}))},69184:function(e,t,n){"use strict";var o=n(3728);e.exports=function(e,t,n){if(o(e),t===undefined)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,o){return e.call(t,n,o)};case 3:return function(n,o,r){return e.call(t,n,o,r)}}return function(){return e.apply(t,arguments)}}},11213:function(e,t,n){"use strict";var o=n(3728),r=n(94053),a=[].slice,i={},c=function(e,t,n){if(!(t in i)){for(var o=[],r=0;r]*>)/g,c=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,t,n,l,d,s){var u=n+e.length,p=l.length,m=c;return d!==undefined&&(d=o(d),m=i),a.call(s,m,(function(o,a){var i;switch(a.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,n);case"'":return t.slice(u);case"<":i=d[a.slice(1,-1)];break;default:var c=+a;if(0===c)return o;if(c>p){var s=r(c/10);return 0===s?o:s<=p?l[s-1]===undefined?a.charAt(1):l[s-1]+a.charAt(1):o}i=l[c-1]}return i===undefined?"":i}))}},27576:function(e,t,n){"use strict";var o=function(e){return e&&e.Math==Math&&e};e.exports=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof n.g&&n.g)||function(){return this}()||Function("return this")()},51800:function(e,t,n){"use strict";var o=n(46850),r={}.hasOwnProperty;e.exports=Object.hasOwn||function(e,t){return r.call(o(e),t)}},62831:function(e){"use strict";e.exports={}},71854:function(e,t,n){"use strict";var o=n(27576);e.exports=function(e,t){var n=o.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},21667:function(e,t,n){"use strict";var o=n(77990);e.exports=o("document","documentElement")},17109:function(e,t,n){"use strict";var o=n(82711),r=n(60219),a=n(43725);e.exports=!o&&!r((function(){return 7!=Object.defineProperty(a("div"),"a",{get:function(){return 7}}).a}))},46743:function(e){"use strict";var t=Math.abs,n=Math.pow,o=Math.floor,r=Math.log,a=Math.LN2;e.exports={pack:function(e,i,c){var l,d,s,u=new Array(c),p=8*c-i-1,m=(1<>1,f=23===i?n(2,-24)-n(2,-77):0,C=e<0||0===e&&1/e<0?1:0,g=0;for((e=t(e))!=e||e===Infinity?(d=e!=e?1:0,l=m):(l=o(r(e)/a),e*(s=n(2,-l))<1&&(l--,s*=2),(e+=l+h>=1?f/s:f*n(2,1-h))*s>=2&&(l++,s/=2),l+h>=m?(d=0,l=m):l+h>=1?(d=(e*s-1)*n(2,i),l+=h):(d=e*n(2,h-1)*n(2,i),l=0));i>=8;u[g++]=255&d,d/=256,i-=8);for(l=l<0;u[g++]=255&l,l/=256,p-=8);return u[--g]|=128*C,u},unpack:function(e,t){var o,r=e.length,a=8*r-t-1,i=(1<>1,l=a-7,d=r-1,s=e[d--],u=127&s;for(s>>=7;l>0;u=256*u+e[d],d--,l-=8);for(o=u&(1<<-l)-1,u>>=-l,l+=t;l>0;o=256*o+e[d],d--,l-=8);if(0===u)u=1-c;else{if(u===i)return o?NaN:s?-Infinity:Infinity;o+=n(2,t),u-=c}return(s?-1:1)*o*n(2,u-t)}}},19286:function(e,t,n){"use strict";var o=n(60219),r=n(87585),a="".split;e.exports=o((function(){return!Object("z").propertyIsEnumerable(0)}))?function(e){return"String"==r(e)?a.call(e,""):Object(e)}:Object},20361:function(e,t,n){"use strict";var o=n(94053),r=n(56226);e.exports=function(e,t,n){var a,i;return r&&"function"==typeof(a=t.constructor)&&a!==n&&o(i=a.prototype)&&i!==n.prototype&&r(e,i),e}},54848:function(e,t,n){"use strict";var o=n(79208),r=Function.toString;"function"!=typeof o.inspectSource&&(o.inspectSource=function(e){return r.call(e)}),e.exports=o.inspectSource},59916:function(e,t,n){"use strict";var o=n(19651),r=n(62831),a=n(94053),i=n(51800),c=n(75808).f,l=n(14889),d=n(20084),s=n(79285),u=n(64687),p=!1,m=s("meta"),h=0,f=Object.isExtensible||function(){return!0},C=function(e){c(e,m,{value:{objectID:"O"+h++,weakData:{}}})},g=e.exports={enable:function(){g.enable=function(){},p=!0;var e=l.f,t=[].splice,n={};n[m]=1,e(n).length&&(l.f=function(n){for(var o=e(n),r=0,a=o.length;r p;p++)if((h=y(e[p]))&&h instanceof d)return h;return new d(!1)}s=u.call(e)}for(f=s.next;!(C=f.call(s)).done;){try{h=y(C.value)}catch(_){throw l(s),_}if("object"==typeof h&&h&&h instanceof d)return h}return new d(!1)}},38829:function(e,t,n){"use strict";var o=n(40140);e.exports=function(e){var t=e["return"];if(t!==undefined)return o(t.call(e)).value}},30579:function(e,t,n){"use strict";var o,r,a,i=n(60219),c=n(77754),l=n(79421),d=n(51800),s=n(96646),u=n(93739),p=s("iterator"),m=!1;[].keys&&("next"in(a=[].keys())?(r=c(c(a)))!==Object.prototype&&(o=r):m=!0);var h=o==undefined||i((function(){var e={};return o[p].call(e)!==e}));h&&(o={}),u&&!h||d(o,p)||l(o,p,(function(){return this})),e.exports={IteratorPrototype:o,BUGGY_SAFARI_ITERATORS:m}},62530:function(e){"use strict";e.exports={}},36922:function(e){"use strict";var t=Math.expm1,n=Math.exp;e.exports=!t||t(10)>22025.465794806718||t(10)<22025.465794806718||-2e-17!=t(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:n(e)-1}:t},17665:function(e,t,n){"use strict";var o=n(2083),r=Math.abs,a=Math.pow,i=a(2,-52),c=a(2,-23),l=a(2,127)*(2-c),d=a(2,-126);e.exports=Math.fround||function(e){var t,n,a=r(e),s=o(e);return al||n!=n?s*Infinity:s*n}},10709:function(e){"use strict";var t=Math.log;e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:t(1+e)}},2083:function(e){"use strict";e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},5241:function(e,t,n){"use strict";var o,r,a,i,c,l,d,s,u=n(27576),p=n(47409).f,m=n(34081).set,h=n(38969),f=n(83603),C=n(53812),g=n(85621),N=u.MutationObserver||u.WebKitMutationObserver,b=u.document,V=u.process,v=u.Promise,k=p(u,"queueMicrotask"),y=k&&k.value;y||(o=function(){var e,t;for(g&&(e=V.domain)&&e.exit();r;){t=r.fn,r=r.next;try{t()}catch(n){throw r?i():a=undefined,n}}a=undefined,e&&e.enter()},h||g||C||!N||!b?!f&&v&&v.resolve?((d=v.resolve(undefined)).constructor=v,s=d.then,i=function(){s.call(d,o)}):i=g?function(){V.nextTick(o)}:function(){m.call(u,o)}:(c=!0,l=b.createTextNode(""),new N(o).observe(l,{characterData:!0}),i=function(){l.data=c=!c})),e.exports=y||function(e){var t={fn:e,next:undefined};a&&(a.next=t),r||(r=t,i()),a=t}},65046:function(e,t,n){"use strict";var o=n(27576);e.exports=o.Promise},41933:function(e,t,n){"use strict";var o=n(12709),r=n(60219);e.exports=!!Object.getOwnPropertySymbols&&!r((function(){var e=Symbol();return!String(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&o&&o<41}))},19753:function(e,t,n){"use strict";var o=n(27576),r=n(54848),a=o.WeakMap;e.exports="function"==typeof a&&/native code/.test(r(a))},67856:function(e,t,n){"use strict";var o=n(3728),r=function(e){var t,n;this.promise=new e((function(e,o){if(t!==undefined||n!==undefined)throw TypeError("Bad Promise constructor");t=e,n=o})),this.resolve=o(t),this.reject=o(n)};e.exports.f=function(e){return new r(e)}},59428:function(e,t,n){"use strict";var o=n(95155);e.exports=function(e){if(o(e))throw TypeError("The method doesn't accept regular expressions");return e}},36953:function(e,t,n){"use strict";var o=n(27576).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&o(e)}},60834:function(e,t,n){"use strict";var o=n(27576),r=n(53632),a=n(24957).trim,i=n(15698),c=o.parseFloat,l=1/c(i+"-0")!=-Infinity;e.exports=l?function(e){var t=a(r(e)),n=c(t);return 0===n&&"-"==t.charAt(0)?-0:n}:c},29682:function(e,t,n){"use strict";var o=n(27576),r=n(53632),a=n(24957).trim,i=n(15698),c=o.parseInt,l=/^[+-]?0[Xx]/,d=8!==c(i+"08")||22!==c(i+"0x16");e.exports=d?function(e,t){var n=a(r(e));return c(n,t>>>0||(l.test(n)?16:10))}:c},55352:function(e,t,n){"use strict";var o=n(82711),r=n(60219),a=n(78318),i=n(57963),c=n(46054),l=n(46850),d=n(19286),s=Object.assign,u=Object.defineProperty;e.exports=!s||r((function(){if(o&&1!==s({b:1},s(u({},"a",{enumerable:!0,get:function(){u(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol(),r="abcdefghijklmnopqrst";return e[n]=7,r.split("").forEach((function(e){t[e]=e})),7!=s({},e)[n]||a(s({},t)).join("")!=r}))?function(e,t){for(var n=l(e),r=arguments.length,s=1,u=i.f,p=c.f;r>s;)for(var m,h=d(arguments[s++]),f=u?a(h).concat(u(h)):a(h),C=f.length,g=0;C>g;)m=f[g++],o&&!p.call(h,m)||(n[m]=h[m]);return n}:s},37541:function(e,t,n){"use strict";var o,r=n(40140),a=n(42551),i=n(61289),c=n(62831),l=n(21667),d=n(43725),s=n(34374),u=s("IE_PROTO"),p=function(){},m=function(e){return"