diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
new file mode 100644
index 00000000000..7953929ce55
--- /dev/null
+++ b/.github/workflows/autochangelog.yml
@@ -0,0 +1,43 @@
+name: Autochangelog
+on:
+ pull_request_target:
+ types: closed
+ branches:
+ - master
+
+env:
+ BASENAME: "polaris"
+
+jobs:
+ autochangelog:
+ name: Autochangelog
+ runs-on: ubuntu-16.04
+ if: github.event.pull_request.merged == true
+ steps:
+ - uses: /actions/checkout@v2
+ with:
+ ref: master
+ - name: Update repository to master
+ run: git pull "origin" master
+ - name: Ensure +x on CI directory
+ run: |
+ chmod -R +x ./tools/ci
+ - uses: actions/setup-python@v2
+ with:
+ python-version: '3.7'
+ - name: Generate Changelog
+ run: |
+ pip install pyyaml
+ python tools/GenerateChangelog/ss13_autochangelog.py \
+ html/changelogs \
+ ${{ github.event.pull_request.number }} \
+ "${{ github.event.pull_request.user.login }}" \
+ "${{ github.event.pull_request.body }}"
+ python tools/GenerateChangelog/ss13_genchangelog.py \
+ html/changelog.html \
+ html/changelogs
+ - uses: stefanzweifel/git-auto-commit-action@v4
+ with:
+ commit_message: Automatic changelog generation for ${{ github.events.pull_request.number }}
+ branch: ${{ github.events.pull_request.base }}
+ commit_user_name: Autochangelog Bot
diff --git a/code/ATMOSPHERICS/pipes/tank_vr.dm b/code/ATMOSPHERICS/pipes/tank_vr.dm
new file mode 100644
index 00000000000..32341ad8f3b
--- /dev/null
+++ b/code/ATMOSPHERICS/pipes/tank_vr.dm
@@ -0,0 +1,5 @@
+/obj/machinery/atmospherics/pipe/tank/phoron/full
+ start_pressure = 15000
+
+/obj/machinery/atmospherics/pipe/tank/air/full
+ start_pressure = 15000
\ No newline at end of file
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index 4e9d7fd6ad7..a2e15e6890e 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -173,6 +173,5 @@ What is the naming convention for planes or layers?
plane = initial(plane)
layer = initial(layer)
-
// Check if a mob can "logically" see an atom plane
#define MOB_CAN_SEE_PLANE(M, P) (P <= PLANE_WORLD || (P in M.planes_visible))
diff --git a/code/__defines/belly_modes_vr.dm b/code/__defines/belly_modes_vr.dm
index ccffcf43416..d497391d3fc 100644
--- a/code/__defines/belly_modes_vr.dm
+++ b/code/__defines/belly_modes_vr.dm
@@ -9,30 +9,17 @@
#define DM_SIZE_STEAL "Size Steal"
#define DM_HEAL "Heal"
#define DM_EGG "Encase In Egg"
-#define DM_TRANSFORM "Transform"
//#define DM_ITEMWEAK "Digest (Item Friendly)"
//#define DM_STRIPDIGEST "Strip Digest (Items Only)"
//#define DM_DIGEST_NUMB "Digest (Numbing)"
-//TF modes
-#define DM_TRANSFORM_HAIR_AND_EYES "Transform (Hair and eyes)"
-#define DM_TRANSFORM_MALE "Transform (Male)"
-#define DM_TRANSFORM_FEMALE "Transform (Female)"
-#define DM_TRANSFORM_KEEP_GENDER "Transform (Keep Gender)"
-#define DM_TRANSFORM_REPLICA "Transform (Replica Of Self)"
-#define DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR "Transform (Change Species and Taur)"
-#define DM_TRANSFORM_CHANGE_SPECIES_AND_TAUR_EGG "Transform (Change Species and Taur) (EGG)"
-#define DM_TRANSFORM_REPLICA_EGG "Transform (Replica Of Self) (EGG)"
-#define DM_TRANSFORM_KEEP_GENDER_EGG "Transform (Keep Gender) (EGG)"
-#define DM_TRANSFORM_MALE_EGG "Transform (Male) (EGG)"
-#define DM_TRANSFORM_FEMALE_EGG "Transform (Female) (EGG)"
-
//Addon mode flags
#define DM_FLAG_NUMBING 0x1
#define DM_FLAG_STRIPPING 0x2
#define DM_FLAG_LEAVEREMAINS 0x4
#define DM_FLAG_THICKBELLY 0x8
+#define DM_FLAG_AFFECTWORN 0x10
//Item related modes
#define IM_HOLD "Hold"
diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm
index c87b9942dfc..db1a71c77a6 100644
--- a/code/__defines/damage_organs.dm
+++ b/code/__defines/damage_organs.dm
@@ -61,4 +61,8 @@
#define INFECTION_LEVEL_ONE 100
#define INFECTION_LEVEL_TWO 500
#define INFECTION_LEVEL_THREE 1000
-#define INFECTION_LEVEL_MAX 1500
\ No newline at end of file
+#define INFECTION_LEVEL_MAX 1500
+
+#define MODULAR_BODYPART_INVALID 0 // Cannot be detached or reattached.
+#define MODULAR_BODYPART_PROSTHETIC 1 // Can be detached or reattached freely.
+#define MODULAR_BODYPART_CYBERNETIC 2 // Can be detached or reattached to compatible parent organs.
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 3e86c138560..a7b3bd86f8f 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -157,6 +157,8 @@
#define MAT_GRAPHITE "graphite"
#define MAT_LEATHER "leather"
#define MAT_CHITIN "chitin"
+#define MAT_CLOTH "cloth"
+#define MAT_SYNCLOTH "syncloth"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"
@@ -480,4 +482,15 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
VOLUME_CHANNEL_ALARMS,
VOLUME_CHANNEL_VORE,
VOLUME_CHANNEL_DOORS,
-))
\ No newline at end of file
+))
+
+#define APPEARANCECHANGER_CHANGED_RACE "Race"
+#define APPEARANCECHANGER_CHANGED_GENDER "Gender"
+#define APPEARANCECHANGER_CHANGED_GENDER_ID "Gender Identity"
+#define APPEARANCECHANGER_CHANGED_SKINTONE "Skin Tone"
+#define APPEARANCECHANGER_CHANGED_SKINCOLOR "Skin Color"
+#define APPEARANCECHANGER_CHANGED_HAIRSTYLE "Hair Style"
+#define APPEARANCECHANGER_CHANGED_HAIRCOLOR "Hair Color"
+#define APPEARANCECHANGER_CHANGED_F_HAIRSTYLE "Facial Hair Style"
+#define APPEARANCECHANGER_CHANGED_F_HAIRCOLOR "Facial Hair Color"
+#define APPEARANCECHANGER_CHANGED_EYES "Eye Color"
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index ca0e186ac90..d166b52fbe1 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -26,7 +26,7 @@
#define BORGMESON 0x1
#define BORGTHERM 0x2
#define BORGXRAY 0x4
-#define BORGMATERIAL 8
+#define BORGMATERIAL 0x8
#define STANCE_ATTACK 11 // Backwards compatability
#define STANCE_ATTACKING 12 // Ditto
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 34c68ebd089..4c80db6450b 100644
--- a/code/__defines/species_languages.dm
+++ b/code/__defines/species_languages.dm
@@ -24,6 +24,29 @@
#define EMP_TOX_DMG 0x80 // EMPs inflict toxin damage
#define EMP_OXY_DMG 0x100 // EMPs inflict oxy damage
+// Species allergens
+#define MEAT 0x1 // Skrell won't like this.
+#define FISH 0x2 // Seperate for completion's sake. Still bad for skrell.
+#define FRUIT 0x4 // An apple a day only keeps the doctor away if they're allergic.
+#define VEGETABLE 0x8 // Taters 'n' carrots. Potato allergy is a thing, apparently.
+#define GRAINS 0x10 // Wheat, oats, etc.
+#define BEANS 0x20 // The musical fruit! Includes soy.
+#define SEEDS 0x40 // Hope you don't have a nut allergy.
+#define DAIRY 0x80 // Lactose intolerance, ho! Also bad for skrell.
+#define FUNGI 0x100 // Delicious shrooms.
+#define COFFEE 0x200 // Mostly here for tajara.
+#define GENERIC 0x400 // Catchall for stuff that doesn't fall into the groups above. You shouldn't be allergic to this type, ever.
+#define SUGARS 0x800 // For unathi-like reactions
+
+// Allergen reactions
+#define AG_TOX_DMG 0x1 // the classic
+#define AG_OXY_DMG 0x2 // intense airway reactions
+#define AG_EMOTE 0x4 // general emote reactions based on affect type
+#define AG_PAIN 0x8 // short-lived hurt
+#define AG_WEAKEN 0x10 // too weak to move, oof
+#define AG_BLURRY 0x20 // blurred vision!
+#define AG_SLEEPY 0x40 // fatigue/exhaustion
+
// Species spawn flags
#define SPECIES_IS_WHITELISTED 0x1 // Must be whitelisted to play.
#define SPECIES_IS_RESTRICTED 0x2 // Is not a core/normally playable species. (castes, mutantraces)
@@ -68,7 +91,7 @@
#define LANGUAGE_ALAI "Alai"
#define LANGUAGE_ZADDAT "Vedahq"
#define LANGUAGE_PROMETHEAN "Promethean Biolinguistics"
-#define LANGUAGE_BLOB "Blob"
+#define LANGUAGE_BLOB "Chemosense Transmission"
#define LANGUAGE_GIBBERISH "Babel"
// Language flags.
diff --git a/code/__defines/species_languages_vr.dm b/code/__defines/species_languages_vr.dm
index 8909238db2d..78054e6ba86 100644
--- a/code/__defines/species_languages_vr.dm
+++ b/code/__defines/species_languages_vr.dm
@@ -10,6 +10,7 @@
#define LANGUAGE_ENOCHIAN "Enochian"
#define LANGUAGE_VESPINAE "Vespinae"
#define LANGUAGE_SPACER "Spacer"
+#define LANGUAGE_CLOWNISH "Coulrian"
#define LANGUAGE_CHIMPANZEE "Chimpanzee"
#define LANGUAGE_NEAERA "Neaera"
diff --git a/code/_global_vars/lists/misc.dm b/code/_global_vars/lists/misc.dm
index e02c99290c7..742708face2 100644
--- a/code/_global_vars/lists/misc.dm
+++ b/code/_global_vars/lists/misc.dm
@@ -5,4 +5,7 @@ GLOBAL_LIST_EMPTY(meteor_list)
GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the `holder_type` as the key, and a list of colors as the value.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
-GLOBAL_LIST_EMPTY(tagger_locations)
\ No newline at end of file
+GLOBAL_LIST_EMPTY(tagger_locations)
+
+GLOBAL_LIST_INIT(char_directory_tags, list("Pred", "Prey", "Switch", "Non-Vore", "Unset"))
+GLOBAL_LIST_INIT(char_directory_erptags, list("Top", "Bottom", "Switch", "No ERP", "Unset"))
\ No newline at end of file
diff --git a/code/_helpers/_global_objects.dm b/code/_helpers/_global_objects.dm
index 4cbbcf33147..adbd2785e85 100644
--- a/code/_helpers/_global_objects.dm
+++ b/code/_helpers/_global_objects.dm
@@ -1 +1,2 @@
-var/datum/gear_tweak/color/gear_tweak_free_color_choice = new()
\ No newline at end of file
+var/datum/gear_tweak/color/gear_tweak_free_color_choice = new()
+var/datum/gear_tweak/implant_location/gear_tweak_implant_location = new()
\ No newline at end of file
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 371f35b0515..0d10e33b492 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -94,13 +94,13 @@ var/global/list/string_slot_flags = list(
"holster" = SLOT_HOLSTER
)
-/proc/get_mannequin(var/ckey)
- if(!mannequins_)
- mannequins_ = new()
- . = mannequins_[ckey]
- if(!.)
- . = new/mob/living/carbon/human/dummy/mannequin()
- mannequins_[ckey] = .
+GLOBAL_LIST_EMPTY(mannequins)
+/proc/get_mannequin(var/ckey = "NULL")
+ var/mob/living/carbon/human/dummy/mannequin/M = GLOB.mannequins[ckey]
+ if(!istype(M))
+ GLOB.mannequins[ckey] = new /mob/living/carbon/human/dummy/mannequin(null)
+ M = GLOB.mannequins[ckey]
+ return M
//////////////////////////
/////Initial Building/////
@@ -215,7 +215,7 @@ var/global/list/string_slot_flags = list(
GLOB.closet_appearances[T] = app
// VOREStation Add - Vore Modes!
- paths = typesof(/datum/digest_mode) - /datum/digest_mode/transform
+ paths = typesof(/datum/digest_mode)
for(var/T in paths)
var/datum/digest_mode/DM = new T
GLOB.digest_modes[DM.id] = DM
diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm
index b2dfae05444..d45406225c1 100644
--- a/code/_helpers/global_lists_vr.dm
+++ b/code/_helpers/global_lists_vr.dm
@@ -3,13 +3,16 @@
*/
var/global/list/ear_styles_list = list() // Stores /datum/sprite_accessory/ears indexed by type
+var/global/list/hair_accesories_list= list()// Stores /datum/sprite_accessory/hair_accessory indexed by type
var/global/list/tail_styles_list = list() // Stores /datum/sprite_accessory/tail indexed by type
var/global/list/wing_styles_list = list() // Stores /datum/sprite_accessory/wing indexed by type
var/global/list/negative_traits = list() // Negative custom species traits, indexed by path
var/global/list/neutral_traits = list() // Neutral custom species traits, indexed by path
+var/global/list/everyone_traits = list() // Neutral traits available to all species, indexed by path
var/global/list/positive_traits = list() // Positive custom species traits, indexed by path
var/global/list/traits_costs = list() // Just path = cost list, saves time in char setup
var/global/list/all_traits = list() // All of 'em at once (same instances)
+var/global/list/active_ghost_pods = list()
var/global/list/sensorpreflist = list("Off", "Binary", "Vitals", "Tracking", "No Preference") //TFF 5/8/19 - Suit Sensors global list
@@ -105,30 +108,74 @@ var/global/list/fancy_release_sounds = list(
)
var/global/list/global_vore_egg_types = list(
- "Unathi" = UNATHI_EGG,
- "Tajaran" = TAJARAN_EGG,
- "Akula" = AKULA_EGG,
- "Skrell" = SKRELL_EGG,
- "Nevrean" = NEVREAN_EGG,
- "Sergal" = SERGAL_EGG,
- "Human" = HUMAN_EGG,
- "Slime" = SLIME_EGG,
- "Egg" = EGG_EGG,
- "Xenochimera" = XENOCHIMERA_EGG,
- "Xenomorph" = XENOMORPH_EGG)
+ "Unathi",
+ "Tajara",
+ "Akula",
+ "Skrell",
+ "Sergal",
+ "Nevrean",
+ "Human",
+ "Slime",
+ "Egg",
+ "Xenochimera",
+ "Xenomorph",
+ "Chocolate",
+ "Boney",
+ "Slime glob",
+ "Chicken",
+ "Synthetic",
+ "Bluespace Floppy",
+ "Bluespace Compressed File",
+ "Bluespace CD",
+ "Escape pod",
+ "Cooking error",
+ "Web cocoon",
+ "Honeycomb",
+ "Bug cocoon",
+ "Rock",
+ "Yellow",
+ "Blue",
+ "Green",
+ "Orange",
+ "Purple",
+ "Red",
+ "Rainbow",
+ "Spotted pink")
var/global/list/tf_vore_egg_types = list(
- "Unathi" = /obj/structure/closet/secure_closet/egg/unathi,
- "Tajara" = /obj/structure/closet/secure_closet/egg/tajaran,
- "Akula" = /obj/structure/closet/secure_closet/egg/shark,
- "Skrell" = /obj/structure/closet/secure_closet/egg/skrell,
- "Sergal" = /obj/structure/closet/secure_closet/egg/sergal,
- "Nevrean" = /obj/structure/closet/secure_closet/egg/nevrean,
- "Human" = /obj/structure/closet/secure_closet/egg/human,
- "Slime" = /obj/structure/closet/secure_closet/egg/slime,
- "Egg" = /obj/structure/closet/secure_closet/egg,
- "Xenochimera" = /obj/structure/closet/secure_closet/egg/scree,
- "Xenomorph" = /obj/structure/closet/secure_closet/egg/xenomorph)
+ "Unathi" = /obj/item/weapon/storage/vore_egg/unathi,
+ "Tajara" = /obj/item/weapon/storage/vore_egg/tajaran,
+ "Akula" = /obj/item/weapon/storage/vore_egg/shark,
+ "Skrell" = /obj/item/weapon/storage/vore_egg/skrell,
+ "Sergal" = /obj/item/weapon/storage/vore_egg/sergal,
+ "Nevrean" = /obj/item/weapon/storage/vore_egg/nevrean,
+ "Human" = /obj/item/weapon/storage/vore_egg/human,
+ "Slime" = /obj/item/weapon/storage/vore_egg/slime,
+ "Egg" = /obj/item/weapon/storage/vore_egg,
+ "Xenochimera" = /obj/item/weapon/storage/vore_egg/scree,
+ "Xenomorph" = /obj/item/weapon/storage/vore_egg/xenomorph,
+ "Chocolate" = /obj/item/weapon/storage/vore_egg/chocolate,
+ "Boney" = /obj/item/weapon/storage/vore_egg/owlpellet,
+ "Slime glob" = /obj/item/weapon/storage/vore_egg/slimeglob,
+ "Chicken" = /obj/item/weapon/storage/vore_egg/chicken,
+ "Synthetic" = /obj/item/weapon/storage/vore_egg/synthetic,
+ "Bluespace Floppy" = /obj/item/weapon/storage/vore_egg/floppy,
+ "Bluespace Compressed File" = /obj/item/weapon/storage/vore_egg/file,
+ "Bluespace CD" = /obj/item/weapon/storage/vore_egg/cd,
+ "Escape pod" = /obj/item/weapon/storage/vore_egg/escapepod,
+ "Cooking error" = /obj/item/weapon/storage/vore_egg/badrecipe,
+ "Web cocoon" = /obj/item/weapon/storage/vore_egg/cocoon,
+ "Honeycomb" = /obj/item/weapon/storage/vore_egg/honeycomb,
+ "Bug cocoon" = /obj/item/weapon/storage/vore_egg/bugcocoon,
+ "Rock" = /obj/item/weapon/storage/vore_egg/rock,
+ "Yellow" = /obj/item/weapon/storage/vore_egg/yellow,
+ "Blue" = /obj/item/weapon/storage/vore_egg/blue,
+ "Green" = /obj/item/weapon/storage/vore_egg/green,
+ "Orange" = /obj/item/weapon/storage/vore_egg/orange,
+ "Purple" = /obj/item/weapon/storage/vore_egg/purple,
+ "Red" = /obj/item/weapon/storage/vore_egg/red,
+ "Rainbow" = /obj/item/weapon/storage/vore_egg/rainbow,
+ "Spotted pink" = /obj/item/weapon/storage/vore_egg/pinkspots)
var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/clothing/accessory/collar, //TFF 10/7/19 - add option to nom collars,
@@ -179,7 +226,8 @@ var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/weapon/storage/fancy/cigarettes,
/obj/item/weapon/storage/fancy/crayons,
/obj/item/weapon/storage/fancy/egg_box,
- /obj/item/weapon/storage/wallet)
+ /obj/item/weapon/storage/wallet,
+ /obj/item/weapon/storage/vore_egg)
var/global/list/contamination_flavors = list(
"Generic" = contamination_flavors_generic,
@@ -451,6 +499,12 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
var/datum/sprite_accessory/wing/instance = new path()
wing_styles_list[path] = instance
+ // Custom Hair Accessories
+ paths = typesof(/datum/sprite_accessory/hair_accessory) - /datum/sprite_accessory/hair_accessory
+ for(var/path in paths)
+ var/datum/sprite_accessory/hair_accessory/instance = new path()
+ hair_accesories_list[path] = instance
+
// Custom species traits
paths = typesof(/datum/trait) - /datum/trait
for(var/path in paths)
@@ -465,6 +519,8 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
negative_traits[path] = instance
if(0)
neutral_traits[path] = instance
+ if(!(instance.custom_only))
+ everyone_traits[path] = instance
if(0.1 to INFINITY)
positive_traits[path] = instance
@@ -481,4 +537,22 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
for(var/species_name in whitelisted_icons)
custom_species_bases += species_name
+ // Weaver recipe stuff
+ paths = typesof(/datum/weaver_recipe/structure) - /datum/weaver_recipe/structure
+ for(var/path in paths)
+ var/datum/weaver_recipe/instance = new path()
+ if(!instance.title)
+ continue //A prototype or something
+ weavable_structures[instance.title] = instance
+
+ paths = typesof(/datum/weaver_recipe/item) - /datum/weaver_recipe/item
+ for(var/path in paths)
+ var/datum/weaver_recipe/instance = new path()
+ if(!instance.title)
+ continue //A prototype or something
+ weavable_items[instance.title] = instance
+
return 1 // Hooks must return 1
+
+var/global/list/weavable_structures = list()
+var/global/list/weavable_items = list()
\ No newline at end of file
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index bc7dca1d749..10fcc662f14 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -1290,6 +1290,9 @@ var/mob/dview/dview_mob = new
/proc/dview(var/range = world.view, var/center, var/invis_flags = 0)
if(!center)
return
+ if(!dview_mob) //VOREStation Add: Debugging
+ dview_mob = new
+ log_error("Had to recreate the dview mob!")
dview_mob.loc = center
@@ -1613,6 +1616,46 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
/proc/href(href_src, list/href_params, href_text)
return "[href_text]"
+// This is a helper for anything that wants to render the map in TGUI
+/proc/get_tgui_plane_masters()
+ . = list()
+ // 'Utility' planes
+ . += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
+ . += new /obj/screen/plane_master/lighting //Lighting system (but different!)
+ . += new /obj/screen/plane_master/ghosts //Ghosts!
+ . += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye!
+
+ . += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds
+ . += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar
+ . += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon
+ . += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon
+ . += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status
+ . += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants
+ . += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants
+ . += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants
+ . += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff
+ . += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD
+
+ . += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use
+ . += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use
+ . += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use
+
+ . += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings.
+ . += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode
+
+ // Real tangible stuff planes
+ . += new /obj/screen/plane_master/main{plane = TURF_PLANE}
+ . += new /obj/screen/plane_master/main{plane = OBJ_PLANE}
+ . += new /obj/screen/plane_master/main{plane = MOB_PLANE}
+ . += new /obj/screen/plane_master/cloaked //Cloaked atoms!
+
+ //VOREStation Add - Random other plane masters
+ . += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_R} //Right-side status icon
+ . += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH_VR} //Health bar but transparent at 100
+ . += new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status
+ . += new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags
+ . += new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality
+ //VOREStation Add End
/proc/CallAsync(datum/source, proctype, list/arguments)
set waitfor = FALSE
- return call(source, proctype)(arglist(arguments))
\ No newline at end of file
+ return call(source, proctype)(arglist(arguments))
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 6a4579f1919..b29a1192d9b 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -354,19 +354,13 @@
facedir(direction)
/obj/screen/click_catcher
+ name = "Darkness"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher"
plane = CLICKCATCHER_PLANE
+ layer = LAYER_HUD_UNDER
mouse_opacity = 2
- screen_loc = "CENTER-7,CENTER-7"
-
-/obj/screen/click_catcher/proc/MakeGreed()
- . = list()
- for(var/i = 0, i<15, i++)
- for(var/j = 0, j<15, j++)
- var/obj/screen/click_catcher/CC = new()
- CC.screen_loc = "NORTH-[i],EAST-[j]"
- . += CC
+ screen_loc = "SOUTHWEST to NORTHEAST"
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
@@ -374,7 +368,8 @@
var/mob/living/carbon/C = usr
C.swap_hand()
else
- var/turf/T = screen_loc2turf(screen_loc, get_turf(usr))
+ var/list/P = params2list(params)
+ var/turf/T = screen_loc2turf(P["screen-loc"], get_turf(usr))
if(T)
T.Click(location, control, params)
. = 1
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index d63d49e8d76..213fe57b90e 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -60,6 +60,8 @@
// Cyborgs have no range-checking unless there is item use
if(!W)
+ if(bolt && !bolt.malfunction && A.loc != module)
+ return
A.add_hiddenprint(src)
A.attack_robot(src)
return
@@ -120,35 +122,56 @@
/atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user)
-/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/user)
+/obj/machinery/door/airlock/BorgCtrlShiftClick(var/mob/living/silicon/robot/user)
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlShiftClick(user)
/atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user)
-/obj/machinery/door/airlock/BorgShiftClick(mob/user) // Opens and closes doors! Forwards to AI code.
+/obj/machinery/door/airlock/BorgShiftClick(var/mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIShiftClick(user)
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user)
-/obj/machinery/door/airlock/BorgCtrlClick(mob/user) // Bolts doors. Forwards to AI code.
+/obj/machinery/door/airlock/BorgCtrlClick(var/mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
-/obj/machinery/power/apc/BorgCtrlClick(mob/user) // turns off/on APCs. Forwards to AI code.
+/obj/machinery/power/apc/BorgCtrlClick(var/mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
-/obj/machinery/turretid/BorgCtrlClick(mob/user) //turret control on/off. Forwards to AI code.
+/obj/machinery/turretid/BorgCtrlClick(var/mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AICtrlClick(user)
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
AltClick(user)
return
-/obj/machinery/door/airlock/BorgAltClick(mob/user) // Eletrifies doors. Forwards to AI code.
+/obj/machinery/door/airlock/BorgAltClick(var/mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIAltClick(user)
-/obj/machinery/turretid/BorgAltClick(mob/user) //turret lethal on/off. Forwards to AI code.
+/obj/machinery/turretid/BorgAltClick(var/mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
+ if(user.bolt && !user.bolt.malfunction)
+ return
+
AIAltClick(user)
/*
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index d31a64dcda6..247d1d3f8bf 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -161,6 +161,13 @@
#define ui_ghost_pai "SOUTH: 6,CENTER+2:24"
#define ui_ghost_updown "SOUTH: 6,CENTER+3:24"
+// NIF Soulcatcher guest ones
+#define ui_nifsc_reenter "SOUTH:6,CENTER-3:24"
+#define ui_nifsc_arproj "SOUTH:6,CENTER-2:24"
+#define ui_nifsc_jumptoowner "SOUTH:6,CENTER-1:24"
+#define ui_nifsc_nme "SOUTH:6,CENTER:24"
+#define ui_nifsc_nsay "SOUTH:6,CENTER+1:24"
+
// Rig panel
#define ui_rig_deco1 "WEST:-7, SOUTH+5"
#define ui_rig_deco2 "WEST:-7, SOUTH+6"
diff --git a/code/_onclick/hud/_defines_vr.dm b/code/_onclick/hud/_defines_vr.dm
index 2b4f4fb85e2..b419c6bd7f8 100644
--- a/code/_onclick/hud/_defines_vr.dm
+++ b/code/_onclick/hud/_defines_vr.dm
@@ -1,3 +1,2 @@
-#define ui_shadekin_dark_display "EAST-1:28,CENTER-3:15"
-#define ui_shadekin_energy_display "EAST-1:28,CENTER-4:15"
+#define ui_shadekin_display "EAST-1:28,CENTER-3:15"
#define ui_xenochimera_danger_display "EAST-1:28,CENTER-3:15"
\ No newline at end of file
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 6387f40d9ec..22e8e459fc5 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -14,7 +14,7 @@
var/other = list()
var/hotkeybuttons = list()
var/slot_info = list()
-
+
HUD.adding = adding
HUD.other = other
HUD.hotkeybuttons = hotkeybuttons //These can be disabled for hotkey users
@@ -258,15 +258,10 @@
hud_elements |= healths
//VOREStation Addition begin
- shadekin_dark_display = new /obj/screen/shadekin/darkness()
- shadekin_dark_display.screen_loc = ui_shadekin_dark_display
- shadekin_dark_display.icon_state = "dark"
- hud_elements |= shadekin_dark_display
-
- shadekin_energy_display = new /obj/screen/shadekin/energy()
- shadekin_energy_display.screen_loc = ui_shadekin_energy_display
- shadekin_energy_display.icon_state = "energy0"
- hud_elements |= shadekin_energy_display
+ shadekin_display = new /obj/screen/shadekin()
+ shadekin_display.screen_loc = ui_shadekin_display
+ shadekin_display.icon_state = "shadekin"
+ hud_elements |= shadekin_display
xenochimera_danger_display = new /obj/screen/xenochimera/danger_level()
xenochimera_danger_display.screen_loc = ui_xenochimera_danger_display
diff --git a/code/_onclick/hud/screen_objects_vr.dm b/code/_onclick/hud/screen_objects_vr.dm
index b3388f7bf76..1d8df98a38b 100644
--- a/code/_onclick/hud/screen_objects_vr.dm
+++ b/code/_onclick/hud/screen_objects_vr.dm
@@ -11,6 +11,11 @@
var/mob/living/simple_mob/shadekin/SK = usr
if(istype(SK))
to_chat(usr,"Energy: [SK.energy] ([SK.dark_gains])")
+ if("shadekin status")
+ var/turf/T = get_turf(usr)
+ if(T)
+ var/darkness = round(1 - T.get_lumcount(),0.1)
+ to_chat(usr,"Darkness: [darkness]")
var/mob/living/carbon/human/H = usr
if(istype(H) && istype(H.species, /datum/species/shadekin))
to_chat(usr,"Energy: [H.shadekin_get_energy(H)]")
diff --git a/code/_onclick/hud/soulcatcher_guest.dm b/code/_onclick/hud/soulcatcher_guest.dm
new file mode 100644
index 00000000000..555bcb8ebaf
--- /dev/null
+++ b/code/_onclick/hud/soulcatcher_guest.dm
@@ -0,0 +1,102 @@
+/obj/screen/nifsc
+ icon = 'icons/mob/screen_nifsc.dmi'
+
+/obj/screen/nifsc/MouseEntered(location,control,params)
+ flick(icon_state + "_anim", src)
+ openToolTip(usr, src, params, title = name, content = desc)
+
+/obj/screen/nifsc/MouseExited()
+ closeToolTip(usr)
+
+/obj/screen/nifsc/Click()
+ closeToolTip(usr)
+
+/obj/screen/nifsc/reenter
+ name = "Re-enter NIF"
+ desc = "Return into the NIF"
+ icon_state = "reenter"
+
+/obj/screen/nifsc/reenter/Click()
+ ..()
+ var/mob/living/carbon/brain/caught_soul/CS = usr
+ CS.reenter_soulcatcher()
+
+/obj/screen/nifsc/arproj
+ name = "AR project"
+ desc = "Project your form into Augmented Reality for those around your predator with the appearance of your loaded character."
+ icon_state = "arproj"
+
+/obj/screen/nifsc/arproj/Click()
+ ..()
+ var/mob/living/carbon/brain/caught_soul/CS = usr
+ CS.ar_project()
+
+/obj/screen/nifsc/jumptoowner
+ name = "Jump back to host"
+ desc = "Jumb back to the Soulcather host"
+ icon_state = "jump"
+
+/obj/screen/nifsc/jumptoowner/Click()
+ ..()
+ var/mob/living/carbon/brain/caught_soul/CS = usr
+ CS.jump_to_owner()
+
+/obj/screen/nifsc/nme
+ name = "Emote into Soulcatcher"
+ desc = "Emote into the NIF's Soulcatcher (circumventing AR emoting)"
+ icon_state = "nme"
+
+/obj/screen/nifsc/nme/Click()
+ ..()
+ var/mob/living/carbon/brain/caught_soul/CS = usr
+ CS.nme()
+
+/obj/screen/nifsc/nsay
+ name = "Speak into Soulcatcher"
+ desc = "Speak into the NIF's Soulcatcher (circumventing AR speaking)"
+ icon_state = "nsay"
+
+/obj/screen/nifsc/nsay/Click()
+ ..()
+ var/mob/living/carbon/brain/caught_soul/CS = usr
+ CS.nsay()
+
+
+/mob/living/carbon/brain/caught_soul/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE)
+ ..()
+
+ var/list/adding = list()
+ HUD.adding = adding
+
+ var/obj/screen/using
+
+ using = new /obj/screen/nifsc/reenter()
+ using.screen_loc = ui_nifsc_reenter
+ using.hud = src
+ adding += using
+
+ using = new /obj/screen/nifsc/arproj()
+ using.screen_loc = ui_nifsc_arproj
+ using.hud = src
+ adding += using
+
+ using = new /obj/screen/nifsc/jumptoowner()
+ using.screen_loc = ui_nifsc_jumptoowner
+ using.hud = src
+ adding += using
+
+ using = new /obj/screen/nifsc/nme()
+ using.screen_loc = ui_nifsc_nme
+ using.hud = src
+ adding += using
+
+ using = new /obj/screen/nifsc/nsay()
+ using.screen_loc = ui_nifsc_nsay
+ using.hud = src
+ adding += using
+
+
+ if(client && apply_to_client)
+ client.screen = list()
+ client.screen += HUD.adding
+ client.screen += client.void
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 2b7aa15bbc0..67d14623cf6 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -496,7 +496,7 @@ var/list/gamemode_cache = list()
config.respawn_time = raw_minutes MINUTES
if ("respawn_message")
- config.respawn_message = value
+ config.respawn_message = "[value]"
if ("servername")
config.server_name = value
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 60b08c71d2c..77c9d3ab94a 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(overlays)
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
- var/initialized = FALSE
var/list/queue // Queue of atoms needing overlay compiling (TODO-VERIFY!)
var/list/stats
var/list/overlay_icon_state_caches // Cache thing
@@ -22,7 +21,6 @@ var/global/image/appearance_bro = new() // Temporarily super-global because of B
stats = list()
/datum/controller/subsystem/overlays/Initialize()
- initialized = TRUE
fire(mc_check = FALSE)
..()
diff --git a/code/controllers/subsystems/processing/chemistry.dm b/code/controllers/subsystems/processing/chemistry.dm
index 7f4fd9c42b6..b4641ba7e00 100644
--- a/code/controllers/subsystems/processing/chemistry.dm
+++ b/code/controllers/subsystems/processing/chemistry.dm
@@ -22,6 +22,7 @@ PROCESSING_SUBSYSTEM_DEF(chemistry)
/datum/controller/subsystem/processing/chemistry/Initialize()
initialize_chemical_reactions()
initialize_chemical_reagents()
+ ..()
//Chemical Reactions - Initialises all /datum/chemical_reaction into a list
// It is filtered into multiple lists within a list.
diff --git a/code/controllers/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm
index 0bce9403851..40039edceb5 100644
--- a/code/controllers/subsystems/shuttles.dm
+++ b/code/controllers/subsystems/shuttles.dm
@@ -4,9 +4,6 @@
// Also handles initialization and processing of overmap sectors.
//
-// This global variable exists for legacy support so we don't have to rename every shuttle_controller to SSshuttles yet.
-var/global/datum/controller/subsystem/shuttles/shuttle_controller
-
SUBSYSTEM_DEF(shuttles)
name = "Shuttles"
wait = 2 SECONDS
@@ -35,9 +32,6 @@ SUBSYSTEM_DEF(shuttles)
var/tmp/list/current_run // Shuttles remaining to process this fire() tick
-/datum/controller/subsystem/shuttles/PreInit()
- global.shuttle_controller = src // TODO - Remove this! Change everything to point at SSshuttles intead
-
/datum/controller/subsystem/shuttles/Initialize(timeofday)
last_landmark_registration_time = world.time
// Find all declared shuttle datums and initailize them. (Okay, queue them for initialization a few lines further down)
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index cdb2adefde3..750f6807cca 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -49,10 +49,7 @@ var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/Initialize()
pregame_timeleft = config.pregame_time
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
-
- // Set up the global announcer
- GLOB.autospeaker = new (null, null, null, 1)
-
+ GLOB.autospeaker = new (null, null, null, 1) //Set up Global Announcer
return ..()
/datum/controller/subsystem/ticker/fire(resumed = FALSE)
@@ -186,11 +183,6 @@ var/global/datum/controller/subsystem/ticker/ticker
if(adm["total"] == 0)
send2adminirc("A round has started with no admins online.")
-/* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler
- master_controller.process() //Start master_controller.process()
- lighting_controller.process() //Start processing DynamicAreaLighting updates
- */
-
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
diff --git a/code/datums/autolathe/devices.dm b/code/datums/autolathe/devices.dm
index 9c6ab5bb97e..eed4839159c 100644
--- a/code/datums/autolathe/devices.dm
+++ b/code/datums/autolathe/devices.dm
@@ -26,6 +26,12 @@
name = "mechanical trap"
path =/obj/item/weapon/beartrap
+/datum/category_item/autolathe/devices/barbedwire
+ name = "barbed wire"
+ path = /obj/item/weapon/material/barbedwire
+ hidden = 1
+ resources = list(DEFAULT_WALL_MATERIAL = 10000)
+
/datum/category_item/autolathe/devices/electropack
name = "electropack"
path =/obj/item/device/radio/electropack
diff --git a/code/datums/autolathe/engineering_vr.dm b/code/datums/autolathe/engineering_vr.dm
index 08e1cf986bf..90970c6e481 100644
--- a/code/datums/autolathe/engineering_vr.dm
+++ b/code/datums/autolathe/engineering_vr.dm
@@ -4,4 +4,24 @@
/datum/category_item/autolathe/engineering/id_restorer
name = "ID restoration console electronics"
- path =/obj/item/weapon/circuitboard/id_restorer
\ No newline at end of file
+ path =/obj/item/weapon/circuitboard/id_restorer
+
+/datum/category_item/autolathe/engineering/oven
+ name = "oven electronics"
+ path =/obj/item/weapon/circuitboard/oven
+
+/datum/category_item/autolathe/engineering/fryer
+ name = "fryer electronics"
+ path =/obj/item/weapon/circuitboard/fryer
+
+/datum/category_item/autolathe/engineering/grill
+ name = "grill electronics"
+ path =/obj/item/weapon/circuitboard/grill
+
+/datum/category_item/autolathe/engineering/cerealmaker
+ name = "cereal maker electronics"
+ path =/obj/item/weapon/circuitboard/cerealmaker
+
+/datum/category_item/autolathe/engineering/candymachine
+ name = "candy machine electronics"
+ path =/obj/item/weapon/circuitboard/candymachine
\ No newline at end of file
diff --git a/code/datums/autolathe/tools.dm b/code/datums/autolathe/tools.dm
index 9e9a87ea71f..9b88a496fa9 100644
--- a/code/datums/autolathe/tools.dm
+++ b/code/datums/autolathe/tools.dm
@@ -48,6 +48,11 @@
path = /obj/item/weapon/reagent_containers/spray
resources = list(MAT_PLASTIC = 2000)
+/datum/category_item/autolathe/devices/slowwire
+ name = "snare wire"
+ path = /obj/item/weapon/material/barbedwire/plastic
+ resources = list(MAT_PLASTIC = 10000)
+
/datum/category_item/autolathe/tools/spraynozzle
name = "spray nozzle"
path = /obj/item/weapon/reagent_containers/spray
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index bca9df5ae1e..82e5f1f78bd 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -55,6 +55,9 @@
var/rev_cooldown = 0
var/tcrystals = 0
+ var/list/purchase_log = new
+ var/used_TC = 0
+
// the world.time since the mob has been brigged, or -1 if not at all
var/brigged_since = -1
@@ -73,7 +76,7 @@
/datum/mind/New(var/key)
src.key = key
-
+ purchase_log = list()
..()
/datum/mind/proc/transfer_to(mob/living/new_character)
@@ -510,8 +513,9 @@
//HUMAN
/mob/living/carbon/human/mind_initialize()
- ..()
- if(!mind.assigned_role) mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
+ . = ..()
+ if(!mind.assigned_role)
+ mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
//slime
/mob/living/simple_mob/slime/mind_initialize()
diff --git a/code/datums/observation/~cleanup.dm b/code/datums/observation/~cleanup.dm
index 825902d4839..9dcc601436a 100644
--- a/code/datums/observation/~cleanup.dm
+++ b/code/datums/observation/~cleanup.dm
@@ -43,7 +43,7 @@ GLOBAL_LIST_EMPTY(event_listen_count)
for(var/entry in GLOB.all_observable_events.events)
var/decl/observ/event = entry
if(event.unregister_global(listener))
- log_debug("[event] - [listener] was deleted while still registered to global events.")
+ // log_debug("[event] - [listener] was deleted while still registered to global events.") // TODO: Apply axe, reimplement with datum component listeners
if(!(--listen_count))
return
@@ -55,7 +55,7 @@ GLOBAL_LIST_EMPTY(event_listen_count)
if(proc_owners)
for(var/proc_owner in proc_owners)
if(event.unregister(event_source, proc_owner))
- log_debug("[event] - [event_source] was deleted while still being listened to by [proc_owner].")
+ // log_debug("[event] - [event_source] was deleted while still being listened to by [proc_owner].") // TODO: Apply axe, reimplement with datum component listeners
if(!(--source_listener_count))
return
@@ -65,6 +65,6 @@ GLOBAL_LIST_EMPTY(event_listen_count)
var/decl/observ/event = entry
for(var/event_source in event.event_sources)
if(event.unregister(event_source, listener))
- log_debug("[event] - [listener] was deleted while still listening to [event_source].")
+ // log_debug("[event] - [listener] was deleted while still listening to [event_source].") // TODO: Apply axe, reimplement with datum component listeners
if(!(--listener_count))
return
\ No newline at end of file
diff --git a/code/datums/outfits/jobs/special_vr.dm b/code/datums/outfits/jobs/special_vr.dm
index dd8316358b6..010010291dd 100644
--- a/code/datums/outfits/jobs/special_vr.dm
+++ b/code/datums/outfits/jobs/special_vr.dm
@@ -9,6 +9,21 @@
id_type = /obj/item/weapon/card/id/centcom
pda_type = /obj/item/device/pda/centcom
+/decl/hierarchy/outfit/job/emergency_responder
+ name = OUTFIT_JOB_NAME("Emergency Responder")
+ uniform = /obj/item/clothing/under/ert
+ shoes = /obj/item/clothing/shoes/boots/swat
+ gloves = /obj/item/clothing/gloves/swat
+ l_ear = /obj/item/device/radio/headset/ert
+ glasses = /obj/item/clothing/glasses/sunglasses
+ back = /obj/item/weapon/storage/backpack/satchel
+ id_type = /obj/item/weapon/card/id/centcom/ERT
+ pda_type = /obj/item/device/pda/centcom
+
+ post_equip(var/mob/living/carbon/human/H)
+ ..()
+ ert.add_antagonist(H.mind)
+
/decl/hierarchy/outfit/job/clown
name = OUTFIT_JOB_NAME("Clown")
uniform = /obj/item/clothing/under/rank/clown
diff --git a/code/datums/roundstats/_defines_local.dm b/code/datums/roundstats/_defines_local.dm
new file mode 100644
index 00000000000..951d7118ff8
--- /dev/null
+++ b/code/datums/roundstats/_defines_local.dm
@@ -0,0 +1,7 @@
+
+#define GOAL_GENERAL "Common Goal"
+#define GOAL_MEDICAL "Medical Goal"
+#define GOAL_SECURITY "Security Goal"
+#define GOAL_ENGINEERING "Engineering Goal"
+#define GOAL_CARGO "Cargo Goal"
+#define GOAL_RESEARCH "Research Goal"
diff --git a/code/datums/roundstats/departmentgoal.dm b/code/datums/roundstats/departmentgoal.dm
new file mode 100644
index 00000000000..333e6c03963
--- /dev/null
+++ b/code/datums/roundstats/departmentgoal.dm
@@ -0,0 +1,101 @@
+
+GLOBAL_LIST(department_goals)
+GLOBAL_LIST(active_department_goals)
+
+/hook/startup/proc/initializeDepartmentGoals()
+ GLOB.department_goals = list(GOAL_GENERAL, GOAL_MEDICAL, GOAL_SECURITY, GOAL_ENGINEERING, GOAL_CARGO, GOAL_RESEARCH)
+ GLOB.active_department_goals = list(GOAL_GENERAL, GOAL_MEDICAL, GOAL_SECURITY, GOAL_ENGINEERING, GOAL_CARGO, GOAL_RESEARCH)
+
+ for(var/category in GLOB.department_goals)
+ GLOB.department_goals[category] = list()
+
+ for(var/subtype in subtypesof(/datum/goal))
+ var/datum/goal/SG = new subtype()
+
+ if(SG.name == "goal")
+ continue
+
+ if(SG.category == category)
+ GLOB.department_goals[category] |= SG
+
+ for(var/category in GLOB.active_department_goals)
+ GLOB.active_department_goals[category] = list()
+ var/list/cat_goals = GLOB.department_goals[category]
+
+ var/goal_count = rand(2,4)
+
+ for(var/count = 1 to goal_count)
+ var/datum/goal/G
+
+ if(LAZYLEN(cat_goals))
+ G = pick(cat_goals)
+
+ if(G)
+ G.active_goal = TRUE
+ cat_goals -= G
+
+ GLOB.active_department_goals[category] |= G
+ return 1
+
+/hook/roundend/proc/checkDepartmentGoals()
+ for(var/category in GLOB.active_department_goals)
+ var/list/cat_goals = GLOB.active_department_goals[category]
+
+ to_world("[category]")
+
+ if(!LAZYLEN(cat_goals))
+ to_world("There were no assigned goals!")
+
+ else
+ for(var/datum/goal/G in cat_goals)
+ var/success = G.check_completion()
+ to_world("[success ? "[G.name]" : "[G.name]"]")
+ to_world("[G.goal_text]")
+ return 1
+
+/datum/goal
+ var/name = "goal"
+
+ var/goal_text = "Do nothing! Congratulations."
+
+ var/active_goal = FALSE
+
+ var/category = GOAL_GENERAL
+
+/datum/goal/proc/check_completion()
+ return FALSE
+
+/datum/goal/common
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+
+/datum/goal/medical
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+ category = GOAL_MEDICAL
+
+/datum/goal/security
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+ category = GOAL_SECURITY
+
+/datum/goal/engineering
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+ category = GOAL_ENGINEERING
+
+/datum/goal/cargo
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+ category = GOAL_CARGO
+
+/datum/goal/research
+ name = "goal"
+
+ goal_text = "Congratulations, you still do nothing."
+ category = GOAL_RESEARCH
diff --git a/code/datums/roundstats/roundstats.dm b/code/datums/roundstats/roundstats.dm
new file mode 100644
index 00000000000..c1453b18aff
--- /dev/null
+++ b/code/datums/roundstats/roundstats.dm
@@ -0,0 +1,57 @@
+
+/*
+ * lbnesquik - Github
+ * Provided massive components of this. Polaris PR #5720.
+ */
+
+//This is for the round end stats system.
+
+//roundstat is used for easy finding of the variables, if you ever want to delete all of this,
+//just search roundstat and you'll find everywhere this thing reaches into.
+//It used to be bazinga but it only fly with microwaves.
+
+GLOBAL_VAR_INIT(cans_opened_roundstat, 0)
+GLOBAL_VAR_INIT(lights_switched_on_roundstat, 0)
+GLOBAL_VAR_INIT(turbo_lift_floors_moved_roundstat, 0)
+GLOBAL_VAR_INIT(lost_limbs_shift_roundstat, 0)
+GLOBAL_VAR_INIT(seed_planted_shift_roundstat, 0)
+GLOBAL_VAR_INIT(step_taken_shift_roundstat, 0)
+GLOBAL_VAR_INIT(destroyed_research_items_roundstat, 0)
+GLOBAL_VAR_INIT(items_sold_shift_roundstat, 0)
+GLOBAL_VAR_INIT(disposals_flush_shift_roundstat, 0)
+GLOBAL_VAR_INIT(rocks_drilled_roundstat, 0)
+GLOBAL_VAR_INIT(mech_destroyed_roundstat, 0)
+
+/hook/roundend/proc/RoundTrivia()//bazinga
+ var/list/valid_stats_list = list() //This is to be populated with the good shit
+
+ if(GLOB.lost_limbs_shift_roundstat > 1)
+ valid_stats_list.Add("[GLOB.lost_limbs_shift_roundstat] limbs left their owners bodies this shift, oh no!")
+ else if(GLOB.destroyed_research_items_roundstat > 13)
+ valid_stats_list.Add("[GLOB.destroyed_research_items_roundstat] objects were destroyed in the name of Science! Keep it up!")
+ else if(GLOB.mech_destroyed_roundstat > 1)
+ valid_stats_list.Add("[GLOB.mech_destroyed_roundstat] mechs were destroyed this shift. What did you do?")
+ else if(GLOB.seed_planted_shift_roundstat > 20)
+ valid_stats_list.Add("[GLOB.seed_planted_shift_roundstat] seeds were planted according to our sensors this shift.")
+
+ if(GLOB.rocks_drilled_roundstat > 80)
+ valid_stats_list.Add("Our strong miners pulverized a whole [GLOB.rocks_drilled_roundstat] piles of pathetic rubble.")
+ else if(GLOB.items_sold_shift_roundstat > 15)
+ valid_stats_list.Add("The vending machines sold [GLOB.items_sold_shift_roundstat] items today.")
+ else if(GLOB.step_taken_shift_roundstat > 900)
+ valid_stats_list.Add("The employees walked a total of [GLOB.step_taken_shift_roundstat] steps for this shift! It should put them on the road to fitness!")
+
+ if(GLOB.cans_opened_roundstat > 0)
+ valid_stats_list.Add("[GLOB.cans_opened_roundstat] cans were drank today!")
+ else if(GLOB.lights_switched_on_roundstat > 0)
+ valid_stats_list.Add("[GLOB.lights_switched_on_roundstat] light switches were flipped today!")
+ else if(GLOB.turbo_lift_floors_moved_roundstat > 20)
+ valid_stats_list.Add("The elevator moved up [GLOB.turbo_lift_floors_moved_roundstat] floors today!")
+ else if(GLOB.disposals_flush_shift_roundstat > 40)
+ valid_stats_list.Add("The disposal system flushed a whole [GLOB.disposals_flush_shift_roundstat] times for this shift. We should really invest in waste treatement.")
+
+ if(LAZYLEN(valid_stats_list))
+ to_world("Shift trivia!")
+
+ for(var/body in valid_stats_list)
+ to_world("[body]")
diff --git a/code/datums/supplypacks/costumes_vr.dm b/code/datums/supplypacks/costumes_vr.dm
index 995e935648b..e31fb2415a4 100644
--- a/code/datums/supplypacks/costumes_vr.dm
+++ b/code/datums/supplypacks/costumes_vr.dm
@@ -21,14 +21,20 @@
/datum/supply_pack/costumes/tesh_smocks_vr
name = "Teshari smocks"
+ num_contained = 4
contains = list(
/obj/item/clothing/under/seromi/smock,
- /obj/item/clothing/under/seromi/smock/rainbow,
- /obj/item/clothing/under/seromi/smock/red,
/obj/item/clothing/under/seromi/smock/white,
- /obj/item/clothing/under/seromi/smock/yellow
+ /obj/item/clothing/under/seromi/smock/red,
+ /obj/item/clothing/under/seromi/smock/yellow,
+ /obj/item/clothing/under/seromi/smock/rainbow,
+ /obj/item/clothing/under/seromi/smock/dress,
+ /obj/item/clothing/under/seromi/smock/blackutilitysmock,
+ /obj/item/clothing/under/seromi/smock/greydress,
+ /obj/item/clothing/under/seromi/smock/blackutility,
+ /obj/item/clothing/under/seromi/smock/bluegreydress
)
- cost = 25
+ cost = 20
containertype = /obj/structure/closet/crate
containername = "Teshari smocks crate"
@@ -36,18 +42,18 @@
name = "Teshari undercoats"
num_contained = 4
contains = list(
- /obj/item/clothing/under/seromi/undercoat/standard/blue_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/brown_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/green_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/lightgrey_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/orange,
/obj/item/clothing/under/seromi/undercoat/standard/orange_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/pink_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/purple_grey,
/obj/item/clothing/under/seromi/undercoat/standard/rainbow,
- /obj/item/clothing/under/seromi/undercoat/standard/red_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/lightgrey_grey,
/obj/item/clothing/under/seromi/undercoat/standard/white_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/yellow_grey
+ /obj/item/clothing/under/seromi/undercoat/standard/red_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/orange,
+ /obj/item/clothing/under/seromi/undercoat/standard/yellow_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/green_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/blue_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/purple_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/pink_grey,
+ /obj/item/clothing/under/seromi/undercoat/standard/brown_grey
)
cost = 20
containertype = /obj/structure/closet/crate
@@ -57,19 +63,18 @@
name = "Teshari undercoats (black)"
num_contained = 4
contains = list(
- /obj/item/clothing/under/seromi/undercoat/standard/black,
- /obj/item/clothing/under/seromi/undercoat/standard/black_blue,
- /obj/item/clothing/under/seromi/undercoat/standard/black_brown,
- /obj/item/clothing/under/seromi/undercoat/standard/black_green,
- /obj/item/clothing/under/seromi/undercoat/standard/black_grey,
- /obj/item/clothing/under/seromi/undercoat/standard/black_lightgrey,
- /obj/item/clothing/under/seromi/undercoat/standard/black_midgrey,
+ /obj/item/clothing/under/seromi/undercoat,
/obj/item/clothing/under/seromi/undercoat/standard/black_orange,
- /obj/item/clothing/under/seromi/undercoat/standard/black_pink,
- /obj/item/clothing/under/seromi/undercoat/standard/black_purple,
- /obj/item/clothing/under/seromi/undercoat/standard/black_red,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_grey,
/obj/item/clothing/under/seromi/undercoat/standard/black_white,
- /obj/item/clothing/under/seromi/undercoat/standard/black_yellow
+ /obj/item/clothing/under/seromi/undercoat/standard/black_red,
+ /obj/item/clothing/under/seromi/undercoat/standard/black,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_yellow,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_green,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_blue,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_purple,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_pink,
+ /obj/item/clothing/under/seromi/undercoat/standard/black_brown
)
cost = 20
containertype = /obj/structure/closet/crate
@@ -79,18 +84,18 @@
name = "Teshari cloaks"
num_contained = 4
contains = list(
- /obj/item/clothing/suit/storage/seromi/cloak/standard/blue_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/brown_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/green_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/lightgrey_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/orange,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/orange_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/pink_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/purple_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/rainbow,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/red_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/white,
/obj/item/clothing/suit/storage/seromi/cloak/standard/white_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/yellow_grey
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/red_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/orange_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/yellow_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/green_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/blue_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/purple_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/pink_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/brown_grey,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/rainbow,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/orange
)
cost = 40
containertype = /obj/structure/closet/crate
@@ -100,19 +105,125 @@
name = "Teshari cloaks (black)"
num_contained = 4
contains = list(
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_blue,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_brown,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_green,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_grey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_lightgrey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_midgrey,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_orange,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_pink,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_purple,
+ /obj/item/clothing/suit/storage/seromi/cloak,
/obj/item/clothing/suit/storage/seromi/cloak/standard/black_red,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_orange,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_yellow,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_green,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_blue,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_purple,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_pink,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_brown,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_grey,
/obj/item/clothing/suit/storage/seromi/cloak/standard/black_white,
- /obj/item/clothing/suit/storage/seromi/cloak/standard/black_yellow
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/black_glow,
+ /obj/item/clothing/suit/storage/seromi/cloak/standard/dark_retrowave
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate
+ containername = "Teshari cloaks crate"
+
+/datum/supply_pack/costumes/tesh_worksuits_vr
+ name = "Teshari worksuits"
+ num_contained = 4
+ contains = list(
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/blackpurple,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/blackorange,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/blackblue,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/blackgreen,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/whitered,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/whitepurple,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/whiteorange,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/whiteblue,
+ /obj/item/clothing/under/seromi/undercoat/standard/worksuit/whitegreen
+ )
+ cost = 20
+ containertype = /obj/structure/closet/crate
+ containername = "Teshari worksuits crate"
+
+/datum/supply_pack/randomised/costumes/tesh_beltcloaks_vr
+ name = "Teshari cloaks (belted)"
+ num_contained = 4
+ contains = list(
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/orange_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/rainbow,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/lightgrey_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/white_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/red_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/orange,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/yellow_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/green_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/blue_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/purple_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/pink_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/brown_grey
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate
+ containername = "Teshari cloaks crate"
+
+/datum/supply_pack/randomised/costumes/tesh_beltcloaks_b_vr
+ name = "Teshari cloaks (belted, black)"
+ num_contained = 4
+ contains = list(
+ /obj/item/clothing/suit/storage/seromi/beltcloak,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_orange,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_grey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_midgrey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_lightgrey,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_white,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_red,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_yellow,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_green,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_blue,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_purple,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_pink,
+ /obj/item/clothing/suit/storage/seromi/beltcloak/standard/black_brown
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate
+ containername = "Teshari cloaks crate"
+
+/datum/supply_pack/randomised/costumes/tesh_hoodcloaks_vr
+ name = "Teshari cloaks (hooded)"
+ num_contained = 4
+ contains = list(
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/orange_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/lightgrey_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/white_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/red_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/orange,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/yellow_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/green_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/blue_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/purple_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/pink_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/brown_grey
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate
+ containername = "Teshari cloaks crate"
+
+/datum/supply_pack/randomised/costumes/tesh_hoodcloaks_b_vr
+ name = "Teshari cloaks (hooded, black)"
+ num_contained = 4
+ contains = list(
+ /obj/item/clothing/suit/storage/hooded/teshari,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_orange,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_grey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_midgrey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_lightgrey,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_white,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_red,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_yellow,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_green,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_blue,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_purple,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_pink,
+ /obj/item/clothing/suit/storage/hooded/teshari/standard/black_brown
)
cost = 40
containertype = /obj/structure/closet/crate
@@ -262,7 +373,7 @@
cost = 60
containertype = /obj/structure/closet/crate
containername = "Saddlebags crate"
-
+
/datum/supply_pack/costumes/knights_gear
name = "Knights Gear"
contains = list(
diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm
index 165c5fbfef2..28a7431ec16 100644
--- a/code/datums/supplypacks/engineering.dm
+++ b/code/datums/supplypacks/engineering.dm
@@ -77,6 +77,14 @@
containertype = /obj/structure/closet/crate/focalpoint
containername = "advanced hull shield generator crate"
+/datum/supply_pack/eng/pointdefense
+ name = "Point Defense Turret"
+ contains = list(/obj/machinery/porta_turret/pointdefense/orderable)
+ cost = 70
+ containertype = /obj/structure/closet/crate/large/secure/heph
+ containername = "point defense crate"
+ access = access_security
+
/datum/supply_pack/eng/electrical
name = "Electrical maintenance crate"
contains = list(
diff --git a/code/datums/supplypacks/misc.dm b/code/datums/supplypacks/misc.dm
index 0aa29b7b9c9..ed528d3bdd0 100644
--- a/code/datums/supplypacks/misc.dm
+++ b/code/datums/supplypacks/misc.dm
@@ -84,7 +84,8 @@
/obj/item/toy/plushie/borgplushie/scrubpuppy,
/obj/item/toy/plushie/foxbear,
/obj/item/toy/plushie/nukeplushie,
- /obj/item/toy/plushie/otter)
+ /obj/item/toy/plushie/otter,
+ /obj/item/toy/plushie/vox)
//VOREStation Add End
name = "Plushies Crate"
cost = 15
diff --git a/code/datums/supplypacks/munitions_vr.dm b/code/datums/supplypacks/munitions_vr.dm
index e8674dd390c..75f2124c962 100644
--- a/code/datums/supplypacks/munitions_vr.dm
+++ b/code/datums/supplypacks/munitions_vr.dm
@@ -2,7 +2,7 @@
name = "Frontier phaser (station-locked) crate"
contains = list(
/obj/item/weapon/gun/energy/locked/frontier = 2,
- /obj/item/weapon/gun/energy/locked/frontier/holdout = 1,
+ /obj/item/weapon/gun/energy/locked/frontier/holdout = 2,
)
cost = 35
containertype = /obj/structure/closet/crate/secure
diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm
index 9bb6b1a4429..eae37c5869b 100644
--- a/code/datums/supplypacks/recreation.dm
+++ b/code/datums/supplypacks/recreation.dm
@@ -51,7 +51,7 @@
/obj/item/weapon/reagent_containers/glass/paint/purple,
/obj/item/weapon/reagent_containers/glass/paint/black,
/obj/item/weapon/reagent_containers/glass/paint/white,
- /obj/item/weapon/contraband/poster,
+ /obj/item/weapon/contraband/poster/custom,
/obj/item/weapon/wrapping_paper = 3
)
cost = 10
diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index 5f8cf6337c8..1928ee7db68 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -189,6 +189,17 @@
containername = "Jumper kit crate"
access = access_robotics
+/datum/supply_pack/robotics/restrainingbolt
+ name = "Restraining bolt crate"
+ contains = list(
+ /obj/item/weapon/implanter = 1,
+ /obj/item/weapon/implantcase/restrainingbolt = 2
+ )
+ cost = 40
+ containertype = /obj/structure/closet/crate/secure/cybersolutions
+ containername = "Restraining bolt crate"
+ access = access_robotics
+
/datum/supply_pack/robotics/bike
name = "Spacebike Crate"
contains = list()
diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm
index 7da82fa5801..6b2cc3d10f6 100644
--- a/code/datums/underwear/undershirts.dm
+++ b/code/datums/underwear/undershirts.dm
@@ -186,4 +186,14 @@
/datum/category_item/underwear/undershirt/pinkblack_tshirt
name = "Pink and Black T-Shirt"
- icon_state = "pinkblack_tshirt"
\ No newline at end of file
+ icon_state = "pinkblack_tshirt"
+
+/datum/category_item/underwear/undershirt/turtle
+ name = "Turtleneck"
+ icon_state = "turtleneck"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/sleevelessturtle
+ name = "Turtleneck, Sleeveless"
+ icon_state = "sleevelessturtle"
+ has_color = TRUE
\ No newline at end of file
diff --git a/code/datums/uplink/ammunition_vr.dm b/code/datums/uplink/ammunition_vr.dm
index 3235bb7311f..18235e53432 100644
--- a/code/datums/uplink/ammunition_vr.dm
+++ b/code/datums/uplink/ammunition_vr.dm
@@ -18,3 +18,5 @@
name = "Void cell"
path = /obj/item/weapon/cell/device/weapon/recharge/alien/hybrid
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
+ antag_roles = list("ert")
+ blacklisted = 1
diff --git a/code/datums/uplink/backup.dm b/code/datums/uplink/backup.dm
index 40f2a468f67..3e21676da3b 100644
--- a/code/datums/uplink/backup.dm
+++ b/code/datums/uplink/backup.dm
@@ -11,7 +11,7 @@
This type comes with a directional shield projector, a supressive fire energy weapon, \
a stunbaton, handcuffs, an agent ID, energy sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
- antag_roles = list("mercenary")
+ antag_roles = list("mercenary", "ert") //VOREStation Edit
path = /obj/item/weapon/antag_spawner/syndicate_drone/protector
/datum/uplink_item/item/backup/syndicate_drone_combat_medic
@@ -21,7 +21,7 @@
a powerful hypospray that can create many potent chemicals, an agent ID, energy \
sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
- antag_roles = list("mercenary")
+ antag_roles = list("mercenary", "ert") //VOREStation Edit
path = /obj/item/weapon/antag_spawner/syndicate_drone/combat_medic
/datum/uplink_item/item/backup/syndicate_drone_mechanist
@@ -31,5 +31,5 @@
a cryptographic sequencer, an AI detector, the ability to analyze and repair full-body prosthetics, \
a set of construction materials, an ionic rapier, an agent ID, energy sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
- antag_roles = list("mercenary")
+ antag_roles = list("mercenary", "ert") //VOREStation Edit
path = /obj/item/weapon/antag_spawner/syndicate_drone/mechanist
\ No newline at end of file
diff --git a/code/datums/uplink/badassery.dm b/code/datums/uplink/badassery.dm
index 65f71f25847..8addcc3f64e 100644
--- a/code/datums/uplink/badassery.dm
+++ b/code/datums/uplink/badassery.dm
@@ -22,22 +22,22 @@
desc = "Buys you one random item."
/datum/uplink_item/item/badassery/random_one/buy(var/obj/item/device/uplink/U, var/mob/user)
- var/datum/uplink_item/item = default_uplink_selection.get_random_item(U.uses)
+ var/datum/uplink_item/item = default_uplink_selection.get_random_item((user ? user.mind.tcrystals : DEFAULT_TELECRYSTAL_AMOUNT), U)
return item.buy(U, user)
-/datum/uplink_item/item/badassery/random_one/can_buy(obj/item/device/uplink/U)
- return default_uplink_selection.get_random_item(U.uses, U) != null
+/datum/uplink_item/item/badassery/random_one/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
+ return default_uplink_selection.get_random_item(telecrystals, U) != null
/datum/uplink_item/item/badassery/random_many
name = "Random Items"
desc = "Buys you as many random items you can afford. Convenient packaging NOT included."
-/datum/uplink_item/item/badassery/random_many/cost(var/telecrystals)
+/datum/uplink_item/item/badassery/random_many/cost(obj/item/device/uplink/U, var/telecrystals)
return max(1, telecrystals)
-/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
var/list/bought_items = list()
- for(var/datum/uplink_item/UI in get_random_uplink_items(U, U.uses, loc))
+ for(var/datum/uplink_item/UI in get_random_uplink_items(U, M.mind.tcrystals, loc))
UI.purchase_log(U)
var/obj/item/I = UI.get_goods(U, loc)
if(istype(I))
@@ -47,7 +47,7 @@
/datum/uplink_item/item/badassery/random_many/purchase_log(obj/item/device/uplink/U)
feedback_add_details("traitor_uplink_items_bought", "[src]")
- log_and_message_admins("used \the [U.loc] to buy \a [src]")
+ log_and_message_admins("used \the [U.loc] to buy \a [src] at random")
/****************
* Surplus Crate *
diff --git a/code/datums/uplink/medical_vr.dm b/code/datums/uplink/medical_vr.dm
index 8f0264d3e9d..5b4a0f31ccc 100644
--- a/code/datums/uplink/medical_vr.dm
+++ b/code/datums/uplink/medical_vr.dm
@@ -100,3 +100,66 @@
name = "Healing Nanite pill bottle"
item_cost = 30
path = /obj/item/weapon/storage/pill_bottle/healing_nanites
+
+/datum/uplink_item/item/medical/vermicetol
+ name = "Vermicetol Bottle"
+ item_cost = 30
+ path = /obj/item/weapon/reagent_containers/glass/bottle/vermicetol
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/dermaline
+ name = "Dermaline Bottle"
+ item_cost = 30
+ path = /obj/item/weapon/reagent_containers/glass/bottle/dermaline
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/carthatoline
+ name = "Carthatoline Bottle"
+ item_cost = 30
+ path = /obj/item/weapon/reagent_containers/glass/bottle/carthatoline
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/dexalinp
+ name = "Dexalin Plus Bottle"
+ item_cost = 30
+ path = /obj/item/weapon/reagent_containers/glass/bottle/dexalinp
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/tramadol
+ name = "Tramadol Bottle"
+ item_cost = 30
+ path = /obj/item/weapon/reagent_containers/glass/bottle/tramadol
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/arithrazine
+ name = "Arithrazine Bottle"
+ item_cost = 50
+ path = /obj/item/weapon/reagent_containers/glass/bottle/arithrazine
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/corophizine
+ name = "Corophizine Bottle"
+ item_cost = 50
+ path = /obj/item/weapon/reagent_containers/glass/bottle/corophizine
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/rezadone
+ name = "Rezadone Bottle"
+ item_cost = 50
+ path = /obj/item/weapon/reagent_containers/glass/bottle/rezadone
+ antag_roles = list("ert")
+ blacklisted = 1
+
+/datum/uplink_item/item/medical/defib
+ name = "Combat Defibrilator"
+ item_cost = 90
+ path = /obj/item/device/defib_kit/compact/combat
+ antag_roles = list("mercenary", "ert")
+ blacklisted = 1
diff --git a/code/datums/uplink/telecrystals.dm b/code/datums/uplink/telecrystals.dm
index f814b55232d..66a099581ee 100644
--- a/code/datums/uplink/telecrystals.dm
+++ b/code/datums/uplink/telecrystals.dm
@@ -5,8 +5,8 @@
category = /datum/uplink_category/telecrystals
blacklisted = 1
-/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/device/uplink/U, var/loc)
- return new /obj/item/stack/telecrystal(loc, cost(U.uses))
+/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
+ return new /obj/item/stack/telecrystal(loc, cost(U, M.mind.tcrystals))
/datum/uplink_item/item/telecrystal/one
name = "Telecrystal - 01"
@@ -35,5 +35,5 @@
/datum/uplink_item/item/telecrystal/all
name = "Telecrystals - Empty Uplink"
-/datum/uplink_item/item/telecrystal/all/cost(var/telecrystals)
- return max(1, telecrystals)
\ No newline at end of file
+/datum/uplink_item/item/telecrystal/all/cost(obj/item/device/uplink/U, mob/M)
+ return max(1, M.mind.tcrystals)
\ No newline at end of file
diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm
index 51d7ec7cd22..eee41e96993 100644
--- a/code/datums/uplink/tools.dm
+++ b/code/datums/uplink/tools.dm
@@ -92,6 +92,12 @@
desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \
a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes."
+/datum/uplink_item/item/tools/wall_elecrtifier
+ name = "Wall Electrifier"
+ item_cost = 10
+ path = /obj/item/weapon/cell/spike
+ desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active."
+
/datum/uplink_item/item/tools/emag
name = "Cryptographic Sequencer"
item_cost = 30
diff --git a/code/datums/uplink/tools_vr.dm b/code/datums/uplink/tools_vr.dm
index 30b2cd725e0..ad68f769229 100644
--- a/code/datums/uplink/tools_vr.dm
+++ b/code/datums/uplink/tools_vr.dm
@@ -26,6 +26,11 @@
item_cost = 5
path = /obj/item/device/survivalcapsule
+/datum/uplink_item/item/tools/popcabin
+ name = "Cabin Capsule"
+ item_cost = 5
+ path = /obj/item/device/survivalcapsule/popcabin
+
/datum/uplink_item/item/tools/nanopaste
name = "Nanopaste (Advanced)"
item_cost = 10
@@ -36,11 +41,26 @@
item_cost = 10
path = /obj/item/clothing/suit/space/void/autolok
+/datum/uplink_item/item/tools/inflatable
+ name = "Inflatables"
+ item_cost = 10
+ path = /obj/item/weapon/storage/briefcase/inflatable
+
/datum/uplink_item/item/tools/elitetablet
name = "Tablet (Advanced)"
item_cost = 15
path = /obj/item/modular_computer/tablet/preset/custom_loadout/advanced
+/datum/uplink_item/item/tools/metal
+ name = "Metal (50 sheets)"
+ item_cost = 15
+ path = /obj/fiftyspawner/steel
+
+/datum/uplink_item/item/tools/glass
+ name = "Glass (50 sheets)"
+ item_cost = 15
+ path = /obj/fiftyspawner/glass
+
/datum/uplink_item/item/tools/elitelaptop
name = "Laptop (Advanced)"
item_cost = 20
diff --git a/code/datums/uplink/uplink_categories.dm b/code/datums/uplink/uplink_categories.dm
index d9e6d84db7d..f7236ddbb08 100644
--- a/code/datums/uplink/uplink_categories.dm
+++ b/code/datums/uplink/uplink_categories.dm
@@ -6,12 +6,6 @@
..()
items = list()
-/datum/uplink_category/proc/can_view(obj/item/device/uplink/U)
- for(var/datum/uplink_item/item in items)
- if(item.can_view(U))
- return 1
- return 0
-
datum/uplink_category/ammunition
name = "Ammunition"
diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm
index 8d9de8f7321..e02e604984f 100644
--- a/code/datums/uplink/uplink_items.dm
+++ b/code/datums/uplink/uplink_items.dm
@@ -31,7 +31,7 @@ var/datum/uplink/uplink = new()
var/item_cost = 0
var/datum/uplink_category/category // Item category
var/list/datum/antagonist/antag_roles // Antag roles this item is displayed to. If empty, display to all.
- var/blacklisted = 0
+ var/blacklisted = FALSE
/datum/uplink_item/item
var/path = null
@@ -48,50 +48,34 @@ var/datum/uplink/uplink = new()
if(!extra_args)
return
- if(!can_buy(U))
+ if(!can_buy(U, user.mind.tcrystals))
return
- if(U.CanUseTopic(user, GLOB.tgui_inventory_state) != STATUS_INTERACTIVE)
+ if(U.tgui_status(user, GLOB.tgui_deep_inventory_state) != STATUS_INTERACTIVE)
return
- var/cost = cost(U.uses, U)
+ var/cost = cost(U, user.mind.tcrystals)
var/goods = get_goods(U, get_turf(user), user, extra_args)
if(!goods)
return
- purchase_log(U)
+ purchase_log(user)
user.mind.tcrystals -= cost
- U.used_TC += cost
+ user.mind.used_TC += cost
return goods
// Any additional arguments you wish to send to the get_goods
/datum/uplink_item/proc/extra_args(var/mob/user)
- return 1
+ return TRUE
-/datum/uplink_item/proc/can_buy(obj/item/device/uplink/U)
- if(cost(U.uses, U) > U.uses)
- return 0
+/datum/uplink_item/proc/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
+ if(cost(U, telecrystals) > telecrystals)
+ return FALSE
- return can_view(U)
+ return TRUE
-/datum/uplink_item/proc/can_view(obj/item/device/uplink/U)
- // Making the assumption that if no uplink was supplied, then we don't care about antag roles
- if(!U || !antag_roles.len)
- return 1
-
- // With no owner, there's no need to check antag status.
- if(!U.uplink_owner)
- return 0
-
- for(var/antag_role in antag_roles)
- var/datum/antagonist/antag = all_antag_types[antag_role]
- if(!isnull(antag))
- if(antag.is_antagonist(U.uplink_owner))
- return 1
- return 0
-
-/datum/uplink_item/proc/cost(var/telecrystals, obj/item/device/uplink/U)
+/datum/uplink_item/proc/cost(obj/item/device/uplink/U, mob/M)
. = item_cost
if(U)
. = U.get_item_cost(src, .)
@@ -100,19 +84,19 @@ var/datum/uplink/uplink = new()
return desc
// get_goods does not necessarily return physical objects, it is simply a way to acquire the uplink item without paying
-/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc)
- return 0
+/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc, mob/user)
+ return FALSE
/datum/uplink_item/proc/log_icon()
return
-/datum/uplink_item/proc/purchase_log(obj/item/device/uplink/U)
+/datum/uplink_item/proc/purchase_log(mob/M)
feedback_add_details("traitor_uplink_items_bought", "[src]")
- log_and_message_admins("used \the [U.loc] to buy \a [src]")
- U.purchase_log[src] = U.purchase_log[src] + 1
+ log_and_message_admins("\the [M] bought \a [src] through the uplink")
+ M.mind.purchase_log[src] += 1
datum/uplink_item/dd_SortValue()
- return cost(INFINITY)
+ return item_cost
/********************************
* *
@@ -133,7 +117,7 @@ datum/uplink_item/dd_SortValue()
A.put_in_any_hand_if_possible(I)
return I
-/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user)
var/obj/item/I = new path(loc)
return I
@@ -208,7 +192,7 @@ datum/uplink_item/dd_SortValue()
/proc/get_surplus_items(var/obj/item/device/uplink/U, var/remaining_TC, var/loc)
var/list/bought_items = list()
- var/override = 1
+ var/override = TRUE
while(remaining_TC)
var/datum/uplink_item/I = all_uplink_selection.get_random_item(remaining_TC, U, bought_items, override)
if(!I)
diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm
index d3ed1dcec34..b939e953de3 100644
--- a/code/datums/uplink/visible_weapons.dm
+++ b/code/datums/uplink/visible_weapons.dm
@@ -103,7 +103,7 @@
name = "Anti-Materiel Rifle (14.5mm)"
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
path = /obj/item/weapon/gun/projectile/heavysniper
- antag_roles = list("mercenary")
+ antag_roles = list("mercenary", "ert") //VOREStation Edit
/datum/uplink_item/item/visible_weapons/heavysnipertraitor
name = "Anti-Materiel Rifle (14.5mm)"
diff --git a/code/datums/wires/mines.dm b/code/datums/wires/mines.dm
index 209fcc4c307..5e757ad16c3 100644
--- a/code/datums/wires/mines.dm
+++ b/code/datums/wires/mines.dm
@@ -1,5 +1,5 @@
/datum/wires/mines
- wire_count = 6
+ wire_count = 7
randomize = TRUE
holder_type = /obj/effect/mine
proper_name = "Explosive Wires"
@@ -7,6 +7,7 @@
/datum/wires/mines/New(atom/_holder)
wires = list(WIRE_EXPLODE, WIRE_EXPLODE_DELAY, WIRE_DISARM, WIRE_BADDISARM)
return ..()
+#define WIRE_TRAP 64
/datum/wires/mines/get_status()
. = ..()
@@ -29,7 +30,13 @@
if(WIRE_DISARM)
C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*")
- new C.mineitemtype(get_turf(C))
+ var/obj/effect/mine/MI = new C.mineitemtype(get_turf(C))
+
+ if(C.trap)
+ MI.trap = C.trap
+ C.trap = null
+ MI.trap.forceMove(MI)
+
spawn(0)
qdel(C)
@@ -37,6 +44,15 @@
C.visible_message("[bicon(C)] *BEEPBEEPBEEP*", "[bicon(C)] *BEEPBEEPBEEP*")
spawn(20)
C.explode()
+
+ if(WIRE_TRAP)
+ C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*")
+
+ if(mend)
+ C.visible_message("[bicon(C)] - The mine recalibrates[C.camo_net ? ", revealing \the [C.trap] inside." : "."]")
+
+ C.alpha = 255
+
..()
/datum/wires/mines/on_pulse(wire)
@@ -57,6 +73,10 @@
if(WIRE_BADDISARM)
C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
+
+ if(WIRE_TRAP)
+ C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
+
..()
/datum/wires/mines/interactable(mob/user)
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 8be56acbf36..ef15cfb26f7 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -297,7 +297,7 @@
/obj/item/weapon/storage/part_replacer
name = "rapid part exchange device"
- desc = "Special mechanical module made to store, sort, and apply standard machine parts."
+ desc = "A special mechanical module made to store, sort, and apply standard machine parts."
icon_state = "RPED"
w_class = ITEMSIZE_HUGE
can_hold = list(/obj/item/weapon/stock_parts)
@@ -311,10 +311,11 @@
max_storage_space = 100
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
+ var/panel_req = TRUE
/obj/item/weapon/storage/part_replacer/adv
name = "advanced rapid part exchange device"
- desc = "Special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity"
+ desc = "A special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity."
icon_state = "RPED"
w_class = ITEMSIZE_HUGE
can_hold = list(/obj/item/weapon/stock_parts)
@@ -327,6 +328,31 @@
max_w_class = ITEMSIZE_NORMAL
max_storage_space = 400
+/obj/item/weapon/storage/part_replacer/adv/discount_bluespace
+ name = "discount bluespace rapid part exchange device"
+ desc = "A special mechanical module made to store, sort, and apply standard machine parts. This one has a further increased storage capacity, \
+ and the ability to work on machines with closed maintenance panels."
+ storage_slots = 400
+ max_storage_space = 800
+ panel_req = FALSE
+
+/obj/item/weapon/storage/part_replacer/drop_contents() // hacky-feeling tier-based drop system
+ hide_from(usr)
+ var/turf/T = get_turf(src)
+ var/lowest_rating = INFINITY // We want the lowest-part tier rating in the RPED so we only drop the lowest-tier parts.
+ /*
+ * Why not just use the stock part's rating variable?
+ * Future-proofing for a potential future where stock parts aren't the only thing that can fit in an RPED.
+ * see: /tg/ and /vg/'s RPEDs fitting power cells, beakers, etc.
+ */
+ for(var/obj/item/B in contents)
+ if(B.rped_rating() < lowest_rating)
+ lowest_rating = B.rped_rating()
+ for(var/obj/item/B in contents)
+ if(B.rped_rating() > lowest_rating)
+ continue
+ remove_from_storage(B, T)
+
/obj/item/weapon/stock_parts
name = "stock part"
desc = "What?"
@@ -342,6 +368,9 @@
src.pixel_y = rand(-5.0, 5)
..()
+/obj/item/weapon/stock_parts/get_rating()
+ return rating
+
//Rank 1
/obj/item/weapon/stock_parts/console_screen
diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm
index efcd5955f74..99216b9ef55 100644
--- a/code/game/antagonist/antagonist_print.dm
+++ b/code/game/antagonist/antagonist_print.dm
@@ -1,7 +1,7 @@
/datum/antagonist/proc/print_player_summary()
if(!current_antagonists.len)
- return 0
+ return FALSE
var/text = "
The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:"
for(var/datum/mind/P in current_antagonists)
@@ -21,7 +21,7 @@
else
text += "Fail."
feedback_add_details(feedback_tag,"[O.type]|FAIL")
- failed = 1
+ failed = TRUE
num++
if(failed)
text += "
The [role_text] has failed."
@@ -32,7 +32,7 @@
text += "
Their objectives were:"
var/num = 1
for(var/datum/objective/O in global_objectives)
- text += print_objective(O, num, 1)
+ text += print_objective(O, num, TRUE)
num++
// Display the results.
@@ -68,14 +68,14 @@
/datum/antagonist/proc/print_player_full(var/datum/mind/ply)
var/text = print_player_lite(ply)
- var/TC_uses = 0
- var/uplink_true = 0
+ var/TC_uses = FALSE
+ var/uplink_true = FALSE
var/purchases = ""
- for(var/obj/item/device/uplink/H in world_uplinks)
- if(H && H.uplink_owner && H.uplink_owner == ply)
- TC_uses += H.used_TC
- uplink_true = 1
- purchases += get_uplink_purchases(H)
+ for(var/mob/M in player_list)
+ if(M.mind && M.mind.used_TC)
+ TC_uses += M.mind.used_TC
+ uplink_true = TRUE
+ purchases += get_uplink_purchases(M.mind)
if(uplink_true)
text += " (used [TC_uses] TC)"
if(purchases)
@@ -83,18 +83,8 @@
return text
-/proc/print_ownerless_uplinks()
- var/has_printed = 0
- for(var/obj/item/device/uplink/H in world_uplinks)
- if(isnull(H.uplink_owner) && H.used_TC)
- if(!has_printed)
- has_printed = 1
- to_world("Ownerless Uplinks")
- to_world("[H.loc] (used [H.used_TC] TC)")
- to_world(get_uplink_purchases(H))
-
-/proc/get_uplink_purchases(var/obj/item/device/uplink/H)
+/proc/get_uplink_purchases(var/datum/mind/M)
var/list/refined_log = new()
- for(var/datum/uplink_item/UI in H.purchase_log)
- refined_log.Add("[H.purchase_log[UI]]x[UI.log_icon()][UI.name]")
+ for(var/datum/uplink_item/UI in M.purchase_log)
+ refined_log.Add("[M.purchase_log[UI]]x[UI.log_icon()][UI.name]")
. = english_list(refined_log, nothing_text = "")
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 04075fe8255..9c8bbccc798 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -50,13 +50,12 @@
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
var/forbid_events = FALSE // If true, random events will not start inside this area.
var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
+ var/soundproofed = FALSE // If true, blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
/area/Initialize()
. = ..()
-
luminosity = !(dynamic_lighting)
icon_state = ""
-
return INITIALIZE_HINT_LATELOAD // Areas tradiationally are initialized AFTER other atoms.
/area/LateInitialize()
@@ -67,7 +66,6 @@
power_change() // all machines set to current power level, also updates lighting icon
if(no_spoilers)
set_spoiler_obfuscation(TRUE)
- return INITIALIZE_HINT_LATELOAD
// Changes the area of T to A. Do not do this manually.
// Area is expected to be a non-null instance.
@@ -379,9 +377,9 @@ var/list/mob/living/forced_ambiance_list = new
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance)))
return
-
+
var/volume_mod = L.get_preference_volume_channel(VOLUME_CHANNEL_AMBIENCE)
-
+
// If we previously were in an area with force-played ambiance, stop it.
if((L in forced_ambiance_list) && initial)
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index bf5fc0ab18c..4bc8892273f 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -134,7 +134,7 @@
for(var/i in loc)
var/atom/movable/thing = i
// We don't call parent so we are calling this for byond
- thing.Crossed(src)
+ thing.Crossed(src, oldloc)
// We're a multi-tile object (multiple locs)
else if(. && newloc)
@@ -303,6 +303,8 @@
if(AM == src)
continue
AM.Uncrossed(src)
+ if(loc != destination) // Uncrossed() triggered a separate movement
+ return
// Information about turf and z-levels for source and dest collected
var/turf/oldturf = get_turf(oldloc)
@@ -327,6 +329,8 @@
if(AM == src)
continue
AM.Crossed(src, oldloc)
+ if(loc != destination) // Crossed triggered a separate movement
+ return
// Call our thingy to inform everyone we moved
Moved(oldloc, NONE, TRUE)
@@ -462,6 +466,8 @@
minor_dir = dx
minor_dist = dist_x
+ range = min(dist_x + dist_y, range)
+
while(src && target && src.throwing && istype(src.loc, /turf) \
&& ((abs(target.x - src.x)+abs(target.y - src.y) > 0 && dist_travelled < range) \
|| (a && a.has_gravity == 0) \
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 4141281df9d..ef0af0fab79 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -118,6 +118,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
var/base_species = "Human"
var/list/species_traits = list()
var/blood_color = "#A10808"
+ var/custom_say
+ var/custom_ask
+ var/custom_whisper
+ var/custom_exclaim
// VOREStation
// New stuff
@@ -139,6 +143,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
new_dna.custom_species=custom_species //VOREStaton Edit
new_dna.species_traits=species_traits.Copy() //VOREStation Edit
new_dna.blood_color=blood_color //VOREStation Edit
+ new_dna.custom_say=custom_say //VOREStaton Edit
+ new_dna.custom_ask=custom_ask //VOREStaton Edit
+ new_dna.custom_whisper=custom_whisper //VOREStaton Edit
+ new_dna.custom_exclaim=custom_exclaim //VOREStaton Edit
for(var/b=1;b<=DNA_SE_LENGTH;b++)
new_dna.SE[b]=SE[b]
if(b<=DNA_UI_LENGTH)
@@ -202,23 +210,13 @@ var/global/list/datum/dna/gene/dna_genes[0]
// Technically custom_species is not part of the UI, but this place avoids merge problems.
src.custom_species = character.custom_species
- if(istype(character.species,/datum/species/custom))
- var/datum/species/custom/CS = character.species
- src.species_traits = CS.traits.Copy()
- src.base_species = CS.base_species
- src.blood_color = CS.blood_color
-
- if(istype(character.species,/datum/species/xenochimera))
- var/datum/species/xenochimera/CS = character.species
- //src.species_traits = CS.traits.Copy() //No traits
- src.base_species = CS.base_species
- src.blood_color = CS.blood_color
-
- if(istype(character.species,/datum/species/alraune))
- var/datum/species/alraune/CS = character.species
- //src.species_traits = CS.traits.Copy() //No traits
- src.base_species = CS.base_species
- src.blood_color = CS.blood_color
+ src.base_species = character.species.base_species
+ src.blood_color = character.species.blood_color
+ src.species_traits = character.species.traits.Copy()
+ src.custom_say = character.custom_say
+ src.custom_ask = character.custom_ask
+ src.custom_whisper = character.custom_whisper
+ src.custom_exclaim = character.custom_exclaim
// +1 to account for the none-of-the-above possibility
SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 0edc6bb636b..d250c441ad4 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -237,20 +237,13 @@
// Technically custom_species is not part of the UI, but this place avoids merge problems.
H.custom_species = dna.custom_species
- if(istype(H.species,/datum/species/custom))
- var/datum/species/custom/CS = H.species
- var/datum/species/custom/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
- new_CS.blood_color = dna.blood_color
-
- if(istype(H.species,/datum/species/xenochimera))
- var/datum/species/xenochimera/CS = H.species
- var/datum/species/xenochimera/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
- new_CS.blood_color = dna.blood_color
-
- if(istype(H.species,/datum/species/alraune))
- var/datum/species/alraune/CS = H.species
- var/datum/species/alraune/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
- new_CS.blood_color = dna.blood_color
+ H.custom_say = dna.custom_say
+ H.custom_ask = dna.custom_ask
+ H.custom_whisper = dna.custom_whisper
+ H.custom_exclaim = dna.custom_exclaim
+ H.species.blood_color = dna.blood_color
+ var/datum/species/S = H.species
+ S.produceCopy(dna.base_species,dna.species_traits,src)
// VOREStation Edit End
H.force_update_organs() //VOREStation Add - Gotta do this too
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index bbf4bfb3437..241d6132756 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -34,7 +34,7 @@
var/last_activation = 0
/obj/structure/cult/pylon/Initialize()
- ..()
+ . = ..()
START_PROCESSING(SSobj, src)
/obj/structure/cult/pylon/attack_hand(mob/M as mob)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 42e6a6ddd00..18d58a33ae8 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -292,7 +292,6 @@ var/global/list/additional_antag_types = list()
antag.check_victory()
antag.print_player_summary()
sleep(10)
- print_ownerless_uplinks()
var/clients = 0
var/surviving_humans = 0
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 0b0b8d014c7..a6ceb219c84 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -13,7 +13,7 @@
/obj/effect/meteor/big=3,
/obj/effect/meteor/flaming=1,
/obj/effect/meteor/irradiated=3
- )
+ )
//for threatening meteor event
/var/list/meteors_threatening = list(
@@ -206,6 +206,21 @@
return
..()
+/obj/effect/meteor/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.excavation_amount)
+ get_hit()
+ if(!QDELETED(src))
+ wall_power -= Proj.excavation_amount + Proj.damage + (Proj.hitscan * 25) // Instant-impact projectiles are inherently better at dealing with meteors.
+ wall_power = max(1, wall_power)
+
+ if(wall_power < Proj.excavation_amount)
+ if(prob(min(90, 100 - Proj.damage)))
+ die(TRUE)
+ else
+ die(FALSE)
+ return
+ return
+
/obj/effect/meteor/proc/make_debris()
for(var/throws = dropamt, throws > 0, throws--)
var/obj/item/O = new meteordrop(get_turf(src))
diff --git a/code/game/jobs/access_datum_vr.dm b/code/game/jobs/access_datum_vr.dm
index 16038248d01..bd3906f16c5 100644
--- a/code/game/jobs/access_datum_vr.dm
+++ b/code/game/jobs/access_datum_vr.dm
@@ -27,4 +27,22 @@ var/const/access_pilot = 67
/datum/access/entertainment
id = access_entertainment
desc = "Entertainment Backstage"
- region = ACCESS_REGION_GENERAL
\ No newline at end of file
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_mime = 138
+/datum/access/mime
+ id = access_mime
+ desc = "Mime Office"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_clown = 136
+/datum/access/clown
+ id = access_clown
+ desc = "Clown Office"
+ region = ACCESS_REGION_GENERAL
+
+/var/const/access_tomfoolery = 137
+/datum/access/tomfoolery
+ id = access_tomfoolery
+ desc = "Tomfoolery Closet"
+ region = ACCESS_REGION_GENERAL
diff --git a/code/game/jobs/job/captain_vr.dm b/code/game/jobs/job/captain_vr.dm
index d2b830ad7ba..dd057fff7bf 100644
--- a/code/game/jobs/job/captain_vr.dm
+++ b/code/game/jobs/job/captain_vr.dm
@@ -26,13 +26,13 @@
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
- access_hop, access_RC_announce, access_keycard_auth)
+ access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
- access_hop, access_RC_announce, access_keycard_auth)
+ access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
/datum/alt_title/deputy_manager
title = "Deputy Manager"
diff --git a/code/game/jobs/job/engineering_vr.dm b/code/game/jobs/job/engineering_vr.dm
index 8799aa39058..39905f0bc85 100644
--- a/code/game/jobs/job/engineering_vr.dm
+++ b/code/game/jobs/job/engineering_vr.dm
@@ -6,12 +6,12 @@
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
- access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
+ access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
- access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
+ access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
alt_titles = list("Head Engineer" = /datum/alt_title/head_engineer, "Foreman" = /datum/alt_title/foreman, "Maintenance Manager" = /datum/alt_title/maintenance_manager)
/datum/alt_title/head_engineer
diff --git a/code/game/jobs/job/exploration_vr.dm b/code/game/jobs/job/exploration_vr.dm
index 0e6e003f7db..5189ca39b0c 100644
--- a/code/game/jobs/job/exploration_vr.dm
+++ b/code/game/jobs/job/exploration_vr.dm
@@ -1,8 +1,3 @@
-var/const/PATHFINDER =(1<<11)
-var/const/EXPLORER =(1<<12)
-var/const/PILOT =(1<<13)
-var/const/SAR =(1<<14)
-
/obj/item/weapon/card/id/medical/sar
assignment = "Field Medic"
rank = "Field Medic"
@@ -64,13 +59,13 @@ var/const/SAR =(1<<14)
/datum/job/pilot
title = "Pilot"
flag = PILOT
- departments = list(DEPARTMENT_PLANET)
- department_flag = MEDSCI
+ departments = list(DEPARTMENT_CIVILIAN)
+ department_flag = CIVILIAN
faction = "Station"
- total_positions = 4
- spawn_positions = 4
- supervisors = "the Pathfinder and the Head of Personnel"
- selection_color = "#999440"
+ total_positions = 5
+ spawn_positions = 5
+ supervisors = "the Head of Personnel"
+ selection_color = "#515151"
economic_modifier = 5
minimal_player_age = 3
pto_type = PTO_EXPLORATION
diff --git a/code/game/jobs/job/medical_vr.dm b/code/game/jobs/job/medical_vr.dm
index 2679137cf0f..6d5ee57c4e4 100644
--- a/code/game/jobs/job/medical_vr.dm
+++ b/code/game/jobs/job/medical_vr.dm
@@ -5,11 +5,11 @@
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
- access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
+ access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
- access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
+ access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
alt_titles = list("Chief Physician" = /datum/alt_title/chief_physician, "Medical Director" = /datum/alt_title/medical_director, "Healthcare Manager" = /datum/alt_title/healthcare_manager)
/datum/alt_title/chief_physician
diff --git a/code/game/jobs/job/science_vr.dm b/code/game/jobs/job/science_vr.dm
index 0356656446b..52647422b4f 100644
--- a/code/game/jobs/job/science_vr.dm
+++ b/code/game/jobs/job/science_vr.dm
@@ -10,7 +10,7 @@
minimal_access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue,
access_tox_storage, access_teleporter,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
- access_RC_announce, access_keycard_auth, access_tcomsat, access_xenoarch, access_eva, access_network, access_xenobotany)
+ access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network, access_xenobotany)
alt_titles = list("Research Supervisor" = /datum/alt_title/research_supervisor, "Research Manager" = /datum/alt_title/research_manager,
"Head of Development" = /datum/alt_title/head_of_development,"Head Scientist" = /datum/alt_title/head_scientist)
diff --git a/code/game/jobs/job/security_vr.dm b/code/game/jobs/job/security_vr.dm
index e9b9017d9af..082531d944e 100644
--- a/code/game/jobs/job/security_vr.dm
+++ b/code/game/jobs/job/security_vr.dm
@@ -6,11 +6,11 @@
access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
- access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks)
+ access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction,
- access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks)
+ access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
alt_titles = list("Security Commander" = /datum/alt_title/sec_commander, "Chief of Security" = /datum/alt_title/sec_chief, "Security Manager" = /datum/alt_title/security_manager)
/datum/alt_title/security_manager
diff --git a/code/game/jobs/job/special_vr.dm b/code/game/jobs/job/special_vr.dm
index d2de3db85c0..34cc2321ce8 100644
--- a/code/game/jobs/job/special_vr.dm
+++ b/code/game/jobs/job/special_vr.dm
@@ -24,47 +24,31 @@
get_access()
return get_all_accesses().Copy()
-/*/datum/job/centcom_visitor //For Pleasure // You mean for admin abuse... -Ace
- title = "CentCom Visitor"
- department = "Civilian"
- head_position = 1
+/datum/job/emergency_responder //For staff managing/leading ERTs
+ title = "Emergency Responder"
+ departments = list("Central Command")
+ department_accounts = list(DEPARTMENT_COMMAND, DEPARTMENT_ENGINEERING, DEPARTMENT_MEDICAL, DEPARTMENT_RESEARCH, DEPARTMENT_SECURITY, DEPARTMENT_CARGO, DEPARTMENT_PLANET, DEPARTMENT_CIVILIAN)
faction = "Station"
total_positions = 2
spawn_positions = 1
supervisors = "company officials and Corporate Regulations"
selection_color = "#1D1D4F"
- idtype = /obj/item/weapon/card/id/centcom
access = list()
minimal_access = list()
minimal_player_age = 14
economic_modifier = 20
whitelist_only = 1
latejoin_only = 1
+ outfit_type = /decl/hierarchy/outfit/job/emergency_responder
+ job_description = "Emergency Responders are usually called in to deal with on-station emergencies that the crew require assistance to deal with."
- minimum_character_age = 25
- ideal_character_age = 40
+ minimum_character_age = 18
+ ideal_character_age = 30
- equip(var/mob/living/carbon/human/H)
- if(!H) return 0
- H.equip_to_slot_or_del(new /obj/item/device/radio/headset/centcom(H), slot_l_ear)
- switch(H.backbag)
- if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back)
- if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
- if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom, slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/device/pda/centcom(H), slot_belt)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcom/officer(H), slot_head)
- H.equip_to_slot_or_del(new /obj/item/clothing/glasses/omnihud(H), slot_l_store)
-
- H.implant_loyalty()
-
- return 1
+ pto_type = PTO_CIVILIAN
get_access()
- var/access = get_all_accesses()
- return access*/
+ return get_all_accesses().Copy()
/datum/job/clown
title = "Clown"
@@ -72,14 +56,14 @@
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = "Station"
- total_positions = -1
- spawn_positions = -1
+ total_positions = 1
+ spawn_positions = 1
supervisors = "the spirit of laughter"
selection_color = "#515151"
economic_modifier = 1
job_description = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!"
whitelist_only = 1
- latejoin_only = 1
+ latejoin_only = 0
outfit_type = /decl/hierarchy/outfit/job/clown
pto_type = PTO_CIVILIAN
alt_titles = list("Jester" = /datum/alt_title/jester, "Fool" = /datum/alt_title/fool)
@@ -92,9 +76,9 @@
/datum/job/clown/get_access()
if(config.assistant_maint)
- return list(access_maint_tunnels, access_entertainment)
+ return list(access_maint_tunnels, access_entertainment, access_clown, access_tomfoolery)
else
- return list(access_entertainment)
+ return list(access_entertainment, access_clown, access_tomfoolery)
/datum/job/mime
title = "Mime"
@@ -102,15 +86,15 @@
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
faction = "Station"
- total_positions = -1
- spawn_positions = -1
+ total_positions = 1
+ spawn_positions = 1
supervisors = "the spirit of performance"
selection_color = "#515151"
economic_modifier = 1
job_description = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!"
alt_titles = list("Poseur" = /datum/alt_title/poseur)
whitelist_only = 1
- latejoin_only = 1
+ latejoin_only = 0
outfit_type = /decl/hierarchy/outfit/job/mime
pto_type = PTO_CIVILIAN
@@ -119,6 +103,6 @@
/datum/job/mime/get_access()
if(config.assistant_maint)
- return list(access_maint_tunnels, access_entertainment)
+ return list(access_maint_tunnels, access_entertainment, access_tomfoolery, access_mime)
else
- return list(access_entertainment)
+ return list(access_entertainment, access_tomfoolery, access_mime)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 4e53589c2ff..96dfbd31834 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -415,7 +415,7 @@ var/global/datum/controller/occupations/job_master
// Implants get special treatment
if(G.slot == "implant")
- var/obj/item/weapon/implant/I = G.spawn_item(H)
+ var/obj/item/weapon/implant/I = G.spawn_item(H, H.client.prefs.gear[G.display_name])
I.invisibility = 100
I.implant_loadout(H)
continue
@@ -514,11 +514,12 @@ var/global/datum/controller/occupations/job_master
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
var/obj/item/weapon/storage/S = locate() in H.contents
- var/obj/item/wheelchair/R = null
+ var/obj/item/wheelchair/R
if(S)
R = locate() in S.contents
if(!l_foot || !r_foot || R)
- var/obj/structure/bed/chair/wheelchair/W = new /obj/structure/bed/chair/wheelchair(H.loc)
+ var/wheelchair_type = R?.unfolded_type || /obj/structure/bed/chair/wheelchair
+ var/obj/structure/bed/chair/wheelchair/W = new wheelchair_type(H.loc)
W.buckle_mob(H)
H.update_canmove()
W.set_dir(H.dir)
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 40f0fdb4a41..9312c84571d 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -26,7 +26,10 @@ var/const/PSYCHIATRIST =(1<<7)
var/const/ROBOTICIST =(1<<8)
var/const/XENOBIOLOGIST =(1<<9)
var/const/PARAMEDIC =(1<<10)
-var/const/XENOBOTANIST =(1<<15) //VOREStation Add
+var/const/PATHFINDER =(1<<11) //VOREStation Add
+var/const/EXPLORER =(1<<12) //VOREStation Add
+var/const/SAR =(1<<13) //VOREStation Add
+var/const/XENOBOTANIST =(1<<14) //VOREStation Add
var/const/CIVILIAN =(1<<2)
@@ -43,9 +46,10 @@ var/const/LAWYER =(1<<9)
var/const/CHAPLAIN =(1<<10)
var/const/ASSISTANT =(1<<11)
var/const/BRIDGE =(1<<12)
-var/const/CLOWN =(1<<13) //VOREStation Add
-var/const/MIME =(1<<14) //VOREStation Add
-var/const/ENTERTAINER =(1<<15) //VOREStation Add
+var/const/PILOT =(1<<13) //VOREStation Add
+var/const/CLOWN =(1<<14) //VOREStation Add
+var/const/MIME =(1<<15) //VOREStation Add
+var/const/ENTERTAINER =(1<<16) //VOREStation Add
//VOREStation Add
var/const/TALON =(1<<3)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index a97fbf986f7..e0ff3a6086c 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -529,5 +529,5 @@
stasis_level = 100 //Just one setting
/obj/machinery/sleeper/survival_pod/Initialize()
- ..()
+ . = ..()
RefreshParts(1)
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index d15ea493ecf..19716f5d74b 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -16,9 +16,3 @@
/obj/machinery/button/attackby(obj/item/weapon/W, mob/user as mob)
return attack_hand(user)
-
-// VOREStation Edit Begin
-/obj/machinery/button/attack_hand(obj/item/weapon/W, mob/user as mob)
- if(..()) return 1
- playsound(src, 'sound/machines/button.ogg', 100, 1)
-// VOREStation Edit End
diff --git a/code/game/machinery/buttons_vr.dm b/code/game/machinery/buttons_vr.dm
new file mode 100644
index 00000000000..a8c9c4bed1e
--- /dev/null
+++ b/code/game/machinery/buttons_vr.dm
@@ -0,0 +1,23 @@
+/obj/machinery/button/attack_hand(obj/item/weapon/W, mob/user as mob)
+ if(..()) return 1
+ playsound(src, 'sound/machines/button.ogg', 100, 1)
+
+/obj/machinery/button/windowtint/multitint
+ name = "tint control"
+ desc = "A remote control switch for polarized windows and doors."
+
+/obj/machinery/button/windowtint/multitint/toggle_tint()
+ use_power(5)
+ active = !active
+ update_icon()
+
+ var/in_range = range(src,range)
+ for(var/obj/structure/window/reinforced/polarized/W in in_range)
+ if(W.id == src.id || !W.id)
+ spawn(0)
+ W.toggle()
+ for(var/obj/machinery/door/D in in_range)
+ if(D.icon_tinted)
+ if(D.id_tint == src.id || !D.id_tint)
+ spawn(0)
+ D.toggle()
\ No newline at end of file
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 7ff97c83e85..25299dcda8c 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -1,4 +1,4 @@
-/obj/machinery/computer/arcade/
+/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
icon_state = "arcade"
@@ -25,15 +25,15 @@
/obj/item/toy/stickhorse = 2
)
-/obj/machinery/computer/arcade/New()
- ..()
+/obj/machinery/computer/arcade/Initialize()
+ . = ..()
// If it's a generic arcade machine, pick a random arcade
// circuit board for it and make the new machine
if(!circuit)
var/choice = pick(subtypesof(/obj/item/weapon/circuitboard/arcade) - /obj/item/weapon/circuitboard/arcade/clawmachine)
var/obj/item/weapon/circuitboard/CB = new choice()
new CB.build_path(loc, CB)
- qdel(src)
+ return INITIALIZE_HINT_QDEL
/obj/machinery/computer/arcade/proc/prizevend()
if(!(contents-circuit).len)
diff --git a/code/game/machinery/computer/camera_vr.dm b/code/game/machinery/computer/camera_vr.dm
new file mode 100644
index 00000000000..1e006b0f4bb
--- /dev/null
+++ b/code/game/machinery/computer/camera_vr.dm
@@ -0,0 +1,26 @@
+/obj/machinery/computer/security/abductor
+ name = "camera uplink"
+ desc = "Used for hacking into camera networks"
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "camera"
+ network = list( "Mercenary",
+ "Cargo",
+ "Circuits",
+ "Civilian",
+ "Command",
+ "Engine",
+ "Engineering",
+ "Exploration",
+ "Medical",
+ "Mining Outpost",
+ "Outside",
+ "Research",
+ "Research Outpost",
+ "Robots",
+ "Security",
+ "Telecommunications",
+ "Tether",
+ "TalonShip",
+ "Entertainment",
+ "Communicators"
+ )
\ No newline at end of file
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index cc05d632176..8d4202d4213 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -26,7 +26,7 @@
light_color = "#315ab4"
/obj/machinery/computer/cloning/Initialize()
- ..()
+ . = ..()
pods = list()
records = list()
set_scan_temp("Scanner ready.", "good")
diff --git a/code/game/machinery/computer/guestpass.dm b/code/game/machinery/computer/guestpass.dm
index 5fc8c77bd0e..20fd6991a01 100644
--- a/code/game/machinery/computer/guestpass.dm
+++ b/code/game/machinery/computer/guestpass.dm
@@ -168,9 +168,9 @@
if(reas)
reason = reas
if("duration")
- var/dur = input("Duration (in minutes) during which pass is valid (up to 120 minutes).", "Duration") as num|null
+ var/dur = input("Duration (in minutes) during which pass is valid (up to 360 minutes).", "Duration") as num|null //VOREStation Edit
if(dur)
- if(dur > 0 && dur <= 120)
+ if(dur > 0 && dur <= 360) //VOREStation Edit
duration = dur
else
to_chat(usr, "Invalid duration.")
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index adf53c80a8e..680ce44345f 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -29,7 +29,7 @@
/obj/machinery/computer/med_data/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"sex" = "Please select new sex:",
diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm
index 1caa7b61a4d..430b42591cf 100644
--- a/code/game/machinery/computer/message.dm
+++ b/code/game/machinery/computer/message.dm
@@ -335,7 +335,7 @@
name = "Monitor Decryption Key"
/obj/item/weapon/paper/monitorkey/Initialize()
- ..() //Late init
+ ..()
return INITIALIZE_HINT_LATELOAD
/obj/item/weapon/paper/monitorkey/LateInitialize()
diff --git a/code/game/machinery/computer/pod.dm b/code/game/machinery/computer/pod.dm
index dbd5ba8383f..5eae5e82d08 100644
--- a/code/game/machinery/computer/pod.dm
+++ b/code/game/machinery/computer/pod.dm
@@ -13,7 +13,7 @@
var/title = "Mass Driver Controls"
/obj/machinery/computer/pod/Initialize()
- ..() //Not returning parent because lateload
+ ..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/pod/LateInitialize()
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 0b6ab77d7a2..40a4d594cbd 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -25,7 +25,7 @@
var/static/list/field_edit_choices
/obj/machinery/computer/secure_data/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"name" = "Please enter new name:",
@@ -317,16 +317,16 @@
if(!length(t1))
return
- for(var/datum/data/record/R in data_core.security)
- if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"]))
- active2 = R
+ for(var/datum/data/record/R in data_core.general)
+ if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["fingerprint"]))
+ active1 = R
break
- if(!active2)
- set_temp("Security record not found. You must enter the person's exact name, ID or DNA.", "danger")
+ if(!active1)
+ set_temp("Security record not found. You must enter the person's exact name, ID, or fingerprint.", "danger")
return
- for(var/datum/data/record/E in data_core.general)
- if(E.fields["name"] == active2.fields["name"] && E.fields["id"] == active2.fields["id"])
- active1 = E
+ 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
break
screen = SEC_DATA_RECORD
if("print_p")
diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm
index 47b9e8ce256..e11f404b165 100644
--- a/code/game/machinery/computer/skills.dm
+++ b/code/game/machinery/computer/skills.dm
@@ -30,7 +30,7 @@
var/static/list/field_edit_choices
/obj/machinery/computer/skills/Initialize()
- ..()
+ . = ..()
field_edit_questions = list(
// General
"name" = "Please input new name:",
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index db275597960..64a3cc1fc78 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -1,111 +1,8 @@
/*
CONTAINS:
Deployable items
-Barricades
*/
-//Barricades!
-/obj/structure/barricade
- name = "barricade"
- desc = "This space is blocked off by a barricade."
- icon = 'icons/obj/structures.dmi'
- icon_state = "barricade"
- anchored = 1.0
- density = 1.0
- var/health = 100
- var/maxhealth = 100
- var/datum/material/material
-
-/obj/structure/barricade/New(var/newloc, var/material_name)
- ..(newloc)
- if(!material_name)
- material_name = "wood"
- material = get_material_by_name("[material_name]")
- if(!material)
- qdel(src)
- return
- name = "[material.display_name] barricade"
- desc = "This space is blocked off by a barricade made of [material.display_name]."
- color = material.icon_colour
- maxhealth = material.integrity
- health = maxhealth
-
-/obj/structure/barricade/get_material()
- return material
-
-/obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob)
- user.setClickCooldown(user.get_attack_speed(W))
- if(istype(W, /obj/item/stack))
- var/obj/item/stack/D = W
- if(D.get_material_name() != material.name)
- return //hitting things with the wrong type of stack usually doesn't produce messages, and probably doesn't need to.
- if(health < maxhealth)
- if(D.get_amount() < 1)
- to_chat(user, "You need one sheet of [material.display_name] to repair \the [src].")
- return
- visible_message("[user] begins to repair \the [src].")
- if(do_after(user,20) && health < maxhealth)
- if(D.use(1))
- health = maxhealth
- visible_message("[user] repairs \the [src].")
- return
- return
- else
- switch(W.damtype)
- if("fire")
- health -= W.force * 1
- if("brute")
- health -= W.force * 0.75
- if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
- else
- playsound(src, 'sound/weapons/smash.ogg', 50, 1)
- CheckHealth()
- ..()
-
-/obj/structure/barricade/proc/CheckHealth()
- if(health <= 0)
- dismantle()
- return
-
-/obj/structure/barricade/take_damage(var/damage)
- health -= damage
- CheckHealth()
- return
-
-/obj/structure/barricade/attack_generic(var/mob/user, var/damage, var/attack_verb)
- visible_message("[user] [attack_verb] the [src]!")
- if(material == get_material_by_name("resin"))
- playsound(src, 'sound/effects/attackblob.ogg', 100, 1)
- else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD)))
- playsound(src, 'sound/effects/woodcutting.ogg', 100, 1)
- else
- playsound(src, 'sound/weapons/smash.ogg', 50, 1)
- user.do_attack_animation(src)
- health -= damage
- CheckHealth()
- return
-
-/obj/structure/barricade/proc/dismantle()
- material.place_dismantled_product(get_turf(src))
- visible_message("\The [src] falls apart!")
- qdel(src)
- return
-
-/obj/structure/barricade/ex_act(severity)
- switch(severity)
- if(1.0)
- dismantle()
- if(2.0)
- health -= 25
- CheckHealth()
-
-/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
- if(istype(mover) && mover.checkpass(PASSTABLE))
- return TRUE
- return FALSE
-
-//Actual Deployable machinery stuff
/obj/machinery/deployable
name = "deployable"
desc = "deployable"
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 014efcb5813..39d54ef96d5 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -862,14 +862,14 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/tgui_data(mob/user)
var/list/data = list()
-
+
var/list/power = list()
power["main"] = main_power_lost_until > 0 ? 0 : 2
power["main_timeleft"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1)
power["backup"] = backup_power_lost_until > 0 ? 0 : 2
power["backup_timeleft"] = round(backup_power_lost_until > 0 ? max(backup_power_lost_until - world.time, 0) / 10 : backup_power_lost_until, 1)
data["power"] = power
-
+
data["shock"] = (electrified_until == 0) ? 2 : 0
data["shock_timeleft"] = round(electrified_until > 0 ? max(electrified_until - world.time, 0) / 10 : electrified_until, 1)
data["id_scanner"] = !aiDisabledIdScanner
diff --git a/code/game/machinery/doors/airlock_vr.dm b/code/game/machinery/doors/airlock_vr.dm
index 90b88e7a086..eb1594283b4 100644
--- a/code/game/machinery/doors/airlock_vr.dm
+++ b/code/game/machinery/doors/airlock_vr.dm
@@ -27,4 +27,8 @@
/obj/machinery/door/airlock/glass_medical/polarized
name = "Electrochromic Medical Airlock"
- icon_tinted = 'icons/obj/doors/doormedtinted_vr.dmi'
\ No newline at end of file
+ icon_tinted = 'icons/obj/doors/doormedtinted_vr.dmi'
+
+/obj/machinery/door/airlock/glass_command/polarized
+ name = "Electrochormic Command Airlock"
+ icon_tinted = 'icons/obj/doors/Doorcomtinted_vr.dmi'
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 08e0979ed57..8526820c33b 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -29,6 +29,7 @@
var/close_sound = 'sound/machines/door/blastdoorclose.ogg'
var/damage = BLAST_DOOR_CRUSH_DAMAGE
var/multiplier = 1 // The multiplier for how powerful our YEET is.
+ var/istransparent = 0
closed_layer = ON_WINDOW_LAYER // Above airlocks when closed
var/id = 1.0
@@ -108,10 +109,13 @@
src.density = 1
update_nearby_tiles()
src.update_icon()
- src.set_opacity(1)
+ if(src.istransparent)
+ src.set_opacity(0)
+ else
+ src.set_opacity(1)
sleep(15)
src.operating = 0
-
+
// Blast door crushing.
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
@@ -276,10 +280,11 @@
// Parameters: None
// Description: Closes the door. Does necessary checks.
/obj/machinery/door/blast/close()
+
if (src.operating || (stat & BROKEN || stat & NOPOWER))
return
- force_close()
+ force_close()
// Proc: repair()
// Parameters: None
@@ -323,5 +328,52 @@ obj/machinery/door/blast/regular/open
icon_state = "shutter1"
damage = SHUTTER_CRUSH_DAMAGE
+// SUBTYPE: Transparent
+// Not technically a blast door but operates like one. Allows air and light.
+obj/machinery/door/blast/gate
+ name = "thick gate"
+ icon_state_open = "tshutter0"
+ icon_state_opening = "tshutterc0"
+ icon_state_closed = "tshutter1"
+ icon_state_closing = "tshutterc1"
+ icon_state = "tshutter1"
+ damage = SHUTTER_CRUSH_DAMAGE
+ maxhealth = 400
+ block_air_zones = 0
+ opacity = 0
+ istransparent = 1
+
+obj/machinery/door/blast/gate/open
+ icon_state = "tshutter0"
+ density = 0
+
+/obj/machinery/door/blast/gate/thin
+ name = "thin gate"
+ icon_state_open = "shutter2_0"
+ icon_state_opening = "shutter2_c0"
+ icon_state_closed = "shutter2_1"
+ icon_state_closing = "shutter2_c1"
+ icon_state = "shutter2_1"
+ maxhealth = 200
+ opacity = 0
+
+/obj/machinery/door/blast/gate/thin/open
+ icon_state = "shutter2_1"
+ density = 0
+
+/obj/machinery/door/blast/gate/bars
+ name = "prison bars"
+ icon_state_open = "bars_0"
+ icon_state_opening = "bars_c0"
+ icon_state_closed = "bars_1"
+ icon_state_closing = "bars_c1"
+ icon_state = "bars_1"
+ maxhealth = 600
+ opacity = 0
+
+/obj/machinery/door/blast/gate/bars/open
+ icon_state = "bars_1"
+ density = 0
+
#undef BLAST_DOOR_CRUSH_DAMAGE
#undef SHUTTER_CRUSH_DAMAGE
\ No newline at end of file
diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm
index f4d9c900ed3..fdd526039b3 100644
--- a/code/game/machinery/doors/brigdoors.dm
+++ b/code/game/machinery/doors/brigdoors.dm
@@ -40,7 +40,6 @@
/obj/machinery/door_timer/Initialize()
..()
- //Doors need to go first, and can't rely on init order, so come back to me.
return INITIALIZE_HINT_LATELOAD
/obj/machinery/door_timer/LateInitialize()
diff --git a/code/game/machinery/doors/door_vr.dm b/code/game/machinery/doors/door_vr.dm
index 83ee1bed159..6c36a2514d3 100644
--- a/code/game/machinery/doors/door_vr.dm
+++ b/code/game/machinery/doors/door_vr.dm
@@ -109,7 +109,7 @@
if(glass)
icon = icon_tinted
glass = 0
- if(!operating)
+ if(!operating && density)
set_opacity(1)
else
icon = initial(icon)
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index a208e6eefd2..c078b854d0c 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -68,6 +68,7 @@
L.updateicon()
area.power_change()
+ GLOB.lights_switched_on_roundstat++
/obj/machinery/light_switch/power_change()
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 1afa9910f45..a96ef4ed0aa 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -327,7 +327,10 @@ Class Procs:
return 0
if(!component_parts)
return 0
- if(panel_open)
+ to_chat(user, "Following parts detected in [src]:")
+ for(var/obj/item/C in component_parts)
+ to_chat(user, " [C.name]")
+ if(panel_open || !R.panel_req)
var/obj/item/weapon/circuitboard/CB = circuit
var/P
for(var/obj/item/weapon/stock_parts/A in component_parts)
@@ -347,10 +350,6 @@ Class Procs:
break
update_icon()
RefreshParts()
- else
- to_chat(user, "Following parts detected in the machine:")
- for(var/var/obj/item/C in component_parts) //var/var/obj/item/C?
- to_chat(user, " [C.name]")
return 1
// Default behavior for wrenching down machines. Supports both delay and instant modes.
@@ -426,6 +425,9 @@ Class Procs:
/obj/machinery/proc/dismantle()
playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
+ for(var/obj/I in contents)
+ if(istype(I,/obj/item/weapon/card/id))
+ I.forceMove(src.loc)
//TFF 3/6/19 - port Cit RP fix of infinite frames. If it doesn't have a circuit board, don't create a frame. Return a smack instead. BONK!
if(!circuit)
return 0
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index c23d02f4d01..a1798ea5e42 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -164,7 +164,7 @@ GLOBAL_LIST_BOILERPLATE(allCasters, /obj/machinery/newscaster)
securityCaster = 1
/obj/machinery/newscaster/Initialize()
- ..() //Not returning . because lateload below
+ ..()
allCasters += src
unit_no = ++unit_no_cur
paper_remaining = 15
diff --git a/code/game/machinery/pointdefense.dm b/code/game/machinery/pointdefense.dm
index 5b10e398a3b..51f48c416b0 100644
--- a/code/game/machinery/pointdefense.dm
+++ b/code/game/machinery/pointdefense.dm
@@ -371,10 +371,13 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
/obj/effect/projectile/tracer/pointdefense
+ icon = 'icons/obj/projectiles_vr.dmi'
icon_state = "beam_pointdef"
/obj/effect/projectile/muzzle/pointdefense
+ icon = 'icons/obj/projectiles_vr.dmi'
icon_state = "muzzle_pointdef"
/obj/effect/projectile/impact/pointdefense
+ icon = 'icons/obj/projectiles_vr.dmi'
icon_state = "impact_pointdef"
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 01a890bd79d..8e9e6da8f71 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -74,6 +74,7 @@
var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos)
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
var/check_all = FALSE //If active, will fire on anything, including synthetics.
+ var/fire_at_movement = FALSE // If active, will fire on the most recent thing to move in range, as soon as possible.
var/ailock = FALSE // AI cannot use this
var/check_down = FALSE //If active, will shoot to kill when lethals are also on
var/faction = null //if set, will not fire at people in the same faction for any reason.
@@ -95,6 +96,8 @@
var/timeout = 10 // When a turret pops up, then finds nothing to shoot at, this number decrements until 0, when it pops down.
var/can_salvage = TRUE // If false, salvaging doesn't give you anything.
+ var/stay_up = FALSE // If true, the turret will remain open while it is powered.
+
/obj/machinery/porta_turret/crescent
req_one_access = list(access_cent_specops)
enabled = FALSE
@@ -276,6 +279,31 @@
)
return data
+/obj/machinery/porta_turret/pointdefense
+ name = "point-defense turret"
+ turret_type = "core"
+ desc = "A basic ship-mounted rock-breaker."
+ description_info = "This turret is capable of blasting incoming meteors into gravel, but it is very limited in range."
+
+ installation = /obj/item/weapon/gun/energy/mininglaser
+
+ check_arrest = FALSE
+ check_records = FALSE
+ check_weapons = FALSE
+ check_access = FALSE
+ check_anomalies = FALSE
+ check_synth = FALSE
+ check_all = FALSE
+ fire_at_movement = TRUE
+ stay_up = TRUE
+ ailock = FALSE
+ check_down = FALSE
+
+/obj/machinery/porta_turret/pointdefense/orderable
+ enabled = FALSE
+ anchored = FALSE
+ locked = FALSE
+
/obj/machinery/porta_turret/Initialize()
//Sets up a spark system
spark_system = new /datum/effect/effect/system/spark_spread
@@ -322,6 +350,8 @@
var/obj/item/projectile/P = initial(E.projectile_type)
//var/obj/item/ammo_casing/shottype = E.projectile_type
+ //GLOB.moved_event.register_global(src, /obj/machinery/porta_turret/proc/point_defense) //VOREStation Removal
+
projectile = P
lethal_projectile = projectile
shot_sound = initial(P.fire_sound)
@@ -377,11 +407,18 @@
lethal_shot_sound = 'sound/weapons/eluger.ogg'
shot_sound = 'sound/weapons/Taser.ogg'
-/obj/machinery/porta_turret/proc/HasController()
- var/area/A = get_area(src)
- return A && A.turret_controls.len > 0
+ if(/obj/item/weapon/gun/energy/mininglaser)
+ lethal_icon_color = "green"
+ lethal_projectile = /obj/item/projectile/beam/mininglaser
+ lethal_shot_sound = 'sound/weapons/eluger.ogg'
+ icon_color = "red"
+ projectile = /obj/item/projectile/beam/weaklaser
+ shot_sound = 'sound/weapons/Laser.ogg'
/obj/machinery/porta_turret/proc/isLocked(mob/user)
+ if(locked && !issilicon(user))
+ to_chat(user, "Controls locked.")
+ return 1
if(HasController())
return TRUE
if(isrobot(user) || isAI(user))
@@ -409,6 +446,10 @@
/obj/machinery/porta_turret/attack_hand(mob/user)
tgui_interact(user)
+/obj/machinery/porta_turret/proc/HasController()
+ var/area/A = get_area(src)
+ return A && A.turret_controls.len > 0
+
/obj/machinery/porta_turret/tgui_interact(mob/user, datum/tgui/ui = null)
if(HasController())
to_chat(user, "[src] can only be controlled using the assigned turret controller.")
@@ -671,6 +712,10 @@
popDown()
return
+ if(stay_up)
+ timeout = 10
+ popUp()
+
var/list/targets = list() //list of primary targets
var/list/secondarytargets = list() //targets that are least important
@@ -693,7 +738,7 @@
if(!tryToShootAt(targets))
if(!tryToShootAt(secondarytargets)) // if no valid targets, go for secondary targets
timeout--
- if(timeout <= 0)
+ if(timeout <= 0 && !stay_up)
spawn()
popDown() // no valid targets, close the cover
@@ -701,6 +746,14 @@
use_power(20000)
health = min(health+1, maxhealth) // 1HP for 20kJ
+// We're expecting the first arg to be a target, for this we don't care about previous and next turfs.
+/obj/machinery/porta_turret/proc/point_defense(var/atom/movable/Targ)
+ if((stat & (NOPOWER|BROKEN)) || !fire_at_movement) // Are we even able or supposed to fire at non-moving targets?
+ return
+
+ if((isliving(Targ) && assess_living(Targ)) || ((istype(Targ, /obj/item) || istype(Targ, /obj/effect/meteor)) && Targ.invisibility < INVISIBILITY_LEVEL_ONE && Targ in view(7,src))) // Is the target a living thing, if so, is it a valid target? Or if it's not living, is it in sight?
+ target(Targ) // Yes? Blast it.
+
/obj/machinery/porta_turret/proc/assess_and_assign(var/mob/living/L, var/list/targets, var/list/secondarytargets)
switch(assess_living(L))
if(TURRET_PRIORITY_TARGET)
@@ -727,10 +780,10 @@
if(L.stat == DEAD && !emagged) //if the perp is dead, no need to bother really
return TURRET_NOT_TARGET //move onto next potential victim!
- if(get_dist(src, L) > 7) //if it's too far away, why bother?
+ if(get_dist(src, get_turf(L)) > 7) //if it's too far away, why bother?
return TURRET_NOT_TARGET
- if(!(L in check_trajectory(L, src))) //check if we have true line of sight
+ if(!(L in check_trajectory(get_turf(L), src))) //check if we have true line of sight
return TURRET_NOT_TARGET
if(emagged) // If emagged not even the dead get a rest
@@ -837,8 +890,9 @@
last_target = target
spawn()
popUp() //pop the turret up if it's not already up.
- set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
- playsound(src, 'sound/machines/turrets/turret_rotate.ogg', 100, 1) // Play rotating sound
+ if(dir != get_dir(src, target))
+ set_dir(get_dir(src, target)) //even if you can't shoot, follow the target
+ playsound(src, 'sound/machines/turrets/turret_rotate.ogg', 100, 1) // Play rotating sound
spawn()
shootAt(target)
return 1
@@ -903,6 +957,8 @@
var/check_anomalies
var/check_all
var/check_down
+ var/fire_at_movement
+ var/stay_up
var/ailock
/obj/machinery/porta_turret/proc/setState(var/datum/turret_checks/TC)
@@ -919,6 +975,8 @@
check_anomalies = TC.check_anomalies
check_all = TC.check_all
check_down = TC.check_down
+ fire_at_movement = TC.fire_at_movement
+ stay_up = TC.stay_up
ailock = TC.ailock
power_change()
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index af7cdd5dfb4..259c907bde9 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -87,25 +87,44 @@
else if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
- // In case they somehow end up with positive values for otherwise unobtainable damage...
- if(H.getToxLoss() > 0)
- H.adjustToxLoss(-(rand(1,3)))
- if(H.getOxyLoss() > 0)
- H.adjustOxyLoss(-(rand(1,3)))
- if(H.getCloneLoss() > 0)
- H.adjustCloneLoss(-(rand(1,3)))
- if(H.getBrainLoss() > 0)
- H.adjustBrainLoss(-(rand(1,3)))
+ if(H.isSynthetic())
+ // In case they somehow end up with positive values for otherwise unobtainable damage...
+ if(H.getToxLoss() > 0)
+ H.adjustToxLoss(-(rand(1,3)))
+ if(H.getOxyLoss() > 0)
+ H.adjustOxyLoss(-(rand(1,3)))
+ if(H.getCloneLoss() > 0)
+ H.adjustCloneLoss(-(rand(1,3)))
+ if(H.getBrainLoss() > 0)
+ H.adjustBrainLoss(-(rand(1,3)))
- // Also recharge their internal battery.
- if(H.isSynthetic() && H.nutrition < 500) //VOREStation Edit
- H.nutrition = min(H.nutrition+10, 500) //VOREStation Edit
- cell.use(7000/450*10)
+ // Also recharge their internal battery.
+ if(H.isSynthetic() && H.nutrition < 500) //VOREStation Edit
+ H.nutrition = min(H.nutrition+10, 500) //VOREStation Edit
+ cell.use(7000/450*10)
- // And clear up radiation
- if(H.radiation > 0)
- H.radiation = max(H.radiation - rand(5, 15), 0)
+ // And clear up radiation
+ if(H.radiation > 0)
+ H.radiation = max(H.radiation - rand(5, 15), 0)
+ if(H.wearing_rig) // stepping into a borg charger to charge your rig and fix your shit
+ var/obj/item/weapon/rig/wornrig = H.get_rig()
+ if(wornrig) // just to make sure
+ for(var/obj/item/rig_module/storedmod in wornrig.installed_modules)
+ if(weld_rate && storedmod.damage && cell.checked_use(weld_power_use * weld_rate * CELLRATE))
+ to_chat(H, "[storedmod] is repaired!")
+ storedmod.damage = 0
+ if(wornrig.chest)
+ var/obj/item/clothing/suit/space/rig/rigchest = wornrig.chest
+ if(weld_rate && rigchest.damage && cell.checked_use(weld_power_use * weld_rate * CELLRATE))
+ rigchest.breaches = list()
+ rigchest.calc_breach_damage()
+ to_chat(H, "[rigchest] is repaired!")
+ if(wornrig.cell)
+ var/obj/item/weapon/cell/rigcell = wornrig.cell
+ var/diff = min(rigcell.maxcharge - rigcell.charge, charging_power * CELLRATE) // Capped by charging_power / tick
+ var/charge_used = cell.use(diff)
+ rigcell.give(charge_used)
/obj/machinery/recharge_station/examine(mob/user)
. = ..()
@@ -237,7 +256,7 @@
else if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
- if(H.isSynthetic())
+ if(H.isSynthetic() || H.wearing_rig)
add_fingerprint(H)
H.reset_view(src)
H.forceMove(src)
diff --git a/code/game/machinery/syndicatebeacon_vr.dm b/code/game/machinery/syndicatebeacon_vr.dm
index ef6b3da0bbf..668b36dcb70 100644
--- a/code/game/machinery/syndicatebeacon_vr.dm
+++ b/code/game/machinery/syndicatebeacon_vr.dm
@@ -25,7 +25,7 @@
updateUsrDialog()
return
var/mob/M = locate(href_list["traitormob"])
- if(M.mind.special_role || jobban_isbanned(M, "Syndicate"))
+ if(M.mind.tcrystals > 0 || jobban_isbanned(M, "Syndicate"))
temptext = "We have no need for you at this time. Have a pleasant day.
"
updateUsrDialog()
return
@@ -33,7 +33,9 @@
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/N = M
to_chat(N, "Access granted, here are the supplies!")
- traitors.equip(N)
+ traitors.spawn_uplink(N)
+ N.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
+ N.mind.accept_tcrystals = 1
message_admins("[N]/([N.ckey]) has recieved an uplink and telecrystals from the syndicate beacon.")
updateUsrDialog()
diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm
index 19bc0304217..813c756ab40 100644
--- a/code/game/machinery/telecomms/broadcaster.dm
+++ b/code/game/machinery/telecomms/broadcaster.dm
@@ -233,17 +233,19 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(is_freq_listening(signal)) // detect subspace signals
- signal.data["done"] = 1 // mark the signal as being broadcasted
+ //signal.data["done"] = 1 // mark the signal as being broadcasted since we're a broadcaster
signal.data["compression"] = 0
+ /*
// Search for the original signal and mark it as done as well
var/datum/signal/original = signal.data["original"]
if(original)
original.data["done"] = 1
+ */
// For some reason level is both used as a list and not a list, and now it needs to be a list.
// Because this is a 'all in one' machine, we're gonna just cheat.
- signal.data["level"] = using_map.contact_levels.Copy()
+ //signal.data["level"] = using_map.contact_levels.Copy()
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
diff --git a/code/game/machinery/telecomms/broadcaster_vr.dm b/code/game/machinery/telecomms/broadcaster_vr.dm
new file mode 100644
index 00000000000..4bdccfbc803
--- /dev/null
+++ b/code/game/machinery/telecomms/broadcaster_vr.dm
@@ -0,0 +1,46 @@
+//ERT version with unlimited range (doesn't even check) and uses no power, to enable ert comms to work anywhere.
+/obj/machinery/telecomms/allinone/ert
+ use_power = USE_POWER_OFF
+ idle_power_usage = 0
+
+/obj/machinery/telecomms/allinone/ert/receive_signal(datum/signal/signal)
+ if(!on) // has to be on to receive messages
+ return
+
+ if(is_freq_listening(signal)) // detect subspace signals
+
+ //signal.data["done"] = 1 // mark the signal as being broadcasted since we're a broadcaster
+ signal.data["compression"] = 0
+
+ /*
+ // Search for the original signal and mark it as done as well
+ var/datum/signal/original = signal.data["original"]
+ if(original)
+ original.data["done"] = 1
+ */
+
+ // For some reason level is both used as a list and not a list, and now it needs to be a list.
+ // Because this is a 'all in one' machine, we're gonna just cheat.
+ //signal.data["level"] = using_map.contact_levels.Copy()
+
+ if(signal.data["slow"] > 0)
+ sleep(signal.data["slow"]) // simulate the network lag if necessary
+
+ /* ###### Broadcast a message using signal.data ###### */
+
+ var/datum/radio_frequency/connection = signal.data["connection"]
+
+ var/list/forced_radios
+ for(var/weakref/wr in linked_radios_weakrefs)
+ var/obj/item/device/radio/R = wr.resolve()
+ if(istype(R))
+ LAZYDISTINCTADD(forced_radios, R)
+
+ if(connection.frequency in CENT_FREQS) // if ert broadcast, just
+ Broadcast_Message(signal.data["connection"], signal.data["mob"],
+ signal.data["vmask"], signal.data["vmessage"],
+ signal.data["radio"], signal.data["message"],
+ signal.data["name"], signal.data["job"],
+ signal.data["realname"], signal.data["vname"], DATA_NORMAL,
+ signal.data["compression"], list(0), connection.frequency,
+ signal.data["verb"], forced_radios)
diff --git a/code/game/machinery/transportpod.dm b/code/game/machinery/transportpod.dm
index 0b499096fea..4a43cb18904 100644
--- a/code/game/machinery/transportpod.dm
+++ b/code/game/machinery/transportpod.dm
@@ -32,7 +32,7 @@
sleep(2)
go_out()
sleep(2)
- del(src)
+ qdel(src)
/obj/machinery/transportpod/relaymove(mob/user as mob)
if(user.stat)
diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm
index ad55fe14a17..7f5a1d8e567 100644
--- a/code/game/machinery/turret_control.dm
+++ b/code/game/machinery/turret_control.dm
@@ -28,9 +28,12 @@
var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg
var/check_all = FALSE //If active, will shoot at anything.
var/check_down = TRUE //If active, won't shoot laying targets.
+ var/stay_up = FALSE //If active, the turret will not pop-down unless it loses power or is disabled.
+ var/fire_at_movement = FALSE //If active, the turret will prioritize objects or creatures that move in its range.
var/ailock = FALSE //Silicons cannot use this
var/syndicate = FALSE
+
req_access = list(access_ai_upload)
/obj/machinery/turretid/stun
@@ -194,6 +197,8 @@
TC.check_anomalies = check_anomalies
TC.check_all = check_all
TC.check_down = check_down
+ TC.stay_up = stay_up
+ TC.fire_at_movement = fire_at_movement
TC.ailock = ailock
if(istype(control_area))
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 4f3d532c279..58107d9d0b4 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -572,7 +572,7 @@ GLOBAL_LIST_EMPTY(vending_products)
vend_ready = 1
currently_vending = null
SStgui.update_uis(src)
-
+ GLOB.items_sold_shift_roundstat++
/obj/machinery/vending/proc/do_logging(datum/stored_item/vending_product/R, mob/user, var/vending = 0)
if(user.GetIdCard())
diff --git a/code/game/machinery/vending_machines.dm b/code/game/machinery/vending_machines.dm
index e04568c1d08..098d231ce77 100644
--- a/code/game/machinery/vending_machines.dm
+++ b/code/game/machinery/vending_machines.dm
@@ -753,7 +753,9 @@
/obj/item/toy/plushie/borgplushie/scrubpuppy = 1,
/obj/item/toy/plushie/foxbear = 1,
/obj/item/toy/plushie/nukeplushie = 1,
- /obj/item/toy/plushie/otter = 1)
+ /obj/item/toy/plushie/otter = 1,
+ /obj/item/toy/plushie/vox = 1,
+ /obj/item/toy/mistletoe = 1)
//VOREStation Add End
premium = list(/obj/item/weapon/reagent_containers/food/drinks/bottle/champagne = 1,
/obj/item/weapon/storage/trinketbox = 2)
@@ -793,7 +795,9 @@
/obj/item/toy/plushie/borgplushie/scrubpuppy = 50,
/obj/item/toy/plushie/foxbear = 50,
/obj/item/toy/plushie/nukeplushie = 50,
- /obj/item/toy/plushie/otter = 50)
+ /obj/item/toy/plushie/otter = 50,
+ /obj/item/toy/plushie/vox = 50,
+ /obj/item/toy/mistletoe = 50)
//VOREStation Add End
diff --git a/code/game/machinery/vending_machines_vr.dm b/code/game/machinery/vending_machines_vr.dm
index a4ce500db2d..c4c4e663d4b 100644
--- a/code/game/machinery/vending_machines_vr.dm
+++ b/code/game/machinery/vending_machines_vr.dm
@@ -84,6 +84,158 @@
)
contraband = list(/obj/item/weapon/reagent_containers/food/snacks/mysterysoup = 10)
vend_delay = 15
+
+//Specific food vending machines for events that want them!
+
+/obj/machinery/vending/fooditalian
+ name = "Italian Imports"
+ desc = "You wanted some italian food? Well here's some imported from the local pizza place!"
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/pastatomato = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/meatballspagetti = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/meatball = 15
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/oldpizza = 1)
+ vend_delay = 10
+
+/obj/machinery/vending/foodfast
+ name = "United Grills"
+ desc = "Not sure how they're united but man is this grilled food delicious! Though it seems to just be a lot of fast food..."
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/monkeyburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/cheeseburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/fishburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/clownburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/mimeburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/superbiteburger = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/burger/bacon = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/hotdog = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chickenfillet = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/fries = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/cheesyfries = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chilicheesefries = 10
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/ghostburger = 3,
+ /obj/item/weapon/reagent_containers/food/snacks/tofuburger = 5)
+ vend_delay = 10
+
+/obj/machinery/vending/foodmeat
+ name = "Meaty Marvels"
+ desc = "What's a marvel is how you're not ordering from this machine yet!"
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/ribplate = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/meat_pocket = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/meatpie = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/bacon_flatbread = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/roastbeef = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/stuffed_meatball = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/meatsteak = 20
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/monkeysdelight = 5)
+ vend_delay = 10
+
+/obj/machinery/vending/foodasian
+ name = "Authenticate Asian"
+ desc = "Some good ol' Sol food!"
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/sliceable/sushi = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chawanmushi = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/generalschicken = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chickenkatsu = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sweet_and_sour = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/bibimbap = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/hotandsoursoup = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/kitsuneudon = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/milosoup = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/lomein = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/friedrice = 10
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/monkeyburger = 1)
+ vend_delay = 10
+
+/obj/machinery/vending/foodfish
+ name = "Fishy Food"
+ desc = "Don't mind the name, this is 100% fish!"
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/sliceable/grilled_carp = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/kudzudonburi = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/zestfish = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/lobstercooked = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sashimi = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sharkmeatcooked = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sharkmeatdip = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sharkmeatcubes = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/cuttlefishcooked = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/monkfishcooked = 10
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/sliceable/monkfish = 1)
+ vend_delay = 10
+
+/obj/machinery/vending/foodveggie
+ name = "Veggie Varieties"
+ desc = "Even vegitarians have their own vending machines! How thoughtful."
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/beetsoup = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/eggplantparm = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/eggbowl = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/flowerchildsalad = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/tossedsalad = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/fruitsalad = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/grilledcheese = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/tofurkey = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/stuffing = 10
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/meatsteak = 1)
+ vend_delay = 10
+
+/obj/machinery/vending/fooddessert
+ name = "Delightful Desserts"
+ desc = "Even if you've stuffed your face with a pizza or two, you ALWAYS have room for dessert!"
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/applepie = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/cherrypie = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/keylimepie = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/pie = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/funnelcake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/peanutcake = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/icecreamsandwich = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/cookie = 15,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/brownies = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatebar = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/chocolatepiece = 20
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/donut/chaos = 10)
+ vend_delay = 10
+
+/obj/machinery/vending/foodstuffing
+ name = "Stuffing Site"
+ desc = "Is... is it just full of stuffing? No wait, there's turkey in there too."
+ icon_state = "hotfood"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/stuffing = 50,
+ /obj/item/weapon/reagent_containers/food/snacks/sliceable/turkey= 20
+ )
+ contraband = list(/obj/item/weapon/reagent_containers/food/snacks/tofurkey = 10)
+ vend_delay = 10
+
+//End of food event machines
+
/* For later, then
/obj/machinery/vending/weapon_machine
name = "Frozen Star Guns&Ammo"
@@ -1294,7 +1446,7 @@
/obj/item/seeds/riceseed = 3,
/obj/item/seeds/rose = 3,
/obj/item/seeds/soyaseed = 3,
- /obj/item/seeds/spineapple = 3,
+ /obj/item/seeds/pineapple = 3,
/obj/item/seeds/sugarcaneseed = 3,
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/shandseed = 2,
@@ -1456,6 +1608,30 @@
req_log_access = access_cmo
has_logs = 1
+/obj/machinery/vending/abductor
+ name = "Abduct-U"
+ desc = "A mysterious machine which can fabricate many tools for acquiring test subjects."
+ icon = 'icons/obj/abductor_vr.dmi'
+ icon_state = "dispenser_2way"
+ products = list(/obj/item/weapon/card/id/syndicate/station_access = 1,
+ /obj/item/weapon/storage/box/syndie_kit/chameleon = 1,
+ /obj/item/clothing/mask/bandana = 1,
+ /obj/item/clothing/glasses/sunglasses = 1,
+ /obj/item/device/radio/headset/syndicate/alt = 1,
+ /obj/item/device/pda = 1,
+ /obj/item/device/communicator = 1,
+ /obj/item/weapon/tape_roll = 2,
+ /obj/item/weapon/handcuffs = 4,
+ /obj/item/weapon/handcuffs/legcuffs = 4,
+ /obj/item/weapon/cell/device/weapon/recharge/alien = 2,
+ /obj/item/device/chameleon = 1,
+ /obj/item/weapon/storage/mre/menu11 = 2,
+ /obj/item/device/flash = 2,
+ /obj/item/weapon/pen/reagent/paralysis = 4,
+ /obj/item/device/perfect_tele/alien = 1
+ )
+ vend_delay = 15
+
/obj/machinery/vending/loadout
name = "Fingers and Toes"
desc = "A special vendor for gloves and shoes!"
@@ -3764,7 +3940,7 @@
/obj/item/weapon/reagent_containers/food/snacks/slice/mushroompizza = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/orangecake = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/peanutcake = 10,
- /obj/item/weapon/reagent_containers/food/snacks/slice/pineapple = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/pineappleslice = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/plaincake = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/pumpkinpie = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/tofubread = 10,
@@ -4228,7 +4404,7 @@
/obj/item/weapon/reagent_containers/food/snacks/slice/mushroompizza = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/orangecake = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/peanutcake = 10,
- /obj/item/weapon/reagent_containers/food/snacks/slice/pineapple = 10,
+ /obj/item/weapon/reagent_containers/food/snacks/pineappleslice = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/plaincake = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/pumpkinpie = 10,
/obj/item/weapon/reagent_containers/food/snacks/slice/tofubread = 10,
@@ -4400,7 +4576,7 @@
/obj/item/seeds/riceseed = 3,
/obj/item/seeds/rose = 3,
/obj/item/seeds/soyaseed = 3,
- /obj/item/seeds/spineapple = 3,
+ /obj/item/seeds/pineapple = 3,
/obj/item/seeds/sugarcaneseed = 3,
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/shandseed = 2,
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index aa5a9e000c1..19bd2b9c53e 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -33,6 +33,9 @@
defence_mode_possible = 1
+ icon_scale_x = 1.5
+ icon_scale_y = 1.5
+
/*
/obj/mecha/combat/durand/New()
..()
diff --git a/code/game/mecha/combat/gorilla.dm b/code/game/mecha/combat/gorilla.dm
index 4052afe8e6a..fecb361f1a2 100644
--- a/code/game/mecha/combat/gorilla.dm
+++ b/code/game/mecha/combat/gorilla.dm
@@ -31,7 +31,7 @@
thrusters_possible = 1
/obj/mecha/combat/gorilla/Initialize()
- ..()
+ . = ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src) // This thing basically cannot function without an external power supply.
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/cannon(src)
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index 0323124c479..1f9d4a0b6e3 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -31,6 +31,9 @@
overload_possible = 1
+ icon_scale_x = 1.35
+ icon_scale_y = 1.35
+
//Not quite sure how to move those yet.
/obj/mecha/combat/gygax/get_commands()
var/output = {"