diff --git a/.github/workflows/autowiki.yml b/.github/workflows/autowiki.yml
index 82d0ac76f32f..fec68f2ca332 100644
--- a/.github/workflows/autowiki.yml
+++ b/.github/workflows/autowiki.yml
@@ -8,7 +8,7 @@ permissions:
jobs:
autowiki:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
steps:
- name: "Check for AUTOWIKI_USERNAME"
id: secrets_set
@@ -32,7 +32,7 @@ jobs:
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
- sudo apt install -o APT::Immediate-Configure=false libssl1.1:i386
+ sudo apt install -o APT::Immediate-Configure=false zlib1g-dev:i386 libssl-dev:i386
bash tools/ci/install_rust_g.sh
- name: Compile and generate Autowiki files
if: steps.secrets_set.outputs.SECRETS_ENABLED
diff --git a/README.md b/README.md
index 94ccaf07031f..abac21f624f0 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,8 @@
## CM-SS13 codebase
-[![resentment](https://forthebadge.com/images/badges/built-with-resentment.svg)](https://www.monkeyuser.com/assets/images/2019/131-bug-free.png) [![resentment](https://forthebadge.com/images/badges/contains-technical-debt.svg)](https://user-images.githubusercontent.com/8171642/50290880-ffef5500-043a-11e9-8270-a2e5b697c86c.png) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
+ [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
[![Build Status](https://github.com/cmss13-devs/cmss13/workflows/CI%20Suite/badge.svg)](https://github.com/cmss13-devs/cmss13/actions?query=workflow%3A%22CI+Suite%22)
-
* **Website:** https://forum.cm-ss13.com/
* **Code:** https://github.com/cmss13-devs/cmss13
* **Wiki:** https://cm-ss13.com/wiki/Main_Page
@@ -36,5 +35,3 @@ The code for CM-SS13 is licensed under the [GNU Affero General Public License v3
Assets including icons and sound are under the [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. Authorship for assets including art and sound under the CC BY-SA license is defined as the active development team of CM-SS13 unless stated otherwise (by author of the commit).
All code is assumed to be licensed under AGPL v3 unless stated otherwise by file header. Commits before 9a001bf520f889b434acd295253a1052420860af are assumed to be licensed under GPLv3 and can be used in closed source repo.
-
-
diff --git a/code/__DEFINES/ARES.dm b/code/__DEFINES/ARES.dm
index ec84a6ab5992..a1b82af25821 100644
--- a/code/__DEFINES/ARES.dm
+++ b/code/__DEFINES/ARES.dm
@@ -26,6 +26,7 @@
#define ARES_RECORD_SECURITY "Security Update"
#define ARES_RECORD_MAINTENANCE "Maintenance Ticket"
#define ARES_RECORD_ACCESS "Access Ticket"
+#define ARES_RECORD_FLIGHT "Flight Record"
/// Not by ARES logged through marine_announcement()
#define ARES_LOG_NONE 0
@@ -34,13 +35,14 @@
/// Logged in the security updates
#define ARES_LOG_SECURITY 2
-/// Access levels specifically for Working Joe management console
-#define APOLLO_ACCESS_REQUEST 0
-#define APOLLO_ACCESS_REPORTER 1
-#define APOLLO_ACCESS_TEMP 2
-#define APOLLO_ACCESS_AUTHED 3
-#define APOLLO_ACCESS_JOE 4
-#define APOLLO_ACCESS_DEBUG 5
+// Access levels specifically for Working Joe management console
+#define APOLLO_ACCESS_LOGOUT 0
+#define APOLLO_ACCESS_REQUEST 1
+#define APOLLO_ACCESS_REPORTER 2
+#define APOLLO_ACCESS_TEMP 3
+#define APOLLO_ACCESS_AUTHED 4
+#define APOLLO_ACCESS_JOE 5
+#define APOLLO_ACCESS_DEBUG 6
/// Ticket statuses, both for Access and Maintenance
/// Pending assignment/rejection
@@ -54,6 +56,13 @@
/// Completed by WJs
#define TICKET_COMPLETED "completed"
+/// Granted Access Ticket
+#define TICKET_GRANTED "granted"
+/// Revoked Access Ticket
+#define TICKET_REVOKED "revoked"
+/// Self-Returned Access Ticket
+#define TICKET_RETURNED "returned"
+
/// Checks for if buttons can be used, these may yet be removed and internalised to the UI programming
#define TICKET_OPEN "OPEN"
#define TICKET_CLOSED "CLOSED"
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index fcc3e7784cb5..3abd79708f7a 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -41,3 +41,4 @@ var/MAX_EXPLOSION_RANGE = 14
/// Used in /obj/structure/pipes/vents/proc/create_gas
#define VENT_GAS_SMOKE "Smoke"
#define VENT_GAS_CN20 "CN20 Nerve Gas"
+#define VENT_GAS_CN20_XENO "CN20-X Nerve Gas"
diff --git a/code/__DEFINES/colours.dm b/code/__DEFINES/colours.dm
index b7457f9ae478..5fa106715f39 100644
--- a/code/__DEFINES/colours.dm
+++ b/code/__DEFINES/colours.dm
@@ -142,6 +142,9 @@
*
* Important note: colours can end up significantly different from the basic html picture, especially when saturated
*/
+
+/// Full white. rgb(255, 255, 255)
+#define LIGHT_COLOR_WHITE "#FFFFFF"
/// Bright but quickly dissipating neon green. rgb(100, 200, 100)
#define LIGHT_COLOUR_GREEN "#64C864"
/// Electric green. rgb(0, 255, 0)
diff --git a/code/__DEFINES/conflict.dm b/code/__DEFINES/conflict.dm
index 30b2627bb1b0..0820c709cdae 100644
--- a/code/__DEFINES/conflict.dm
+++ b/code/__DEFINES/conflict.dm
@@ -26,7 +26,7 @@
#define AMMO_IGNORE_RESIST (1<<10)
#define AMMO_BALLISTIC (1<<11)
#define AMMO_IGNORE_COVER (1<<12)
-// (1<<13) unused, previously was AMMO_SCANS_NEARBY
+#define AMMO_ANTIVEHICLE (1<<13)
#define AMMO_STOPPED_BY_COVER (1<<14)
#define AMMO_SPECIAL_EMBED (1<<15)
/// If the projectile hits a dense turf it'll do on_hit_turf on the turf just in front of the turf instead of on the turf itself
@@ -90,6 +90,8 @@
#define ATTACH_IGNORE_EMPTY (1<<5)
/// This attachment should activate if you attack() with it attached.
#define ATTACH_MELEE (1<<6)
+/// Override for attachies so you can fire them with a single hand . ONLY FOR PROJECTILES!!
+#define ATTACH_WIELD_OVERRIDE (1<<7)
//Ammo magazine defines, for flags_magazine
@@ -218,6 +220,7 @@
#define UNIFORM_HAS_SENSORS 1
#define UNIFORM_FORCED_SENSORS 2
+#define EYE_PROTECTION_NEGATIVE -1
#define EYE_PROTECTION_NONE 0
#define EYE_PROTECTION_FLAVOR 1
#define EYE_PROTECTION_FLASH 2
diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm
index e1f221dccbde..9368caf3c6e3 100644
--- a/code/__DEFINES/cooldowns.dm
+++ b/code/__DEFINES/cooldowns.dm
@@ -3,6 +3,7 @@
#define COOLDOWN_HIJACK_BARRAGE "gamemode_explosive_barrage"
#define COOLDOWN_HIJACK_GROUND_CHECK "gamemode_ground_check"
#define COOLDOWN_ITEM_HOOD_SOUND "item_hood_sound"
+#define COOLDOWN_LIGHT "cooldown_light"
//Define for ship alt
#define COOLDOWN_ALTITUDE_CHANGE "altitude_change"
diff --git a/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm b/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm
index b38339d1af17..0a9e00b59e04 100644
--- a/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm
+++ b/code/__DEFINES/dcs/signals/atom/mob/living/signals_human.dm
@@ -12,7 +12,7 @@
#define COMSIG_HUMAN_REVIVED "human_revived"
/// From /mob/living/carbon/human/bullet_act
#define COMSIG_HUMAN_PRE_BULLET_ACT "human_pre_bullet_act"
-/// From /mob/living/carbon/human/bullet_act(): (damage_result, ammo_flags, obj/item/projectile/P)
+/// From /mob/living/carbon/human/bullet_act(): (damage_result, ammo_flags, obj/projectile/P)
#define COMSIG_HUMAN_BULLET_ACT "human_bullet_act"
#define COMPONENT_CANCEL_BULLET_ACT (1<<0)
diff --git a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm
index 323e0ee6966c..9eff6fa3ddc8 100644
--- a/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm
+++ b/code/__DEFINES/dcs/signals/atom/mob/signals_mob.dm
@@ -116,3 +116,9 @@
#define COMSIG_MOB_MOUSEDRAG "mob_mousedrag" //from /client/MouseDrag(): (atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params)
#define COMSIG_MOB_CLICK_CANCELED (1<<0)
#define COMSIG_MOB_CLICK_HANDLED (1<<1)
+
+#define COMSIG_MOB_DEPLOYED_BIPOD "mob_deployed_bipod"
+#define COMSIG_MOB_UNDEPLOYED_BIPOD "mob_undeployed_bipod"
+
+/// From /obj/item/proc/pickup() : (obj/item/picked_up)
+#define COMSIG_MOB_PICKUP_ITEM "mob_pickup_item"
diff --git a/code/__DEFINES/dcs/signals/atom/signals_atom.dm b/code/__DEFINES/dcs/signals/atom/signals_atom.dm
index 0cbe28d0438c..7431c5593b17 100644
--- a/code/__DEFINES/dcs/signals/atom/signals_atom.dm
+++ b/code/__DEFINES/dcs/signals/atom/signals_atom.dm
@@ -26,5 +26,22 @@
///from /turf/ChangeTurf
#define COMSIG_ATOM_TURF_CHANGE "movable_turf_change"
+//from atom/set_light(): (l_range, l_power, l_color)
+#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
+
+///Called right before the atom changes the value of light_range to a different one, from base atom/set_light_range(): (new_range)
+#define COMSIG_ATOM_SET_LIGHT_RANGE "atom_set_light_range"
+///Called right before the atom changes the value of light_power to a different one, from base atom/set_light_power(): (new_power)
+#define COMSIG_ATOM_SET_LIGHT_POWER "atom_set_light_power"
+///Called right before the atom changes the value of light_color to a different one, from base atom/set_light_color(): (new_color)
+#define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color"
+///Called right before the atom changes the value of light_on to a different one, from base atom/set_light_on(): (new_value)
+#define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on"
+///Called right before the atom changes the value of light_flags to a different one, from base atom/set_light_flags(): (new_value)
+#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags"
+
+///from base of atom/set_opacity(): (new_opacity)
+#define COMSIG_ATOM_SET_OPACITY "atom_set_opacity"
+
///When the transform or an atom is varedited through vv topic.
#define COMSIG_ATOM_VV_MODIFY_TRANSFORM "atom_vv_modify_transform"
diff --git a/code/__DEFINES/dcs/signals/atom/signals_item.dm b/code/__DEFINES/dcs/signals/atom/signals_item.dm
index b7bbca9f64a3..6c31b77f76a4 100644
--- a/code/__DEFINES/dcs/signals/atom/signals_item.dm
+++ b/code/__DEFINES/dcs/signals/atom/signals_item.dm
@@ -55,6 +55,11 @@
#define COMSIG_GUN_BURST_SHOTS_TO_FIRE_MODIFIED "gun_burst_shots_to_fire_modified"
#define COMSIG_GUN_BURST_SHOT_DELAY_MODIFIED "gun_burst_shot_delay_modified"
+#define COMSIG_GUN_VULTURE_FIRED_ONEHAND "gun_vulture_fired_onehand"
+#define COMSIG_VULTURE_SCOPE_MOVED "vulture_scope_moved"
+#define COMSIG_VULTURE_SCOPE_SCOPED "vulture_scope_scoped"
+#define COMSIG_VULTURE_SCOPE_UNSCOPED "vulture_scope_unscoped"
+
/// from /obj/item/weapon/gun/proc/recalculate_attachment_bonuses() : ()
#define COMSIG_GUN_RECALCULATE_ATTACHMENT_BONUSES "gun_recalculate_attachment_bonuses"
diff --git a/code/__DEFINES/dcs/signals/atom/signals_projectile.dm b/code/__DEFINES/dcs/signals/atom/signals_projectile.dm
index 861f351a1f58..46014d5351d5 100644
--- a/code/__DEFINES/dcs/signals/atom/signals_projectile.dm
+++ b/code/__DEFINES/dcs/signals/atom/signals_projectile.dm
@@ -15,17 +15,17 @@
#define COMSIG_AMMO_POINT_BLANK "ammo_point_blank"
#define COMPONENT_CANCEL_AMMO_POINT_BLANK (1<<0)
-/// From /obj/item/projectile/handle_mob(): (mob/living/target)
+/// From /obj/projectile/handle_mob(): (mob/living/target)
#define COMSIG_BULLET_PRE_HANDLE_MOB "bullet_pre_handle_mob"
-/// From /obj/item/projectile/handle_mob(): (mob/living/target)
+/// From /obj/projectile/handle_mob(): (mob/living/target)
#define COMSIG_BULLET_POST_HANDLE_MOB "bullet_post_handle_mob"
-/// From /obj/item/projectile/handle_obj(): (obj/target, did_hit)
+/// From /obj/projectile/handle_obj(): (obj/target, did_hit)
#define COMSIG_BULLET_POST_HANDLE_OBJ "bullet_post_handle_obj"
-/// From /obj/item/projectile/handle_obj(): (obj/target)
+/// From /obj/projectile/handle_obj(): (obj/target)
#define COMSIG_BULLET_PRE_HANDLE_OBJ "bullet_pre_handle_obj"
-/// From /obj/item/projectile/scan_a_turf(): (turf/target)
+/// From /obj/projectile/scan_a_turf(): (turf/target)
#define COMSIG_BULLET_POST_HANDLE_TURF "bullet_post_handle_turf"
-/// From /obj/item/projectile/scan_a_turf(): (turf/target)
+/// From /obj/projectile/scan_a_turf(): (turf/target)
#define COMSIG_BULLET_PRE_HANDLE_TURF "bullet_pre_handle_turf"
#define COMPONENT_BULLET_PASS_THROUGH (1<<0)
#define COMSIG_BULLET_TERMINAL "bullet_terminal"
diff --git a/code/__DEFINES/equipment.dm b/code/__DEFINES/equipment.dm
index 461eae27a2a3..210aee450406 100644
--- a/code/__DEFINES/equipment.dm
+++ b/code/__DEFINES/equipment.dm
@@ -42,6 +42,8 @@
#define ATOM_DECORATED (1<<16)
/// Whether or not the object uses hearing
#define USES_HEARING (1<<17)
+/// Should we use the initial icon for display? Mostly used by overlay only objects
+#define HTML_USE_INITAL_ICON (1<<18)
//==========================================================================================
@@ -233,6 +235,8 @@
#define SLOT_LEGS (1<<13)
#define SLOT_ACCESSORY (1<<14)
#define SLOT_SUIT_STORE (1<<15) //this allows items to be stored in the suit slot regardless of suit
+/// Anything with this flag cannot be worn in suit storage, period.
+#define SLOT_BLOCK_SUIT_STORE (1<<16)
//=================================================
//slots
diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 78d90c65ecb1..38e5693dcbe5 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -17,3 +17,9 @@
#define APPEARANCE_UI_IGNORE_ALPHA (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA|PIXEL_SCALE)
/// Used for HUD objects
#define APPEARANCE_UI (RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|PIXEL_SCALE)
+
+// Notification action types
+#define NOTIFY_JUMP "jump"
+#define NOTIFY_ATTACK "attack"
+#define NOTIFY_ORBIT "orbit"
+#define NOTIFY_JOIN_XENO "join_xeno"
diff --git a/code/__DEFINES/human.dm b/code/__DEFINES/human.dm
index 846119d6b55d..ebf08f495752 100644
--- a/code/__DEFINES/human.dm
+++ b/code/__DEFINES/human.dm
@@ -116,14 +116,15 @@
#define ORDER_FOCUS_MAX_LEVEL 50
//Human Overlays Indexes used in update_icons/////////
-#define UNDERWEAR_LAYER 41
-#define UNDERSHIRT_LAYER 40
-#define MUTANTRACE_LAYER 39
+#define BODYPARTS_LAYER 42
+#define DAMAGE_LAYER 41
-/// For use by Hunter Flay
-#define FLAY_LAYER 38
+#define UNDERWEAR_LAYER 40
+#define UNDERSHIRT_LAYER 39
+#define MUTANTRACE_LAYER 38
-#define DAMAGE_LAYER 37
+/// For use by Hunter Flay
+#define FLAY_LAYER 37
#define UNIFORM_LAYER 36
/// bs12 specific. this hack is probably gonna come back to haunt me
@@ -176,7 +177,7 @@
/// If you're hit by an acid DoT
#define EFFECTS_LAYER 1
-#define TOTAL_LAYERS 41
+#define TOTAL_LAYERS 42
//////////////////////////////////
//Synthetic Defines
diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm
index eac5121f173e..600f7d14b0aa 100644
--- a/code/__DEFINES/job.dm
+++ b/code/__DEFINES/job.dm
@@ -288,12 +288,16 @@ var/global/list/job_command_roles = JOB_COMMAND_ROLES_LIST
//-------- TWE --------//
#define JOB_TWE_REPRESENTATIVE "TWE Representative"
-#define JOB_TWE_YONTO "RMC Yonto"
-#define JOB_TWE_SANTO "RMC Santo"
-#define JOB_TWE_NITO "RMC Nito"
-#define JOB_TWE_ITTO "RMC Itto"
+//RMC
+#define JOB_TWE_RMC_RIFLEMAN "RMC Rifleman"
+#define JOB_TWE_RMC_MARKSMAN "RMC Marksman"
+#define JOB_TWE_RMC_SMARTGUNNER "RMC Smartgunner"
+#define JOB_TWE_RMC_BREACHER "RMC Breacher"
+#define JOB_TWE_RMC_TEAMLEADER "RMC Team Leader"
+#define JOB_TWE_RMC_LIEUTENANT "RMC Lieutenant"
+#define JOB_TWE_RMC_COMMANDER "RMC Commander"
-#define TWE_COMMANDO_JOB_LIST list(JOB_TWE_YONTO, JOB_TWE_SANTO, JOB_TWE_NITO, JOB_TWE_ITTO)
+#define TWE_COMMANDO_JOB_LIST list(JOB_TWE_RMC_RIFLEMAN, JOB_TWE_RMC_BREACHER, JOB_TWE_RMC_SMARTGUNNER,JOB_TWE_RMC_MARKSMAN ,JOB_TWE_RMC_TEAMLEADER, JOB_TWE_RMC_LIEUTENANT, JOB_TWE_RMC_COMMANDER)
#define JOB_TWE_SEAMAN "TWE Seaman"
#define JOB_TWE_LSEAMAN "TWE Leading Seaman"
@@ -326,7 +330,6 @@ var/global/list/job_command_roles = JOB_COMMAND_ROLES_LIST
#define JOB_TIS_SA "UAAC-TIS Special Agent"
#define TIS_JOB_LIST list(JOB_TIS_SA, JOB_TIS_IO)
-
//-------- DUTCH'S DOZEN --------//
#define JOB_DUTCH_ARNOLD "Dutch's Dozen - Dutch"
#define JOB_DUTCH_RIFLEMAN "Dutch's Dozen - Rifleman"
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 74a390e2db47..c0ccd5164b0b 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -141,8 +141,6 @@
#define ABOVE_FLY_LAYER 6
-#define ABOVE_LIGHTING_PLANE 16
-
/// blip from motion detector
#define BELOW_FULLSCREEN_LAYER 16.9
#define FULLSCREEN_LAYER 17
@@ -160,6 +158,8 @@
#define FULLSCREEN_BLIND_LAYER 17.15
/// pain flashes
#define FULLSCREEN_PAIN_LAYER 17.2
+/// Vulture sniper/spotter scope
+#define FULLSCREEN_VULTURE_SCOPE_LAYER 17.21
/// in critical
#define FULLSCREEN_CRIT_LAYER 17.25
@@ -168,11 +168,44 @@
#define CINEMATIC_LAYER 21
-#define TYPING_LAYER 500
-
/// for areas, so they appear above everything else on map file.
#define AREAS_LAYER 999
+//---------- EMISSIVES -------------
+//Layering order of these is not particularly meaningful.
+//Important part is the seperation of the planes for control via plane_master
+
+/// This plane masks out lighting to create an "emissive" effect, ie for glowing lights in otherwise dark areas.
+#define EMISSIVE_PLANE 90
+/// The render target used by the emissive layer.
+#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
+/// The layer you should use if you _really_ don't want an emissive overlay to be blocked.
+#define EMISSIVE_LAYER_UNBLOCKABLE 9999
+
+#define LIGHTING_BACKPLANE_LAYER 14.5
+
+#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
+
+#define SHADOW_RENDER_TARGET "SHADOW_RENDER_TARGET"
+
+/// Plane for balloon text (text that fades up)
+#define BALLOON_CHAT_PLANE 110
+/// Bubble for typing indicators
+#define TYPING_LAYER 500
+
+#define O_LIGHTING_VISUAL_PLANE 120
+#define O_LIGHTING_VISUAL_LAYER 16
+#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
+
+#define LIGHTING_PRIMARY_LAYER 15 //The layer for the main lights of the station
+#define LIGHTING_PRIMARY_DIMMER_LAYER 15.1 //The layer that dims the main lights of the station
+#define LIGHTING_SECONDARY_LAYER 16 //The colourful, usually small lights that go on top
+
+#define LIGHTING_SHADOW_LAYER 17 //Where the shadows happen
+
+#define ABOVE_LIGHTING_PLANE 150
+#define ABOVE_LIGHTING_LAYER 18
+
/*=============================*\
| |
| PLANE DEFINES |
@@ -194,6 +227,7 @@
#define GHOST_PLANE 80
+///--------------- FULLSCREEN RUNECHAT BUBBLES ------------
#define LIGHTING_PLANE 100
#define EXTERIOR_LIGHTING_PLANE 101
diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm
index 5a4ba7676233..097a0f5d5e71 100644
--- a/code/__DEFINES/lighting.dm
+++ b/code/__DEFINES/lighting.dm
@@ -1,5 +1,109 @@
+///Object doesn't use any of the light systems. Should be changed to add a light source to the object.
+#define NO_LIGHT_SUPPORT 0
+///Light made with the lighting datums, applying a matrix.
+#define STATIC_LIGHT 1
+///Light made by masking the lighting darkness plane.
+#define MOVABLE_LIGHT 2
+///A mix of the above, cheaper on moving items than dynamic, but heavier on rendering than movable
+#define HYBRID_LIGHT 3
+///Pointy light
+#define DIRECTIONAL_LIGHT 4
+
+#define LIGHT_ATTACHED (1<<0)
+
+#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
+
+#define LIGHTING_ICON 'icons/effects/lighting_object.dmi' // icon used for lighting shading effects
+#define LIGHTING_ICON_BIG 'icons/effects/lighting_object_big.dmi' //! icon used for lighting shading effects
+
+#define ALPHA_TO_INTENSITY(alpha) (-(((clamp(alpha, 0, 22) - 22) / 6) ** 4) + 255)
+
+
+#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
+
#define LIGHTING_PLANE_ALPHA_VISIBLE 255
///The dim natural vision of Yautja
#define LIGHTING_PLANE_ALPHA_YAUTJA 235
+#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 127
#define LIGHTING_PLANE_ALPHA_INVISIBLE 0
+
+
+#define FLASH_LIGHT_DURATION 2
+#define FLASH_LIGHT_POWER 3
+#define FLASH_LIGHT_RANGE 3.8
+
+// Emissive blocking.
+/// Uses vis_overlays to leverage caching so that very few new items need to be made for the overlay. For anything that doesn't change outline or opaque area much or at all.
+#define EMISSIVE_BLOCK_GENERIC 1
+/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
+#define EMISSIVE_BLOCK_UNIQUE 2
+
+/// The color matrix applied to all emissive overlays. Should be solely dependent on alpha and not have RGB overlap with [EM_BLOCK_COLOR].
+#define EMISSIVE_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,1,0)
+/// A globaly cached version of [EMISSIVE_COLOR] for quick access.
+GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR)
+/// The color matrix applied to all emissive blockers. Should be solely dependent on alpha and not have RGB overlap with [EMISSIVE_COLOR].
+#define EM_BLOCK_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
+/// A globaly cached version of [EM_BLOCK_COLOR] for quick access.
+GLOBAL_LIST_INIT(em_block_color, EM_BLOCK_COLOR)
+/// A set of appearance flags applied to all emissive and emissive blocker overlays.
+#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR|RESET_TRANSFORM)
+/// The color matrix used to mask out emissive blockers on the emissive plane. Alpha should default to zero, be solely dependent on the RGB value of [EMISSIVE_COLOR], and be independant of the RGB value of [EM_BLOCK_COLOR].
+#define EM_MASK_MATRIX list(0,0,0,1/3, 0,0,0,1/3, 0,0,0,1/3, 0,0,0,0, 1,1,1,0)
+/// A globaly cached version of [EM_MASK_MATRIX] for quick access.
+GLOBAL_LIST_INIT(em_mask_matrix, EM_MASK_MATRIX)
+
+/// Returns the red part of a #RRGGBB hex sequence as number
+#define GETREDPART(hexa) hex2num(copytext(hexa, 2, 4))
+
+/// Returns the green part of a #RRGGBB hex sequence as number
+#define GETGREENPART(hexa) hex2num(copytext(hexa, 4, 6))
+
+/// Returns the blue part of a #RRGGBB hex sequence as number
+#define GETBLUEPART(hexa) hex2num(copytext(hexa, 6, 8))
+
+/// Parse the hexadecimal color into lumcounts of each perspective.
+#define PARSE_LIGHT_COLOR(source) \
+do { \
+ if (source.light_color != COLOR_WHITE) { \
+ var/__light_color = source.light_color; \
+ source.lum_r = GETREDPART(__light_color) / 255; \
+ source.lum_g = GETGREENPART(__light_color) / 255; \
+ source.lum_b = GETBLUEPART(__light_color) / 255; \
+ } else { \
+ source.lum_r = 1; \
+ source.lum_g = 1; \
+ source.lum_b = 1; \
+ }; \
+} while (FALSE)
+
+
+//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it //thats how defines work, hello?
+#define LIGHTING_INTERVAL 5 // frequency, in 1/10ths of a second, of the lighting process
+
+#define MOVABLE_MAX_RANGE 7
+
+#define LIGHTING_FALLOFF 1 // type of falloff to use for lighting; 1 for circular, 2 for square
+#define LIGHTING_LAMBERTIAN 0 // use lambertian shading for light sources
+#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
+#define LIGHTING_ROUND_VALUE (1 / 64) //Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
+
+/// If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting objects. Set to zero to disable soft lighting. Luminosity changes then work if it's lit at all.
+#define LIGHTING_SOFT_THRESHOLD 0
+
+// If I were you I'd leave this alone.
+#define LIGHTING_BASE_MATRIX \
+ list \
+ ( \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 1, 1, 1, 0, \
+ 0, 0, 0, 1 \
+ ) \
+
+#define LIGHTING_NO_UPDATE 0
+#define LIGHTING_VIS_UPDATE 1
+#define LIGHTING_CHECK_UPDATE 2
+#define LIGHTING_FORCE_UPDATE 3
diff --git a/code/__DEFINES/mob_hud.dm b/code/__DEFINES/mob_hud.dm
index 2704e52d2f85..02f992694832 100644
--- a/code/__DEFINES/mob_hud.dm
+++ b/code/__DEFINES/mob_hud.dm
@@ -65,3 +65,6 @@
#define TRACKER_HIVE "Hive Core"
#define TRACKER_LEADER "Leader"
#define TRACKER_TUNNEL "Tunnel"
+
+//These are used to manage the same HUD having multiple sources
+#define HUD_SOURCE_ADMIN "admin"
diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm
index bb31f4d84b1e..d13fd8169fca 100644
--- a/code/__DEFINES/mode.dm
+++ b/code/__DEFINES/mode.dm
@@ -6,7 +6,7 @@
#define SHUTTLE_LOCK_COOLDOWN 10 MINUTES
#define MONORAIL_LOCK_COOLDOWN 3 MINUTES
#define SHUTTLE_LOCK_TIME_LOCK 1 MINUTES
-#define EVACUATION_AUTOMATIC_DEPARTURE 10 MINUTES //All pods automatically depart in 10 minutes, unless they are full or unable to launch for some reason.
+#define EVACUATION_AUTOMATIC_DEPARTURE (10 MINUTES) //All pods automatically depart in 10 minutes, unless they are full or unable to launch for some reason.
#define EVACUATION_ESTIMATE_DEPARTURE ((evac_time + EVACUATION_AUTOMATIC_DEPARTURE - world.time) * 0.1)
#define EVACUATION_STATUS_STANDING_BY 0
@@ -71,6 +71,7 @@
#define MODE_SHIPSIDE_SD (1<<8) /// Toggles whether Predators can big SD when not on the groundmap
#define MODE_HARDCORE_PERMA (1<<9) /// Toggles Hardcore for all marines, meaning they instantly perma upon death
#define MODE_DISPOSABLE_MOBS (1<<10) // Toggles if mobs fit in disposals or not. Off by default.
+#define MODE_BYPASS_JOE (1<<11) // Toggles if ghosts can bypass Working Joe spawn limitations, does NOT bypass WL requirement. Off by default.
#define ROUNDSTATUS_FOG_DOWN 1
#define ROUNDSTATUS_PODDOORS_OPEN 2
@@ -240,7 +241,7 @@ var/global/list/whitelist_hierarchy = list(WHITELIST_NORMAL, WHITELIST_COUNCIL,
#define FACTION_LIST_MARINE list(FACTION_MARINE)
#define FACTION_LIST_HUMANOID list(FACTION_MARINE, FACTION_PMC, FACTION_WY, FACTION_WY_DEATHSQUAD, FACTION_CLF, FACTION_CONTRACTOR, FACTION_UPP, FACTION_FREELANCER, FACTION_SURVIVOR, FACTION_NEUTRAL, FACTION_COLONIST, FACTION_MERCENARY, FACTION_DUTCH, FACTION_HEFA, FACTION_GLADIATOR, FACTION_PIRATE, FACTION_PIZZA, FACTION_SOUTO, FACTION_YAUTJA, FACTION_ZOMBIE)
-#define FACTION_LIST_ERT list(FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_CLF, FACTION_CONTRACTOR, FACTION_UPP, FACTION_FREELANCER, FACTION_MERCENARY, FACTION_DUTCH, FACTION_HEFA, FACTION_GLADIATOR, FACTION_PIRATE, FACTION_PIZZA, FACTION_SOUTO, FACTION_MARSHAL)
+#define FACTION_LIST_ERT list(FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_CLF, FACTION_CONTRACTOR, FACTION_UPP, FACTION_FREELANCER, FACTION_MERCENARY, FACTION_DUTCH, FACTION_HEFA, FACTION_GLADIATOR, FACTION_PIRATE, FACTION_PIZZA, FACTION_SOUTO, FACTION_MARSHAL, FACTION_TWE)
#define FACTION_LIST_WY list(FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_WY)
#define FACTION_LIST_MARINE_WY list(FACTION_MARINE, FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_WY)
#define FACTION_LIST_MARINE_UPP list(FACTION_MARINE, FACTION_UPP)
diff --git a/code/__DEFINES/objects.dm b/code/__DEFINES/objects.dm
index 0a34ac9d6fe9..a6b95c879ae4 100644
--- a/code/__DEFINES/objects.dm
+++ b/code/__DEFINES/objects.dm
@@ -168,3 +168,8 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse
// For reinforced table status
#define RTABLE_WEAKENED 1
#define RTABLE_NORMAL 2
+
+//Lights define
+#define CHECKS_PASSED 1
+#define STILL_ON_COOLDOWN 2
+#define NO_LIGHT_STATE_CHANGE 3
diff --git a/code/__DEFINES/pred.dm b/code/__DEFINES/pred.dm
index 5826a2ca56f6..a8bc1007d51e 100644
--- a/code/__DEFINES/pred.dm
+++ b/code/__DEFINES/pred.dm
@@ -1,5 +1,6 @@
#define PRED_MATERIALS list("ebony", "silver", "bronze", "crimson", "bone")
#define PRED_TRANSLATORS list("Modern", "Retro", "Combo")
+#define PRED_LEGACIES list("None", "Dragon", "Swamp", "Enforcer", "Collector")
#define PRED_SKIN_COLOR list("tan", "green", "purple", "blue", "red", "black")
#define PRED_YAUTJA_CAPE "yautja cape"
diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm
index 44f47d7adfdb..e2bd155fcb0d 100644
--- a/code/__DEFINES/radio.dm
+++ b/code/__DEFINES/radio.dm
@@ -26,6 +26,7 @@
#define RADIO_CHANNEL_HEADSET "headset"
#define RADIO_CHANNEL_ENGI "Engi"
#define RADIO_CHANNEL_HIGHCOM "HighCom"
+#define RADIO_CHANNEL_PROVOST "Provost"
#define RADIO_CHANNEL_INTERCOM "intercom"
#define RADIO_CHANNEL_INTEL "Intel"
#define RADIO_CHANNEL_JTAC "JTAC"
@@ -64,5 +65,7 @@
#define RADIO_CHANNEL_DUTCH_DOZEN "DD"
#define RADIO_CHANNEL_VAI "VAI"
#define RADIO_CHANNEL_CMB "CMB"
+#define RADIO_CHANNEL_ROYAL_MARINE "Royal Marine"
#define RADIO_CHANNEL_YAUTJA "Yautja"
+
diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm
index 126a8f82ece8..d283656ccae6 100644
--- a/code/__DEFINES/shuttles.dm
+++ b/code/__DEFINES/shuttles.dm
@@ -95,6 +95,7 @@
#define MOBILE_SHUTTLE_ID_ERT1 "ert_response_shuttle"
#define MOBILE_SHUTTLE_ID_ERT2 "ert_pmc_shuttle"
#define MOBILE_SHUTTLE_ID_ERT3 "ert_upp_shuttle"
+#define MOBILE_SHUTTLE_ID_ERT4 "ert_twe_shuttle"
#define MOBILE_SHUTTLE_ID_ERT_SMALL "ert_rescue_shuttle"
#define MOBILE_SHUTTLE_ID_ERT_BIG "ert_boarding_shuttle"
diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm
index fdd1a8f083ad..5dabb4545a32 100644
--- a/code/__DEFINES/skills.dm
+++ b/code/__DEFINES/skills.dm
@@ -8,6 +8,7 @@
#define SKILL_ENGINEER "engineer"
#define SKILL_CONSTRUCTION "construction"
#define SKILL_LEADERSHIP "leadership"
+#define SKILL_OVERWATCH "overwatch"
#define SKILL_MEDICAL "medical"
#define SKILL_SURGERY "surgery"
#define SKILL_RESEARCH "research"
@@ -134,7 +135,6 @@
#define SKILL_POWERLOADER_MASTER 2 //Pilot, CT, Req, OT, CE
#define SKILL_POWERLOADER_MAX 2
-
//leadership skill
#define SKILL_LEAD_NOVICE 0 //Anyone but the above. Using SL items is possible but painfully slow
#define SKILL_LEAD_TRAINED 1 //SL
@@ -142,6 +142,11 @@
#define SKILL_LEAD_MASTER 3 //XO, CO
#define SKILL_LEAD_MAX 3
+//overwatch skill
+#define SKILL_OVERWATCH_DEFAULT 0
+#define SKILL_OVERWATCH_TRAINED 1 //Allows use of overwatch consoles
+#define SKILL_OVERWATCH_MAX 1
+
//JTAC skill
#define SKILL_JTAC_NOVICE 0 //Anyone but those following.
diff --git a/code/__DEFINES/sounds.dm b/code/__DEFINES/sounds.dm
index f01ddfc86792..a6bb381100e7 100644
--- a/code/__DEFINES/sounds.dm
+++ b/code/__DEFINES/sounds.dm
@@ -21,6 +21,7 @@
#define ITEM_EQUIP_VOLUME 50
//Reserved channels
+#define SOUND_CHANNEL_NOTIFY 1016
#define SOUND_CHANNEL_VOX 1017
#define SOUND_CHANNEL_MUSIC 1018
#define SOUND_CHANNEL_AMBIENCE 1019
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 1aaf3714182e..793e7b6b2f35 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -177,6 +177,8 @@
#define TRAIT_USING_WHEELCHAIR "t_using_wheelchair"
/// If the mob will instantly go permadead upon death
#define TRAIT_HARDCORE "t_hardcore"
+/// If the mob is able to use the vulture rifle or spotting scope
+#define TRAIT_VULTURE_USER "t_vulture_user"
// -- ability traits --
/// Xenos with this trait cannot have plasma transfered to them
@@ -204,6 +206,10 @@
// GUN TRAITS
#define TRAIT_GUN_SILENCED "t_gun_silenced"
+#define TRAIT_GUN_BIPODDED "t_gun_bipodded"
+
+#define TRAIT_GUN_LIGHT_DEACTIVATED "t_gun_light_deactivated"
+
// Miscellaneous item traits.
// Do NOT bloat this category, if needed make a new category (like shoe traits, xeno item traits...)
@@ -238,7 +244,8 @@ GLOBAL_LIST_INIT(mob_traits, list(
TRAIT_LEADERSHIP,
TRAIT_DEXTROUS,
TRAIT_REAGENT_SCANNER,
- TRAIT_ABILITY_BURROWED
+ TRAIT_ABILITY_BURROWED,
+ TRAIT_VULTURE_USER,
))
/*
@@ -270,6 +277,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_EMOTE_CD_EXEMPT" = TRAIT_EMOTE_CD_EXEMPT,
"TRAIT_LISPING" = TRAIT_LISPING,
"TRAIT_CANNOT_EAT" = TRAIT_CANNOT_EAT,
+ "TRAIT_VULTURE_USER" = TRAIT_VULTURE_USER,
),
/mob/living/carbon/xenomorph = list(
"TRAIT_ABILITY_NO_PLASMA_TRANSFER" = TRAIT_ABILITY_NO_PLASMA_TRANSFER,
@@ -298,6 +306,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/obj/item/weapon/gun = list(
"TRAIT_GUN_SILENCED" = TRAIT_GUN_SILENCED,
+ "TRAIT_GUN_BIPODDED" = TRAIT_GUN_BIPODDED,
),
/obj/structure/surface/table = list(
"TRAIT_STRUCTURE_FLIPPING" = TRAIT_TABLE_FLIPPING,
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index ecdd9f64ec38..eb248e8a30a7 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -134,3 +134,6 @@
#define VV_HK_TOGGLEPOWER "togglepower"
#define VV_HK_ADD_ITEMS_TO_VENDOR "add_items_to_vendor"
+
+// /obj/structure/pipes/vents
+#define VV_HK_GAS "release_gas"
diff --git a/code/__DEFINES/weapon_stats.dm b/code/__DEFINES/weapon_stats.dm
index 590223426a66..beac54d98892 100644
--- a/code/__DEFINES/weapon_stats.dm
+++ b/code/__DEFINES/weapon_stats.dm
@@ -136,6 +136,7 @@ As such, don't expect any values assigned to common firearms to even consider ho
//How many ticks you have to wait between firing. Burst delay uses the same variable!
*/
+#define FIRE_DELAY_TIER_VULTURE 20
#define FIRE_DELAY_TIER_1 12
#define FIRE_DELAY_TIER_2 10
#define FIRE_DELAY_TIER_3 9
diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm
index 0f822385ad13..b178f0692dd6 100644
--- a/code/__DEFINES/xeno.dm
+++ b/code/__DEFINES/xeno.dm
@@ -169,7 +169,7 @@
#define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES)
/// The time when xenos can start taking over comm towers
-#define XENO_COMM_ACQUISITION_TIME (90 MINUTES)
+#define XENO_COMM_ACQUISITION_TIME (55 MINUTES)
/// The time it takes for a pylon to give one larva while activated
#define XENO_PYLON_ACTIVATION_COOLDOWN (5 MINUTES)
diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm
index 6c913b016083..fe15e6d84c79 100644
--- a/code/__HELPERS/_lists.dm
+++ b/code/__HELPERS/_lists.dm
@@ -38,6 +38,32 @@
};\
} while(FALSE)
+// binary search sorted insert
+// IN: Object to be inserted
+// LIST: List to insert object into
+#define BINARY_INSERT_NUM(IN, LIST) \
+ var/__BIN_CTTL = length(LIST);\
+ if(!__BIN_CTTL) {\
+ LIST += IN;\
+ } else {\
+ var/__BIN_LEFT = 1;\
+ var/__BIN_RIGHT = __BIN_CTTL;\
+ var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ var/__BIN_ITEM;\
+ while(__BIN_LEFT < __BIN_RIGHT) {\
+ __BIN_ITEM = LIST[__BIN_MID];\
+ if(__BIN_ITEM <= IN) {\
+ __BIN_LEFT = __BIN_MID + 1;\
+ } else {\
+ __BIN_RIGHT = __BIN_MID;\
+ };\
+ __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ };\
+ __BIN_ITEM = LIST[__BIN_MID];\
+ __BIN_MID = __BIN_ITEM > IN ? __BIN_MID : __BIN_MID + 1;\
+ LIST.Insert(__BIN_MID, IN);\
+ }
+
//Like typesof() or subtypesof(), but returns a typecache instead of a list
/proc/typecacheof(path, ignore_root_path, only_root_path = FALSE)
if(ispath(path))
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index c05795c32b10..66ecf9ea034f 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -268,7 +268,7 @@
// copied from join as xeno
var/deathtime = world.time - cur_obs.timeofdeath
- if(deathtime < XENO_JOIN_DEAD_TIME && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN) || !cur_obs.bypass_time_of_death_checks))
+ if(deathtime < XENO_JOIN_DEAD_TIME && ( !cur_obs.client.admin_holder || !(cur_obs.client.admin_holder.rights & R_ADMIN)) && !cur_obs.bypass_time_of_death_checks)
continue
// AFK players cannot be drafted
diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm
index 4c8e1fe31354..99f621919771 100644
--- a/code/__HELPERS/icons.dm
+++ b/code/__HELPERS/icons.dm
@@ -323,176 +323,138 @@ world
. = list(r, g, b)
if(usealpha) . += alpha
-
-
/// Create a single [/icon] from a given [/atom] or [/image].
///
/// Very low-performance. Should usually only be used for HTML, where BYOND's
/// appearance system (overlays/underlays, etc.) is not available.
///
/// Only the first argument is required.
-/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
- //Define... defines.
+/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
+ // Loop through the underlays, then overlays, sorting them into the layers list
+ #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \
+ for (var/i in 1 to process.len) { \
+ var/image/current = process[i]; \
+ if (!current) { \
+ continue; \
+ } \
+ if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \
+ continue; \
+ } \
+ var/current_layer = current.layer; \
+ if (current_layer < 0) { \
+ if (current_layer <= -1000) { \
+ return flat; \
+ } \
+ current_layer = base_layer + appearance.layer + current_layer / 1000; \
+ } \
+ for (var/index_to_compare_to in 1 to layers.len) { \
+ var/compare_to = layers[index_to_compare_to]; \
+ if (current_layer < layers[compare_to]) { \
+ layers.Insert(index_to_compare_to, current); \
+ break; \
+ } \
+ } \
+ layers[current] = current_layer; \
+ }
+
var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing")
- #define BLANK icon(flat_template)
- #define GENERATE_FLAT_IMAGE_ICON(ICON_VAR, IMG_SOURCE, icon_to_use, icon_state_to_use, dir_to_use)\
- var/icon/SELF_ICON=icon(icon(icon_to_use, icon_state_to_use, dir_to_use), "", SOUTH, no_anim ? 1 : null);\
- if(##IMG_SOURCE.alpha < 255)\
- SELF_ICON.Blend(rgb(255, 255, 255, ##IMG_SOURCE.alpha), ICON_MULTIPLY);\
- if(##IMG_SOURCE.color) {\
- if(islist(##IMG_SOURCE.color))\
- SELF_ICON.MapColors(arglist(##IMG_SOURCE.color));\
- else\
- SELF_ICON.Blend(##IMG_SOURCE.color, ICON_MULTIPLY);\
- }\
- ##ICON_VAR = SELF_ICON;
- #define INDEX_X_LOW 1
- #define INDEX_X_HIGH 2
- #define INDEX_Y_LOW 3
- #define INDEX_Y_HIGH 4
-
- #define flatX1 flat_size[INDEX_X_LOW]
- #define flatX2 flat_size[INDEX_X_HIGH]
- #define flatY1 flat_size[INDEX_Y_LOW]
- #define flatY2 flat_size[INDEX_Y_HIGH]
- #define addX1 add_size[INDEX_X_LOW]
- #define addX2 add_size[INDEX_X_HIGH]
- #define addY1 add_size[INDEX_Y_LOW]
- #define addY2 add_size[INDEX_Y_HIGH]
-
- #define PROCESS_SET_UNDERLAYS 0
- #define PROCESS_SET_VIS_CONTENTS 1
- #define PROCESS_SET_OVERLAYS 2
-
- if(!A || A.alpha <= 0)
- return BLANK
-
- var/noIcon = FALSE
+ if(!appearance || appearance.alpha <= 0)
+ return icon(flat_template)
+
if(start)
if(!defdir)
- defdir = A.dir
+ defdir = appearance.dir
if(!deficon)
- deficon = A.icon
+ deficon = appearance.icon
if(!defstate)
- defstate = A.icon_state
+ defstate = appearance.icon_state
if(!defblend)
- defblend = A.blend_mode
+ defblend = appearance.blend_mode
+
+ var/curicon = appearance.icon || deficon
+ var/curstate = appearance.icon_state || defstate
+ var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir
- var/curicon = A.icon || deficon
- var/curstate = A.icon_state || defstate
+ var/render_icon = curicon
- if(!(noIcon = (!curicon)))
+ if (render_icon)
var/curstates = icon_states(curicon)
if(!(curstate in curstates))
- if("" in curstates)
+ if ("" in curstates)
curstate = ""
else
- noIcon = TRUE // Do not render this object.
+ render_icon = FALSE
- var/curdir
var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
- //These should use the parent's direction (most likely)
- if(!A.dir || A.dir == SOUTH)
- curdir = defdir
- else
- curdir = A.dir
-
//Try to remove/optimize this section ASAP, CPU hog.
//Determines if there's directionals.
- if(!noIcon && curdir != SOUTH)
- var/exist = FALSE
- var/static/list/checkdirs = list(NORTH, EAST, WEST)
- for(var/i in checkdirs) //Not using GLOB for a reason.
- if(length(icon_states(icon(curicon, curstate, i))))
- exist = TRUE
- break
- if(!exist)
+ if(render_icon && curdir != SOUTH)
+ if (
+ !length(icon_states(icon(curicon, curstate, NORTH))) \
+ && !length(icon_states(icon(curicon, curstate, EAST))) \
+ && !length(icon_states(icon(curicon, curstate, WEST))) \
+ )
base_icon_dir = SOUTH
if(!base_icon_dir)
base_icon_dir = curdir
- ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0.
-
- var/curblend = A.blend_mode || defblend
+ var/curblend = appearance.blend_mode || defblend
- var/atom/movable/AM = A
- if(length(A.overlays) || length(A.underlays) || (istype(AM) && AM.vis_contents))
- var/icon/flat = BLANK
+ if(appearance.overlays.len || appearance.underlays.len)
+ var/icon/flat = icon(flat_template)
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
var/list/layers = list()
var/image/copy
// Add the atom's icon itself, without pixel_x/y offsets.
- if(!noIcon)
- copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir)
- copy.color = A.color
- copy.alpha = A.alpha
+ if(render_icon)
+ copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir)
+ copy.color = appearance.color
+ copy.alpha = appearance.alpha
copy.blend_mode = curblend
- layers[copy] = A.layer
-
- // Loop through the underlays, then vis_contents, then overlays, sorting them into the layers list
- for(var/process_set in PROCESS_SET_UNDERLAYS to PROCESS_SET_OVERLAYS)
- var/list/process
- switch(process_set)
- if(PROCESS_SET_UNDERLAYS)
- process = A.underlays
- if(PROCESS_SET_VIS_CONTENTS)
- if(!istype(AM))
- continue
- process = A.vis_contents
- else // PROCESS_SET_OVERLAYS
- process = A.overlays
- for(var/i in 1 to process.len)
- var/image/current = process[i]
- if(!current)
- continue
- if(process_set == PROCESS_SET_VIS_CONTENTS && !istype(current))
- current = image(icon = current.icon, icon_state = current.icon_state, layer = current.layer, dir = current.dir)
- var/current_layer = current.layer
- if(current_layer < 0)
- if(current_layer <= -1000)
- return flat
- current_layer = A.layer + ((process_set ? 1000 : 0)+current_layer) / 1000
-
- for(var/p in 1 to layers.len)
- var/image/cmp = layers[p]
- if(current_layer < layers[cmp])
- layers.Insert(p, current)
- break
- layers[current] = current_layer
+ layers[copy] = appearance.layer
+
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0)
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1)
var/icon/add // Icon of overlay being added
- // Current dimensions of flattened icon
- var/list/flat_size = list(1, flat.Width(), 1, flat.Height())
- // Dimensions of overlay being added
- var/list/add_size[4]
+ var/flatX1 = 1
+ var/flatX2 = flat.Width()
+ var/flatY1 = 1
+ var/flatY2 = flat.Height()
- for(var/V in layers)
- var/image/I = V
- if(I.alpha == 0)
+ var/addX1 = 0
+ var/addX2 = 0
+ var/addY1 = 0
+ var/addY2 = 0
+
+ for(var/image/layer_image as anything in layers)
+ if(layer_image.alpha == 0)
continue
- if(I == copy) // 'I' is an /image based on the object being flattened.
+ if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
- add = icon(I.icon, I.icon_state, base_icon_dir)
- else // 'I' is an /image
- var/image_has_icon = I.icon
- if(image_has_icon)
- GENERATE_FLAT_IMAGE_ICON(add, I, I.icon, I.icon_state, base_icon_dir)
+ add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir)
+ else // 'I' is an appearance object.
+ add = getFlatIcon(image(layer_image), curdir, curicon, curstate, curblend, FALSE, no_anim)
if(!add)
continue
+
// Find the new dimensions of the flat icon to fit the added overlay
- add_size = list(
- min(flatX1, I.pixel_x+1),
- max(flatX2, I.pixel_x+add.Width()),
- min(flatY1, I.pixel_y+1),
- max(flatY2, I.pixel_y+add.Height())
+ addX1 = min(flatX1, layer_image.pixel_x + 1)
+ addX2 = max(flatX2, layer_image.pixel_x + add.Width())
+ addY1 = min(flatY1, layer_image.pixel_y + 1)
+ addY2 = max(flatY2, layer_image.pixel_y + add.Height())
+
+ if (
+ addX1 != flatX1 \
+ && addX2 != flatX2 \
+ && addY1 != flatY1 \
+ && addY2 != flatY2 \
)
-
- if(flat_size ~! add_size)
// Resize the flattened icon so the new icon fits
flat.Crop(
addX1 - flatX1 + 1,
@@ -500,48 +462,46 @@ world
addX2 - flatX1 + 1,
addY2 - flatY1 + 1
)
- flat_size = add_size.Copy()
+
+ flatX1 = addX1
+ flatX2 = addY1
+ flatY1 = addX2
+ flatY2 = addY2
// Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
+ flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1)
- if(A.color)
- if(islist(A.color))
- flat.MapColors(arglist(A.color))
+ if(appearance.color)
+ if(islist(appearance.color))
+ flat.MapColors(arglist(appearance.color))
else
- flat.Blend(A.color, ICON_MULTIPLY)
+ flat.Blend(appearance.color, ICON_MULTIPLY)
- if(A.alpha < 255)
- flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(appearance.alpha < 255)
+ flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
if(no_anim)
//Clean up repeated frames
var/icon/cleaned = new /icon()
cleaned.Insert(flat, "", SOUTH, 1, 0)
- . = cleaned
+ return cleaned
else
- . = icon(flat, "", SOUTH)
- else //There's no overlays.
- if(!noIcon)
- GENERATE_FLAT_IMAGE_ICON(., A, curicon, curstate, base_icon_dir)
-
- //Clear defines
- #undef flatX1
- #undef flatX2
- #undef flatY1
- #undef flatY2
- #undef addX1
- #undef addX2
- #undef addY1
- #undef addY2
-
- #undef INDEX_X_LOW
- #undef INDEX_X_HIGH
- #undef INDEX_Y_LOW
- #undef INDEX_Y_HIGH
-
- #undef GENERATE_FLAT_IMAGE_ICON
- #undef BLANK
+ return icon(flat, "", SOUTH)
+ else if (render_icon) // There's no overlays.
+ var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null)
+
+ if (appearance.alpha < 255)
+ final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY)
+
+ if (appearance.color)
+ if (islist(appearance.color))
+ final_icon.MapColors(arglist(appearance.color))
+ else
+ final_icon.Blend(appearance.color, ICON_MULTIPLY)
+
+ return final_icon
+
+ #undef PROCESS_OVERLAYS_OR_UNDERLAYS
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
@@ -611,12 +571,100 @@ world
I.color = color
I.flick_overlay(src, time)
-/proc/icon2html(thing, target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE)
+/// generates a filename for a given asset.
+/// like generate_asset_name(), except returns the rsc reference and the rsc file hash as well as the asset name (sans extension)
+/// used so that certain asset files dont have to be hashed twice
+/proc/generate_and_hash_rsc_file(file, dmi_file_path)
+ var/rsc_ref = fcopy_rsc(file)
+ var/hash
+ //if we have a valid dmi file path we can trust md5'ing the rsc file because we know it doesnt have the bug described in http://www.byond.com/forum/post/2611357
+ if(dmi_file_path)
+ hash = md5(rsc_ref)
+ else //otherwise, we need to do the expensive fcopy() workaround
+ hash = md5asfile(rsc_ref)
+
+ return list(rsc_ref, hash, "asset.[hash]")
+
+///given a text string, returns whether it is a valid dmi icons folder path
+/proc/is_valid_dmi_file(icon_path)
+ if(!istext(icon_path) || !length(icon_path))
+ return FALSE
+
+ var/is_in_icon_folder = findtextEx(icon_path, "icons/")
+ var/is_dmi_file = findtextEx(icon_path, ".dmi")
+
+ if(is_in_icon_folder && is_dmi_file)
+ return TRUE
+ return FALSE
+
+/// given an icon object, dmi file path, or atom/image/mutable_appearance, attempts to find and return an associated dmi file path.
+/// a weird quirk about dm is that /icon objects represent both compile-time or dynamic icons in the rsc,
+/// but stringifying rsc references returns a dmi file path
+/// ONLY if that icon represents a completely unchanged dmi file from when the game was compiled.
+/// so if the given object is associated with an icon that was in the rsc when the game was compiled, this returns a path. otherwise it returns ""
+/proc/get_icon_dmi_path(icon/icon)
+ /// the dmi file path we attempt to return if the given object argument is associated with a stringifiable icon
+ /// if successful, this looks like "icons/path/to/dmi_file.dmi"
+ var/icon_path = ""
+
+ if(isatom(icon) || istype(icon, /image) || istype(icon, /mutable_appearance))
+ var/atom/atom_icon = icon
+ icon = atom_icon.icon
+ //atom icons compiled in from 'icons/path/to/dmi_file.dmi' are weird and not really icon objects that you generate with icon().
+ //if theyre unchanged dmi's then they're stringifiable to "icons/path/to/dmi_file.dmi"
+
+ if(isicon(icon) && isfile(icon))
+ //icons compiled in from 'icons/path/to/dmi_file.dmi' at compile time are weird and arent really /icon objects,
+ ///but they pass both isicon() and isfile() checks. theyre the easiest case since stringifying them gives us the path we want
+ var/icon_ref = text_ref(icon)
+ var/locate_icon_string = "[locate(icon_ref)]"
+
+ icon_path = locate_icon_string
+
+ else if(isicon(icon) && "[icon]" == "/icon")
+ // icon objects generated from icon() at runtime are icons, but they ARENT files themselves, they represent icon files.
+ // if the files they represent are compile time dmi files in the rsc, then
+ // the rsc reference returned by fcopy_rsc() will be stringifiable to "icons/path/to/dmi_file.dmi"
+ var/rsc_ref = fcopy_rsc(icon)
+
+ var/icon_ref = text_ref(rsc_ref)
+
+ var/icon_path_string = "[locate(icon_ref)]"
+
+ icon_path = icon_path_string
+
+ else if(istext(icon))
+ var/rsc_ref = fcopy_rsc(icon)
+ //if its the text path of an existing dmi file, the rsc reference returned by fcopy_rsc() will be stringifiable to a dmi path
+
+ var/rsc_ref_ref = text_ref(rsc_ref)
+ var/rsc_ref_string = "[locate(rsc_ref_ref)]"
+
+ icon_path = rsc_ref_string
+
+ if(is_valid_dmi_file(icon_path))
+ return icon_path
+
+ return FALSE
+
+/**
+ * generate an asset for the given icon or the icon of the given appearance for [thing], and send it to any clients in target.
+ * Arguments:
+ * * thing - either a /icon object, or an object that has an appearance (atom, image, mutable_appearance).
+ * * target - either a reference to or a list of references to /client's or mobs with clients
+ * * icon_state - string to force a particular icon_state for the icon to be used
+ * * dir - dir number to force a particular direction for the icon to be used
+ * * frame - what frame of the icon_state's animation for the icon being used
+ * * moving - whether or not to use a moving state for the given icon
+ * * sourceonly - if TRUE, only generate the asset and send back the asset url, instead of tags that display the icon to players
+ * * extra_clases - string of extra css classes to use when returning the icon string
+ */
+/proc/icon2html(atom/thing, client/target, icon_state, dir = SOUTH, frame = 1, moving = FALSE, sourceonly = FALSE, extra_classes = null)
if (!thing)
return
var/key
- var/icon/I = thing
+ var/icon/icon2collapse = thing
if (!target)
return
@@ -628,46 +676,64 @@ world
targets = list(target)
else
targets = target
- if (!targets.len)
- return
- if (!isicon(I))
+ if(!length(targets))
+ return
+
+ //check if the given object is associated with a dmi file in the icons folder. if it is then we dont need to do a lot of work
+ //for asset generation to get around byond limitations
+ var/icon_path = get_icon_dmi_path(thing)
+
+ if (!isicon(icon2collapse))
if (isfile(thing)) //special snowflake
- var/name = sanitize_filename("[generate_asset_name(thing)].png")
+ var/name = SANITIZE_FILENAME("[generate_asset_name(thing)].png")
if (!SSassets.cache[name])
SSassets.transport.register_asset(name, thing)
for (var/thing2 in targets)
SSassets.transport.send_assets(thing2, name)
if(sourceonly)
return SSassets.transport.get_asset_url(name)
- return ""
- var/atom/A = thing
+ return ""
+
+ //its either an atom, image, or mutable_appearance, we want its icon var
+ icon2collapse = thing.icon
- I = A.icon
if (isnull(icon_state))
- icon_state = A.icon_state
- if (!icon_state)
- icon_state = initial(A.icon_state)
+ icon_state = thing.icon_state
+ //Despite casting to atom, this code path supports mutable appearances, so let's be nice to them
+ if(isnull(icon_state) || (isatom(thing) && thing.flags_atom & HTML_USE_INITAL_ICON))
+ icon_state = initial(thing.icon_state)
if (isnull(dir))
- dir = initial(A.dir)
+ dir = initial(thing.dir)
if (isnull(dir))
- dir = A.dir
+ dir = thing.dir
+
+ if (ishuman(thing)) // Shitty workaround for a BYOND issue.
+ var/icon/temp = icon2collapse
+ icon2collapse = icon()
+ icon2collapse.Insert(temp, dir = SOUTH)
+ dir = SOUTH
else
if (isnull(dir))
dir = SOUTH
if (isnull(icon_state))
icon_state = ""
- I = icon(I, icon_state, dir, frame, moving)
+ icon2collapse = icon(icon2collapse, icon_state, dir, frame, moving)
+
+ var/list/name_and_ref = generate_and_hash_rsc_file(icon2collapse, icon_path)//pretend that tuples exist
+
+ var/rsc_ref = name_and_ref[1] //weird object thats not even readable to the debugger, represents a reference to the icons rsc entry
+ var/file_hash = name_and_ref[2]
+ key = "[name_and_ref[3]].png"
- key = "[generate_asset_name(I)].png"
if(!SSassets.cache[key])
- SSassets.transport.register_asset(key, I)
- for (var/thing2 in targets)
- SSassets.transport.send_assets(thing2, key)
+ SSassets.transport.register_asset(key, rsc_ref, file_hash, icon_path)
+ for (var/client_target in targets)
+ SSassets.transport.send_assets(client_target, key)
if(sourceonly)
return SSassets.transport.get_asset_url(key)
- return ""
+ return ""
//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
/proc/costly_icon2html(thing, target, sourceonly = FALSE)
diff --git a/code/__HELPERS/lighting.dm b/code/__HELPERS/lighting.dm
new file mode 100644
index 000000000000..08c360849b58
--- /dev/null
+++ b/code/__HELPERS/lighting.dm
@@ -0,0 +1,11 @@
+/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EMISSIVE_COLOR].
+/proc/emissive_appearance(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
+ var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
+ appearance.color = GLOB.emissive_color
+ return appearance
+
+/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EM_BLOCK_COLOR].
+/proc/emissive_blocker(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
+ var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
+ appearance.color = GLOB.em_block_color
+ return appearance
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 2e48c9f80cd3..9a6ee4362088 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -894,7 +894,7 @@
if(ismob(source))
var/mob/M = source
has_nightvision = M.see_in_dark >= 12
- if(!has_nightvision && target_turf.lighting_lumcount == 0)
+ if(!has_nightvision && target_turf.get_lumcount() == 0)
return FALSE
while(current != target_turf)
@@ -1227,12 +1227,11 @@ var/global/image/action_purple_power_up
if(A.vars.Find(lowertext(varname))) return 1
else return 0
-//Returns: all the non-lighting areas in the world, sorted.
+//Returns: all the areas in the world, sorted.
/proc/return_sorted_areas()
var/list/area/AL = list()
for(var/area/A in GLOB.sorted_areas)
- if(!A.lighting_subarea)
- AL += A
+ AL += A
return AL
//Takes: Area type as text string or as typepath OR an instance of the area.
@@ -1252,13 +1251,8 @@ var/global/image/action_purple_power_up
var/area/A = GLOB.areas_by_type[areatype]
// Fix it up with /area/var/related due to lighting shenanigans
- var/list/area/LA
- if(!length(A.related))
- LA = list(A)
- else LA = A.related
- for(var/area/Ai in LA)
- for(var/turf/T in Ai)
- turfs += T
+ for(var/turf/T in A)
+ turfs += T
return turfs
@@ -1382,7 +1376,7 @@ var/global/image/action_purple_power_up
// if(AR.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn
// X.opacity = !X.opacity
-// X.SetOpacity(!X.opacity)
+// X.set_opacity(!X.opacity)
toupdate += X
@@ -1766,6 +1760,85 @@ var/list/WALLITEMS = list(
if(location == src)
return TRUE
+GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
+
+/// Version of view() which ignores darkness, because BYOND doesn't have it (I actually suggested it but it was tagged redundant, BUT HEARERS IS A T- /rant).
+/proc/dview(range = world.view, center, invis_flags = 0)
+ if(!center)
+ return
+
+ GLOB.dview_mob.loc = center
+
+ GLOB.dview_mob.see_invisible = invis_flags
+
+ . = view(range, GLOB.dview_mob)
+ GLOB.dview_mob.loc = null
+
+/mob/dview
+ name = "INTERNAL DVIEW MOB"
+ invisibility = 101
+ density = FALSE
+ see_in_dark = 1e6
+ var/ready_to_die = FALSE
+
+/mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists
+ SHOULD_CALL_PARENT(FALSE)
+ if(flags_atom & INITIALIZED)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ flags_atom |= INITIALIZED
+ return INITIALIZE_HINT_NORMAL
+
+/mob/dview/Destroy(force = FALSE)
+ if(!ready_to_die)
+ stack_trace("ALRIGHT WHICH FUCKER TRIED TO DELETE *MY* DVIEW?")
+
+ if (!force)
+ return QDEL_HINT_LETMELIVE
+
+ log_world("EVACUATE THE SHITCODE IS TRYING TO STEAL MUH JOBS")
+ GLOB.dview_mob = new
+ return ..()
+
+
+#define FOR_DVIEW(type, range, center, invis_flags) \
+ GLOB.dview_mob.loc = center; \
+ GLOB.dview_mob.see_invisible = invis_flags; \
+ for(type in view(range, GLOB.dview_mob))
+
+#define FOR_DVIEW_END GLOB.dview_mob.loc = null
+
+/proc/get_turf_pixel(atom/AM)
+ if(!istype(AM))
+ return
+
+ //Find AM's matrix so we can use it's X/Y pixel shifts
+ var/matrix/M = matrix(AM.transform)
+
+ var/pixel_x_offset = AM.pixel_x + M.get_x_shift()
+ var/pixel_y_offset = AM.pixel_y + M.get_y_shift()
+
+ //Irregular objects
+ var/icon/AMicon = icon(AM.icon, AM.icon_state)
+ var/AMiconheight = AMicon.Height()
+ var/AMiconwidth = AMicon.Width()
+ if(AMiconheight != world.icon_size || AMiconwidth != world.icon_size)
+ pixel_x_offset += ((AMiconwidth/world.icon_size)-1)*(world.icon_size*0.5)
+ pixel_y_offset += ((AMiconheight/world.icon_size)-1)*(world.icon_size*0.5)
+
+ //DY and DX
+ var/rough_x = round(round(pixel_x_offset,world.icon_size)/world.icon_size)
+ var/rough_y = round(round(pixel_y_offset,world.icon_size)/world.icon_size)
+
+ //Find coordinates
+ var/turf/T = get_turf(AM) //use AM's turfs, as it's coords are the same as AM's AND AM's coords are lost if it is inside another atom
+ if(!T)
+ return null
+ var/final_x = T.x + rough_x
+ var/final_y = T.y + rough_y
+
+ if(final_x || final_y)
+ return locate(final_x, final_y, T.z)
+
//used to check if a mob can examine an object
/atom/proc/can_examine(mob/user)
if(!user.client)
@@ -1993,3 +2066,30 @@ GLOBAL_LIST_INIT(duplicate_forbidden_vars,list(
if(stop_type && istype(turf_to_check, stop_type))
break
return turf_to_check
+
+/// Given a direction, return the direction and the +-45 degree directions next to it
+/proc/get_related_directions(direction = NORTH)
+ switch(direction)
+ if(NORTH)
+ return list(NORTH, NORTHEAST, NORTHWEST)
+
+ if(EAST)
+ return list(EAST, NORTHEAST, SOUTHEAST)
+
+ if(SOUTH)
+ return list(SOUTH, SOUTHEAST, SOUTHWEST)
+
+ if(WEST)
+ return list(WEST, NORTHWEST, SOUTHWEST)
+
+ if(NORTHEAST)
+ return list(NORTHEAST, NORTH, EAST)
+
+ if(SOUTHEAST)
+ return list(SOUTHEAST, EAST, SOUTH)
+
+ if(SOUTHWEST)
+ return list(SOUTHWEST, SOUTH, WEST)
+
+ if(NORTHWEST)
+ return list(NORTHWEST, NORTH, WEST)
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index d71125c318f6..53dd40ff6035 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -249,6 +249,7 @@ DEFINE_BITFIELD(valid_equip_slots, list(
"SLOT_LEGS" = SLOT_LEGS,
"SLOT_ACCESSORY" = SLOT_ACCESSORY,
"SLOT_SUIT_STORE" = SLOT_SUIT_STORE,
+ "SLOT_BLOCK_SUIT_STORE" = SLOT_BLOCK_SUIT_STORE,
))
DEFINE_BITFIELD(flags_alarm_state, list(
@@ -417,6 +418,7 @@ DEFINE_BITFIELD(toggleable_flags, list(
"MODE_LZ_PROTECTION" = MODE_LZ_PROTECTION,
"MODE_SHIPSIDE_SD" = MODE_SHIPSIDE_SD,
"MODE_DISPOSABLE_MOBS" = MODE_DISPOSABLE_MOBS,
+ "MODE_BYPASS_JOE" = MODE_BYPASS_JOE,
))
DEFINE_BITFIELD(state, list(
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index df7dd48a1dd1..86390718b6ca 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -210,7 +210,7 @@
return TRUE
if (mods["ctrl"])
- if (Adjacent(user))
+ if (Adjacent(user) && user.next_move < world.time)
user.start_pulling(src)
return TRUE
return FALSE
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index 139de9e59a35..c6b642974881 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -27,3 +27,10 @@
#define ui_ghost_slot3 "SOUTH:6,CENTER:0"
#define ui_ghost_slot4 "SOUTH:6,CENTER+1:0"
#define ui_ghost_slot5 "SOUTH:6,CENTER+2:0"
+
+//Upper-middle right (alerts)
+#define ui_alert1 "EAST-1:28,CENTER+5:27"
+#define ui_alert2 "EAST-1:28,CENTER+4:25"
+#define ui_alert3 "EAST-1:28,CENTER+3:23"
+#define ui_alert4 "EAST-1:28,CENTER+2:21"
+#define ui_alert5 "EAST-1:28,CENTER+1:19"
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
index 293cdbd6374e..fec62c35317f 100644
--- a/code/_onclick/hud/fullscreen.dm
+++ b/code/_onclick/hud/fullscreen.dm
@@ -72,9 +72,11 @@
var/severity = 0
var/fs_view = 7
var/show_when_dead = FALSE
+ /// If this should try and resize if the user's view is bigger than the default
+ var/should_resize = TRUE
/atom/movable/screen/fullscreen/proc/update_for_view(client_view)
- if (screen_loc == "CENTER-7,CENTER-7" && fs_view != client_view)
+ if (screen_loc == "CENTER-7,CENTER-7" && fs_view != client_view && should_resize)
var/list/actualview = getviewsize(client_view)
fs_view = client_view
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
@@ -169,6 +171,14 @@
/atom/movable/screen/fullscreen/laser_blind
icon_state = "impairedoverlay1"
+/atom/movable/screen/fullscreen/vulture
+ icon_state = "vulture_scope_overlay_sniper"
+ layer = FULLSCREEN_VULTURE_SCOPE_LAYER
+
+/atom/movable/screen/fullscreen/vulture/spotter
+ icon_state = "vulture_scope_overlay_spotter"
+ should_resize = FALSE
+
//Weather overlays//
/atom/movable/screen/fullscreen/weather
@@ -186,3 +196,34 @@
/atom/movable/screen/fullscreen/weather/high
icon_state = "impairedoverlay3"
+
+/atom/movable/screen/fullscreen/lighting_backdrop
+ icon = 'icons/mob/hud/screen1.dmi'
+ icon_state = "flash"
+ transform = matrix(200, 0, 0, 0, 200, 0)
+ plane = LIGHTING_PLANE
+ blend_mode = BLEND_OVERLAY
+ show_when_dead = TRUE
+
+/atom/movable/screen/fullscreen/lighting_backdrop/update_for_view(client_view)
+ return
+
+//Provides darkness to the back of the lighting plane
+/atom/movable/screen/fullscreen/lighting_backdrop/lit_secondary
+ invisibility = INVISIBILITY_LIGHTING
+ layer = BACKGROUND_LAYER + LIGHTING_PRIMARY_DIMMER_LAYER
+ color = "#000"
+ alpha = 60
+
+/atom/movable/screen/fullscreen/lighting_backdrop/backplane
+ invisibility = INVISIBILITY_LIGHTING
+ layer = LIGHTING_BACKPLANE_LAYER
+ color = "#000"
+ blend_mode = BLEND_ADD
+
+/atom/movable/screen/fullscreen/see_through_darkness
+ icon_state = "nightvision"
+ plane = LIGHTING_PLANE
+ layer = LIGHTING_PRIMARY_LAYER
+ blend_mode = BLEND_ADD
+ show_when_dead = TRUE
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 7f9ad85e154e..392f3ae9a060 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -400,3 +400,40 @@
zone_sel.color = ui_color
zone_sel.update_icon(mymob)
static_inventory += zone_sel
+
+// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
+/datum/hud/proc/reorganize_alerts(mob/viewmob)
+ var/mob/screenmob = viewmob || mymob
+ if(!screenmob.client)
+ return
+ var/list/alerts = mymob.alerts
+ if(!length(alerts))
+ return FALSE
+ if(!hud_shown)
+ for(var/category in alerts)
+ var/atom/movable/screen/alert/alert = alerts[category]
+ screenmob.client.screen -= alert
+ return TRUE
+ var/c = 0
+ for(var/category in alerts)
+ var/atom/movable/screen/alert/alert = alerts[category]
+ c++
+ switch(c)
+ if(1)
+ . = ui_alert1
+ if(2)
+ . = ui_alert2
+ if(3)
+ . = ui_alert3
+ if(4)
+ . = ui_alert4
+ if(5)
+ . = ui_alert5 // Right now there's 5 slots
+ else
+ . = ""
+ alert.screen_loc = .
+ screenmob.client.screen |= alert
+ if(!viewmob)
+ for(var/obs in mymob.observers)
+ reorganize_alerts(obs)
+ return TRUE
diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm
index d29228f4c16e..91c0e24fae1f 100644
--- a/code/_onclick/hud/rendering/plane_master.dm
+++ b/code/_onclick/hud/rendering/plane_master.dm
@@ -76,6 +76,17 @@
appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR | PIXEL_SCALE
//byond internal end
+/*!
+ * This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.
+ *
+ * Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.
+ * Emissive blockers are pasted with an atom color that converts them to be entirely some different color.
+ * Emissive overlays and emissive blockers are put onto the same plane.
+ * The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.
+ * A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.
+ * This is then used to alpha mask the lighting plane.
+ */
+
///Contains all lighting objects
/atom/movable/screen/plane_master/lighting
name = "lighting plane master"
@@ -83,10 +94,41 @@
blend_mode_override = BLEND_MULTIPLY
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+/atom/movable/screen/plane_master/lighting/backdrop(mob/mymob)
+ . = ..()
+ mymob.overlay_fullscreen("lighting_backdrop", /atom/movable/screen/fullscreen/lighting_backdrop/backplane)
+ mymob.overlay_fullscreen("lighting_backdrop_lit_secondary", /atom/movable/screen/fullscreen/lighting_backdrop/lit_secondary)
+
+/atom/movable/screen/plane_master/lighting/Initialize()
+ . = ..()
+ add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE))
+ add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE))
+
/atom/movable/screen/plane_master/lighting/exterior
name = "exterior lighting plane master"
plane = EXTERIOR_LIGHTING_PLANE
+/**
+ * Handles emissive overlays and emissive blockers.
+ */
+/atom/movable/screen/plane_master/emissive
+ name = "emissive plane master"
+ plane = EMISSIVE_PLANE
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ render_target = EMISSIVE_RENDER_TARGET
+ render_relay_plane = null
+
+/atom/movable/screen/plane_master/emissive/Initialize()
+ . = ..()
+ add_filter("em_block_masking", 1, color_matrix_filter(GLOB.em_mask_matrix))
+
+/atom/movable/screen/plane_master/above_lighting
+ name = "above lighting plane master"
+ plane = ABOVE_LIGHTING_PLANE
+ appearance_flags = PLANE_MASTER //should use client color
+ blend_mode = BLEND_OVERLAY
+ render_relay_plane = RENDER_PLANE_GAME
+
/atom/movable/screen/plane_master/runechat
name = "runechat plane master"
plane = RUNECHAT_PLANE
@@ -94,6 +136,14 @@
blend_mode = BLEND_OVERLAY
render_relay_plane = RENDER_PLANE_NON_GAME
+/atom/movable/screen/plane_master/o_light_visual
+ name = "overlight light visual plane master"
+ plane = O_LIGHTING_VISUAL_PLANE
+ render_target = O_LIGHTING_VISUAL_RENDER_TARGET
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ blend_mode = BLEND_MULTIPLY
+ blend_mode_override = BLEND_MULTIPLY
+
/atom/movable/screen/plane_master/runechat/backdrop(mob/mymob)
. = ..()
remove_filter("AO")
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 9643d0f652ae..206b1dbf9979 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -639,3 +639,7 @@
/atom/movable/screen/rotate/alt
dir = WEST
rotate_amount = -90
+
+/atom/movable/screen/vulture_scope // The part of the vulture's scope that drifts over time
+ icon_state = "vulture_unsteady"
+ screen_loc = "CENTER,CENTER"
diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm
deleted file mode 100644
index 9b6088b9bc1e..000000000000
--- a/code/controllers/_DynamicAreaLighting_TG.dm
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- Modified DynamicAreaLighting for TGstation - Coded by Carnwennan
-
- This is TG's 'new' lighting system. It's basically a heavily modified combination of Forum_Account's and
- ShadowDarke's respective lighting libraries. Credits, where due, to them.
-
- Like sd_DAL (what we used to use), it changes the shading overlays of areas by splitting each type of area into sub-areas
- by using the var/tag variable and moving turfs into the contents list of the correct sub-area. This method is
- much less costly than using overlays or objects.
-
- Unlike sd_DAL however it uses a queueing system. Everytime we call a change to opacity or luminosity
- (through SetOpacity() or SetLuminosity()) we are simply updating variables and scheduling certain lights/turfs for an
- update. Actual updates are handled periodically by the lighting_controller. This carries additional overheads, however it
- means that each thing is changed only once per lighting_controller.processing_interval ticks. Allowing for greater control
- over how much priority we'd like lighting updates to have. It also makes it possible for us to simply delay updates by
- setting lighting_controller.processing = 0 at say, the start of a large explosion, waiting for it to finish, and then
- turning it back on with lighting_controller.processing = 1.
-
- Unlike our old system there are hardcoded maximum luminositys (different for certain atoms).
- This is to cap the cost of creating lighting effects.
- (without this, an atom with luminosity of 20 would have to update 41^2 turfs!) :s
-
- Also, in order for the queueing system to work, each light remembers the effect it casts on each turf. This is going to
- have larger memory requirements than our previous system but it's easily worth the hassle for the greater control we
- gain. It also reduces cost of removing lighting effects by a lot!
-
- Known Issues/TODO:
- Shuttles still do not have support for dynamic lighting (I hope to fix this at some point)
- No directional lighting support. (prototype looked ugly)
-*/
-
-#define LIGHTING_CIRCULAR 1 //comment this out to use old square lighting effects.
-#define LIGHTING_LAYER 10 //Drawing layer for lighting overlays
-#define LIGHTING_ICON 'icons/effects/ss13_dark_alpha6.dmi' //Icon used for lighting shading effects
-#define LIGHTING_STATES 6
-
-// Update these lists if the luminosity cap
-// of 8 is removed
-GLOBAL_LIST_INIT(comp1table, list(
- 0,
- 0.934,
- 1.868,
- 2.802,
- 3.736,
- 4.67,
- 5.604,
- 6.538,
- 7.472,
-))
-GLOBAL_LIST_INIT(comp2table, list(
- 0,
- 0.427,
- 0.854,
- 1.281,
- 1.708,
- 2.135,
- 2.562,
- 2.989,
- 3.416,
-))
-/datum/light_source
- var/atom/owner
- var/changed = 1
- var/list/effect = list()
- var/__x = 0 //x coordinate at last update
- var/__y = 0 //y coordinate at last update
- var/__z = 0 //z coordinate at last update
-
-#define turf_update_lumcount(T, amount)\
- T.lighting_lumcount += amount;\
- if(!T.lighting_changed){\
- SSlighting.changed_turfs += T;\
- T.lighting_changed = TRUE;\
- }
-
-#define ls_remove_effect(ls)\
- for(var/t in ls.effect){\
- var/turf/T = t;\
- turf_update_lumcount(T, -ls.effect[T]);\
- }\
- ls.effect.Cut();
-
-/datum/light_source/New(atom/A)
- if(!istype(A))
- CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
- ..()
- owner = A
- __x = owner.x
- __y = owner.y
- __z = owner.z
- // the lighting object maintains a list of all light sources
- SSlighting.lights.Add(src)
-
-//Check a light to see if its effect needs reprocessing. If it does, remove any old effect and create a new one
-/datum/light_source/proc/check()
- if(!owner)
- ls_remove_effect(src)
- return TRUE //causes it to be removed from our list of lights. The garbage collector will then destroy it.
-
- if(owner.luminosity > 8)
- owner.luminosity = 8
-
- changed = FALSE
-
- ls_remove_effect(src)
- if(owner.loc && owner.luminosity > 0)
- for(var/turf/T in view(owner.luminosity, owner))
- var/dist
- var/dx = abs(T.x - __x)
- var/dy = abs(T.y - __y)
- // Use dx+1 and dy+1 because lists use 1-based indexing
- if(dx >= dy)
- dist = (GLOB.comp1table[dx+1]) + (GLOB.comp2table[dy+1])
- else
- dist = (GLOB.comp2table[dx+1]) + (GLOB.comp1table[dy+1])
- var/delta_lumen = owner.luminosity - dist
- if(delta_lumen > 0)
- effect[T] = delta_lumen
- turf_update_lumcount(T, delta_lumen)
- return FALSE
- else
- owner.light = null
- return TRUE
-
-/datum/light_source/proc/changed()
- if(owner)
- __x = owner.x
- __y = owner.y
-
- if(!changed)
- changed = 1
- SSlighting.lights.Add(src)
-
-
-/datum/light_source/proc/remove_effect()
- // before we apply the effect we remove the light's current effect.
- for(var/turf/T in effect) // negate the effect of this light source
- turf_update_lumcount(T, -effect[T])
- effect.Cut() // clear the effect list
-
-/atom
- var/datum/light_source/light
- var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
- // We may read it, but NEVER set it directly.
-
-//Movable atoms with opacity when they are constructed will trigger nearby lights to update
-//Movable atoms with luminosity when they are constructed will create a light_source automatically
-/atom/movable/Initialize(mapload, ...)
- . = ..()
- if(opacity)
- if(isturf(loc))
- var/turf/T = loc
- if(T.lighting_lumcount > 1)
- UpdateAffectingLights()
- if(luminosity)
- if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
- trueLuminosity = luminosity * luminosity
- light = new(src)
-
-//Objects with opacity will trigger nearby lights to update at next lighting process.
-/atom/movable/Destroy()
- if(opacity)
- if(isturf(loc))
- var/turf/T = loc
- if(T.lighting_lumcount > 1)
- UpdateAffectingLights()
- . = ..()
-
-/atom/vv_edit_var(var_name, var_value)
- switch(var_name)
- if(NAMEOF(src, luminosity))
- SetLuminosity(var_value)
- return ..()
-
-//Sets our luminosity.
-//If we have no light it will create one.
-//If we are setting luminosity to 0 the light will be cleaned up by the controller and garbage collected once all its
-//queues are complete.
-//if we have a light already it is merely updated, rather than making a new one.
-/atom/proc/SetLuminosity(new_luminosity, trueLum = FALSE, atom/source)
- if(new_luminosity < 0)
- new_luminosity = 0
- if(!trueLum)
- new_luminosity *= new_luminosity
- if(light)
- if(trueLuminosity != new_luminosity) //non-luminous lights are removed from the lights list in add_effect()
- light.changed()
- else
- if(new_luminosity)
- light = new(src)
- trueLuminosity = new_luminosity
- if (trueLuminosity < 1)
- luminosity = 0
- else if (trueLuminosity <= 100)
- luminosity = sqrtTable[trueLuminosity]
- else
- luminosity = sqrt(trueLuminosity)
-
-//This slightly modifies human luminosity. Source of light do NOT stack.
-//When you drop a light source it should keep a running total of your actual luminosity and set it accordingly.
-/mob/SetLuminosity(new_luminosity, trueLum, atom/source)
- LAZYREMOVE(luminosity_sources, source)
- if(source)
- UnregisterSignal(source, COMSIG_PARENT_QDELETING)
- var/highest_luminosity = 0
- for(var/luminosity_source as anything in luminosity_sources)
- var/lumonisity_rating = luminosity_sources[luminosity_source]
- if(highest_luminosity < lumonisity_rating)
- highest_luminosity = lumonisity_rating
- if(source && new_luminosity > 0)
- LAZYSET(luminosity_sources, source, new_luminosity)
- RegisterSignal(source, COMSIG_PARENT_QDELETING, PROC_REF(remove_luminosity_source))
- if(new_luminosity < highest_luminosity)
- new_luminosity = highest_luminosity
- return ..()
-
-/mob/proc/remove_luminosity_source(atom/source)
- SetLuminosity(0, FALSE, source)
-
-/area/SetLuminosity(new_luminosity) //we don't want dynamic lighting for areas
- luminosity = !!new_luminosity
- trueLuminosity = luminosity
-
-
-//change our opacity (defaults to toggle), and then update all lights that affect us.
-/atom/proc/SetOpacity(new_opacity)
- if(new_opacity == null)
- new_opacity = !opacity //default = toggle opacity
- else if(opacity == new_opacity)
- return FALSE //opacity hasn't changed! don't bother doing anything
- opacity = new_opacity //update opacity, the below procs now call light updates.
- return TRUE
-
-/turf/SetOpacity(new_opacity)
- . = ..()
- //only bother if opacity changed
- if(!.)
- return
- if(lighting_lumcount) //only bother with an update if our turf is currently affected by a light
- UpdateAffectingLights()
-
-/atom/movable/SetOpacity(new_opacity)
- . = ..()
- // only bother if opacity changed
- if(!.)
- return
- // only bother with an update if we're on a turf
- if(isturf(loc))
- var/turf/T = loc
- // only bother with an update if our turf is currently affected by a light
- if(T.lighting_lumcount)
- UpdateAffectingLights()
-
-
-/turf
- var/lighting_lumcount = 0
- var/lighting_changed = 0
- var/cached_lumcount = 0
-
-/turf/open/space
- lighting_lumcount = 4 //starlight
-
-/turf/proc/update_lumcount(amount, removing = 0)
- lighting_lumcount += amount
-
- if(!lighting_changed)
- SSlighting.changed_turfs += src
- lighting_changed = 1
-
-/turf/proc/lighting_tag(const/level)
- var/area/A = loc
- return A.tagbase + "sd_L[level]"
-
-/turf/proc/build_lighting_area(const/tag, const/level)
- var/area/Area = loc
- var/area/A = new Area.type() // create area if it wasn't found
- // replicate vars
- for(var/V in Area.vars)
- switch(V)
- if ("contents","lighting_overlay", "overlays")
- continue
- else
- if(issaved(Area.vars[V])) A.vars[V] = Area.vars[V]
-
- A.tag = tag
- A.lighting_subarea = 1
- A.lighting_space = 0 // in case it was copied from a space subarea
-
- A.SetLightLevel(level)
- Area.related += A
-
- if(SSweather.is_weather_event && SSweather.map_holder.should_affect_area(A))
- A.overlays += SSweather.curr_master_turf_overlay
-
- return A
-
-/turf/proc/shift_to_subarea()
- lighting_changed = 0
- var/area/Area = loc
-
- if(!istype(Area) || !Area.lighting_use_dynamic) return
-
- var/level = min(max(round(lighting_lumcount,1),0),LIGHTING_STATES)
- var/new_tag = lighting_tag(level)
-
- if(Area.tag!=new_tag) //skip if already in this area
- var/area/A = locate(new_tag) // find an appropriate area
-
- if (!A)
- A = build_lighting_area(new_tag, level)
-
- A.contents += src // move the turf into the area
-
-// Dedicated lighting sublevel for space turfs
-// helps us depower things in space, remove space fire alarms,
-// and evens out space lighting
-/turf/open/space/lighting_tag(level)
- var/area/A = loc
- return A.tagbase + "sd_L_space"
-/turf/open/space/build_lighting_area(tag, level)
- var/area/A = ..(tag,4)
- A.lighting_space = 1
- A.SetLightLevel(4)
- A.icon_state = null
- return A
-
-
-/area
- var/lighting_use_dynamic = 1 //Turn this flag off to prevent sd_DynamicAreaLighting from affecting this area
- var/image/lighting_overlay //tracks the darkness image of the area for easy removal
- var/lighting_subarea = 0 //tracks whether we're a lighting sub-area
- var/lighting_space = 0 // true for space-only lighting subareas
- var/tagbase
- var/exterior_light = 2
-
-/area/proc/SetLightLevel(light)
- if(!src) return
- if(light <= 0)
- light = 0
- luminosity = 1
- if(light > LIGHTING_STATES)
- light = LIGHTING_STATES
-
- if(lighting_overlay)
- overlays -= lighting_overlay
- lighting_overlay.icon_state = "[light]"
- else
- lighting_overlay = image(LIGHTING_ICON,,num2text(light),LIGHTING_LAYER)
- lighting_overlay.plane = ceiling <= CEILING_GLASS ? EXTERIOR_LIGHTING_PLANE : LIGHTING_PLANE
- if (light < 6)
- overlays.Add(lighting_overlay)
-
-/area/proc/SetDynamicLighting()
- src.lighting_use_dynamic = 1
- for(var/turf/T in src.contents)
- turf_update_lumcount(T, 0)
-
-/area/proc/InitializeLighting() //TODO: could probably improve this bit ~Carn
- tagbase = "[type]"
- if(!tag) tag = tagbase
- if(!lighting_use_dynamic)
- if(!lighting_subarea) // see if this is a lighting subarea already
- //show the dark overlay so areas, not yet in a lighting subarea, won't be bright as day and look silly.
- SetLightLevel(4)
-
-//#undef LIGHTING_LAYER
-#undef LIGHTING_CIRCULAR
-//#undef LIGHTING_ICON
-
-#define LIGHTING_MAX_LUMINOSITY_STATIC 8 //Maximum luminosity to reduce lag.
-#define LIGHTING_MAX_LUMINOSITY_MOBILE 6 //Moving objects have a lower max luminosity since these update more often. (lag reduction)
-#define LIGHTING_MAX_LUMINOSITY_TURF 1 //turfs have a severely shortened range to protect from inevitable floor-lighttile spam.
-
-//set the changed status of all lights which could have possibly lit this atom.
-//We don't need to worry about lights which lit us but moved away, since they will have change status set already
-//This proc can cause lots of lights to be updated. :(
-/atom/proc/UpdateAffectingLights()
-// for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src))
-// if(A.light)
-// A.light.changed() //force it to update at next process()
-
-/atom/movable/UpdateAffectingLights()
- if(isturf(loc))
- loc.UpdateAffectingLights()
-
-/turf/UpdateAffectingLights()
- for(var/atom/A in oview(LIGHTING_MAX_LUMINOSITY_STATIC-1,src))
- if(A.light)
- A.light.changed()
-
-//caps luminosity effects max-range based on what type the light's owner is.
-/atom/proc/get_light_range()
- return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
-
-/atom/movable/get_light_range()
- return min(luminosity, LIGHTING_MAX_LUMINOSITY_MOBILE)
-
-/obj/structure/machinery/light/get_light_range()
- return min(luminosity, LIGHTING_MAX_LUMINOSITY_STATIC)
-
-/turf/get_light_range()
- return min(luminosity, LIGHTING_MAX_LUMINOSITY_TURF)
-
-#undef LIGHTING_MAX_LUMINOSITY_STATIC
-#undef LIGHTING_MAX_LUMINOSITY_MOBILE
-#undef LIGHTING_MAX_LUMINOSITY_TURF
diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm
index a98eaa0f7876..a5c5271c8d7d 100644
--- a/code/controllers/subsystem/communications.dm
+++ b/code/controllers/subsystem/communications.dm
@@ -73,6 +73,7 @@ var/const/YAUT_FREQ = 1205
var/const/DUT_FREQ = 1210
var/const/CMB_FREQ = 1220
var/const/VAI_FREQ = 1215
+var/const/RMC_FREQ = 1216
//WY Channels (1230-1249)
var/const/WY_FREQ = 1231
@@ -105,6 +106,7 @@ var/const/MAX_FREQ = 1468 // ---------------------------------------------------
//USCM High Command (USCM 1470-1499)
var/const/HC_FREQ = 1471
var/const/SOF_FREQ = 1472
+var/const/PVST_FREQ = 1473
//Ship department channels
var/const/SENTRY_FREQ = 1480
@@ -139,8 +141,10 @@ var/list/radiochannels = list(
RADIO_CHANNEL_VAI = VAI_FREQ,
RADIO_CHANNEL_CMB = CMB_FREQ,
RADIO_CHANNEL_DUTCH_DOZEN = DUT_FREQ,
+ RADIO_CHANNEL_ROYAL_MARINE = RMC_FREQ,
RADIO_CHANNEL_HIGHCOM = HC_FREQ,
+ RADIO_CHANNEL_PROVOST = PVST_FREQ,
RADIO_CHANNEL_ALMAYER = PUB_FREQ,
RADIO_CHANNEL_COMMAND = COMM_FREQ,
RADIO_CHANNEL_MEDSCI = MED_FREQ,
@@ -188,7 +192,7 @@ var/list/radiochannels = list(
)
// Response Teams
-#define ERT_FREQS list(VAI_FREQ, DUT_FREQ, YAUT_FREQ, CMB_FREQ)
+#define ERT_FREQS list(VAI_FREQ, DUT_FREQ, YAUT_FREQ, CMB_FREQ, RMC_FREQ)
// UPP Frequencies
#define UPP_FREQS list(UPP_FREQ, UPP_CMD_FREQ, UPP_ENGI_FREQ, UPP_MED_FREQ, UPP_CCT_FREQ, UPP_KDO_FREQ)
@@ -249,6 +253,7 @@ SUBSYSTEM_DEF(radio)
"[INTEL_FREQ]" = "intelradio",
"[WY_FREQ]" = "wyradio",
"[VAI_FREQ]" = "vairadio",
+ "[RMC_FREQ]" = "rmcradio",
"[CMB_FREQ]" = "cmbradio",
"[CLF_FREQ]" = "clfradio",
"[ALPHA_FREQ]" = "alpharadio",
@@ -259,6 +264,7 @@ SUBSYSTEM_DEF(radio)
"[CRYO_FREQ]" = "cryoradio",
"[SOF_FREQ]" = "hcradio",
"[HC_FREQ]" = "hcradio",
+ "[PVST_FREQ]" = "pvstradio",
"[COLONY_FREQ]" = "deptradio",
)
diff --git a/code/controllers/subsystem/interior.dm b/code/controllers/subsystem/interior.dm
index f81cc6c8d88c..389e95fe6022 100644
--- a/code/controllers/subsystem/interior.dm
+++ b/code/controllers/subsystem/interior.dm
@@ -19,7 +19,17 @@ SUBSYSTEM_DEF(interior)
var/list/bottom_left = reserved_area.bottom_left_coords
- template.load(locate(bottom_left[1] + (INTERIOR_BORDER_SIZE / 2), bottom_left[2] + (INTERIOR_BORDER_SIZE / 2), bottom_left[3]), centered = FALSE)
+ var/list/bounds = template.load(locate(bottom_left[1] + (INTERIOR_BORDER_SIZE / 2), bottom_left[2] + (INTERIOR_BORDER_SIZE / 2), bottom_left[3]), centered = FALSE)
+
+ var/list/turfs = block( locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]),
+ locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ]))
+
+ var/list/areas = list()
+ for(var/turf/current_turf as anything in turfs)
+ areas |= current_turf.loc
+
+ for(var/area/current_area as anything in areas)
+ current_area.add_base_lighting()
interiors += interior
return reserved_area
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 26ee4c9a648e..3c3d14468bc2 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -1,68 +1,124 @@
SUBSYSTEM_DEF(lighting)
- name = "Lighting"
+ name = "Lighting"
+ wait = 2
init_order = SS_INIT_LIGHTING
- priority = SS_PRIORITY_LIGHTING
- wait = 0.4 SECONDS
- runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY
- var/list/datum/light_source/lights_current = list()
- var/list/datum/light_source/lights = list()
+ //debug var for tracking updates before init is complete
+ var/duplicate_shadow_updates_in_init = 0
+ ///Total times shadows were updated, debug
+ var/total_shadow_calculations = 0
- var/list/turf/changed_turfs_current = list()
- var/list/turf/changed_turfs = list()
+ ///Whether the SS has begun setting up yet
+ var/started = FALSE
+ var/static/list/static_sources_queue = list() //! List of static lighting sources queued for update.
+ var/static/list/corners_queue = list() //! List of lighting corners queued for update.
+ var/static/list/objects_queue = list() //! List of lighting objects queued for update.
-/datum/controller/subsystem/lighting/stat_entry(msg)
- msg = "L:[lights.len]; T:[changed_turfs.len]"
- return ..()
+ var/static/list/mask_queue = list() //! List of hybrid lighting sources queued for update.
/datum/controller/subsystem/lighting/Initialize(timeofday)
- for(var/thing in lights)
- var/datum/light_source/L = thing
- if(L)
- L.check()
- lights.Cut()
+ started = TRUE
+ if(!initialized)
+ //Handle static lightnig
+ create_all_lighting_objects()
+ fire(FALSE, TRUE)
+ return SS_INIT_SUCCESS
- var/z_start = 1
- var/z_finish = world.maxz
+/datum/controller/subsystem/lighting/stat_entry()
+ . = ..("ShCalcs:[total_shadow_calculations]|SourcQ:[static_sources_queue.len]|CcornQ:[corners_queue.len]|ObjQ:[objects_queue.len]|HybrQ:[mask_queue.len]")
- var/list/init_turfs = block(locate(1,1,z_start),locate(world.maxx,world.maxy,z_finish))
+/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
+ MC_SPLIT_TICK_INIT(3)
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+ var/updators_num = 0
+ while(updators_num < length(static_sources_queue))
+ updators_num += 1
- for(var/turf/thing in init_turfs)
- if(istype(thing))
- thing.shift_to_subarea()
+ var/datum/static_light_source/L = static_sources_queue[updators_num]
+ L.update_corners()
- return SS_INIT_SUCCESS
+ if(!QDELETED(L))
+ L.needs_update = LIGHTING_NO_UPDATE
+ else
+ updators_num -= 1
+ if(init_tick_checks)
+ if(!TICK_CHECK)
+ continue
+ static_sources_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ stoplag()
+ else if (MC_TICK_CHECK)
+ break
+ if(updators_num)
+ static_sources_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
-/datum/controller/subsystem/lighting/fire(resumed = FALSE)
- if(!resumed)
- lights_current = lights
- lights = list()
- changed_turfs_current = changed_turfs
- changed_turfs = list()
+ while(updators_num < length(corners_queue))
+ updators_num += 1
+ var/datum/static_lighting_corner/C = corners_queue[updators_num]
+ C.needs_update = FALSE //update_objects() can call qdel if the corner is storing no data
+ C.update_objects()
- while(lights_current.len)
- var/datum/light_source/L = lights_current[lights_current.len]
- lights_current.len--
- if(!L)
- continue
- if(!L.owner || L.changed)
- L.check()
- if(MC_TICK_CHECK)
- return
-
- while(changed_turfs_current.len)
- var/turf/T = changed_turfs_current[changed_turfs_current.len]
- changed_turfs_current.len--
- if(!T)
+ if(init_tick_checks)
+ if(!TICK_CHECK)
+ continue
+ corners_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ stoplag()
+ else if (MC_TICK_CHECK)
+ break
+ if(updators_num)
+ corners_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+
+ while(updators_num < length(objects_queue))
+ updators_num += 1
+
+ var/datum/static_lighting_object/O = objects_queue[updators_num]
+ if (QDELETED(O))
continue
- if(T.lighting_changed)
- if(T.lighting_lumcount != T.cached_lumcount)
- T.cached_lumcount = T.lighting_lumcount
- T.shift_to_subarea()
- T.lighting_changed = FALSE
- if (MC_TICK_CHECK)
- return
+ O.update()
+ O.needs_update = FALSE
+
+ if(init_tick_checks)
+ if(!TICK_CHECK)
+ continue
+ objects_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ else if (MC_TICK_CHECK)
+ break
+ if(updators_num)
+ objects_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ if(!init_tick_checks)
+ MC_SPLIT_TICK
+
+ while(updators_num > length(mask_queue))
+ updators_num += 1
+
+ var/atom/movable/lighting_mask/mask_to_update = mask_queue[updators_num]
+ mask_to_update.calculate_lighting_shadows()
+
+ if(init_tick_checks)
+ if(!TICK_CHECK)
+ continue
+ mask_queue.Cut(1, updators_num + 1)
+ updators_num = 0
+ stoplag()
+ else if (MC_TICK_CHECK)
+ break
+ if(updators_num)
+ mask_queue.Cut(1, updators_num + 1)
+
+/datum/controller/subsystem/lighting/Recover()
+ initialized = SSlighting.initialized
+ return ..()
diff --git a/code/controllers/subsystem/projectiles.dm b/code/controllers/subsystem/projectiles.dm
index 075a4f7facc5..a23303ea282d 100644
--- a/code/controllers/subsystem/projectiles.dm
+++ b/code/controllers/subsystem/projectiles.dm
@@ -6,11 +6,11 @@ SUBSYSTEM_DEF(projectiles)
priority = SS_PRIORITY_PROJECTILES
/// List of projectiles handled by the subsystem
- VAR_PRIVATE/list/obj/item/projectile/projectiles
+ VAR_PRIVATE/list/obj/projectile/projectiles
/// List of projectiles on hold due to sleeping
- VAR_PRIVATE/list/obj/item/projectile/sleepers
+ VAR_PRIVATE/list/obj/projectile/sleepers
/// List of projectiles handled this controller firing
- VAR_PRIVATE/list/obj/item/projectile/flying
+ VAR_PRIVATE/list/obj/projectile/flying
/*
* Scheduling notes:
@@ -42,14 +42,14 @@ SUBSYSTEM_DEF(projectiles)
flying = projectiles.Copy()
flying -= sleepers
while(flying.len)
- var/obj/item/projectile/projectile = flying[flying.len]
+ var/obj/projectile/projectile = flying[flying.len]
flying.len--
var/delta_time = wait * world.tick_lag * (1 SECONDS)
handle_projectile_flight(projectile, delta_time)
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/projectiles/proc/handle_projectile_flight(obj/item/projectile/projectile, delta_time)
+/datum/controller/subsystem/projectiles/proc/handle_projectile_flight(obj/projectile/projectile, delta_time)
PRIVATE_PROC(TRUE)
set waitfor = FALSE
// We're in double-check land here because there ARE rulebreakers.
@@ -66,15 +66,15 @@ SUBSYSTEM_DEF(projectiles)
stop_projectile(projectile) // Ideally this was already done thru process()
qdel(projectile)
-/datum/controller/subsystem/projectiles/proc/process_wrapper(obj/item/projectile/projectile, delta_time)
+/datum/controller/subsystem/projectiles/proc/process_wrapper(obj/projectile/projectile, delta_time)
// set waitfor=TRUE
. = PROC_RETURN_SLEEP
. = projectile.process(delta_time)
sleepers -= projectile // Recover from sleep
-/datum/controller/subsystem/projectiles/proc/queue_projectile(obj/item/projectile/projectile)
+/datum/controller/subsystem/projectiles/proc/queue_projectile(obj/projectile/projectile)
projectiles |= projectile
-/datum/controller/subsystem/projectiles/proc/stop_projectile(obj/item/projectile/projectile)
+/datum/controller/subsystem/projectiles/proc/stop_projectile(obj/projectile/projectile)
projectiles -= projectile
flying -= projectile // avoids problems with deleted projs
projectile.speed = 0
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 0e23b99a9cc2..db6c3c71a7fa 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -199,6 +199,8 @@ SUBSYSTEM_DEF(ticker)
if(CONFIG_GET(flag/autooocmute))
ooc_allowed = FALSE
+ round_start_time = world.time
+
CHECK_TICK
for(var/I in round_start_events)
var/datum/callback/cb = I
@@ -222,9 +224,7 @@ SUBSYSTEM_DEF(ticker)
equip_characters()
GLOB.data_core.manifest()
-
log_world("Game start took [(world.timeofday - init_start) / 10]s")
- round_start_time = world.time
//SSdbcore.SetRoundStart()
current_state = GAME_STATE_PLAYING
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 7610c007df90..325c45fe2300 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -47,7 +47,7 @@ SUBSYSTEM_DEF(weather)
/datum/controller/subsystem/weather/proc/setup_weather_areas()
weather_areas = list()
for(var/area/A in all_areas)
- if(A == A.master && A.weather_enabled && map_holder.should_affect_area(A))
+ if(A.weather_enabled && map_holder.should_affect_area(A))
weather_areas += A
curr_master_turf_overlay = new /obj/effect/weather_vfx_holder
@@ -146,8 +146,7 @@ SUBSYSTEM_DEF(weather)
curr_master_turf_overlay.icon_state = weather_event_instance.turf_overlay_icon_state
curr_master_turf_overlay.alpha = weather_event_instance.turf_overlay_alpha
for(var/area/area as anything in weather_areas)
- for(var/area/subarea as anything in area.related)
- subarea.overlays += curr_master_turf_overlay
+ area.overlays += curr_master_turf_overlay
update_mobs_weather()
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_WEATHER_CHANGE)
@@ -169,8 +168,7 @@ SUBSYSTEM_DEF(weather)
message_admins(SPAN_BLUE("Weather Event of unknown type [weather_event_type] ending after [DisplayTimeText(world.time - current_event_start_time)]."))
for(var/area/area as anything in weather_areas)
- for(var/area/subarea as anything in area.related)
- subarea.overlays -= curr_master_turf_overlay
+ area.overlays -= curr_master_turf_overlay
if (map_holder.no_weather_turf_icon_state)
curr_master_turf_overlay.icon_state = map_holder.no_weather_turf_icon_state
diff --git a/code/datums/agents/tools/tranq_gun.dm b/code/datums/agents/tools/tranq_gun.dm
index e95f853cef82..91f6f8c294b7 100644
--- a/code/datums/agents/tools/tranq_gun.dm
+++ b/code/datums/agents/tools/tranq_gun.dm
@@ -1,7 +1,7 @@
/obj/item/weapon/gun/pistol/tranquilizer
name = "Tranquilizer gun"
desc = "Contains horse tranquilizer darts. Useful at knocking people out."
- icon = 'icons/obj/items/weapons/guns/guns_by_faction/upp.dmi'
+ icon = 'icons/obj/items/weapons/guns/guns_by_faction/event.dmi'
icon_state = "pk9r"
item_state = "pk9r"
current_mag = /obj/item/ammo_magazine/pistol/tranq
@@ -28,7 +28,7 @@
name = "\improper Tranquilizer magazine (Horse Tranquilizer)"
default_ammo = /datum/ammo/bullet/pistol/tranq
caliber = ".22"
- icon = 'icons/obj/items/weapons/guns/ammo_by_faction/upp.dmi'
+ icon = 'icons/obj/items/weapons/guns/ammo_by_faction/event.dmi'
icon_state = "pk-9_tranq"
max_rounds = 5
gun_type = /obj/item/weapon/gun/pistol/tranquilizer
diff --git a/code/datums/components/cluster_stack.dm b/code/datums/components/cluster_stack.dm
index c79ce855e5b1..01d266d01a15 100644
--- a/code/datums/components/cluster_stack.dm
+++ b/code/datums/components/cluster_stack.dm
@@ -75,7 +75,7 @@
SIGNAL_HANDLER
L += "Cluster Stack: [cluster_stacks]/[MAX_CLUSTER_STACKS]"
-/datum/component/cluster_stack/proc/apply_cluster_stacks(mob/living/L, damage_result, ammo_flags, obj/item/projectile/P)
+/datum/component/cluster_stack/proc/apply_cluster_stacks(mob/living/L, damage_result, ammo_flags, obj/projectile/P)
SIGNAL_HANDLER
if(cluster_stacks >= MAX_CLUSTER_STACKS)
var/old_dmg_cont = damage_counter
diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm
new file mode 100644
index 000000000000..00a5e86b5d60
--- /dev/null
+++ b/code/datums/components/overlay_lighting.dm
@@ -0,0 +1,513 @@
+///For switchable lights, is it on and currently emitting light?
+#define LIGHTING_ON (1<<0)
+///Is the parent attached to something else, its loc? Then we need to keep an eye of this.
+#define LIGHTING_ATTACHED (1<<1)
+
+#define GET_PARENT (parent_attached_to || parent)
+
+#define SHORT_CAST 2
+
+
+/**
+ * Movable atom overlay-based lighting component.
+ *
+ * * Component works by applying a visual object to the parent target.
+ *
+ * * The component tracks the parent's loc to determine the current_holder.
+ * * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible.
+ *
+ * * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency.
+ * * This component uses the visible_mask visual object to apply said light mask on the darkness.
+ *
+ * * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job.
+ *
+ * * Another limitation is for big lights: you only see the light if you see the object emiting it.
+ * * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy.
+*/
+/datum/component/overlay_lighting
+ ///How far the light reaches, float.
+ var/range = 1
+ ///Ceiling of range, integer without decimal entries.
+ var/lumcount_range = 0
+ ///How much this light affects the dynamic_lumcount of turfs.
+ var/lum_power = 0.5
+ ///Transparency value.
+ var/set_alpha = 0
+ ///For light sources that can be turned on and off.
+ var/overlay_lighting_flags = NONE
+
+ ///Cache of the possible light overlays, according to size.
+ var/static/list/light_overlays = list(
+ "32" = 'icons/effects/light_overlays/light_32.dmi',
+ "64" = 'icons/effects/light_overlays/light_64.dmi',
+ "96" = 'icons/effects/light_overlays/light_96.dmi',
+ "128" = 'icons/effects/light_overlays/light_128.dmi',
+ "160" = 'icons/effects/light_overlays/light_160.dmi',
+ "192" = 'icons/effects/light_overlays/light_192.dmi',
+ "224" = 'icons/effects/light_overlays/light_224.dmi',
+ "256" = 'icons/effects/light_overlays/light_256.dmi',
+ "288" = 'icons/effects/light_overlays/light_288.dmi',
+ "320" = 'icons/effects/light_overlays/light_320.dmi',
+ "352" = 'icons/effects/light_overlays/light_352.dmi',
+ "384" = 'icons/effects/light_overlays/light_384.dmi',
+ "416" = 'icons/effects/light_overlays/light_416.dmi',
+ )
+
+ ///Overlay effect to cut into the darkness and provide light.
+ var/image/visible_mask
+ ///Lazy list to track the turfs being affected by our light, to determine their visibility.
+ var/list/turf/affected_turfs
+ ///Movable atom currently holding the light. Parent might be a flashlight, for example, but that might be held by a mob or something else.
+ var/atom/movable/current_holder
+ ///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself.
+ var/atom/movable/parent_attached_to
+ ///Whether we're a directional light
+ var/directional = FALSE
+ ///A cone overlay for directional light, it's alpha and color are dependant on the light
+ var/image/cone
+ ///Current tracked direction for the directional cast behaviour
+ var/current_direction
+ ///Tracks current directional x offset so we dont update unecessarily
+ var/directional_offset_x
+ ///Tracks current directional y offset so we dont update unecessarily
+ var/directional_offset_y
+ ///Cast range for the directional cast (how far away the atom is moved)
+ var/cast_range = 2
+
+
+/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on, is_directional)
+ if(!ismovable(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/atom/movable/movable_parent = parent
+ if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != DIRECTIONAL_LIGHT)
+ stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT]/[DIRECTIONAL_LIGHT] instead.")
+ return COMPONENT_INCOMPATIBLE
+
+ . = ..()
+
+ visible_mask = image('icons/effects/light_overlays/light_32.dmi', icon_state = "light")
+ visible_mask.plane = O_LIGHTING_VISUAL_PLANE
+ visible_mask.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ visible_mask.alpha = 0
+ if(is_directional)
+ directional = TRUE
+ cone = image('icons/effects/light_overlays/light_cone.dmi', icon_state = "light")
+ cone.plane = O_LIGHTING_VISUAL_PLANE
+ cone.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ cone.alpha = 110
+ cone.transform = cone.transform.Translate(-32, -32)
+ set_direction(movable_parent.dir)
+ if(!isnull(_range))
+ movable_parent.set_light_range(_range)
+ set_range(parent, movable_parent.light_range)
+ if(!isnull(_power))
+ movable_parent.set_light_power(_power)
+ set_power(parent, movable_parent.light_power)
+ if(!isnull(_color))
+ movable_parent.set_light_color(_color)
+ set_color(parent, movable_parent.light_color)
+ if(!isnull(starts_on))
+ movable_parent.set_light_on(starts_on)
+
+/datum/component/overlay_lighting/RegisterWithParent()
+ . = ..()
+ if(directional)
+ RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_parent_dir_change))
+ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved))
+ RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(check_holder))
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_RANGE, PROC_REF(set_range))
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_POWER, PROC_REF(set_power))
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, PROC_REF(set_color))
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(on_toggle))
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, PROC_REF(on_light_flags_change))
+ var/atom/movable/movable_parent = parent
+ if(movable_parent.light_flags & LIGHT_ATTACHED)
+ overlay_lighting_flags |= LIGHTING_ATTACHED
+ set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
+ check_holder()
+ if(movable_parent.light_on)
+ turn_on()
+
+
+
+/datum/component/overlay_lighting/UnregisterFromParent()
+ overlay_lighting_flags &= ~LIGHTING_ATTACHED
+ set_parent_attached_to(null)
+ set_holder(null)
+ clean_old_turfs()
+ UnregisterSignal(parent, list(
+ COMSIG_MOVABLE_MOVED,
+ COMSIG_ATOM_SET_LIGHT_RANGE,
+ COMSIG_ATOM_SET_LIGHT_POWER,
+ COMSIG_ATOM_SET_LIGHT_COLOR,
+ COMSIG_ATOM_SET_LIGHT_ON,
+ COMSIG_ATOM_SET_LIGHT_FLAGS,
+ ))
+ if(directional)
+ UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE)
+ if(overlay_lighting_flags & LIGHTING_ON)
+ turn_off()
+ return ..()
+
+
+/datum/component/overlay_lighting/Destroy()
+ set_parent_attached_to(null)
+ set_holder(null)
+ clean_old_turfs()
+ visible_mask = null
+ cone = null
+ parent_attached_to = null
+ return ..()
+
+
+///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light.
+/datum/component/overlay_lighting/proc/clean_old_turfs()
+ for(var/turf/lit_turf as anything in affected_turfs)
+ lit_turf.dynamic_lumcount -= lum_power
+ affected_turfs = null
+
+
+///Populates the affected_turfs lazylist, adding to its contents the effects of being near the light.
+/datum/component/overlay_lighting/proc/get_new_turfs()
+ if(!current_holder)
+ return
+ LAZYINITLIST(affected_turfs)
+ if(range <= 2)
+ //Range here is 1 because actual range of lighting mask is 1 tile even if it says that range is 2
+ for(var/turf/lit_turf in RANGE_TURFS(1, current_holder.loc))
+ lit_turf.dynamic_lumcount += lum_power
+ affected_turfs += lit_turf
+ else
+ for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder)))
+ lit_turf.dynamic_lumcount += lum_power
+ affected_turfs += lit_turf
+
+
+///Clears the old affected turfs and populates the new ones.
+/datum/component/overlay_lighting/proc/make_luminosity_update()
+ clean_old_turfs()
+ if(!isturf(current_holder?.loc))
+ return
+ if(directional)
+ cast_directional_light()
+ get_new_turfs()
+
+
+///Adds the luminosity and source for the afected movable atoms to keep track of their visibility.
+/datum/component/overlay_lighting/proc/add_dynamic_lumi()
+ LAZYSET(current_holder.affected_movable_lights, src, lumcount_range + 1)
+ current_holder.underlays += visible_mask
+ current_holder.update_dynamic_luminosity()
+ if(directional)
+ current_holder.underlays += cone
+
+///Removes the luminosity and source for the afected movable atoms to keep track of their visibility.
+/datum/component/overlay_lighting/proc/remove_dynamic_lumi()
+ LAZYREMOVE(current_holder.affected_movable_lights, src)
+ current_holder.underlays -= visible_mask
+ current_holder.update_dynamic_luminosity()
+ if(directional)
+ current_holder.underlays -= cone
+
+///Called to change the value of parent_attached_to.
+/datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to)
+ if(new_parent_attached_to == parent_attached_to)
+ return
+
+ . = parent_attached_to
+ parent_attached_to = new_parent_attached_to
+ if(.)
+ var/atom/movable/old_parent_attached_to = .
+ UnregisterSignal(old_parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(old_parent_attached_to == current_holder)
+ RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel))
+ RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
+ if(parent_attached_to)
+ if(parent_attached_to == current_holder)
+ UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ RegisterSignal(parent_attached_to, COMSIG_PARENT_QDELETING, PROC_REF(on_parent_attached_to_qdel))
+ RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_attached_to_moved))
+ check_holder()
+
+
+///Called to change the value of current_holder.
+/datum/component/overlay_lighting/proc/set_holder(atom/movable/new_holder)
+ if(new_holder == current_holder)
+ return
+ if(current_holder)
+ if(current_holder != parent && current_holder != parent_attached_to)
+ UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(directional)
+ UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
+ if(overlay_lighting_flags & LIGHTING_ON)
+ remove_dynamic_lumi()
+ current_holder = new_holder
+ if(new_holder == null)
+ clean_old_turfs()
+ return
+ if(new_holder != parent && new_holder != parent_attached_to)
+ RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel))
+ if(overlay_lighting_flags & LIGHTING_ON)
+ RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
+ if(directional)
+ RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_holder_dir_change))
+ if(directional && current_direction != new_holder.dir)
+ current_direction = new_holder.dir
+ if(overlay_lighting_flags & LIGHTING_ON)
+ add_dynamic_lumi()
+ make_luminosity_update()
+
+
+///Used to determine the new valid current_holder from the parent's loc.
+/datum/component/overlay_lighting/proc/check_holder()
+ var/atom/movable/movable_parent = GET_PARENT
+ if(isturf(movable_parent.loc))
+ set_holder(movable_parent)
+ return
+ var/atom/inside = movable_parent.loc //Parent's loc
+ if(isnull(inside))
+ set_holder(null)
+ return
+ if(isturf(inside.loc))
+ set_holder(inside)
+ return
+ set_holder(null)
+
+
+///Called when the current_holder is qdeleted, to remove the light effect.
+/datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force)
+ UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(directional)
+ UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
+ set_holder(null)
+
+
+///Called when current_holder changes loc.
+/datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced)
+ if(!(overlay_lighting_flags & LIGHTING_ON))
+ return
+ make_luminosity_update()
+
+///Called when the current_holder is qdeleted, to remove the light effect.
+/datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force)
+ SIGNAL_HANDLER
+ UnregisterSignal(parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(directional)
+ UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE)
+ if(parent_attached_to == current_holder)
+ set_holder(null)
+ set_parent_attached_to(null)
+
+///Called when parent_attached_to changes loc.
+/datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced)
+ SIGNAL_HANDLER
+ check_holder()
+ if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
+ return
+ make_luminosity_update()
+
+///Called when parent changes loc.
+/datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced)
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ if(overlay_lighting_flags & LIGHTING_ATTACHED)
+ set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
+ check_holder()
+ if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
+ return
+ make_luminosity_update()
+
+
+///Changes the range which the light reaches. 0 means no light, 7 is the maximum value.
+/datum/component/overlay_lighting/proc/set_range(atom/source, new_range)
+ SIGNAL_HANDLER
+ if(range == new_range)
+ return
+ if(range == 0)
+ turn_off()
+ range = clamp(CEILING(new_range, 0.5), 1, 7)
+ var/pixel_bounds = ((range - 1) * 64) + 32
+ lumcount_range = CEILING(range, 1)
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays -= visible_mask
+ visible_mask.icon = light_overlays["[pixel_bounds]"]
+ if(pixel_bounds == 32)
+ visible_mask.transform = null
+ return
+ var/offset = (pixel_bounds - 32) * 0.5
+ var/matrix/transform = new
+ transform.Translate(-offset, -offset)
+ visible_mask.transform = transform
+ directional_offset_x = 0
+ directional_offset_y = 0
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += visible_mask
+ if(directional)
+ cast_range = clamp(round(new_range * 0.5), 1, 3)
+ if(overlay_lighting_flags & LIGHTING_ON)
+ make_luminosity_update()
+
+
+///Changes the intensity/brightness of the light by altering the visual object's alpha.
+/datum/component/overlay_lighting/proc/set_power(atom/source, new_power)
+ SIGNAL_HANDLER
+ set_lum_power(new_power >= 0 ? 0.5 : -0.5)
+ set_alpha = min(230, (abs(new_power) * 120) + 30)
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays -= visible_mask
+ visible_mask.alpha = set_alpha
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += visible_mask
+
+ if(!directional)
+ return
+
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays -= cone
+ cone.alpha = min(200, (abs(new_power) * 90)+20)
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += cone
+
+
+///Changes the light's color, pretty straightforward.
+/datum/component/overlay_lighting/proc/set_color(atom/source, new_color)
+ SIGNAL_HANDLER
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays -= visible_mask
+ visible_mask.color = new_color
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += visible_mask
+
+ if(!directional)
+ return
+
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays -= cone
+ cone.color = new_color
+ if(current_holder && overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += cone
+
+
+///Toggles the light on and off.
+/datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value)
+ SIGNAL_HANDLER
+ if(new_value) //Truthy value input, turn on.
+ turn_on()
+ return
+ turn_off() //Falsey value, turn off.
+
+///Triggered right after the parent light flags change.
+/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, new_flags)
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+
+ if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property
+ overlay_lighting_flags |= LIGHTING_ATTACHED
+ if(ismovable(movable_parent.loc))
+ set_parent_attached_to(movable_parent.loc)
+ else // Lost the [LIGHT_ATTACHED] property
+ overlay_lighting_flags &= ~LIGHTING_ATTACHED
+ set_parent_attached_to(null)
+
+///Toggles the light on.
+/datum/component/overlay_lighting/proc/turn_on()
+ if(overlay_lighting_flags & LIGHTING_ON)
+ return
+ overlay_lighting_flags |= LIGHTING_ON
+ if(current_holder)
+ add_dynamic_lumi(current_holder)
+ if(directional)
+ cast_directional_light()
+ if(current_holder && current_holder != parent && current_holder != parent_attached_to)
+ RegisterSignal(current_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
+ get_new_turfs()
+
+
+///Toggles the light off.
+/datum/component/overlay_lighting/proc/turn_off()
+ if(!(overlay_lighting_flags & LIGHTING_ON))
+ return
+ if(current_holder)
+ remove_dynamic_lumi()
+ overlay_lighting_flags &= ~LIGHTING_ON
+ if(current_holder && current_holder != parent && current_holder != parent_attached_to)
+ UnregisterSignal(current_holder, COMSIG_MOVABLE_MOVED)
+ clean_old_turfs()
+
+
+///Here we append the behavior associated to changing lum_power.
+/datum/component/overlay_lighting/proc/set_lum_power(new_lum_power)
+ if(lum_power == new_lum_power)
+ return
+ . = lum_power
+ lum_power = new_lum_power
+ var/difference = . - lum_power
+ for(var/t in affected_turfs)
+ var/turf/lit_turf = t
+ lit_turf.dynamic_lumcount -= difference
+
+///Here we append the behavior associated to changing lum_power.
+/datum/component/overlay_lighting/proc/cast_directional_light()
+ var/final_distance = cast_range
+ //Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast
+ if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction))
+ final_distance -= 1
+ var/turf/scanning = get_turf(current_holder)
+ for(var/i in 1 to final_distance)
+ var/turf/next_turf = get_step(scanning, current_direction)
+ if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf))
+ final_distance = i
+ break
+ scanning = next_turf
+
+ current_holder.underlays -= visible_mask
+
+ var/translate_x = -((range - 1) * 32)
+ var/translate_y = translate_x
+ switch(current_direction)
+ if(NORTH)
+ translate_y += 32 * final_distance
+ if(SOUTH)
+ translate_y += -32 * final_distance
+ if(EAST)
+ translate_x += 32 * final_distance
+ if(WEST)
+ translate_x += -32 * final_distance
+ if((directional_offset_x != translate_x) || (directional_offset_y != translate_y))
+ directional_offset_x = translate_x
+ directional_offset_y = translate_y
+ var/matrix/transform = matrix()
+ transform.Translate(translate_x, translate_y)
+ visible_mask.transform = transform
+ if(overlay_lighting_flags & LIGHTING_ON)
+ current_holder.underlays += visible_mask
+
+///Called when current_holder changes loc.
+/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir)
+ SIGNAL_HANDLER
+ set_direction(newdir)
+
+///Called when parent changes loc.
+/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir)
+ SIGNAL_HANDLER
+
+ if(current_holder?.dir != newdir)
+ return
+
+ set_direction(newdir)
+
+///Sets a new direction for the directional cast, then updates luminosity
+/datum/component/overlay_lighting/proc/set_direction(newdir)
+ if(!newdir)
+ return
+ if(current_direction == newdir)
+ return
+ current_direction = newdir
+ if(overlay_lighting_flags & LIGHTING_ON)
+ make_luminosity_update()
+
+#undef LIGHTING_ON
+#undef LIGHTING_ATTACHED
+#undef GET_PARENT
+#undef SHORT_CAST
diff --git a/code/datums/effects/acid.dm b/code/datums/effects/acid.dm
index 721fe27a0d0d..d89f7261a223 100644
--- a/code/datums/effects/acid.dm
+++ b/code/datums/effects/acid.dm
@@ -104,7 +104,7 @@
if(!acids_area)
return
- if(SSweather.is_weather_event && locate(acids_area.master) in SSweather.weather_areas)
+ if(SSweather.is_weather_event && locate(acids_area) in SSweather.weather_areas)
//smothering_strength is 1-10, we use this to take a proportional amount off the stats
duration = duration - (duration * (SSweather.weather_event_instance.fire_smothering_strength * 0.1))
damage_in_total_human = damage_in_total_human - (damage_in_total_human * (SSweather.weather_event_instance.fire_smothering_strength * 0.1))
diff --git a/code/datums/effects/neurotoxin.dm b/code/datums/effects/neurotoxin.dm
index 836fccf49ca3..1657d41d8a36 100644
--- a/code/datums/effects/neurotoxin.dm
+++ b/code/datums/effects/neurotoxin.dm
@@ -123,13 +123,8 @@
return TRUE
/datum/effects/neurotoxin/proc/process_hallucination(mob/living/carbon/human/victim)
- /// area of the victim for areachecks
- var/hallu_area = get_area(victim)
switch(rand(0, 100))
if(0 to 5)
- if(hallu_area)
- for(var/mob/dead/observer/observer as anything in GLOB.observer_list)
- to_chat(observer, SPAN_DEADSAY("[victim] has experienced a rare neuro-induced 'Schizo Lurker Pounce' hallucination (5% chance) at \the [hallu_area]" + " [OBSERVER_JMP(observer, victim)]"))
playsound_client(victim?.client,pick('sound/voice/alien_pounce.ogg','sound/voice/alien_pounce.ogg'))
victim.KnockDown(3)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound_client), victim.client,"alien_claw_flesh"), 1 SECONDS)
@@ -140,18 +135,12 @@
victim.apply_effect(AGONY,10)
victim.emote("pain")
if(6 to 10)
- if(hallu_area)
- for(var/mob/dead/observer/observer as anything in GLOB.observer_list)
- to_chat(observer, SPAN_DEADSAY("[victim] has experienced a rare neuro-induced 'OB' hallucination (4% chance) at \the [hallu_area]" + " [OBSERVER_JMP(observer, victim)]"))
playsound_client(victim.client,'sound/effects/ob_alert.ogg')
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound_client), victim.client,'sound/weapons/gun_orbital_travel.ogg'), 2 SECONDS)
if(11 to 16)
playsound_client(victim.client,'sound/voice/alien_queen_screech.ogg')
victim.KnockDown(1)
if(17 to 24)
- if(hallu_area)
- for(var/mob/dead/observer/observer as anything in GLOB.observer_list)
- to_chat(observer, SPAN_DEADSAY("[victim] has experienced a rare neuro-induced 'Fake CAS firemission' hallucination (7% chance) at \the [hallu_area]" + " [OBSERVER_JMP(observer, victim)]"))
hallucination_fakecas_sequence(victim) //Not gonna spam a billion timers for this one so outsourcing to a proc with sleeps is a better async solution
if(25 to 42)
to_chat(victim,SPAN_HIGHDANGER("A SHELL IS ABOUT TO IMPACT [pick(SPAN_UNDERLINE("TOWARDS THE [pick("WEST","EAST","SOUTH","NORTH")]"),SPAN_UNDERLINE("RIGHT ONTOP OF YOU!"))]!"))
diff --git a/code/datums/elements/bullet_trait/bullet_trait.md b/code/datums/elements/bullet_trait/bullet_trait.md
index 9253b3a6311a..8081843bd000 100644
--- a/code/datums/elements/bullet_trait/bullet_trait.md
+++ b/code/datums/elements/bullet_trait/bullet_trait.md
@@ -1,7 +1,7 @@
# A PROTOTYPE FOR MAKING ANY BULLET TRAITS
Element representing traits that can be applied to bullets upon being fired
-* Must be attached to a projectile (`/obj/item/projectile` in `projectile.dm`)
+* Must be attached to a projectile (`/obj/projectile` in `projectile.dm`)
* Allows for the customization of bullet behavior based on ammo types or guns (or other things)
By convention, bullet_traits should be named bullet_trait_[insert rest of name here]
@@ -16,7 +16,7 @@ By convention, bullet_traits should be named bullet_trait_[insert rest of name h
/datum/element/bullet_trait/databaseAttach(datum/target)
. = ..()
// All bullet traits can only be applied to projectiles
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
[handling here]
diff --git a/code/datums/elements/bullet_trait/damage_boost.dm b/code/datums/elements/bullet_trait/damage_boost.dm
index 1d93851dd73d..a0370f2d36b6 100644
--- a/code/datums/elements/bullet_trait/damage_boost.dm
+++ b/code/datums/elements/bullet_trait/damage_boost.dm
@@ -44,7 +44,7 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))
*/
/datum/element/bullet_trait_damage_boost/Attach(datum/target, damage_mult, list/damage_boosted_atoms)
. = ..()
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
src.damage_mult = damage_mult
@@ -66,7 +66,7 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))
//add more cases for other interactions (switch doesn't seem to work with istype)
else return 0
-/datum/element/bullet_trait_damage_boost/proc/handle_bullet(obj/item/projectile/P, atom/A)
+/datum/element/bullet_trait_damage_boost/proc/handle_bullet(obj/projectile/P, atom/A)
SIGNAL_HANDLER
atom_type = check_type(A)
diff --git a/code/datums/elements/bullet_trait/iff.dm b/code/datums/elements/bullet_trait/iff.dm
index bd08c100d0f4..ab48b29f4812 100644
--- a/code/datums/elements/bullet_trait/iff.dm
+++ b/code/datums/elements/bullet_trait/iff.dm
@@ -1,5 +1,5 @@
/// This is the iff_group
-/obj/item/projectile/var/runtime_iff_group
+/obj/projectile/var/runtime_iff_group
/datum/element/bullet_trait_iff
// General bullet trait vars
@@ -13,7 +13,7 @@
/datum/element/bullet_trait_iff/Attach(datum/target, iff_group)
. = ..()
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
if(!iff_group)
@@ -39,7 +39,7 @@
/datum/element/bullet_trait_iff/proc/set_iff(datum/target, mob/living/carbon/human/firer)
SIGNAL_HANDLER
- var/obj/item/projectile/P = target
+ var/obj/projectile/P = target
P.runtime_iff_group = get_user_iff_group(firer)
// We have a "cache" to avoid getting ID card iff every shot,
diff --git a/code/datums/elements/bullet_trait/ignored_range.dm b/code/datums/elements/bullet_trait/ignored_range.dm
index 668e5dab2dd7..3910fb400bdb 100644
--- a/code/datums/elements/bullet_trait/ignored_range.dm
+++ b/code/datums/elements/bullet_trait/ignored_range.dm
@@ -12,7 +12,7 @@
/datum/element/bullet_trait_ignored_range/Attach(datum/target, range_to_ignore)
. = ..()
ignored_range = range_to_ignore
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_BULLET_CHECK_MOB_SKIPPING, PROC_REF(check_distance))
@@ -22,7 +22,7 @@
return ..()
-/datum/element/bullet_trait_ignored_range/proc/check_distance(obj/item/projectile/P, mob/living/carbon/human/projectile_target)
+/datum/element/bullet_trait_ignored_range/proc/check_distance(obj/projectile/P, mob/living/carbon/human/projectile_target)
SIGNAL_HANDLER
if(P.distance_travelled <= ignored_range)
diff --git a/code/datums/elements/bullet_trait/incendiary.dm b/code/datums/elements/bullet_trait/incendiary.dm
index c7f6e75e8e3b..2d5d0a15f368 100644
--- a/code/datums/elements/bullet_trait/incendiary.dm
+++ b/code/datums/elements/bullet_trait/incendiary.dm
@@ -8,7 +8,7 @@
/datum/element/bullet_trait_incendiary/Attach(datum/target, reagent = /datum/reagent/napalm/ut, stacks = 20)
. = ..()
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
if(ispath(reagent))
diff --git a/code/datums/elements/bullet_trait/penetrating/heavy.dm b/code/datums/elements/bullet_trait/penetrating/heavy.dm
new file mode 100644
index 000000000000..fa41b8dcfc4e
--- /dev/null
+++ b/code/datums/elements/bullet_trait/penetrating/heavy.dm
@@ -0,0 +1,47 @@
+/datum/element/bullet_trait_penetrating/heavy
+ // Generic bullet trait vars
+ element_flags = ELEMENT_DETACH|ELEMENT_BESPOKE
+ id_arg_index = 3
+
+ /// For every turf this pierces, how much damage should this lose?
+ var/damage_lost_per_pen = 100
+ /// Typecache of things to annihilate if the bullet is on a tile with it
+ var/static/list/bullet_destroy_structures = typecacheof(list(
+ /obj/structure/surface,
+ /obj/structure/barricade,
+ ))
+
+/datum/element/bullet_trait_penetrating/heavy/Attach(datum/target, distance_loss_per_hit = 3, damage_lost_per_pen = 75)
+ . = ..()
+ if(. == ELEMENT_INCOMPATIBLE)
+ return
+
+ src.damage_lost_per_pen = damage_lost_per_pen
+
+/datum/element/bullet_trait_penetrating/heavy/handle_passthrough_movables(obj/projectile/bullet, atom/movable/hit_movable, did_hit)
+ if(did_hit)
+ var/slow_mult = 1
+ if(ismob(hit_movable))
+ var/mob/mob = hit_movable
+ if(mob.mob_size >= MOB_SIZE_BIG)
+ slow_mult = 2
+
+ bullet.distance_travelled += (distance_loss_per_hit * slow_mult)
+
+ if(is_type_in_typecache(hit_movable, bullet_destroy_structures))
+ var/obj/structure/cade = hit_movable
+ cade.deconstruct() // This bullet just tears through whatever cades you put it up against from either side
+ bullet.damage -= damage_lost_per_pen
+
+ return COMPONENT_BULLET_PASS_THROUGH
+
+/datum/element/bullet_trait_penetrating/heavy/handle_passthrough_turf(obj/projectile/bullet, turf/closed/wall/hit_wall)
+ bullet.distance_travelled += distance_loss_per_hit
+ bullet.damage -= damage_lost_per_pen
+
+ if(!istype(hit_wall))
+ return COMPONENT_BULLET_PASS_THROUGH
+
+ if(!hit_wall.hull)
+ return COMPONENT_BULLET_PASS_THROUGH
+
diff --git a/code/datums/elements/bullet_trait/penetrating.dm b/code/datums/elements/bullet_trait/penetrating/penetrating.dm
similarity index 89%
rename from code/datums/elements/bullet_trait/penetrating.dm
rename to code/datums/elements/bullet_trait/penetrating/penetrating.dm
index 00fb330a7330..d3ba8a78f7f4 100644
--- a/code/datums/elements/bullet_trait/penetrating.dm
+++ b/code/datums/elements/bullet_trait/penetrating/penetrating.dm
@@ -8,7 +8,7 @@
/datum/element/bullet_trait_penetrating/Attach(datum/target, distance_loss_per_hit = 3)
. = ..()
- if(!istype(target, /obj/item/projectile))
+ if(!istype(target, /obj/projectile))
return ELEMENT_INCOMPATIBLE
src.distance_loss_per_hit = distance_loss_per_hit
@@ -27,13 +27,13 @@
))
return ..()
-/datum/element/bullet_trait_penetrating/proc/handle_passthrough_movables(obj/item/projectile/P, atom/movable/A, did_hit)
+/datum/element/bullet_trait_penetrating/proc/handle_passthrough_movables(obj/projectile/P, atom/movable/A, did_hit)
SIGNAL_HANDLER
if(did_hit)
P.distance_travelled += distance_loss_per_hit
return COMPONENT_BULLET_PASS_THROUGH
-/datum/element/bullet_trait_penetrating/proc/handle_passthrough_turf(obj/item/projectile/P, turf/closed/wall/T)
+/datum/element/bullet_trait_penetrating/proc/handle_passthrough_turf(obj/projectile/P, turf/closed/wall/T)
SIGNAL_HANDLER
P.distance_travelled += distance_loss_per_hit
diff --git a/code/datums/elements/light_blocking.dm b/code/datums/elements/light_blocking.dm
new file mode 100644
index 000000000000..9fef194f1cd4
--- /dev/null
+++ b/code/datums/elements/light_blocking.dm
@@ -0,0 +1,43 @@
+/**
+ * Attached to movable atoms with opacity. Listens to them move and updates their old and new turf loc's opacity accordingly.
+ */
+/datum/element/light_blocking
+ element_flags = ELEMENT_DETACH
+
+
+/datum/element/light_blocking/Attach(datum/target)
+ . = ..()
+ if(!ismovable(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_move))
+ var/atom/movable/movable_target = target
+ if(!isturf(movable_target.loc))
+ return
+ for(var/turf/turf_loc as anything in movable_target.locs)
+ turf_loc.add_opacity_source(target)
+
+
+/datum/element/light_blocking/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED))
+ var/atom/movable/movable_target = target
+ if(!isturf(movable_target.loc))
+ return
+ for(var/turf/turf_loc as anything in movable_target.locs)
+ turf_loc.remove_opacity_source(target)
+
+
+///Updates old and new turf loc opacities.
+///Updates old and new turf loc opacities.
+/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/old_loc, dir, forced, list/old_locs)
+ SIGNAL_HANDLER
+ if(isturf(old_loc))
+ if(old_locs)
+ for(var/turf/old_turf as anything in old_locs)
+ old_turf.remove_opacity_source(source)
+ else
+ var/turf/old_turf = old_loc
+ old_turf.remove_opacity_source(source)
+ if(isturf(source.loc))
+ for(var/turf/new_turf as anything in source.locs)
+ new_turf.add_opacity_source(source)
diff --git a/code/datums/emergency_calls/cryo_marines.dm b/code/datums/emergency_calls/cryo_marines.dm
index e7dcba08ed61..7ed61852e9bf 100644
--- a/code/datums/emergency_calls/cryo_marines.dm
+++ b/code/datums/emergency_calls/cryo_marines.dm
@@ -1,13 +1,12 @@
-//whiskey outpost extra marines
/datum/emergency_call/cryo_squad
name = "Marine Cryo Reinforcements (Squad)"
mob_max = 10
mob_min = 1
probability = 0
objectives = "Assist the USCM forces"
- max_engineers = 4
+ max_engineers = 2
max_medics = 2
name_of_spawn = /obj/effect/landmark/ert_spawns/distress_cryo
shuttle_id = ""
@@ -95,3 +94,10 @@
/obj/effect/landmark/ert_spawns/distress_cryo
name = "Distress_Cryo"
+
+/datum/emergency_call/cryo_squad/tech
+ name = "Marine Cryo Reinforcements (Tech)"
+ mob_max = 5
+ max_engineers = 1
+ max_medics = 1
+ max_heavies = 0
diff --git a/code/datums/emergency_calls/cryo_spec.dm b/code/datums/emergency_calls/cryo_spec.dm
new file mode 100644
index 000000000000..6cc7c905efbc
--- /dev/null
+++ b/code/datums/emergency_calls/cryo_spec.dm
@@ -0,0 +1,43 @@
+/datum/emergency_call/cryo_spec
+ name = "Marine Cryo Reinforcement (Spec)"
+ mob_max = 1
+ mob_min = 1
+ probability = 0
+ objectives = "Assist the USCM forces"
+ name_of_spawn = /obj/effect/landmark/ert_spawns/distress_cryo
+ shuttle_id = ""
+ spawn_max_amount = TRUE
+
+/datum/emergency_call/cryo_spec/create_member(datum/mind/mind, turf/override_spawn_loc)
+ set waitfor = FALSE
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_WHISKEY_OUTPOST)
+ name_of_spawn = /obj/effect/landmark/ert_spawns/distress_wo
+ var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point()
+
+ if(!istype(spawn_loc))
+ return //Didn't find a useable spawn point.
+
+ var/mob/living/carbon/human/human = new(spawn_loc)
+
+ if(mind)
+ mind.transfer_to(human, TRUE)
+ else
+ human.create_hud()
+
+ if(!mind)
+ for(var/obj/structure/machinery/cryopod/pod in view(7,human))
+ if(pod && !pod.occupant)
+ pod.go_in_cryopod(human, silent = TRUE)
+ break
+
+ sleep(5)
+ human.client?.prefs.copy_all_to(human, JOB_SQUAD_SPECIALIST, TRUE, TRUE)
+ arm_equipment(human, /datum/equipment_preset/uscm/spec/cryo, mind == null, TRUE)
+ to_chat(human, SPAN_ROLE_HEADER("You are a Weapons Specialist in the USCM"))
+ to_chat(human, SPAN_ROLE_BODY("Your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to the chain of command."))
+ to_chat(human, SPAN_BOLDWARNING("If you wish to cryo or ghost upon spawning in, you must ahelp and inform staff so you can be replaced."))
+
+ sleep(10)
+ if(!mind)
+ human.free_for_ghosts()
+ to_chat(human, SPAN_BOLD("Objectives: [objectives]"))
diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm
index 3d43917b2bc7..390a8cfd5d61 100644
--- a/code/datums/emergency_calls/emergency_call.dm
+++ b/code/datums/emergency_calls/emergency_call.dm
@@ -8,12 +8,19 @@
/datum/game_mode
var/list/datum/emergency_call/all_calls = list() //initialized at round start and stores the datums.
var/datum/emergency_call/picked_calls[] = list() //Which distress calls are currently active
+ var/ert_dispatched = FALSE
/datum/game_mode/proc/ares_online()
var/name = "ARES Online"
var/input = "ARES. Online. Good morning, marines."
shipwide_ai_announcement(input, name, 'sound/AI/ares_online.ogg')
+/datum/game_mode/proc/request_ert(user, ares = FALSE)
+ if(!user)
+ return FALSE
+ message_admins("[key_name(user)] has requested a Distress Beacon! [ares ? SPAN_ORANGE("(via ARES)") : ""] ([SSticker.mode.ert_dispatched ? SPAN_RED("A random ERT was dispatched previously.") : SPAN_GREEN("No previous random ERT dispatched.")]) [CC_MARK(user)] (SEND) (DENY) [ADMIN_JMP_USER(user)] [CC_REPLY(user)]")
+ return TRUE
+
//The distress call parent. Cannot be called itself due to "name" being a filtered target.
/datum/emergency_call
var/name = "name"
@@ -106,6 +113,7 @@
give_action(M, /datum/action/join_ert, src)
/datum/game_mode/proc/activate_distress()
+ ert_dispatched = TRUE
var/datum/emergency_call/random_call = get_random_call()
if(!istype(random_call, /datum/emergency_call)) //Something went horribly wrong
return
@@ -147,7 +155,6 @@
var/choice = tgui_input_list(src, "Choose a distress beacon to join", "", beacons)
if(!choice)
- to_chat(src, "Something seems to have gone wrong!")
return
if(!beacons[choice] || !(beacons[choice] in SSticker.mode.picked_calls))
diff --git a/code/datums/emergency_calls/royal_marines.dm b/code/datums/emergency_calls/royal_marines.dm
new file mode 100644
index 000000000000..b3feaccf87bb
--- /dev/null
+++ b/code/datums/emergency_calls/royal_marines.dm
@@ -0,0 +1,75 @@
+/datum/emergency_call/royal_marines
+ name = "Royal Marines Commando (Squad) (Friendly)"
+ mob_max = 7
+ probability = 0
+ name_of_spawn = /obj/effect/landmark/ert_spawns/distress_twe
+ item_spawn = /obj/effect/landmark/ert_spawns/distress_twe/item
+ max_engineers = 0
+ max_medics = 0
+ max_heavies = 3
+
+/datum/emergency_call/royal_marines/New()
+ ..()
+ arrival_message = "[MAIN_SHIP_NAME], this is [pick_weight(list("HMS Patna"= 50, "HMS Thunderchild" = 50))]; we are responding to your distress call and boarding in accordance with the Military Aid Act of 2177, Authentication code Lima-18153. "
+ objectives = "Ensure the survival of the [MAIN_SHIP_NAME], eliminate any hostiles, and assist the crew in any way possible."
+
+
+/datum/emergency_call/royal_marines/create_member(datum/mind/spawning_mind, turf/override_spawn_loc)
+ var/turf/spawn_loc = override_spawn_loc ? override_spawn_loc : get_spawn_point()
+
+ if(!istype(spawn_loc))
+ return //Didn't find a useable spawn point.
+
+ var/mob/living/carbon/human/mob = new(spawn_loc)
+ spawning_mind.transfer_to(mob, TRUE)
+
+ if(!leader && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_LEADER) && check_timelock(mob.client, JOB_SQUAD_LEADER, time_required_for_job))
+ leader = mob
+ to_chat(mob, SPAN_ROLE_HEADER("You are an Officer in the Royal Marines Commando. Born in the Three World Empire."))
+ arm_equipment(mob, /datum/equipment_preset/twe/royal_marine/team_leader, TRUE, TRUE)
+ else if(heavies < max_heavies && HAS_FLAG(mob.client.prefs.toggles_ert, PLAY_HEAVY) && check_timelock(mob.client, JOB_SQUAD_SPECIALIST))
+ var/specialist_kit = pick("Sniper", "Smartgun", "Breach")
+ switch(specialist_kit)
+ if("Sniper")
+ to_chat(mob, SPAN_ROLE_HEADER("You are a skilled marksman in the Royal Marines Commando. Born in the Three World Empire."))
+ arm_equipment(mob, /datum/equipment_preset/twe/royal_marine/spec/marksman, TRUE, TRUE)
+ if("Smartgun")
+ to_chat(mob, SPAN_ROLE_HEADER("You are a Smartgunner in the Royal Marines Commando. Born in the Three World Empire."))
+ arm_equipment(mob, /datum/equipment_preset/twe/royal_marine/spec/machinegun, TRUE, TRUE)
+ if("Breach")
+ to_chat(mob, SPAN_ROLE_HEADER("You are a CQB Specialist in the Royal Marines Commando. Born in the Three World Empire."))
+ arm_equipment(mob, /datum/equipment_preset/twe/royal_marine/spec/breacher, TRUE, TRUE)
+ heavies++
+ else
+ to_chat(mob, SPAN_ROLE_HEADER("You are a member of the Royal Marines Commando. Born in the three world empire."))
+ arm_equipment(mob, /datum/equipment_preset/twe/royal_marine/standard, TRUE, TRUE)
+
+ print_backstory(mob)
+
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS)
+
+
+/datum/emergency_call/royal_marines/print_backstory(mob/living/carbon/human/spawning_mob)
+ to_chat(spawning_mob, SPAN_BOLD("You were born in the Three World Empire to a [pick_weight(list("average" = 75, "poor" = 15, "well-established" = 10))] family."))
+ to_chat(spawning_mob, SPAN_BOLD("Joining the Royal Marines gave you a lot of combat experience and useful skills."))
+ to_chat(spawning_mob, SPAN_BOLD("You are [pick_weight(list("unaware" = 75, "faintly aware" = 15, "knoledgeable" = 10))] of the xenomorph threat."))
+ to_chat(spawning_mob, SPAN_BOLD("You are a citizen of the three world empire and joined the Royal Marines Commando"))
+ to_chat(spawning_mob, SPAN_BOLD("You are apart of a jointed UA/TWE taskforce onboard the HMS Patna and Thunderchild."))
+ to_chat(spawning_mob, SPAN_BOLD("Under the directive of the RMC high command, you have been assisting USCM forces with maintaining peace in the area."))
+ to_chat(spawning_mob, SPAN_BOLD("Assist the USCMC Force of the [MAIN_SHIP_NAME] however you can."))
+
+/datum/emergency_call/royal_marines/platoon
+ name = "Royal Marines Commando (Platoon) (Friendly)"
+ mob_min = 7
+ mob_max = 28
+ probability = 0
+ max_medics = 0
+ max_heavies = 6
+ max_engineers = 0
+
+/obj/effect/landmark/ert_spawns/distress_twe
+ name = "Distress_TWE"
+
+/obj/effect/landmark/ert_spawns/distress_twe/item
+ name = "Distress_TWEItem"
+
diff --git a/code/datums/emergency_calls/upp.dm b/code/datums/emergency_calls/upp.dm
index 94d4bf2a0ab6..04bcfecf9128 100644
--- a/code/datums/emergency_calls/upp.dm
+++ b/code/datums/emergency_calls/upp.dm
@@ -77,14 +77,14 @@
var/equipment_path = /datum/equipment_preset/upp/specialist
if(heavy_pick)
if(HAS_FLAG(H.client.prefs.toggles_ert, PLAY_HEAVY) && HAS_FLAG(H.client.prefs.toggles_ert, PLAY_SMARTGUNNER))
- equipment_path = pick(/datum/equipment_preset/upp/specialist, /datum/equipment_preset/upp/minigunner)
+ equipment_path = pick(/datum/equipment_preset/upp/specialist, /datum/equipment_preset/upp/machinegunner)
else if(HAS_FLAG(H.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && !HAS_FLAG(H.client.prefs.toggles_ert, PLAY_HEAVY))
- equipment_path = /datum/equipment_preset/upp/minigunner
+ equipment_path = /datum/equipment_preset/upp/machinegunner
arm_equipment(H, equipment_path, TRUE, TRUE)
else if(smartgunners < max_smartgunners && HAS_FLAG(H.client.prefs.toggles_ert, PLAY_SMARTGUNNER) && check_timelock(H.client, JOB_SQUAD_SMARTGUN, time_required_for_job))
smartgunners++
to_chat(H, SPAN_ROLE_HEADER("You are a sergeant of the Union of Progressive People, a powerful socialist state that rivals the United Americas!"))
- arm_equipment(H, /datum/equipment_preset/upp/minigunner, TRUE, TRUE)
+ arm_equipment(H, /datum/equipment_preset/upp/machinegunner, TRUE, TRUE)
else
to_chat(H, SPAN_ROLE_HEADER("You are a soldier of the Union of Progressive People, a powerful socialist state that rivals the United Americas!"))
arm_equipment(H, /datum/equipment_preset/upp/soldier, TRUE, TRUE)
diff --git a/code/datums/entities/player_note.dm b/code/datums/entities/player_note.dm
index 420bb5f0a470..216e20b40701 100644
--- a/code/datums/entities/player_note.dm
+++ b/code/datums/entities/player_note.dm
@@ -94,4 +94,4 @@ BSQL_PROTECT_DATUM(/datum/entity/player_note)
/// Returns all notes associated with a CKEY, structured as a list of strings.
/proc/get_all_notes(player_ckey)
for(var/datum/view_record/note_view/note in DB_VIEW(/datum/view_record/note_view, DB_COMP("player_ckey", DB_EQUALS, player_ckey)))
- LAZYADDASSOC(., "[note.note_category]", "\"[note.text]\", by [note.admin_ckey] ([note.admin_rank]) on [note.date] ([note.round_id])")
+ LAZYADDASSOCLIST(., "[note.note_category]", "\"[note.text]\", by [note.admin_ckey] ([note.admin_rank]) on [note.date] ([note.round_id])")
diff --git a/code/datums/factions/clf.dm b/code/datums/factions/clf.dm
index 38e0d576f805..ce53b505b352 100644
--- a/code/datums/factions/clf.dm
+++ b/code/datums/factions/clf.dm
@@ -31,12 +31,12 @@
list("PRIMARY FIREARMS", 0, null, null, null),
list("ABR-40 Hunting Rifle", 30, /obj/item/weapon/gun/rifle/l42a/abr40, null, VENDOR_ITEM_REGULAR),
list("Basira-Armstrong Bolt-Action", 15, /obj/item/weapon/gun/boltaction, null, VENDOR_ITEM_REGULAR),
- list("CZ-81 Machine Pistol", 20, /obj/item/ammo_magazine/pistol/skorpion, null, VENDOR_ITEM_REGULAR),
list("Double Barrel Shotgun", 30, /obj/item/weapon/gun/shotgun/double, null, VENDOR_ITEM_REGULAR),
list("HG 37-12 Pump Shotgun", 30, /obj/item/weapon/gun/shotgun/double/sawn, null, VENDOR_ITEM_REGULAR),
list("M16 Rifle", 30, /obj/item/weapon/gun/rifle/m16, null, VENDOR_ITEM_REGULAR),
list("MAR-30 Battle Carbine", 30, /obj/item/weapon/gun/rifle/mar40/carbine, null, VENDOR_ITEM_REGULAR),
list("MAR-40 Battle Rifle", 30, /obj/item/weapon/gun/rifle/mar40, null, VENDOR_ITEM_REGULAR),
+ list("Type-64 Submachinegun", 20, /obj/item/weapon/gun/smg/bizon, null, VENDOR_ITEM_REGULAR),
list("MAC-15 Submachinegun", 20, /obj/item/weapon/gun/smg/mac15, null, VENDOR_ITEM_REGULAR),
list("MP27 Submachinegun", 20, /obj/item/weapon/gun/smg/mp27, null, VENDOR_ITEM_REGULAR),
list("MP5 Submachinegun", 20, /obj/item/weapon/gun/smg/mp5, null, VENDOR_ITEM_REGULAR),
@@ -48,12 +48,12 @@
list("Box Of Buckshot Shells", 10, /obj/item/ammo_magazine/shotgun/buckshot, null, VENDOR_ITEM_REGULAR),
list("Box Of Flechette Shells", 10, /obj/item/ammo_magazine/shotgun/flechette, null, VENDOR_ITEM_REGULAR),
list("Box Of Shotgun Slugs", 10, /obj/item/ammo_magazine/shotgun, null, VENDOR_ITEM_REGULAR),
- list("CZ-81 Magazine (.32ACP)", 5, /obj/item/ammo_magazine/pistol/skorpion, null, VENDOR_ITEM_REGULAR),
list("M16 AP Magazine (5.56x45mm)", 15, /obj/item/ammo_magazine/rifle/m16/ap, null, VENDOR_ITEM_REGULAR),
list("M16 Magazine (5.56x45mm)", 5, /obj/item/ammo_magazine/rifle/m16, null, VENDOR_ITEM_REGULAR),
list("MAC-15 Magazine (9mm)", 5, /obj/item/ammo_magazine/smg/mac15, null, VENDOR_ITEM_REGULAR),
list("MAR Magazine (7.62x39mm)", 5, /obj/item/ammo_magazine/rifle/mar40, null, VENDOR_ITEM_REGULAR),
list("MAR Extended Magazine (7.62x39mm)", 15, /obj/item/ammo_magazine/rifle/mar40/extended, null, VENDOR_ITEM_REGULAR),
+ list("Type-64 Helical Magazine (.7.62x19mm)", 5, /obj/item/ammo_magazine/smg/bizon, null, VENDOR_ITEM_REGULAR),
list("MP27 Magazine (4.6x30mm)", 5, /obj/item/ammo_magazine/smg/mp27, null, VENDOR_ITEM_REGULAR),
list("MP5 Magazine (9mm)", 5, /obj/item/ammo_magazine/smg/mp5, null, VENDOR_ITEM_REGULAR),
@@ -99,13 +99,13 @@
list("PRIMARY FIREARMS", -1, null, null),
list("ABR-40 Hunting Rifle", 30, /obj/item/weapon/gun/rifle/l42a/abr40, null, VENDOR_ITEM_REGULAR),
list("Basira-Armstrong Bolt-Action", 15, /obj/item/weapon/gun/boltaction, null, VENDOR_ITEM_REGULAR),
- list("CZ-81 Machine Pistol", 20, /obj/item/ammo_magazine/pistol/skorpion, VENDOR_ITEM_REGULAR),
list("Double Barrel Shotgun", 20, /obj/item/weapon/gun/shotgun/double, VENDOR_ITEM_REGULAR),
list("HG 37-12 Pump Shotgun", 20, /obj/item/weapon/gun/shotgun/double/sawn, VENDOR_ITEM_REGULAR),
list("M16 Rifle", 20, /obj/item/weapon/gun/rifle/m16, VENDOR_ITEM_REGULAR),
list("MAC-15 Submachinegun", 20, /obj/item/weapon/gun/smg/mac15, VENDOR_ITEM_REGULAR),
list("MAR-30 Battle Carbine", 20, /obj/item/weapon/gun/rifle/mar40/carbine, VENDOR_ITEM_REGULAR),
list("MAR-40 Battle Rifle", 20, /obj/item/weapon/gun/rifle/mar40, VENDOR_ITEM_REGULAR),
+ list("Type 64 Submachinegun", 20, /obj/item/weapon/gun/smg/bizon, VENDOR_ITEM_REGULAR),
list("MP27 Submachinegun", 20, /obj/item/weapon/gun/smg/mp27, VENDOR_ITEM_REGULAR),
list("MP5 Submachinegun", 20, /obj/item/weapon/gun/smg/mp5, VENDOR_ITEM_REGULAR),
list("Sawn-Off Shotgun", 20, /obj/item/weapon/gun/shotgun/pump/dual_tube/cmb, VENDOR_ITEM_REGULAR),
@@ -116,12 +116,12 @@
list("Box Of Buckshot Shells", 15, /obj/item/ammo_magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR),
list("Box Of Flechette Shells", 15, /obj/item/ammo_magazine/shotgun/flechette, VENDOR_ITEM_REGULAR),
list("Box Of Shotgun Slugs", 15, /obj/item/ammo_magazine/shotgun, VENDOR_ITEM_REGULAR),
- list("CZ-81 Magazine (.32ACP)", 60, /obj/item/ammo_magazine/pistol/skorpion, VENDOR_ITEM_REGULAR),
list("M16 AP Magazine (5.56x45mm)", 10, /obj/item/ammo_magazine/rifle/m16/ap, VENDOR_ITEM_REGULAR),
list("M16 Magazine (5.56x45mm)", 60, /obj/item/ammo_magazine/rifle/m16, VENDOR_ITEM_REGULAR),
list("MAC-15 Magazine (9mm)", 60, /obj/item/ammo_magazine/smg/mac15, VENDOR_ITEM_REGULAR),
list("MAR Magazine (7.62x39mm)", 60, /obj/item/ammo_magazine/rifle/mar40, VENDOR_ITEM_REGULAR),
list("MAR Extended Magazine (7.62x39mm)", 10, /obj/item/ammo_magazine/rifle/mar40/extended, VENDOR_ITEM_REGULAR),
+ list("Type 64 Helical Magazine (7.62x19mm)", 60, /obj/item/ammo_magazine/smg/bizon, VENDOR_ITEM_REGULAR),
list("MP27 Magazine (4.6x30mm)", 60, /obj/item/ammo_magazine/smg/mp27, VENDOR_ITEM_REGULAR),
list("MP5 Magazine (9mm)", 60, /obj/item/ammo_magazine/smg/mp5, VENDOR_ITEM_REGULAR),
diff --git a/code/datums/factions/royalmarinescommando.dm b/code/datums/factions/royalmarinescommando.dm
new file mode 100644
index 000000000000..2fab0348bcfa
--- /dev/null
+++ b/code/datums/factions/royalmarinescommando.dm
@@ -0,0 +1,94 @@
+/datum/faction/royal_marines_commando
+ name = "Royal Marines Commando"
+ faction_tag = FACTION_TWE
+
+/datum/faction/royal_marines_commando/modify_hud_holder(image/holder, mob/living/carbon/human/H)
+ var/hud_icon_state
+ var/obj/item/card/id/dogtag/ID = H.get_idcard()
+ var/_role
+ if(H.mind)
+ _role = H.job
+ else if(ID)
+ _role = ID.rank
+ switch(_role)
+ if(JOB_TWE_RMC_LIEUTENANT)
+ hud_icon_state = "lieutenant"
+ if(JOB_TWE_RMC_TEAMLEADER)
+ hud_icon_state = "teamleader"
+ if(JOB_TWE_RMC_MARKSMAN)
+ hud_icon_state = "marksman"
+ if(JOB_TWE_RMC_RIFLEMAN)
+ hud_icon_state = "rifleman"
+ if(JOB_TWE_RMC_SMARTGUNNER)
+ hud_icon_state = "smartgunner"
+ if(JOB_TWE_RMC_BREACHER)
+ hud_icon_state = "breacher"
+ if(hud_icon_state)
+ holder.overlays += image('icons/mob/hud/marine_hud.dmi', H, "rmc_[hud_icon_state]")
+
+/datum/faction/royal_marines_commando/get_antag_guns_snowflake_equipment()
+ return list(
+ list("PRIMARY FIREARMS", 0, null, null, null),
+ list("F903A1 Rifle", 20, /obj/item/weapon/gun/rifle/rmc_f90, null, VENDOR_ITEM_REGULAR),
+ list("F903A2 Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/a_grip, null, VENDOR_ITEM_REGULAR),
+ list("F903A1 Marksman Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/scope, null, VENDOR_ITEM_REGULAR),
+ list("F903A1/B 'Breacher' Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/shotgun, null, VENDOR_ITEM_REGULAR),
+
+ list("PRIMARY AMMUNITION", 0, null, null, null),
+ list("F903 Magazine (10x24mm)", 5, /obj/item/ammo_magazine/rifle/rmc_f90, null, VENDOR_ITEM_REGULAR),
+ list("F903A1 Marksman Magazine (10x24mm)", 15, /obj/item/ammo_magazine/rifle/rmc_f90/marksman, null, VENDOR_ITEM_REGULAR),
+
+ list("SIDEARMS", 0, null, null, null),
+ list("VP78 Pistol", 20, /obj/item/weapon/gun/pistol/vp78, null, VENDOR_ITEM_REGULAR),
+ list("88 Mod 4 Combat Pistol", 15, /obj/item/weapon/gun/pistol/mod88, null, VENDOR_ITEM_REGULAR),
+
+ list("SIDEARM AMMUNITION", 0, null, null, null),
+ list("VP78 magazine (9mm)", 5, /obj/item/ammo_magazine/pistol/vp78, null, VENDOR_ITEM_REGULAR),
+ list("88M4 AP Magazine (9mm)", 5, /obj/item/ammo_magazine/pistol/mod88, null, VENDOR_ITEM_REGULAR),
+
+ list("ATTACHMENTS", 0, null, null, null),
+ list("Angled Grip", 15, /obj/item/attachable/angledgrip, null, VENDOR_ITEM_REGULAR),
+ list("Burst Fire Assembly", 15, /obj/item/attachable/burstfire_assembly, null, VENDOR_ITEM_REGULAR),
+ list("Extended Barrel", 15, /obj/item/attachable/extended_barrel, null, VENDOR_ITEM_REGULAR),
+ list("Laser Sight", 15, /obj/item/attachable/lasersight, null, VENDOR_ITEM_REGULAR),
+ list("Rail Flashlight", 5, /obj/item/attachable/flashlight, null, VENDOR_ITEM_REGULAR),
+ list("Red-Dot Sight", 15, /obj/item/attachable/reddot, null, VENDOR_ITEM_REGULAR),
+ list("Reflex Sight", 15, /obj/item/attachable/reflex, null, VENDOR_ITEM_REGULAR),
+ list("Suppressor", 15, /obj/item/attachable/suppressor, null, VENDOR_ITEM_REGULAR),
+ list("Vertical Grip", 15, /obj/item/attachable/verticalgrip, null, VENDOR_ITEM_REGULAR),
+
+ list("UTILITIES", 0, null, null, null),
+ list("M94 Marking Flare Pack", 3, /obj/item/storage/box/m94, null, VENDOR_ITEM_RECOMMENDED),
+ list("Smoke Grenade", 7, /obj/item/explosive/grenade/smokebomb, null, VENDOR_ITEM_REGULAR),
+ list("R2175/B HIDP grenade packet", 7, /obj/item/storage/box/packet/rmc/incin, null, VENDOR_ITEM_REGULAR),
+ list("R2175/A HEDP grenade packet", 7, /obj/item/storage/box/packet/rmc/he, null, VENDOR_ITEM_REGULAR),
+ list("L5 bayonet", 3, /obj/item/attachable/bayonet/rmc, null, VENDOR_ITEM_REGULAR),
+ )
+
+/datum/faction/royal_marines_commando/get_antag_guns_sorted_equipment()
+ return list(
+ list("PRIMARY FIREARMS", -1, null, null),
+ list("F903A1 Rifle", 20, /obj/item/weapon/gun/rifle/rmc_f90, null, VENDOR_ITEM_REGULAR),
+ list("F903A2 Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/a_grip, null, VENDOR_ITEM_REGULAR),
+ list("F903A1 Marksman Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/scope, null, VENDOR_ITEM_REGULAR),
+ list("F903A1/B 'Breacher' Rifle", 30, /obj/item/weapon/gun/rifle/rmc_f90/shotgun, null, VENDOR_ITEM_REGULAR),
+
+ list("PRIMARY AMMUNITION", -1, null, null),
+ list("F903 Magazine (10x24mm)", 5, /obj/item/ammo_magazine/rifle/rmc_f90, null, VENDOR_ITEM_REGULAR),
+ list("F903A1 Marksman Magazine (10x24mm)", 15, /obj/item/ammo_magazine/rifle/rmc_f90/marksman, null, VENDOR_ITEM_REGULAR),
+
+ list("SIDEARMS", -1, null, null),
+ list("VP78 Pistol", 20, /obj/item/weapon/gun/pistol/vp78, null, VENDOR_ITEM_REGULAR),
+ list("88 Mod 4 Combat Pistol", 15, /obj/item/weapon/gun/pistol/mod88, null, VENDOR_ITEM_REGULAR),
+
+ list("SIDEARM AMMUNITION", -1, null, null),
+ list("VP78 magazine (9mm)", 5, /obj/item/ammo_magazine/pistol/vp78, null, VENDOR_ITEM_REGULAR),
+ list("88M4 AP Magazine (9mm)", 5, /obj/item/ammo_magazine/pistol/mod88, null, VENDOR_ITEM_REGULAR),
+
+ list("UTILITIES", -1, null, null),
+ list("M94 Marking Flare Pack", 3, /obj/item/storage/box/m94, null, VENDOR_ITEM_RECOMMENDED),
+ list("Smoke Grenade", 7, /obj/item/explosive/grenade/smokebomb, null, VENDOR_ITEM_REGULAR),
+ list("R2175/B HIDP grenade packet", 7, /obj/item/storage/box/packet/rmc/incin, null, VENDOR_ITEM_REGULAR),
+ list("R2175/A HEDP grenade packet", 7, /obj/item/storage/box/packet/rmc/he, null, VENDOR_ITEM_REGULAR),
+ list("L5 bayonet", 3, /obj/item/attachable/bayonet/rmc, null, VENDOR_ITEM_REGULAR),
+ )
diff --git a/code/datums/factions/upp.dm b/code/datums/factions/upp.dm
index a5a89cfd0a80..9f28e5967831 100644
--- a/code/datums/factions/upp.dm
+++ b/code/datums/factions/upp.dm
@@ -47,24 +47,24 @@
/datum/faction/upp/get_antag_guns_snowflake_equipment()
return list(
list("PRIMARY FIREARMS", 0, null, null, null),
- list("CZ-81 Machine Pistol", 20, /obj/item/weapon/gun/pistol/skorpion/upp, null, VENDOR_ITEM_REGULAR),
+ list("Type 64 Submachinegun", 20, /obj/item/weapon/gun/smg/bizon/upp, null, VENDOR_ITEM_REGULAR),
list("Type 71 Pulse Rifle", 30, /obj/item/weapon/gun/rifle/type71, null, VENDOR_ITEM_REGULAR),
list("Type 71 Pulse Rifle Carbine", 30, /obj/item/weapon/gun/rifle/type71/carbine, null, VENDOR_ITEM_REGULAR),
list("PRIMARY AMMUNITION", 0, null, null, null),
- list("CZ-81 Magazine (.32ACP)", 5, /obj/item/ammo_magazine/pistol/skorpion, null, VENDOR_ITEM_REGULAR),
+ list("Type 64 Helical Magazine (7.62x19mm)", 5, /obj/item/ammo_magazine/smg/bizon, null, VENDOR_ITEM_REGULAR),
list("Type 71 AP Magazine (5.45x39mm)", 15, /obj/item/ammo_magazine/rifle/type71/ap, null, VENDOR_ITEM_REGULAR),
list("Type 71 Magazine (5.45x39mm)", 5, /obj/item/ammo_magazine/rifle/type71, null, VENDOR_ITEM_REGULAR),
list("SIDEARMS", 0, null, null, null),
- list("Highpower Automag", 15, /obj/item/weapon/gun/pistol/highpower, null, VENDOR_ITEM_REGULAR),
- list("Korovin PK-9 Pistol", 15, /obj/item/weapon/gun/pistol/c99/upp, null, VENDOR_ITEM_REGULAR),
- list("N-Y 7.62mm Revolver", 15, /obj/item/weapon/gun/revolver/nagant, null, VENDOR_ITEM_REGULAR),
+ list("Type 73 Pistol", 25, /obj/item/weapon/gun/pistol/t73, null, VENDOR_ITEM_REGULAR),
+ list("NP92 Pistol", 15, /obj/item/weapon/gun/pistol/np92, null, VENDOR_ITEM_REGULAR),
+ list("ZHNK-72 Revolver", 15, /obj/item/weapon/gun/revolver/upp, null, VENDOR_ITEM_REGULAR),
list("SIDEARM AMMUNITION", 0, null, null, null),
- list("Highpower Magazine (9mm)", 5, /obj/item/ammo_magazine/pistol/highpower, null, VENDOR_ITEM_REGULAR),
- list("N-Y Speed Loader (7.62x38mmR)", 5, /obj/item/ammo_magazine/revolver/upp, null, VENDOR_ITEM_REGULAR),
- list("PK-9 Magazine (.22 Hollowpoint)", 5, /obj/item/ammo_magazine/pistol/c99, null, VENDOR_ITEM_REGULAR),
+ list("Type 73 Magazine (7.62x25mm Tokarev)", 5, /obj/item/ammo_magazine/pistol/t73, null, VENDOR_ITEM_REGULAR),
+ list("ZHNK-72 Speed Loader (7.62x38mmR)", 5, /obj/item/ammo_magazine/revolver/upp, null, VENDOR_ITEM_REGULAR),
+ list("NP92 Magazine (9x18mm Makarov)", 40, /obj/item/ammo_magazine/pistol/np92, null, VENDOR_ITEM_REGULAR),
list("ATTACHMENTS", 0, null, null, null),
list("Angled Grip", 15, /obj/item/attachable/angledgrip, null, VENDOR_ITEM_REGULAR),
@@ -86,24 +86,24 @@
/datum/faction/upp/get_antag_guns_sorted_equipment()
return list(
list("PRIMARY FIREARMS", -1, null, null),
- list("CZ-81 Machine Pistol", 20, /obj/item/weapon/gun/pistol/skorpion/upp, VENDOR_ITEM_REGULAR),
+ list("Type 64 Submachinegun", 20, /obj/item/weapon/gun/smg/bizon/upp, VENDOR_ITEM_REGULAR),
list("Type 71 Pulse Rifle", 20, /obj/item/weapon/gun/rifle/type71, VENDOR_ITEM_REGULAR),
list("Type 71 Pulse Rifle Carbine", 20, /obj/item/weapon/gun/rifle/type71/carbine, VENDOR_ITEM_REGULAR),
list("PRIMARY AMMUNITION", -1, null, null),
- list("CZ-81 Magazine (.32ACP)", 60, /obj/item/ammo_magazine/pistol/skorpion, VENDOR_ITEM_REGULAR),
+ list("Type 64 Helical Magazine (7.62x19mm)", 60, /obj/item/ammo_magazine/smg/bizon, VENDOR_ITEM_REGULAR),
list("Type 71 AP Magazine (5.45x39mm)", 60, /obj/item/ammo_magazine/rifle/type71/ap, VENDOR_ITEM_REGULAR),
list("Type 71 Magazine (5.45x39mm)", 60, /obj/item/ammo_magazine/rifle/type71, VENDOR_ITEM_REGULAR),
list("SIDEARMS", -1, null, null),
- list("Highpower Automag", 20, /obj/item/weapon/gun/pistol/highpower, VENDOR_ITEM_REGULAR),
- list("Korovin PK-9 Pistol", 20, /obj/item/weapon/gun/pistol/c99/upp, VENDOR_ITEM_REGULAR),
- list("N-Y 7.62mm Revolver", 20, /obj/item/weapon/gun/revolver/nagant, VENDOR_ITEM_REGULAR),
+ list("Type 73 Pistol", 20, /obj/item/weapon/gun/pistol/t73, VENDOR_ITEM_REGULAR),
+ list("NP02 Pistol", 20, /obj/item/weapon/gun/pistol/np92, VENDOR_ITEM_REGULAR),
+ list("ZHNK-72 Revolver", 20, /obj/item/weapon/gun/revolver/upp, VENDOR_ITEM_REGULAR),
list("SIDEARM AMMUNITION", -1, null, null),
- list("Highpower Magazine (9mm)", 40, /obj/item/ammo_magazine/pistol/highpower, VENDOR_ITEM_REGULAR),
- list("N-Y Speed Loader (7.62x38mmR)", 40, /obj/item/ammo_magazine/revolver/upp, VENDOR_ITEM_REGULAR),
- list("PK-9 Magazine (.22 Hollowpoint)", 40, /obj/item/ammo_magazine/pistol/c99, VENDOR_ITEM_REGULAR),
+ list("Type 73 Magazine (7.62x25mm Tokarev)", 40, /obj/item/ammo_magazine/pistol/t73, VENDOR_ITEM_REGULAR),
+ list("ZHNK-72 Speed Loader (7.62x38mmR)", 40, /obj/item/ammo_magazine/revolver/upp, VENDOR_ITEM_REGULAR),
+ list("NP92 Magazine (9x18mm Makarov)", 40, /obj/item/ammo_magazine/pistol/np92, VENDOR_ITEM_REGULAR),
list("UTILITIES", -1, null, null),
list("M94 Marking Flare Pack", 20, /obj/item/storage/box/m94, VENDOR_ITEM_RECOMMENDED),
diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm
index aa1bc9b40783..65c5a47896fa 100644
--- a/code/datums/mob_hud.dm
+++ b/code/datums/mob_hud.dm
@@ -30,10 +30,18 @@ var/list/datum/mob_hud/huds = list(
// Stop displaying a HUD to a specific person
// (took off medical glasses)
-/datum/mob_hud/proc/remove_hud_from(mob/user)
+/datum/mob_hud/proc/remove_hud_from(mob/user, source)
+ if(length(hudusers[user]) && (source in hudusers[user]))
+ hudusers[user] -= source
+
+ if(length(hudusers[user]))
+ return FALSE
+
for(var/mob/target in hudmobs)
remove_from_single_hud(user, target)
+
hudusers -= user
+ return TRUE
// Stop rendering a HUD on a target
// "unenroll" them so to speak
@@ -53,8 +61,24 @@ var/list/datum/mob_hud/huds = list(
user.client.images -= target.clone.hud_list[i]
// Allow user to view a HUD (putting on medical glasses)
-/datum/mob_hud/proc/add_hud_to(mob/user)
+/datum/mob_hud/proc/add_hud_to(mob/user, source)
hudusers |= user
+ if(hudusers[user])
+ hudusers[user] |= list(source)
+ else
+ hudusers[user] += list(source)
+
+ for(var/mob/target in hudmobs)
+ add_to_single_hud(user, target)
+
+/// Refreshes the HUD, adding user and sources if missing and then calls to add the HUD
+/datum/mob_hud/proc/refresh_hud(mob/user, list/source)
+ hudusers |= user
+ if(hudusers[user])
+ hudusers[user] |= source
+ else
+ hudusers[user] += source
+
for(var/mob/target in hudmobs)
add_to_single_hud(user, target)
@@ -229,13 +253,13 @@ var/list/datum/mob_hud/huds = list(
for(var/datum/mob_hud/hud in huds)
if(istype(hud, /datum/mob_hud/xeno))
hud.remove_from_hud(src)
- hud.remove_hud_from(src)
+ hud.remove_hud_from(src, src)
else if (istype(hud, /datum/mob_hud/xeno_infection))
- hud.remove_hud_from(src)
+ hud.remove_hud_from(src, src)
if (xeno_hostile_hud)
xeno_hostile_hud = FALSE
var/datum/mob_hud/hostile_hud = huds[MOB_HUD_XENO_HOSTILE]
- hostile_hud.remove_hud_from(src)
+ hostile_hud.remove_hud_from(src, src)
@@ -243,13 +267,7 @@ var/list/datum/mob_hud/huds = list(
var/mob/M = source_mob ? source_mob : src
for(var/datum/mob_hud/hud in huds)
if(M in hud.hudusers)
- readd_hud(hud)
-
-/mob/proc/readd_hud(datum/mob_hud/hud)
- hud.add_hud_to(src)
-
-
-
+ hud.refresh_hud(src, hud.hudusers[M])
//Medical HUDs
diff --git a/code/datums/paygrades/factions/twe/twe.dm b/code/datums/paygrades/factions/twe/twe.dm
index 214d70890c18..9707e89e6171 100644
--- a/code/datums/paygrades/factions/twe/twe.dm
+++ b/code/datums/paygrades/factions/twe/twe.dm
@@ -2,42 +2,56 @@
name = "TWE Paygrade"
pay_multiplier = 2 // less people = more to pay them
-//TWE RMC
-/datum/paygrade/twe/rc1
- paygrade = "TC1"
- name = "Yonto"
- prefix = "Yt."
+//RMC Emlisted
+/datum/paygrade/twe/e1
+ paygrade = "RMC E1"
+ name = "Heitai-Marine"
+ prefix = "Hti-Mne."
-/datum/paygrade/twe/rc2
- paygrade = "TC2"
- name = "Santo"
- prefix = "St."
+/datum/paygrade/twe/e2
+ paygrade = "RMC E2"
+ name = "Santo-Lance Corporal"
+ prefix = "St-LCpl."
pay_multiplier = 2.1
-/datum/paygrade/twe/rc3
- paygrade = "TC3"
- name = "Nito"
- prefix = "Nt."
+/datum/paygrade/twe/e3
+ paygrade = "RMC E3"
+ name = "Nito-Corporal"
+ prefix = "Nt-Cpl."
pay_multiplier = 2.2
-/datum/paygrade/twe/rc4
- paygrade = "TC4"
- name = "Itto"
- prefix = "It."
+/datum/paygrade/twe/e4
+ paygrade = "RMC E4"
+ name = "Itto-Sergeant"
+ prefix = "Sgt."
pay_multiplier = 2.3
+//RMC Officer
+
+/datum/paygrade/twe/o1/rmc
+ paygrade = "RMC O1"
+ name = "Second Lieutenant"
+ prefix = "2nd LT."
+ pay_multiplier = 3
+
+//TWE Warrent Officer
+/datum/paygrade/twe/wo1
+ paygrade = "TWE WO."
+ name = "Warrant Officer"
+ prefix = "WO."
+ pay_multiplier = 3.5
//TWE Naval Officers
/datum/paygrade/twe/o1
- paygrade = "TO1"
- name = "Seaman"
- prefix = "SN."
+ paygrade = "TWE O1"
+ name = "Second Lieutenant"
+ prefix = "2nd LT"
pay_multiplier = 3
/datum/paygrade/twe/o2
- paygrade = "TO2"
- name = "Leading Seaman"
- prefix = "LR."
+ paygrade = "RMC O2"
+ name = "First Lieutenant"
+ prefix = "1st LT"
pay_multiplier = 3.25
/datum/paygrade/twe/o3
@@ -46,12 +60,6 @@
prefix = "SO."
pay_multiplier = 3.5
-/datum/paygrade/twe/o3e
- paygrade = "TO3E"
- name = "Warrant Officer"
- prefix = "WO."
- pay_multiplier = 3.5
-
/datum/paygrade/twe/o4
paygrade = "TO4"
name = "Captain"
diff --git a/code/datums/skills.dm b/code/datums/skills.dm
index 9bc53007173d..f80b391123f2 100644
--- a/code/datums/skills.dm
+++ b/code/datums/skills.dm
@@ -79,6 +79,11 @@
else
REMOVE_TRAIT(owner, TRAIT_LEADERSHIP, TRAIT_SOURCE_SKILL(skill_name))
+/datum/skill/overwatch
+ skill_name = SKILL_OVERWATCH
+ skill_level = SKILL_OVERWATCH_DEFAULT
+ max_skill_level = SKILL_OVERWATCH_MAX
+
/datum/skill/medical
skill_name = SKILL_MEDICAL
skill_level = SKILL_MEDICAL_DEFAULT
@@ -281,6 +286,7 @@ CIVILIAN
skills = list(
SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_ENGINEER = SKILL_ENGINEER_TRAINED,
SKILL_VEHICLE = SKILL_VEHICLE_SMALL,
@@ -292,6 +298,7 @@ CIVILIAN
skills = list(
SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_ENGINEER = SKILL_ENGINEER_TRAINED,
SKILL_VEHICLE = SKILL_VEHICLE_SMALL,
@@ -312,6 +319,7 @@ CIVILIAN
name = "Weyland-Yutani Manager"
skills = list(
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_INTEL = SKILL_INTEL_EXPERT,
)
@@ -576,6 +584,7 @@ COMMAND STAFF
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
@@ -593,6 +602,7 @@ COMMAND STAFF
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SURGERY = SKILL_SURGERY_NOVICE,
SKILL_POLICE = SKILL_POLICE_SKILLED,
@@ -614,6 +624,7 @@ COMMAND STAFF
SKILL_ENGINEER = SKILL_ENGINEER_ENGI, //to fix CIC apc.
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SURGERY = SKILL_SURGERY_NOVICE,
SKILL_POLICE = SKILL_POLICE_FLASH,
@@ -633,6 +644,7 @@ COMMAND STAFF
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_POLICE = SKILL_POLICE_FLASH,
SKILL_FIREMAN = SKILL_FIREMAN_TRAINED,
@@ -650,6 +662,7 @@ COMMAND STAFF
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SURGERY = SKILL_SURGERY_TRAINED,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -676,6 +689,7 @@ COMMAND STAFF
skills = list(
SKILL_FIREARMS = SKILL_FIREARMS_CIVILIAN,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SURGERY = SKILL_SURGERY_TRAINED,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -692,6 +706,7 @@ COMMAND STAFF
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED,
SKILL_JTAC = SKILL_JTAC_EXPERT,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
@@ -707,6 +722,7 @@ COMMAND STAFF
SKILL_PILOT = SKILL_PILOT_EXPERT,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_SURGERY = SKILL_SURGERY_NOVICE,
SKILL_JTAC = SKILL_JTAC_EXPERT,
@@ -725,6 +741,7 @@ COMMAND STAFF
SKILL_ENGINEER = SKILL_ENGINEER_MASTER,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_MASTER,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_POLICE = SKILL_POLICE_FLASH,
SKILL_FIREMAN = SKILL_FIREMAN_TRAINED,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
@@ -738,6 +755,7 @@ COMMAND STAFF
skills = list(
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
SKILL_POLICE = SKILL_POLICE_FLASH,
SKILL_FIREMAN = SKILL_FIREMAN_TRAINED,
@@ -783,6 +801,7 @@ MILITARY NONCOMBATANT
SKILL_PILOT = SKILL_PILOT_EXPERT,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_SURGERY = SKILL_SURGERY_NOVICE,
SKILL_JTAC = SKILL_JTAC_TRAINED,
@@ -817,6 +836,7 @@ MILITARY NONCOMBATANT
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
@@ -881,6 +901,7 @@ SYNTHETIC
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_SPEC_WEAPONS = SKILL_SPEC_ALL,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MASTER,
SKILL_SURGERY = SKILL_SURGERY_EXPERT,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -940,6 +961,7 @@ SYNTHETIC
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_SPEC_WEAPONS = SKILL_SPEC_ALL,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MASTER,
SKILL_SURGERY = SKILL_SURGERY_EXPERT,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -1043,6 +1065,7 @@ United States Colonial Marines
skills = list(
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_CQC = SKILL_CQC_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -1113,6 +1136,7 @@ COLONIAL LIBERATION FRONT
SKILL_ENGINEER = SKILL_ENGINEER_ENGI, // to use their C4
SKILL_CQC = SKILL_CQC_SKILLED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_EXPERT,
@@ -1130,6 +1154,7 @@ COLONIAL LIBERATION FRONT
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CQC = SKILL_CQC_SKILLED,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_EXPERT,
@@ -1176,6 +1201,7 @@ FREELANCERS
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_CQC = SKILL_CQC_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_JTAC = SKILL_JTAC_EXPERT,
)
@@ -1243,6 +1269,7 @@ UNITED PROGRESSIVE PEOPLES
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_CQC = SKILL_CQC_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_JTAC = SKILL_JTAC_EXPERT,
)
@@ -1269,6 +1296,7 @@ UNITED PROGRESSIVE PEOPLES
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENGINEER = SKILL_ENGINEER_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
@@ -1283,6 +1311,7 @@ UNITED PROGRESSIVE PEOPLES
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_EXPERT,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
@@ -1290,6 +1319,7 @@ UNITED PROGRESSIVE PEOPLES
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_VEHICLE = SKILL_VEHICLE_SMALL,
SKILL_JTAC = SKILL_JTAC_EXPERT,
+ SKILL_EXECUTION = SKILL_EXECUTION_TRAINED,
)
/datum/skills/upp/conscript
name = "UPP Conscript"
@@ -1385,6 +1415,7 @@ Private Military Contractors
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CQC = SKILL_CQC_SKILLED,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_JTAC = SKILL_JTAC_TRAINED,
@@ -1400,6 +1431,7 @@ Private Military Contractors
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_CQC = SKILL_CQC_SKILLED,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -1461,6 +1493,7 @@ Private Military Contractors
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_CQC = SKILL_CQC_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
SKILL_JTAC = SKILL_JTAC_MASTER,
SKILL_EXECUTION = SKILL_EXECUTION_TRAINED,
@@ -1494,6 +1527,7 @@ CONTRACTORS
SKILL_FIREARMS = SKILL_FIREARMS_MAX,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_POLICE = SKILL_POLICE_SKILLED,
SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
@@ -1582,6 +1616,7 @@ COLONIAL MARSHALS
SKILL_CQC = SKILL_CQC_EXPERT,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_FIREMAN = SKILL_FIREMAN_MASTER,
@@ -1601,6 +1636,7 @@ COLONIAL MARSHALS
SKILL_FIREARMS = SKILL_FIREARMS_TRAINED,
SKILL_SPEC_WEAPONS = SKILL_SPEC_ALL,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT, // incase the synth needs to use consoles for investigations or tracking
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SURGERY = SKILL_SURGERY_TRAINED, // Not a medical Synthetic, but operate if absolutely needed.
SKILL_RESEARCH = SKILL_RESEARCH_TRAINED,
@@ -1672,7 +1708,7 @@ COLONIAL MARSHALS
SKILL_FIREARMS = SKILL_FIREARMS_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_CQC = SKILL_CQC_TRAINED,
- SKILL_VEHICLE = SKILL_VEHICLE_DEFAULT,
+ SKILL_VEHICLE = SKILL_VEHICLE_LARGE,
)
/datum/skills/military/survivor/upp_sl
@@ -1681,12 +1717,14 @@ COLONIAL MARSHALS
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_ENDURANCE = SKILL_ENDURANCE_TRAINED,
+ SKILL_SPEC_WEAPONS = SKILL_SPEC_UPP,
SKILL_FIREARMS = SKILL_FIREARMS_TRAINED,
SKILL_CQC = SKILL_CQC_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
- SKILL_VEHICLE = SKILL_VEHICLE_DEFAULT,
+ SKILL_VEHICLE = SKILL_VEHICLE_LARGE,
SKILL_JTAC = SKILL_JTAC_EXPERT,
)
@@ -1777,6 +1815,7 @@ SPEC-OPS
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MAX,
@@ -1890,6 +1929,7 @@ MISCELLANEOUS
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_FIREARMS = SKILL_FIREARMS_MAX,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
SKILL_JTAC = SKILL_JTAC_MASTER,
@@ -1932,6 +1972,7 @@ MISCELLANEOUS
skills = list(
SKILL_VEHICLE = SKILL_VEHICLE_CREWMAN,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
@@ -1967,6 +2008,7 @@ MISCELLANEOUS
SKILL_MELEE_WEAPONS = SKILL_MELEE_SUPER,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER, //Spartacus!
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MAX,
SKILL_JTAC = SKILL_JTAC_MASTER,
)
@@ -1995,6 +2037,7 @@ MISCELLANEOUS
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_DOCTOR,
SKILL_SPEC_WEAPONS = SKILL_SPEC_ALL,
SKILL_ENDURANCE = SKILL_ENDURANCE_MAX,
@@ -2012,6 +2055,7 @@ MISCELLANEOUS
SKILL_ENGINEER = SKILL_ENGINEER_MASTER,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_ENDURANCE = SKILL_ENDURANCE_MAX,
SKILL_JTAC = SKILL_JTAC_MASTER,
)
@@ -2040,6 +2084,7 @@ MISCELLANEOUS
SKILL_ENGINEER = SKILL_ENGINEER_MAX,
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_MAX,
SKILL_LEADERSHIP = SKILL_LEAD_MAX,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_MAX,
SKILL_MEDICAL = SKILL_MEDICAL_MAX,
SKILL_SURGERY = SKILL_SURGERY_MAX,
SKILL_RESEARCH = SKILL_RESEARCH_MAX,
@@ -2053,3 +2098,75 @@ MISCELLANEOUS
SKILL_EXECUTION = SKILL_EXECUTION_MAX,
SKILL_INTEL = SKILL_INTEL_MAX,
)
+
+/*
+----------------------------
+Royal Marines Commando
+----------------------------
+*/
+
+//NOTE: Skills take heavy from PMCs
+
+/datum/skills/rmc
+ name = "Royal Marines Commando"
+ skills = list(
+ SKILL_CQC = SKILL_CQC_TRAINED,
+ SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
+ SKILL_POLICE = SKILL_POLICE_SKILLED,
+ SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
+ SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
+ SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
+ SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
+ SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
+ SKILL_SURGERY = SKILL_SURGERY_NOVICE,
+ )
+
+/datum/skills/rmc/specialist
+ name = "Royal Marines Commando Specialist"
+ skills = list(
+ SKILL_CQC = SKILL_CQC_TRAINED,
+ SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
+ SKILL_POLICE = SKILL_POLICE_SKILLED,
+ SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
+ SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
+ SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
+ SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
+ SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
+ SKILL_SURGERY = SKILL_SURGERY_NOVICE,
+ SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
+ SKILL_JTAC = SKILL_JTAC_BEGINNER,
+ )
+
+/datum/skills/rmc/smartgun
+ name = "Royal Marines Commando Smartgunner"
+ skills = list(
+ SKILL_CQC = SKILL_CQC_TRAINED,
+ SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
+ SKILL_POLICE = SKILL_POLICE_SKILLED,
+ SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
+ SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
+ SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
+ SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
+ SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
+ SKILL_SURGERY = SKILL_SURGERY_NOVICE,
+ SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
+ SKILL_JTAC = SKILL_JTAC_BEGINNER,
+ SKILL_SPEC_WEAPONS = SKILL_SPEC_SMARTGUN,
+ )
+
+/datum/skills/rmc/leader
+ name = "Royal Marines Commando Leader"
+ skills = list(
+ SKILL_CQC = SKILL_CQC_SKILLED,
+ SKILL_FIREARMS = SKILL_FIREARMS_EXPERT,
+ SKILL_POLICE = SKILL_POLICE_SKILLED,
+ SKILL_FIREMAN = SKILL_FIREMAN_SKILLED,
+ SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
+ SKILL_ENGINEER = SKILL_ENGINEER_ENGI,
+ SKILL_ENDURANCE = SKILL_ENDURANCE_MASTER,
+ SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
+ SKILL_SURGERY = SKILL_SURGERY_NOVICE,
+ SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED,
+ SKILL_JTAC = SKILL_JTAC_TRAINED,
+ SKILL_LEADERSHIP = SKILL_LEAD_TRAINED,
+ )
diff --git a/code/datums/supply_packs/black_market.dm b/code/datums/supply_packs/black_market.dm
index 3f4453d03f32..1737a66e85a9 100644
--- a/code/datums/supply_packs/black_market.dm
+++ b/code/datums/supply_packs/black_market.dm
@@ -332,15 +332,15 @@ Additionally, weapons that are way too good to put in the basically-flavor black
dollar_cost = 5
containertype = /obj/structure/largecrate/black_market
-/datum/supply_packs/contraband/seized/ppsh
- name = "PPSh-17b submachinegun crate (x5 magazines included)"
+/datum/supply_packs/contraband/seized/pps43
+ name = "Type-19 submachinegun crate (x5 magazines included)"
contains = list(
- /obj/item/weapon/gun/smg/ppsh,
- /obj/item/ammo_magazine/smg/ppsh/extended,
- /obj/item/ammo_magazine/smg/ppsh/extended,
- /obj/item/ammo_magazine/smg/ppsh,
- /obj/item/ammo_magazine/smg/ppsh,
- /obj/item/ammo_magazine/smg/ppsh,
+ /obj/item/weapon/gun/smg/pps43,
+ /obj/item/ammo_magazine/smg/pps43/extended,
+ /obj/item/ammo_magazine/smg/pps43/extended,
+ /obj/item/ammo_magazine/smg/pps43,
+ /obj/item/ammo_magazine/smg/pps43,
+ /obj/item/ammo_magazine/smg/pps43,
)
dollar_cost = 15
containertype = /obj/structure/largecrate/black_market
@@ -373,18 +373,18 @@ Additionally, weapons that are way too good to put in the basically-flavor black
dollar_cost = 45
containertype = /obj/structure/largecrate/black_market
-/datum/supply_packs/contraband/seized/c99
- name = "Korovin PK-9 pistol crate (x6 magazines included)"
+/datum/supply_packs/contraband/seized/t73
+ name = "Type 73 pistol crate (x6 magazines included)"
contains = list(
- /obj/item/weapon/gun/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
- /obj/item/ammo_magazine/pistol/c99,
+ /obj/item/weapon/gun/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
+ /obj/item/ammo_magazine/pistol/t73,
)
- dollar_cost = 5
+ dollar_cost = 15
containertype = /obj/structure/largecrate/black_market
/datum/supply_packs/contraband/seized/kt42
@@ -415,14 +415,14 @@ Additionally, weapons that are way too good to put in the basically-flavor black
dollar_cost = 5
containertype = /obj/structure/largecrate/black_market
-/datum/supply_packs/contraband/seized/skorpion
- name = "CZ-81 machine pistol (x4 magazines included)"
+/datum/supply_packs/contraband/seized/bizon
+ name = "Type 64 Submachinegun (x4 magazines included)"
contains = list(
- /obj/item/weapon/gun/pistol/skorpion,
- /obj/item/ammo_magazine/pistol/skorpion,
- /obj/item/ammo_magazine/pistol/skorpion,
- /obj/item/ammo_magazine/pistol/skorpion,
- /obj/item/ammo_magazine/pistol/skorpion,
+ /obj/item/weapon/gun/smg/bizon,
+ /obj/item/ammo_magazine/smg/bizon,
+ /obj/item/ammo_magazine/smg/bizon,
+ /obj/item/ammo_magazine/smg/bizon,
+ /obj/item/ammo_magazine/smg/bizon,
)
dollar_cost = 15
containertype = /obj/structure/largecrate/black_market
@@ -456,10 +456,10 @@ Additionally, weapons that are way too good to put in the basically-flavor black
dollar_cost = 15
containertype = /obj/structure/largecrate/black_market
-/datum/supply_packs/contraband/seized/nagant
- name = "N-Y 7.62mm revolver (x6 magazines included)"
+/datum/supply_packs/contraband/seized/upprevolver
+ name = "ZHNK-72 revolver (x6 magazines included)"
contains = list(
- /obj/item/weapon/gun/revolver/nagant,
+ /obj/item/weapon/gun/revolver/upp,
/obj/item/ammo_magazine/revolver/upp,
/obj/item/ammo_magazine/revolver/upp,
/obj/item/ammo_magazine/revolver/upp,
@@ -467,7 +467,7 @@ Additionally, weapons that are way too good to put in the basically-flavor black
/obj/item/ammo_magazine/revolver/upp,
/obj/item/ammo_magazine/revolver/upp,
)
- dollar_cost = 10
+ dollar_cost = 15
containertype = /obj/structure/largecrate/black_market
/datum/supply_packs/contraband/seized/r4t
@@ -1067,11 +1067,11 @@ Things that don't fit anywhere else. If they're meant for shipside use, they pro
new picked_type(loc)
loot_message = SPAN_NOTICE("It's some strange elite gear...?")
if(11 to 15)
- //Skorpion
- new /obj/item/weapon/gun/pistol/skorpion(loc)
- new /obj/item/ammo_magazine/pistol/skorpion(loc)
- new /obj/item/ammo_magazine/pistol/skorpion(loc)
- new /obj/item/ammo_magazine/pistol/skorpion(loc)
+ //Type 64
+ new /obj/item/weapon/gun/smg/bizon(loc)
+ new /obj/item/ammo_magazine/smg/bizon(loc)
+ new /obj/item/ammo_magazine/smg/bizon(loc)
+ new /obj/item/ammo_magazine/smg/bizon(loc)
// Somehow they found a Webley.
new /obj/item/weapon/gun/revolver/m44/custom/webley(loc)
new /obj/item/ammo_magazine/revolver/webley(loc)
@@ -1079,11 +1079,11 @@ Things that don't fit anywhere else. If they're meant for shipside use, they pro
new /obj/item/ammo_magazine/revolver/webley(loc)
loot_message = SPAN_NOTICE("It's some CLF pistol armaments!")
if(16 to 20)
- // PPSH
- new /obj/item/weapon/gun/smg/ppsh/with_drum_mag(loc)
- new /obj/item/ammo_magazine/smg/ppsh/extended(loc)
- new /obj/item/ammo_magazine/smg/ppsh/extended(loc)
- new /obj/item/ammo_magazine/smg/ppsh/extended(loc)
+ // Type 19
+ new /obj/item/weapon/gun/smg/pps43/extended_mag(loc)
+ new /obj/item/ammo_magazine/smg/pps43/extended(loc)
+ new /obj/item/ammo_magazine/smg/pps43/extended(loc)
+ new /obj/item/ammo_magazine/smg/pps43/extended(loc)
// MAC-15
new /obj/item/weapon/gun/smg/mac15/extended(loc)
new /obj/item/ammo_magazine/smg/mac15/extended(loc)
diff --git a/code/datums/supply_packs/food.dm b/code/datums/supply_packs/food.dm
index caef6e3f8664..9e0527aed6cf 100644
--- a/code/datums/supply_packs/food.dm
+++ b/code/datums/supply_packs/food.dm
@@ -141,7 +141,7 @@
//all the finish snacks.
/datum/supply_packs/donuts
- name = "boxe of donut (x5)"
+ name = "box of donuts (x5)"
contains = list(
/obj/item/storage/donut_box,
/obj/item/storage/donut_box,
@@ -151,7 +151,7 @@
)
cost = 10
containertype = /obj/structure/closet/crate/supply
- containername = "\improper boxe of donut (x5)"
+ containername = "box of donuts (x5)"
group = "Food"
/datum/supply_packs/mre
diff --git a/code/datums/supply_packs/weapons.dm b/code/datums/supply_packs/weapons.dm
index a28e0c7191ce..927db853e9fd 100644
--- a/code/datums/supply_packs/weapons.dm
+++ b/code/datums/supply_packs/weapons.dm
@@ -42,7 +42,7 @@
group = "Weapons"
/datum/supply_packs/grenade_launchers
- name = "M79 Grenade Launcher Crate (x2 Guncasess)"
+ name = "M79 Grenade Launcher Crate (x2 Guncases)"
contains = list(
/obj/item/storage/box/guncase/m79,
/obj/item/storage/box/guncase/m79,
@@ -120,6 +120,16 @@
containername = "\improper XM88 Heavy Rifle crate"
group = "Weapons"
+/* Uncomment me if it's decided to let the m707 be purchasable through req
+/datum/supply_packs/gun/m707
+ name = "M707 Anti-Materiel Rifle crate (M707 x1)"
+ contains = list()
+ cost = 120
+ containertype = /obj/structure/closet/crate/secure/vulture
+ containername = "M707 crate"
+ group = "Weapons"
+*/
+
/datum/supply_packs/gun/merc
contains = list()
name = "black market firearms (x1)"
diff --git a/code/game/area/BigRed.dm b/code/game/area/BigRed.dm
index 59d7c40cd56f..57e062195a3c 100644
--- a/code/game/area/BigRed.dm
+++ b/code/game/area/BigRed.dm
@@ -654,6 +654,7 @@
minimap_color = MINIMAP_AREA_LZ
icon_state = "tcomsatcham"
requires_power = FALSE
+ is_resin_allowed = FALSE
/area/bigredv2/landing/console
name = "\improper LZ1 'Telecomms'"
diff --git a/code/game/area/DesertDam.dm b/code/game/area/DesertDam.dm
index 73635eb6385d..96e5eb1f62e5 100644
--- a/code/game/area/DesertDam.dm
+++ b/code/game/area/DesertDam.dm
@@ -682,7 +682,6 @@
/area/desert_dam/exterior
requires_power = 1
always_unpowered = 1
- lighting_use_dynamic = 1
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
diff --git a/code/game/area/IceColony.dm b/code/game/area/IceColony.dm
index 2c7bbee2969c..40289b92b5ad 100644
--- a/code/game/area/IceColony.dm
+++ b/code/game/area/IceColony.dm
@@ -28,7 +28,6 @@
icon_state = "cliff_blocked"
requires_power = 1
always_unpowered = 1
- lighting_use_dynamic = 1
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
@@ -65,6 +64,7 @@
name = "\improper Emergency Landing Pad"
icon_state = "landing_pad"
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
//Everything around the physical landing pad
@@ -79,6 +79,7 @@
name = "\improper Aerodrome Container Yard"
icon_state = "container_yard"
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
//
// Valleys
diff --git a/code/game/area/LV522_Chances_Claim.dm b/code/game/area/LV522_Chances_Claim.dm
index 3d15d49c3df7..ffd6a5897e4e 100644
--- a/code/game/area/LV522_Chances_Claim.dm
+++ b/code/game/area/LV522_Chances_Claim.dm
@@ -52,7 +52,6 @@
name = "Chance's Claim - Dropship Alamo Landing Zone"
icon_state = "shuttle"
icon = 'icons/turf/area_shiva.dmi'
- lighting_use_dynamic = TRUE
/area/lv522/landing_zone_1/lz1_console
name = "Chance's Claim - Dropship Alamo Console"
@@ -75,7 +74,6 @@
name = "Chance's Claim - Dropship Normandy Landing Zone"
icon_state = "shuttle2"
icon = 'icons/turf/area_shiva.dmi'
- lighting_use_dynamic = TRUE
/area/lv522/landing_zone_2/lz2_console
name = "Chance's Claim - Dropship Normandy Console"
@@ -180,6 +178,7 @@
name = "North LZ1 - Spaceport"
icon_state = "red"
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/lv522/indoors/lone_buildings/outdoor_bot
name = "East LZ1 - Outdoor T-Comms"
diff --git a/code/game/area/Sulaco.dm b/code/game/area/Sulaco.dm
index 851025e1b63a..ae197537143a 100644
--- a/code/game/area/Sulaco.dm
+++ b/code/game/area/Sulaco.dm
@@ -117,7 +117,7 @@
//DISTRESS SHUTTLES
/area/shuttle/distress
- lighting_use_dynamic = FALSE
+ base_lighting_alpha = 255
unique = TRUE
/area/shuttle/distress/start
diff --git a/code/game/area/WhiskeyOutpost.dm b/code/game/area/WhiskeyOutpost.dm
index 583a5dafc299..02d94dc942da 100644
--- a/code/game/area/WhiskeyOutpost.dm
+++ b/code/game/area/WhiskeyOutpost.dm
@@ -79,7 +79,6 @@
//ambience = list('sound/ambience/jungle_amb1.ogg')
requires_power = 1
always_unpowered = 1
- lighting_use_dynamic = 1
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
@@ -180,7 +179,6 @@
ceiling = CEILING_UNDERGROUND_ALLOW_CAS
requires_power = 1
always_unpowered = 1
- lighting_use_dynamic = 1
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
diff --git a/code/game/area/admin_level.dm b/code/game/area/admin_level.dm
index 501047c46d08..00b408c04adf 100644
--- a/code/game/area/admin_level.dm
+++ b/code/game/area/admin_level.dm
@@ -3,14 +3,13 @@
/area/adminlevel
ceiling = CEILING_METAL
+ base_lighting_alpha = 255
/area/adminlevel/bunker01
icon_state = "thunder"
requires_power = FALSE
statistic_exempt = TRUE
flags_area = AREA_NOTUNNEL
- luminosity = TRUE
- lighting_use_dynamic = FALSE
/area/adminlevel/bunker01/mainroom
name = "\improper Bunker Main Room"
@@ -78,8 +77,7 @@
ceiling = CEILING_UNDERGROUND_ALLOW_CAS
always_unpowered = TRUE
requires_power = TRUE
- lighting_use_dynamic = TRUE
- luminosity = FALSE
+ base_lighting_alpha = 0
/area/adminlevel/bunker01/caves/outpost
name = "\improper Bunker Outpost"
@@ -87,8 +85,6 @@
ceiling = CEILING_UNDERGROUND_ALLOW_CAS
requires_power = TRUE
always_unpowered = FALSE
- lighting_use_dynamic = TRUE
- luminosity = FALSE
/area/adminlevel/bunker01/caves/xeno
name = "\improper Bunker Xeno Hive"
@@ -129,6 +125,10 @@
name = "Freelancer Station"
icon_state = "yellow"
+/area/adminlevel/ert_station/royal_marines_station
+ name = "HMS Patna Hangerbay"
+ icon_state = "yellow"
+
/area/adminlevel/ert_station/shuttle_dispatch
name = "Shuttle Dispatch Station"
soundscape_playlist = SCAPE_PL_ELEVATOR_MUSIC
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 2c274665fa19..826b2dc0585f 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -28,9 +28,6 @@
var/unique = TRUE
var/has_gravity = 1
- var/area/master // master area used for power calcluations
- // (original area before splitting due to sd_DAL)
- var/list/related // the other areas of the same type as this
// var/list/lights // list of all lights on this area
var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
var/air_doors_activated = 0
@@ -89,10 +86,8 @@
if(unique)
GLOB.areas_by_type[type] = src
..()
- master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references loc.loc.master ~Carn
- related = list(src)
- initialize_power_and_lighting()
+ initialize_power()
/area/Initialize(mapload, ...)
icon_state = "" //Used to reset the icon overlay, I assume.
@@ -105,24 +100,26 @@
if(is_mainship_level(z))
GLOB.ship_areas += src
-/area/proc/initialize_power_and_lighting(override_power)
+ if(base_lighting_alpha)
+ return INITIALIZE_HINT_ROUNDSTART
+
+/area/LateInitialize()
+ . = ..()
+
+ update_base_lighting()
+
+/area/proc/initialize_power(override_power)
if(requires_power)
- luminosity = 0
if(override_power) //Reset everything if you want to override.
power_light = TRUE
power_equip = TRUE
power_environ = TRUE
- if(lighting_use_dynamic)
- SetDynamicLighting()
else
power_light = FALSE //rastaf0
power_equip = FALSE //rastaf0
power_environ = FALSE //rastaf0
- luminosity = 1
- lighting_use_dynamic = 0
power_change() // all machines set to current power level, also updates lighting icon
- InitializeLighting()
/// Returns the correct ambience sound track for a client in this area
/area/proc/get_sound_ambience(client/target)
@@ -135,13 +132,12 @@
poweralm = state
if(istype(source)) //Only report power alarms on the z-level where the source is located.
var/list/cameras = list()
- for (var/area/RA in related)
- for (var/obj/structure/machinery/camera/C in RA)
- cameras += C
- if(state == 1)
- C.network.Remove(CAMERA_NET_POWER_ALARMS)
- else
- C.network.Add(CAMERA_NET_POWER_ALARMS)
+ for (var/obj/structure/machinery/camera/C in src)
+ cameras += C
+ if(state == 1)
+ C.network.Remove(CAMERA_NET_POWER_ALARMS)
+ else
+ C.network.Add(CAMERA_NET_POWER_ALARMS)
for (var/mob/living/silicon/aiPlayer in ai_mob_list)
if(aiPlayer.z == source.z)
if (state == 1)
@@ -161,10 +157,9 @@
// return 0 //redudant
//Check all the alarms before lowering atmosalm. Raising is perfectly fine.
- for (var/area/RA in related)
- for (var/obj/structure/machinery/alarm/AA in RA)
- if ( !(AA.inoperable()) && !AA.shorted)
- danger_level = max(danger_level, AA.danger_level)
+ for (var/obj/structure/machinery/alarm/AA in src)
+ if ( !(AA.inoperable()) && !AA.shorted)
+ danger_level = max(danger_level, AA.danger_level)
if(danger_level != atmosalm)
if (danger_level < 1 && atmosalm >= 1)
@@ -172,9 +167,8 @@
air_doors_open()
if (danger_level < 2 && atmosalm >= 2)
- for(var/area/RA in related)
- for(var/obj/structure/machinery/camera/C in RA)
- C.network.Remove(CAMERA_NET_ATMOSPHERE_ALARMS)
+ for(var/obj/structure/machinery/camera/C in src)
+ C.network.Remove(CAMERA_NET_ATMOSPHERE_ALARMS)
for(var/mob/living/silicon/aiPlayer in ai_mob_list)
aiPlayer.cancelAlarm("Atmosphere", src, src)
for(var/obj/structure/machinery/computer/station_alert/a in machines)
@@ -182,11 +176,10 @@
if (danger_level >= 2 && atmosalm < 2)
var/list/cameras = list()
- for(var/area/RA in related)
- //updateicon()
- for(var/obj/structure/machinery/camera/C in RA)
- cameras += C
- C.network.Add(CAMERA_NET_ATMOSPHERE_ALARMS)
+ //updateicon()
+ for(var/obj/structure/machinery/camera/C in src)
+ cameras += C
+ C.network.Add(CAMERA_NET_ATMOSPHERE_ALARMS)
for(var/mob/living/silicon/aiPlayer in ai_mob_list)
aiPlayer.triggerAlarm("Atmosphere", src, cameras, src)
for(var/obj/structure/machinery/computer/station_alert/a in machines)
@@ -194,40 +187,38 @@
air_doors_close()
atmosalm = danger_level
- for(var/area/RA in related)
- for (var/obj/structure/machinery/alarm/AA in RA)
- AA.update_icon()
+ for (var/obj/structure/machinery/alarm/AA in src)
+ AA.update_icon()
return 1
return 0
/area/proc/air_doors_close()
- if(!src.master.air_doors_activated)
- src.master.air_doors_activated = 1
- for(var/obj/structure/machinery/door/firedoor/E in src.master.all_doors)
- if(!E:blocked)
- if(E.operating)
- E:nextstate = OPEN
- else if(!E.density)
- INVOKE_ASYNC(E, TYPE_PROC_REF(/obj/structure/machinery/door, close))
+ for(var/obj/structure/machinery/door/firedoor/E in all_doors)
+ if(E.blocked)
+ continue
+
+ if(E.operating)
+ E.nextstate = OPEN
+ else if(!E.density)
+ E.close()
+
/area/proc/air_doors_open()
- if(src.master.air_doors_activated)
- src.master.air_doors_activated = 0
- for(var/obj/structure/machinery/door/firedoor/E in src.master.all_doors)
- if(!E:blocked)
- if(E.operating)
- E:nextstate = OPEN
- else if(E.density)
- INVOKE_ASYNC(E, TYPE_PROC_REF(/obj/structure/machinery/door, open))
+ for(var/obj/structure/machinery/door/firedoor/E in all_doors)
+ if(E.blocked)
+ continue
+ if(E.operating)
+ E.nextstate = OPEN
+ else if(E.density)
+ E.open()
/area/proc/firealert()
if(name == "Space") //no fire alarms in space
return
if(!(flags_alarm_state & ALARM_WARNING_FIRE))
- flags_alarm_state |= ALARM_WARNING_FIRE
- master.flags_alarm_state |= ALARM_WARNING_FIRE //used for firedoor checks
+ flags_alarm_state |= ALARM_WARNING_FIRE //used for firedoor checks
updateicon()
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
for(var/obj/structure/machinery/door/firedoor/D in all_doors)
@@ -237,10 +228,9 @@
else if(!D.density)
INVOKE_ASYNC(D, TYPE_PROC_REF(/obj/structure/machinery/door, close))
var/list/cameras = list()
- for(var/area/RA in related)
- for (var/obj/structure/machinery/camera/C in RA)
- cameras.Add(C)
- C.network.Add(CAMERA_NET_FIRE_ALARMS)
+ for (var/obj/structure/machinery/camera/C in src)
+ cameras.Add(C)
+ C.network.Add(CAMERA_NET_FIRE_ALARMS)
for (var/mob/living/silicon/ai/aiPlayer in ai_mob_list)
aiPlayer.triggerAlarm("Fire", src, cameras, src)
for (var/obj/structure/machinery/computer/station_alert/a in machines)
@@ -248,8 +238,7 @@
/area/proc/firereset()
if(flags_alarm_state & ALARM_WARNING_FIRE)
- flags_alarm_state &= ~ALARM_WARNING_FIRE
- master.flags_alarm_state &= ~ALARM_WARNING_FIRE //used for firedoor checks
+ flags_alarm_state &= ~ALARM_WARNING_FIRE //used for firedoor checks
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
updateicon()
for(var/obj/structure/machinery/door/firedoor/D in all_doors)
@@ -258,9 +247,8 @@
D.nextstate = OPEN
else if(D.density)
INVOKE_ASYNC(D, TYPE_PROC_REF(/obj/structure/machinery/door, open))
- for(var/area/RA in related)
- for (var/obj/structure/machinery/camera/C in RA)
- C.network.Remove(CAMERA_NET_FIRE_ALARMS)
+ for (var/obj/structure/machinery/camera/C in src)
+ C.network.Remove(CAMERA_NET_FIRE_ALARMS)
for (var/mob/living/silicon/ai/aiPlayer in ai_mob_list)
aiPlayer.cancelAlarm("Fire", src, src)
for (var/obj/structure/machinery/computer/station_alert/a in machines)
@@ -278,16 +266,16 @@
/*
/area/proc/toggle_evacuation() //toggles lights and creates an overlay.
flags_alarm_state ^= ALARM_WARNING_EVAC
- master.flags_alarm_state ^= ALARM_WARNING_EVAC
+ flags_alarm_state ^= ALARM_WARNING_EVAC
//if(flags_alarm_state & ALARM_WARNING_EVAC)
- // master.lightswitch = FALSE
+ // lightswitch = FALSE
//lightswitch = FALSE //Lights going off.
// else
- // master.lightswitch = TRUE
+ // lightswitch = TRUE
//lightswitch = TRUE //Coming on.
- master.updateicon()
+ updateicon()
- //master.power_change()
+ //power_change()
/area/proc/toggle_shut_down()
@@ -312,75 +300,72 @@
if(icon_state != I) icon_state = I //If the icon state changed, change it. Otherwise do nothing.
/area/proc/powered(chan) // return true if the area has power to given channel
- if(!master.requires_power)
+ if(!requires_power)
return 1
- if(master.always_unpowered)
+ if(always_unpowered)
return 0
switch(chan)
if(POWER_CHANNEL_EQUIP)
- return master.power_equip
+ return power_equip
if(POWER_CHANNEL_LIGHT)
- return master.power_light
+ return power_light
if(POWER_CHANNEL_ENVIRON)
- return master.power_environ
+ return power_environ
return 0
/area/proc/update_power_channels(equip, light, environ)
- if(!master)
- CRASH("CALLED update_power_channels on non-master channel!")
var/changed = FALSE
- if(master.power_equip != equip)
- master.power_equip = equip
+ if(power_equip != equip)
+ power_equip = equip
changed = TRUE
- if(master.power_light != light)
- master.power_light = light
+ if(power_light != light)
+ power_light = light
changed = TRUE
- if(master.power_environ != environ)
- master.power_environ = environ
+ if(power_environ != environ)
+ power_environ = environ
changed = TRUE
if(changed) //Something got changed power-wise, time for an update!
power_change()
// called when power status changes
/area/proc/power_change()
- for(var/area/RA in related)
- for(var/obj/structure/machinery/M in RA) // for each machine in the area
- if(!M.gc_destroyed)
- M.power_change() // reverify power status (to update icons etc.)
- if(flags_alarm_state)
- RA.updateicon()
+ for(var/obj/structure/machinery/M in src) // for each machine in the area
+ if(!M.gc_destroyed)
+ M.power_change() // reverify power status (to update icons etc.)
+ if(flags_alarm_state)
+ updateicon()
/area/proc/usage(chan, reset_oneoff = FALSE)
var/used = 0
switch(chan)
if(POWER_CHANNEL_LIGHT)
- used += master.used_light
+ used += used_light
if(POWER_CHANNEL_EQUIP)
- used += master.used_equip
+ used += used_equip
if(POWER_CHANNEL_ENVIRON)
- used += master.used_environ
+ used += used_environ
if(POWER_CHANNEL_ONEOFF)
- used += master.used_oneoff
+ used += used_oneoff
if(reset_oneoff)
- master.used_oneoff = 0
+ used_oneoff = 0
if(POWER_CHANNEL_TOTAL)
- used += master.used_light + master.used_equip + master.used_environ + master.used_oneoff
+ used += used_light + used_equip + used_environ + used_oneoff
if(reset_oneoff)
- master.used_oneoff = 0
+ used_oneoff = 0
return used
/area/proc/use_power(amount, chan)
switch(chan)
if(POWER_CHANNEL_EQUIP)
- master.used_equip += amount
+ used_equip += amount
if(POWER_CHANNEL_LIGHT)
- master.used_light += amount
+ used_light += amount
if(POWER_CHANNEL_ENVIRON)
- master.used_environ += amount
+ used_environ += amount
if(POWER_CHANNEL_ONEOFF)
- master.used_oneoff += amount
+ used_oneoff += amount
/area/Entered(A,atom/OldLoc)
if(ismob(A))
@@ -388,7 +373,7 @@
return
var/mob/M = A
var/area/old_area = get_area(OldLoc)
- if(old_area.master == master)
+ if(old_area == src)
return
M?.client?.soundOutput?.update_ambience(src, null, TRUE)
else if(istype(A, /obj/structure/machinery))
@@ -416,24 +401,21 @@
A.has_gravity = gravitystate
- for(var/area/SubA in A.related)
- SubA.has_gravity = gravitystate
-
- if(gravitystate)
- for(var/mob/living/carbon/human/M in SubA)
- thunk(M)
- for(var/mob/M1 in SubA)
- M1.make_floating(0)
- else
- for(var/mob/M in SubA)
- if(M.Check_Dense_Object() && istype(src,/mob/living/carbon/human/))
- var/mob/living/carbon/human/H = src
- if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags_inventory & NOSLIPPING)) //magboots + dense_object = no floaty effect
- H.make_floating(0)
- else
- H.make_floating(1)
+ if(gravitystate)
+ for(var/mob/living/carbon/human/M in A)
+ thunk(M)
+ for(var/mob/M1 in A)
+ M1.make_floating(0)
+ else
+ for(var/mob/M in A)
+ if(M.Check_Dense_Object() && istype(src,/mob/living/carbon/human/))
+ var/mob/living/carbon/human/H = src
+ if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags_inventory & NOSLIPPING)) //magboots + dense_object = no floaty effect
+ H.make_floating(0)
else
- M.make_floating(1)
+ H.make_floating(1)
+ else
+ M.make_floating(1)
/area/proc/thunk(M)
if(istype(get_turf(M), /turf/open/space)) // Can't fall onto nothing.
diff --git a/code/game/area/areas_event.dm b/code/game/area/areas_event.dm
index fe34d74363d5..c43dae3a65b2 100644
--- a/code/game/area/areas_event.dm
+++ b/code/game/area/areas_event.dm
@@ -47,20 +47,12 @@ structure:
//events are not part of regular gameplay, therefore, no statistics
statistic_exempt = TRUE
- //no dynamic lighting
- exterior_light = 0
- lighting_use_dynamic = FALSE
+ base_lighting_alpha = 255
//always powered
requires_power = FALSE
unlimited_power = TRUE
-/area/event/Initialize()
- . = ..()
- if(exterior_light)
- for(var/turf/T in contents)
- T.update_lumcount(exterior_light)
-
//no dynamic lighting, unpowered.
/area/event/unpowered
name = "Open grounds (event)"
@@ -75,7 +67,6 @@ structure:
icon_state = "event_dyn"
requires_power = TRUE
unlimited_power = TRUE
- lighting_use_dynamic = TRUE
//no dynamic lighting, unpowered.
/area/event/dynamic/unpowered
@@ -83,13 +74,14 @@ structure:
icon_state = "event_dyn_nopower"
unlimited_power = FALSE
+ base_lighting_alpha = 255
//dynamic lighting, lit, powered.
/area/event/dynamic/lit
name = "Open grounds (event PDL)"
icon_state = "event_dyn_lit"
- exterior_light = 3
+ base_lighting_alpha = 255
//dynamic lighting, lit, unpowered.
/area/event/dynamic/lit/unpowered
@@ -97,6 +89,7 @@ structure:
icon_state = "event_dyn_lit_nopower"
unlimited_power = FALSE
+ base_lighting_alpha = 255
//-----------------------CEILING_METAL--------------------------
@@ -122,7 +115,6 @@ structure:
icon_state = "metal_dyn"
requires_power = TRUE
unlimited_power = TRUE
- lighting_use_dynamic = TRUE
//no dynamic lighting, unpowered.
/area/event/metal/dynamic/unpowered
@@ -137,7 +129,7 @@ structure:
name = "Building interior (event PDL)"
icon_state = "metal_dyn_lit"
- exterior_light = 3
+ base_lighting_alpha = 255
//dynamic lighting, lit, unpowered.
/area/event/metal/dynamic/lit/unpowered
@@ -176,7 +168,6 @@ structure:
icon_state = "under_dyn"
requires_power = TRUE
unlimited_power = TRUE
- lighting_use_dynamic = TRUE
//no dynamic lighting, unpowered.
/area/event/underground/dynamic/unpowered
@@ -191,7 +182,7 @@ structure:
name = "Small caves (event PDL)"
icon_state = "under_dyn_lit"
- exterior_light = 3
+ base_lighting_alpha = 255
//dynamic lighting, lit, unpowered.
/area/event/underground/dynamic/lit/unpowered
@@ -232,7 +223,6 @@ structure:
icon_state = "undercas_dyn"
requires_power = TRUE
unlimited_power = TRUE
- lighting_use_dynamic = TRUE
//no dynamic lighting, unpowered.
/area/event/underground_no_CAS/dynamic/unpowered
@@ -246,7 +236,7 @@ structure:
name = "Caves (event PDL)"
icon_state = "undercas_dyn_lit"
- exterior_light = 3
+ base_lighting_alpha = 255
//dynamic lighting, lit, unpowered.
/area/event/underground_no_CAS/dynamic/lit/unpowered
@@ -286,7 +276,6 @@ structure:
icon_state = "deep_dyn"
requires_power = TRUE
unlimited_power = TRUE
- lighting_use_dynamic = TRUE
//no dynamic lighting, unpowered.
/area/event/deep_underground/dynamic/unpowered
@@ -301,7 +290,7 @@ structure:
name = "Deep underground (event PDL)"
icon_state = "deep_dyn_lit"
- exterior_light = 3
+ base_lighting_alpha = 255
//dynamic lighting, lit, unpowered.
/area/event/deep_underground/dynamic/lit/unpowered
diff --git a/code/game/area/chinook.dm b/code/game/area/chinook.dm
index 62bbdee7bd17..b9cd440fd548 100644
--- a/code/game/area/chinook.dm
+++ b/code/game/area/chinook.dm
@@ -9,7 +9,6 @@
requires_power = TRUE
statistic_exempt = TRUE
flags_area = AREA_NOTUNNEL
- lighting_use_dynamic = TRUE
sound_environment = SOUND_ENVIRONMENT_ROOM
unlimited_power = TRUE
ceiling = CEILING_METAL
diff --git a/code/game/area/kutjevo.dm b/code/game/area/kutjevo.dm
index 48f18091df4a..422017c0a46b 100644
--- a/code/game/area/kutjevo.dm
+++ b/code/game/area/kutjevo.dm
@@ -8,20 +8,17 @@
icon_state = "kutjevo"
can_build_special = TRUE //T-Comms structure
temperature = 308.7 //kelvin, 35c, 95f
- lighting_use_dynamic = 1
minimap_color = MINIMAP_AREA_ENGI
/area/shuttle/drop1/kutjevo
name = "Kutjevo - Dropship Alamo Landing Zone"
icon_state = "shuttle"
icon = 'icons/turf/area_kutjevo.dmi'
- lighting_use_dynamic = 1
/area/shuttle/drop2/kutjevo
name = "Kutjevo - Dropship Normandy Landing Zone"
icon_state = "shuttle2"
icon = 'icons/turf/area_kutjevo.dmi'
- lighting_use_dynamic = 1
/area/kutjevo/exterior
name = "Kutjevo - Exterior"
diff --git a/code/game/area/prison_v3_fiorina.dm b/code/game/area/prison_v3_fiorina.dm
index deb5d8758784..9c60f8173ab8 100644
--- a/code/game/area/prison_v3_fiorina.dm
+++ b/code/game/area/prison_v3_fiorina.dm
@@ -8,7 +8,6 @@
icon_state = "fiorina"
can_build_special = TRUE //T-Comms structure
temperature = T20C
- lighting_use_dynamic = 1
ceiling = CEILING_GLASS
minimap_color = MINIMAP_AREA_COLONY
@@ -71,14 +70,13 @@
name = "Fiorina - LZ"
is_landing_zone = TRUE
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/fiorina/lz/near_lzI
name = "Fiorina - LZ1 Aux Port"
- is_resin_allowed = FALSE
/area/fiorina/lz/near_lzII
name = "Fiorina - LZ2 Prison Port"
- is_resin_allowed = FALSE
/area/fiorina/lz/console_I
name = "Fiorina - LZ1 Control Console"
diff --git a/code/game/area/shiva.dm b/code/game/area/shiva.dm
index 8ca47c03e5ca..e4939cd67e1e 100644
--- a/code/game/area/shiva.dm
+++ b/code/game/area/shiva.dm
@@ -7,14 +7,12 @@
icon_state = "shiva"
can_build_special = TRUE //T-Comms structure
temperature = ICE_COLONY_TEMPERATURE
- lighting_use_dynamic = TRUE
minimap_color = MINIMAP_AREA_COLONY
/area/shuttle/drop1/shiva
name = "Shiva's Snowball - Dropship Alamo Landing Zone"
icon_state = "shuttle"
icon = 'icons/turf/area_shiva.dmi'
- lighting_use_dynamic = TRUE
is_resin_allowed = FALSE
minimap_color = MINIMAP_AREA_LZ
@@ -22,7 +20,6 @@
name = "Shiva's Snowball - Dropship Normandy Landing Zone"
icon_state = "shuttle2"
icon = 'icons/turf/area_shiva.dmi'
- lighting_use_dynamic = TRUE
is_resin_allowed = FALSE
minimap_color = MINIMAP_AREA_LZ
diff --git a/code/game/area/shuttles.dm b/code/game/area/shuttles.dm
index f61f13097d12..62c42406e795 100644
--- a/code/game/area/shuttles.dm
+++ b/code/game/area/shuttles.dm
@@ -1,13 +1,15 @@
/area/shuttle
name = "Shuttle"
requires_power = FALSE
+ unlimited_power = TRUE
always_unpowered = FALSE
icon_state = "shuttle"
ceiling_muffle = TRUE
// Loading the same shuttle map at a different time will produce distinct area instances.
unique = FALSE
- lighting_use_dynamic = FALSE
+
+ base_lighting_alpha = 255
///area/shuttle/Initialize()
@@ -37,6 +39,7 @@
name = "Hyperspace"
desc = "Weeeeee"
ambience_exterior = 'sound/ambience/shuttle_fly_loop.ogg'
+ base_lighting_alpha = 255
/area/shuttle/vehicle_elevator
name = "Vehicle ASRS"
@@ -52,7 +55,7 @@
/area/shuttle/trijent_shuttle/elevator
requires_power = TRUE
- lighting_use_dynamic = FALSE
+ unlimited_power = FALSE
powernet_name = "ground"
/area/shuttle/trijent_shuttle/lz1
@@ -66,6 +69,7 @@
/area/shuttle/trijent_shuttle/omega
name = "Trijent Omega"
+
/area/shuttle/escape_pod
icon = 'icons/turf/area_almayer.dmi'
icon_state = "lifeboat"
diff --git a/code/game/area/space_station_13_areas.dm b/code/game/area/space_station_13_areas.dm
index 226ca555cd57..df5e54a77013 100644
--- a/code/game/area/space_station_13_areas.dm
+++ b/code/game/area/space_station_13_areas.dm
@@ -18,7 +18,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Space"
requires_power = 1
always_unpowered = 1
- lighting_use_dynamic = 0
+ base_lighting_alpha = 255
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
@@ -39,7 +39,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ceiling = CEILING_METAL
/area/admin/droppod
- lighting_use_dynamic = FALSE
+ base_lighting_alpha = 255
/area/admin/droppod/holding
name = "\improper Admin Supply Drops Droppod"
@@ -56,9 +56,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "start area"
icon_state = "start"
ceiling = CEILING_MAX
- requires_power = 0
- luminosity = 1
- lighting_use_dynamic = 0
+ requires_power = FALSE
+ static_lighting = FALSE
+ base_lighting_alpha = 255
has_gravity = 1
// === end remove
@@ -72,6 +72,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
statistic_exempt = TRUE
ceiling = CEILING_METAL
+ base_lighting_alpha = 255
+
/area/centcom/control
name = "\improper abandoned Centcom Control"
@@ -86,6 +88,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
statistic_exempt = TRUE
ceiling = CEILING_METAL
+ base_lighting_alpha = 255
+
/area/tdome/tdome1
name = "\improper abandoned Thunderdome (Team 1)"
icon_state = "green"
diff --git a/code/game/area/strata.dm b/code/game/area/strata.dm
index 1cf0eac58d1c..117cffa600d4 100644
--- a/code/game/area/strata.dm
+++ b/code/game/area/strata.dm
@@ -18,14 +18,16 @@ EXTERIOR is FUCKING FREEZING, and refers to areas out in the open and or exposed
/area/shuttle/drop1/strata //Not in Sulaco.DM because holy shit we need to sort things.
name = "Dropship Alamo Landing Zone"
icon_state = "shuttle"
- lighting_use_dynamic = 0 //No bad
+ base_lighting_alpha = 255
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/shuttle/drop2/strata
name = "Dropship Normandy Landing Zone"
icon_state = "shuttle2"
- lighting_use_dynamic = 0
+ base_lighting_alpha = 255
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/strata/ag
name = "Above Ground Area"
@@ -92,6 +94,7 @@ EXTERIOR is FUCKING FREEZING, and refers to areas out in the open and or exposed
unlimited_power = 1 //So the DS computer always works for the Queen
is_landing_zone = TRUE
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/strata/ag/exterior/landingzone_2
name = "Landing Zone 2 Pad - Ice Fields"
@@ -100,6 +103,7 @@ EXTERIOR is FUCKING FREEZING, and refers to areas out in the open and or exposed
unlimited_power = 1 //So the DS computer always works for the Queen
is_landing_zone = TRUE
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/strata/ag/interior/nearlz1
name = "Landing Zone 1 - Mining Aerodrome"
@@ -113,6 +117,7 @@ EXTERIOR is FUCKING FREEZING, and refers to areas out in the open and or exposed
icon_state = "nearlz2"
weather_enabled = TRUE //This LZ is outside, but consider disabling if it destroys the meta.
minimap_color = MINIMAP_AREA_LZ
+ is_resin_allowed = FALSE
/area/strata/ag/exterior/landingzone_valley
name = "Landing Zone Valley"
diff --git a/code/game/area/techtree.dm b/code/game/area/techtree.dm
index 70b70e3852be..24510562ab57 100644
--- a/code/game/area/techtree.dm
+++ b/code/game/area/techtree.dm
@@ -1,5 +1,5 @@
/area/techtree
- lighting_use_dynamic = FALSE
+ base_lighting_alpha = 255
ceiling = CEILING_MAX
requires_power = 0
ambience_exterior = AMBIENCE_ALMAYER
diff --git a/code/game/area/varadero.dm b/code/game/area/varadero.dm
index 09b082f2acd6..682f3ded1c66 100644
--- a/code/game/area/varadero.dm
+++ b/code/game/area/varadero.dm
@@ -8,7 +8,6 @@
icon_state = "varadero"
can_build_special = TRUE //T-Comms structure
temperature = TROPICAL_TEMP
- lighting_use_dynamic = TRUE
minimap_color = MINIMAP_AREA_COLONY
//shuttle stuff
@@ -17,7 +16,6 @@
name = "New Varadero - Dropship Alamo Landing Zone"
icon_state = "shuttle"
icon = 'icons/turf/area_varadero.dmi'
- lighting_use_dynamic = TRUE
is_resin_allowed = FALSE
minimap_color = MINIMAP_AREA_LZ
@@ -26,7 +24,6 @@
name = "New Varadero - Dropship Normandy Landing Zone"
icon_state = "shuttle2"
icon = 'icons/turf/area_varadero.dmi'
- lighting_use_dynamic = TRUE
is_resin_allowed = FALSE
minimap_color = MINIMAP_AREA_LZ
@@ -35,7 +32,6 @@
/area/varadero/exterior
name = "New Varadero - Exterior"
ceiling = CEILING_NONE
- lighting_use_dynamic = TRUE
ambience_exterior = AMBIENCE_NV
//soundscape_playlist
@@ -119,7 +115,6 @@
name = "New Varadero - East Beach"
is_resin_allowed = FALSE
icon_state = "varadero1"
- lighting_use_dynamic = TRUE
minimap_color = MINIMAP_AREA_JUNGLE
/area/varadero/exterior/monsoon
@@ -130,7 +125,6 @@
/area/varadero/exterior/pool
name = "New Varadero - Interior Pool"
icon_state = "varadero1"
- lighting_use_dynamic = TRUE
minimap_color = MINIMAP_AREA_COMMAND_CAVE
/area/varadero/exterior/eastocean
@@ -292,8 +286,6 @@
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
- luminosity = 0
- lighting_use_dynamic = 1
sound_environment = SOUND_ENVIRONMENT_AUDITORIUM
minimap_color = MINIMAP_AREA_CAVES
@@ -311,8 +303,7 @@
power_light = FALSE
power_equip = FALSE
power_environ = FALSE
- luminosity = 0
- lighting_use_dynamic = 1
+ minimap_color = MINIMAP_AREA_RESEARCH_CAVE
/area/varadero/interior_protected/caves/central
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index d2cad09edc83..e1541f8368b8 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -59,6 +59,36 @@
///Default pixel y shifting for the atom's icon.
var/base_pixel_y = 0
+ //light stuff
+
+ ///Light systems, only one of the three should be active at the same time.
+ var/light_system = STATIC_LIGHT
+ ///Range of the light in tiles. Zero means no light.
+ var/light_range = 0
+ ///Intensity of the light. The stronger, the less shadows you will see on the lit area.
+ var/light_power = 1
+ ///Hexadecimal RGB string representing the colour of the light. White by default.
+ var/light_color = COLOR_WHITE
+ ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values.
+ var/light_on = FALSE
+ ///Bitflags to determine lighting-related atom properties.
+ var/light_flags = NONE
+ ///Our light source. Don't fuck with this directly unless you have a good reason!
+ var/tmp/datum/dynamic_light_source/light
+ ///Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
+ var/tmp/list/hybrid_light_sources
+
+ //Values should avoid being close to -16, 16, -48, 48 etc.
+ //Best keep them within 10 units of a multiple of 32, as when the light is closer to a wall, the probability
+ //that a shadow extends to opposite corners of the light mask square is increased, resulting in more shadow
+ //overlays.
+ ///x offset for dynamic lights on this atom
+ var/light_pixel_x
+ ///y offset for dynamic lights on this atom
+ var/light_pixel_y
+ ///typepath for the lighting maskfor dynamic light sources
+ var/light_mask_type = null
+
///The color this atom will be if we choose to draw it on the minimap
var/minimap_color = MINIMAP_SOLID
@@ -77,7 +107,7 @@ Make sure the return value equals the return value of the parent so that the
directive is properly returned.
*/
//===========================================================================
-/atom/Destroy()
+/atom/Destroy(force)
orbiters = null // The component is attached to us normally and will be deleted elsewhere
QDEL_NULL(reagents)
QDEL_NULL(light)
@@ -327,6 +357,12 @@ Parameters are passed from New.
CRASH("Warning: [src]([type]) initialized multiple times!")
flags_atom |= INITIALIZED
+ if(light_system != MOVABLE_LIGHT && light_system != DIRECTIONAL_LIGHT && light_power && light_range)
+ update_light()
+ if(isturf(loc) && opacity)
+ var/turf/opaque_turf = loc
+ opaque_turf.directional_opacity = ALL_CARDINALS // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
+
pass_flags = pass_flags_cache[type]
if (isnull(pass_flags))
pass_flags = new()
@@ -569,6 +605,37 @@ Parameters are passed from New.
var/icon/I = icon(icon, icon_state, dir)
return (I.Width() + I.Height()) * 0.5
+/**
+ * If this object has lights, turn it on/off.
+ * user: the mob actioning this
+ * toggle_on: if TRUE, will try to turn ON the light. Opposite if FALSE
+ * cooldown: how long until you can toggle the light on/off again
+ * sparks: if a spark effect will be generated
+ * forced: if TRUE and toggle_on = FALSE, will cause the light to turn on in cooldown second
+ * originated_turf: if not null, will check if the obj_turf is closer than distance_max to originated_turf, and the proc will return if not
+ * distance_max: used to check if originated_turf is close to obj.loc
+*/
+/atom/proc/turn_light(mob/user, toggle_on , cooldown = 1 SECONDS, sparks = FALSE, forced = FALSE, light_again = FALSE)
+ if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_LIGHT) && !forced)
+ return STILL_ON_COOLDOWN
+ if(cooldown <= 0)
+ cooldown = 1 SECONDS
+ TIMER_COOLDOWN_START(src, COOLDOWN_LIGHT, cooldown)
+ if(toggle_on == light_on)
+ return NO_LIGHT_STATE_CHANGE
+ if(light_again && !toggle_on) //Is true when turn light is called by nightfall and the light is already on
+ addtimer(CALLBACK(src, PROC_REF(reset_light)), cooldown + 1)
+ if(sparks && light_on)
+ var/datum/effect_system/spark_spread/spark_system = new
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+ spark_system.start(src)
+ return CHECKS_PASSED
+
+///Turn on the light, should be called by a timer
+/atom/proc/reset_light()
+ turn_light(null, TRUE, 1 SECONDS, FALSE, TRUE)
+
/**
* Return the markup to for the dropdown list for the VV panel for this atom
*
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 17b37ce76630..b8a901ccf321 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -21,13 +21,24 @@
var/datum/component/orbiter/orbiting
+ /// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE]
+ var/blocks_emissive = FALSE
+ ///Internal holder for emissive blocker object, do not use directly use blocks_emissive
+ var/atom/movable/emissive_blocker/em_block
+
+ ///Lazylist to keep track on the sources of illumination.
+ var/list/affected_movable_lights
+ ///Highest-intensity light affecting us, which determines our visibility.
+ var/affecting_dynamic_lumi = 0
+
//===========================================================================
-/atom/movable/Destroy()
+/atom/movable/Destroy(force)
for(var/atom/movable/I in contents)
qdel(I)
if(pulledby)
pulledby.stop_pulling()
QDEL_NULL(launch_metadata)
+ QDEL_NULL(em_block)
if(loc)
loc.on_stored_atom_del(src) //things that container need to do when a movable atom inside it is deleted
@@ -38,6 +49,9 @@
. = ..()
moveToNullspace() //so we move into null space. Must be after ..() b/c atom's Dispose handles deleting our lighting stuff
+ QDEL_NULL(light)
+ QDEL_NULL(static_light)
+
//===========================================================================
//Overlays
@@ -60,6 +74,48 @@
return src.master.attack_hand(a, b, c)
return
+/atom/movable/Initialize(mapload, ...)
+ . = ..()
+ switch(blocks_emissive)
+ if(EMISSIVE_BLOCK_GENERIC)
+ var/mutable_appearance/gen_emissive_blocker = mutable_appearance(icon, icon_state, plane = EMISSIVE_PLANE, alpha = src.alpha)
+ gen_emissive_blocker.color = GLOB.em_block_color
+ gen_emissive_blocker.dir = dir
+ gen_emissive_blocker.appearance_flags |= appearance_flags
+ overlays += gen_emissive_blocker
+ if(EMISSIVE_BLOCK_UNIQUE)
+ render_target = ref(src)
+ em_block = new(src, render_target)
+ overlays += list(em_block)
+ if(opacity)
+ AddElement(/datum/element/light_blocking)
+ if(light_system == MOVABLE_LIGHT)
+ AddComponent(/datum/component/overlay_lighting)
+ if(light_system == DIRECTIONAL_LIGHT)
+ AddComponent(/datum/component/overlay_lighting, is_directional = TRUE)
+
+/*
+
+///Updates this movables emissive overlay
+/atom/movable/proc/update_emissive_block()
+ if(!blocks_emissive)
+ return
+ else if (blocks_emissive == EMISSIVE_BLOCK_GENERIC)
+ var/mutable_appearance/gen_emissive_blocker = emissive_blocker(icon, icon_state, alpha = src.alpha, appearance_flags = src.appearance_flags)
+ gen_emissive_blocker.dir = dir
+ if(blocks_emissive == EMISSIVE_BLOCK_UNIQUE)
+ if(!em_block)
+ render_target = ref(src)
+ em_block = new(src, render_target)
+ return em_block
+
+/atom/movable/update_overlays()
+ . = ..()
+
+ . += update_emissive_block()
+
+*/
+
/atom/movable/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION(VV_HK_EDIT_PARTICLES, "Edit Particles")
@@ -215,7 +271,7 @@
/atom/movable/clone/get_examine_text(mob/user)
return src.mstr.get_examine_text(user)
-/atom/movable/clone/bullet_act(obj/item/projectile/P)
+/atom/movable/clone/bullet_act(obj/projectile/P)
return src.mstr.bullet_act(P)
/////////////////////
@@ -251,10 +307,10 @@
if(light) //Clone lighting
if(!clone.light)
- clone.SetLuminosity(luminosity) //Create clone light
+ clone.set_light(luminosity) //Create clone light
else
if(clone.light)
- clone.SetLuminosity(0) //Kill clone light
+ clone.set_light(0) //Kill clone light
/atom/movable/proc/destroy_clone()
clones.Remove(src.clone)
@@ -279,3 +335,23 @@
//if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
// return
return throw_atom(target, range, speed, thrower, spin)
+
+///Keeps track of the sources of dynamic luminosity and updates our visibility with the highest.
+/atom/movable/proc/update_dynamic_luminosity()
+ var/highest = 0
+ for(var/i in affected_movable_lights)
+ if(affected_movable_lights[i] <= highest)
+ continue
+ highest = affected_movable_lights[i]
+ if(highest == affecting_dynamic_lumi)
+ return
+ luminosity -= affecting_dynamic_lumi
+ affecting_dynamic_lumi = highest
+ luminosity += affecting_dynamic_lumi
+
+
+///Helper to change several lighting overlay settings.
+/atom/movable/proc/set_light_range_power_color(range, power, color)
+ set_light_range(range)
+ set_light_power(power)
+ set_light_color(color)
diff --git a/code/game/cas_manager/datums/cas_fire_envelope.dm b/code/game/cas_manager/datums/cas_fire_envelope.dm
index 450fe8e6a82b..d7c939b76e16 100644
--- a/code/game/cas_manager/datums/cas_fire_envelope.dm
+++ b/code/game/cas_manager/datums/cas_fire_envelope.dm
@@ -125,10 +125,6 @@
mission_error = mission.error_message(check_result)
return 0
- if(target_turf && target_turf.signal_loc)
- var/turf/TT = get_turf(target_turf.signal_loc)
- if(TT && TT.z)
- msg_admin_niche("[key_name(usr)] launching Fire Mission '[mission.name]' onto [target_turf.name] at ([TT.x],[TT.y],[TT.z]) [ADMIN_JMP(TT)]")
//actual firemission code
execute_firemission_unsafe(target_turf, offset, dir, mission)
return 1
diff --git a/code/game/cas_manager/datums/cas_fire_mission.dm b/code/game/cas_manager/datums/cas_fire_mission.dm
index 42f5b4bd8655..0a04876414e7 100644
--- a/code/game/cas_manager/datums/cas_fire_mission.dm
+++ b/code/game/cas_manager/datums/cas_fire_mission.dm
@@ -98,6 +98,17 @@
if(initial_turf == null || check(linked_console) != FIRE_MISSION_ALL_GOOD)
return FIRE_MISSION_NOT_EXECUTABLE
+ var/obj/effect/firemission_effect = new(initial_turf)
+
+ firemission_effect.icon = 'icons/obj/items/weapons/projectiles.dmi'
+ firemission_effect.icon_state = "laser_target2"
+ firemission_effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ firemission_effect.invisibility = INVISIBILITY_MAXIMUM
+ QDEL_IN(firemission_effect, 5 SECONDS)
+
+ notify_ghosts(header = "CAS Fire Mission", message = "[usr ? usr : "Someone"] is launching Fire Mission '[name]' at [get_area(initial_turf)].", source = firemission_effect)
+ msg_admin_niche("[usr ? key_name(usr) : "Someone"] is launching Fire Mission '[name]' at ([initial_turf.x],[initial_turf.y],[initial_turf.z]) [ADMIN_JMP(initial_turf)]")
+
var/relative_dir
for(var/mob/M in range(15, initial_turf))
if(get_turf(M) == initial_turf)
diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm
index becee89adb6d..36271054bb21 100644
--- a/code/game/gamemodes/cm_initialize.dm
+++ b/code/game/gamemodes/cm_initialize.dm
@@ -567,21 +567,39 @@ Additional game mode variables.
var/hive_picked = tgui_input_list(xeno_candidate, "Select which Hive to attempt joining.", "Hive Choice", active_hives, theme="hive_status")
if(!hive_picked)
to_chat(xeno_candidate, SPAN_ALERT("Hive choice error. Aborting."))
- return
+ return FALSE
hive = GLOB.hive_datum[active_hives[hive_picked]]
else
hive = GLOB.hive_datum[last_active_hive]
- if(!hive.hive_location)
- to_chat(xeno_candidate, SPAN_WARNING("The selected hive does not have a hive core to spawn from!"))
- return
-
for(var/mob_name in hive.banished_ckeys)
if(hive.banished_ckeys[mob_name] == xeno_candidate.ckey)
to_chat(xeno_candidate, SPAN_WARNING("You are banished from the [hive], you may not rejoin unless the Queen re-admits you or dies."))
- return
+ return FALSE
+
+ var/list/selection_list = list()
+ var/list/selection_list_structure = list()
+
+ if(hive.hive_location?.lesser_drone_spawns >= 1)
+ selection_list += "hive core"
+ selection_list_structure += hive.hive_location
+
+ for(var/obj/effect/alien/resin/special/pylon/cycled_pylon as anything in hive.hive_structures[XENO_STRUCTURE_PYLON])
+ if(cycled_pylon.lesser_drone_spawns >= 1)
+ selection_list += "[cycled_pylon.name] at [get_area(cycled_pylon)]"
+ selection_list_structure += cycled_pylon
+
+ if(!length(selection_list))
+ to_chat(xeno_candidate, SPAN_WARNING("The selected hive does not have enough power for a lesser drone at any hive core or pylon!"))
+ return FALSE
+
+ var/prompt = tgui_input_list(xeno_candidate, "Select spawn?", "Spawnpoint Selection", selection_list)
+ if(!prompt)
+ return FALSE
+
+ var/obj/effect/alien/resin/special/pylon/selected_structure = selection_list_structure[selection_list.Find(prompt)]
- hive.hive_location.spawn_lesser_drone(xeno_candidate)
+ selected_structure.spawn_lesser_drone(xeno_candidate)
return TRUE
@@ -939,7 +957,7 @@ Additional game mode variables.
to_chat(joe_candidate, SPAN_WARNING("You are not whitelisted! You may apply on the forums to be whitelisted as a synth."))
return
- if(joe_candidate.ckey in joes)
+ if((joe_candidate.ckey in joes) && !MODE_HAS_TOGGLEABLE_FLAG(MODE_BYPASS_JOE))
if(show_warning)
to_chat(joe_candidate, SPAN_WARNING("You already were a Working Joe this round!"))
return
@@ -947,12 +965,12 @@ Additional game mode variables.
// council doesn't count towards this conditional.
if(joe_job.get_whitelist_status(RoleAuthority.roles_whitelist, joe_candidate.client) == WHITELIST_NORMAL)
var/joe_max = joe_job.total_positions
- if(joe_job.current_positions >= joe_max)
+ if((joe_job.current_positions >= joe_max) && !MODE_HAS_TOGGLEABLE_FLAG(MODE_BYPASS_JOE))
if(show_warning)
to_chat(joe_candidate, SPAN_WARNING("Only [joe_max] Working Joes may spawn per round."))
return
- if(!enter_allowed)
+ if(!enter_allowed && !MODE_HAS_TOGGLEABLE_FLAG(MODE_BYPASS_JOE))
if(show_warning)
to_chat(joe_candidate, SPAN_WARNING("There is an administrative lock from entering the game."))
return
diff --git a/code/game/gamemodes/cm_self_destruct.dm b/code/game/gamemodes/cm_self_destruct.dm
index 8c022fd0d916..d2f9c4eac784 100644
--- a/code/game/gamemodes/cm_self_destruct.dm
+++ b/code/game/gamemodes/cm_self_destruct.dm
@@ -103,7 +103,7 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
for(var/obj/structure/machinery/status_display/SD in machines)
if(is_mainship_level(SD.z))
SD.set_picture("evac")
- for(var/obj/docking_port/mobile/escape_shuttle/shuttle in SSshuttle.mobile)
+ for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile)
shuttle.prepare_evac()
activate_lifeboats()
process_evacuation()
@@ -121,7 +121,7 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
if(is_mainship_level(SD.z))
SD.set_picture("redalert")
- for(var/obj/docking_port/mobile/escape_shuttle/shuttle in SSshuttle.mobile)
+ for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile)
shuttle.cancel_evac()
return TRUE
@@ -132,17 +132,17 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
ai_announcement("WARNING: Evacuation order confirmed. Launching escape pods.", 'sound/AI/evacuation_confirmed.ogg')
addtimer(CALLBACK(src, PROC_REF(launch_lifeboats)), 10 SECONDS) // giving some time to board lifeboats
- for(var/obj/docking_port/mobile/escape_shuttle/shuttle in SSshuttle.mobile)
+ for(var/obj/docking_port/mobile/crashable/escape_shuttle/shuttle in SSshuttle.mobile)
shuttle.evac_launch()
sleep(50)
sleep(300) //Sleep 30 more seconds to make sure everyone had a chance to leave.
var/lifesigns = 0
// lifesigns += P.passengers
- var/obj/docking_port/mobile/lifeboat/lifeboat1 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_PORT)
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat1 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_PORT)
lifeboat1.check_for_survivors()
lifesigns += lifeboat1.survivors
- var/obj/docking_port/mobile/lifeboat/lifeboat2 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_STARBOARD)
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat2 = SSshuttle.getShuttle(MOBILE_SHUTTLE_LIFEBOAT_STARBOARD)
lifeboat2.check_for_survivors()
lifesigns += lifeboat2.survivors
ai_announcement("ATTENTION: Evacuation complete. Outbound lifesigns detected: [lifesigns ? lifesigns : "none"].", 'sound/AI/evacuation_complete.ogg')
@@ -166,7 +166,7 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
// LIFEBOATS CORNER
/datum/authority/branch/evacuation/proc/activate_lifeboats()
for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks)
- var/obj/docking_port/mobile/lifeboat/lifeboat = lifeboat_dock.get_docked()
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked()
if(lifeboat && lifeboat.available)
lifeboat.status = LIFEBOAT_ACTIVE
lifeboat_dock.open_dock()
@@ -174,15 +174,15 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
/datum/authority/branch/evacuation/proc/deactivate_lifeboats()
for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks)
- var/obj/docking_port/mobile/lifeboat/lifeboat = lifeboat_dock.get_docked()
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked()
if(lifeboat && lifeboat.available)
lifeboat.status = LIFEBOAT_INACTIVE
/datum/authority/branch/evacuation/proc/launch_lifeboats()
for(var/obj/docking_port/stationary/lifeboat_dock/lifeboat_dock in GLOB.lifeboat_almayer_docks)
- var/obj/docking_port/mobile/lifeboat/lifeboat = lifeboat_dock.get_docked()
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = lifeboat_dock.get_docked()
if(lifeboat && lifeboat.available)
- lifeboat.send_to_infinite_transit()
+ lifeboat.evac_launch()
//=========================================================================================
//=========================================================================================
diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost/skills.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost/skills.dm
index d6dfc695c5d0..a5126627adaf 100644
--- a/code/game/gamemodes/colonialmarines/whiskey_outpost/skills.dm
+++ b/code/game/gamemodes/colonialmarines/whiskey_outpost/skills.dm
@@ -17,6 +17,7 @@
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
SKILL_MEDICAL = SKILL_MEDICAL_TRAINED,
SKILL_LEADERSHIP = SKILL_LEAD_EXPERT,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_JTAC = SKILL_JTAC_EXPERT,
)
@@ -37,6 +38,7 @@
SKILL_ENGINEER = SKILL_ENGINEER_ENGI, //to fix CIC apc.
SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_ENGI,
SKILL_LEADERSHIP = SKILL_LEAD_MASTER,
+ SKILL_OVERWATCH = SKILL_OVERWATCH_TRAINED,
SKILL_MEDICAL = SKILL_MEDICAL_MEDIC,
SKILL_POLICE = SKILL_POLICE_FLASH,
SKILL_POWERLOADER = SKILL_POWERLOADER_MASTER,
diff --git a/code/game/jobs/job/civilians/support/working_joe.dm b/code/game/jobs/job/civilians/support/working_joe.dm
index d4b575f324f2..bdc7d3aa071b 100644
--- a/code/game/jobs/job/civilians/support/working_joe.dm
+++ b/code/game/jobs/job/civilians/support/working_joe.dm
@@ -12,6 +12,7 @@
flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_WHITELISTED|ROLE_CUSTOM_SPAWN
flags_whitelist = WHITELIST_JOE
gear_preset = /datum/equipment_preset/synth/working_joe
+ gets_emergency_kit = FALSE
job_options = list(STANDARD_VARIANT = "JOE", HAZMAT_VARIANT = "HAZ")
var/standard = TRUE
@@ -45,11 +46,6 @@
else
. = {"You are a Working Joe for Hazardous Environments! You are held to a higher standard and are required to obey not only the Server Rules but Marine Law, Roleplay Expectations and Synthetic Rules. You are a variant of the Working Joe built for tougher environments and fulfill the specific duty of dangerous repairs or maintenance. Your primary task is to maintain the reactor, SMES and AI Core. Your secondary task is to respond to hazardous environments, such as an atmospheric breach or biohazard spill, and assist with repairs when ordered to by either an AI Mainframe, or a Commisioned Officer. You should not be seen outside of emergencies besides in Engineering and the AI Core! Stay in character at all times. Use the APOLLO link to communicate with your uplink!"}
-
-/datum/job/civilian/working_joe/announce_entry_message(mob/living/carbon/human/H)
- addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(ai_announcement), "[H.real_name] has been activated."), 1.5 SECONDS)
- return ..()
-
/obj/effect/landmark/start/working_joe
name = JOB_WORKING_JOE
icon_state = "wj_spawn"
diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm
index 234902e11d22..0785fc5c337f 100644
--- a/code/game/jobs/job/job.dm
+++ b/code/game/jobs/job/job.dm
@@ -37,6 +37,8 @@
/// When set you will be able to choose between the different job options when selecting your role.
/// Associated list. Main list elements - actual options, associated values - shorthands for job preferences menu (keep those short).
var/job_options
+ /// If TRUE, this job will spawn w/ a cryo emergency kit during evac/red alert
+ var/gets_emergency_kit = TRUE
/datum/job/New()
. = ..()
diff --git a/code/game/jobs/job/marine/squads.dm b/code/game/jobs/job/marine/squads.dm
index fb85be012d30..116de402104d 100644
--- a/code/game/jobs/job/marine/squads.dm
+++ b/code/game/jobs/job/marine/squads.dm
@@ -370,13 +370,14 @@
var/message_colour = chat_color
if(only_leader)
if(squad_leader)
- var/mob/living/carbon/human/SL = squad_leader
- if(!SL.stat && SL.client)
- SL.play_screen_text("[title_text]
" + text, /atom/movable/screen/text/screen_text/command_order, message_colour)
+ if(!squad_leader.stat && squad_leader.client)
+ playsound_client(squad_leader.client, 'sound/effects/radiostatic.ogg', squad_leader.loc, 25, FALSE)
+ squad_leader.play_screen_text("[title_text]
" + text, /atom/movable/screen/text/screen_text/command_order, message_colour)
else
- for(var/mob/living/carbon/human/M in marines_list)
- if(!M.stat && M.client) //Only living and connected people in our squad
- M.play_screen_text("[title_text]
" + text, /atom/movable/screen/text/screen_text/command_order, message_colour)
+ for(var/mob/living/carbon/human/marine in marines_list)
+ if(!marine.stat && marine.client) //Only living and connected people in our squad
+ playsound_client(marine.client, 'sound/effects/radiostatic.ogg', marine.loc, 25, FALSE)
+ marine.play_screen_text("[title_text]
" + text, /atom/movable/screen/text/screen_text/command_order, message_colour)
/// Displays a message to the squad members in chat
/datum/squad/proc/send_message(text = "", plus_name = 0, only_leader = 0)
diff --git a/code/game/machinery/ARES/ARES.dm b/code/game/machinery/ARES/ARES.dm
index de4140ef1b81..ed4391c89c24 100644
--- a/code/game/machinery/ARES/ARES.dm
+++ b/code/game/machinery/ARES/ARES.dm
@@ -149,14 +149,17 @@
var/list/records_talking = list()
/// Holds all (/datum/ares_record/requisition_log)s
var/list/records_asrs = list()
- /// Holds all (/datum/ares_record/security)s and (/datum/ares_record/antiair)s
+ /// Holds all (/datum/ares_record/security)s (including AA)
var/list/records_security = list()
+ /// Holds all (/datum/ares_record/flight)s
+ var/list/records_flight = list()
/// Is nuke request usable or not?
var/nuke_available = TRUE
COOLDOWN_DECLARE(ares_distress_cooldown)
COOLDOWN_DECLARE(ares_nuclear_cooldown)
+ COOLDOWN_DECLARE(ares_quarters_cooldown)
/obj/structure/machinery/computer/ares_console/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override)
if(link && !override)
@@ -205,12 +208,6 @@
var/list/login_list = list()
- /// If this is used to create AI Core access tickets
- var/ticket_console = FALSE
- var/obj/item/card/id/authenticator_id
- var/ticket_authenticated = FALSE
- var/obj/item/card/id/target_id
-
/obj/structure/machinery/computer/working_joe/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override)
if(link && !override)
return FALSE
diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm
index a335a36994e5..e03f218f0f34 100644
--- a/code/game/machinery/ARES/ARES_procs.dm
+++ b/code/game/machinery/ARES/ARES_procs.dm
@@ -32,6 +32,8 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/// Working Joe stuff
var/list/tickets_maintenance = list()
var/list/tickets_access = list()
+ var/list/waiting_ids = list()
+ var/list/active_ids = list()
/datum/ares_link/Destroy()
for(var/obj/structure/machinery/ares/link in linked_systems)
@@ -57,20 +59,23 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/datum/ares_link/proc/log_ares_bioscan(title, input)
interface.records_bioscan.Add(new /datum/ares_record/bioscan(title, input))
-/datum/ares_link/proc/log_ares_bombardment(mob/living/user, ob_name, coordinates)
- interface.records_bombardment.Add(new /datum/ares_record/bombardment(ob_name, "Bombardment fired at [coordinates].", user))
+/datum/ares_link/proc/log_ares_bombardment(user_name, ob_name, coordinates)
+ interface.records_bombardment.Add(new /datum/ares_record/bombardment(ob_name, "Bombardment fired at [coordinates].", user_name))
/datum/ares_link/proc/log_ares_announcement(title, message)
interface.records_announcement.Add(new /datum/ares_record/announcement(title, message))
-/datum/ares_link/proc/log_ares_antiair(mob/living/user, details)
- interface.records_security.Add(new /datum/ares_record/antiair(details, user))
-
-/datum/ares_link/proc/log_ares_requisition(source, details, mob/living/user)
- interface.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user))
+/datum/ares_link/proc/log_ares_requisition(source, details, user_name)
+ interface.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user_name))
/datum/ares_link/proc/log_ares_security(title, details)
interface.records_security.Add(new /datum/ares_record/security(title, details))
+
+/datum/ares_link/proc/log_ares_antiair(details)
+ interface.records_security.Add(new /datum/ares_record/security/antiair(details))
+
+/datum/ares_link/proc/log_ares_flight(user_name, details)
+ interface.records_flight.Add(new /datum/ares_record/flight(details, user_name))
// ------ End ARES Logging Procs ------ //
/proc/ares_apollo_talk(broadcast_message)
@@ -208,6 +213,7 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
data["distresstime"] = ares_distress_cooldown
data["distresstimelock"] = DISTRESS_TIME_LOCK
+ data["quarterstime"] = ares_quarters_cooldown
data["mission_failed"] = SSticker.mode.is_in_endgame
data["nuketimelock"] = NUCLEAR_TIME_LOCK
data["nuke_available"] = nuke_available
@@ -224,8 +230,6 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
var/list/logged_alerts = list()
for(var/datum/ares_record/security/security_alert as anything in records_security)
- if(!istype(security_alert))
- continue
var/list/current_alert = list()
current_alert["time"] = security_alert.time
current_alert["title"] = security_alert.title
@@ -234,6 +238,17 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
logged_alerts += list(current_alert)
data["records_security"] = logged_alerts
+ var/list/logged_flights = list()
+ for(var/datum/ares_record/flight/flight_log as anything in records_flight)
+ var/list/current_flight = list()
+ current_flight["time"] = flight_log.time
+ current_flight["title"] = flight_log.title
+ current_flight["details"] = flight_log.details
+ current_flight["user"] = flight_log.user
+ current_flight["ref"] = "\ref[flight_log]"
+ logged_flights += list(current_flight)
+ data["records_flight"] = logged_flights
+
var/list/logged_bioscans = list()
for(var/datum/ares_record/bioscan/scan as anything in records_bioscan)
var/list/current_scan = list()
@@ -279,18 +294,6 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
logged_discussions += list(deleted_disc)
data["deleted_discussions"] = logged_discussions
- var/list/logged_adjustments = list()
- for(var/datum/ares_record/antiair/aa_adjustment as anything in records_security)
- if(!istype(aa_adjustment))
- continue
- var/list/current_adjustment = list()
- current_adjustment["time"] = aa_adjustment.time
- current_adjustment["details"] = aa_adjustment.details
- current_adjustment["user"] = aa_adjustment.user
- current_adjustment["ref"] = "\ref[aa_adjustment]"
- logged_adjustments += list(current_adjustment)
- data["aa_adjustments"] = logged_adjustments
-
var/list/logged_orders = list()
for(var/datum/ares_record/requisition_log/req_order as anything in records_asrs)
if(!istype(req_order))
@@ -428,12 +431,12 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
if("page_security")
last_menu = current_menu
current_menu = "security"
+ if("page_flight")
+ last_menu = current_menu
+ current_menu = "flight_log"
if("page_requisitions")
last_menu = current_menu
current_menu = "requisitions"
- if("page_antiair")
- last_menu = current_menu
- current_menu = "antiair"
if("page_emergency")
last_menu = current_menu
current_menu = "emergency"
@@ -457,7 +460,7 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
new_title = "[record.title] at [record.time]"
new_details = record.details
records_announcement -= record
- if(ARES_RECORD_SECURITY)
+ if(ARES_RECORD_SECURITY, ARES_RECORD_ANTIAIR)
new_title = "[record.title] at [record.time]"
new_details = record.details
records_security -= record
@@ -506,16 +509,18 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
// -- Emergency Buttons -- //
if("general_quarters")
- if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA)
- to_chat(usr, SPAN_WARNING("Alert level is already red or above, General Quarters cannot be called."))
+ if(!COOLDOWN_FINISHED(src, ares_quarters_cooldown))
+ to_chat(usr, SPAN_WARNING("It has not been long enough since the last General Quarters call!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
- set_security_level(2, no_sound = TRUE, announce = FALSE)
+ if(security_level < SEC_LEVEL_RED)
+ set_security_level(SEC_LEVEL_RED, no_sound = TRUE, announce = FALSE)
shipwide_ai_announcement("ATTENTION! GENERAL QUARTERS. ALL HANDS, MAN YOUR BATTLESTATIONS.", MAIN_AI_SYSTEM, 'sound/effects/GQfullcall.ogg')
log_game("[key_name(usr)] has called for general quarters via ARES.")
message_admins("[key_name_admin(usr)] has called for general quarters via ARES.")
var/datum/ares_link/link = GLOB.ares_link
link.log_ares_security("General Quarters", "[last_login] has called for general quarters via ARES.")
+ COOLDOWN_START(src, ares_quarters_cooldown, 10 MINUTES)
. = TRUE
if("evacuation_start")
@@ -563,7 +568,7 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
for(var/client/admin in GLOB.admins)
if((R_ADMIN|R_MOD) & admin.admin_holder.rights)
playsound_client(admin,'sound/effects/sos-morse-code.ogg',10)
- message_admins("[key_name(usr)] has requested a Distress Beacon (via ARES)! [CC_MARK(usr)] (SEND) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]")
+ SSticker.mode.request_ert(usr, TRUE)
to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM High Command."))
COOLDOWN_START(src, ares_distress_cooldown, COOLDOWN_COMM_REQUEST)
return TRUE
@@ -620,100 +625,22 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/obj/structure/machinery/computer/working_joe/ares_auth_to_text(access_level)
switch(access_level)
- if(APOLLO_ACCESS_REQUEST)//0
+ if(APOLLO_ACCESS_LOGOUT)//0
+ return "Logged Out"
+ if(APOLLO_ACCESS_REQUEST)//1
return "Unauthorized Personnel"
- if(APOLLO_ACCESS_REPORTER)//1
+ if(APOLLO_ACCESS_REPORTER)//2
return "Validated Incident Reporter"
- if(APOLLO_ACCESS_TEMP)//2
+ if(APOLLO_ACCESS_TEMP)//3
return "Authorized Visitor"
- if(APOLLO_ACCESS_AUTHED)//3
+ if(APOLLO_ACCESS_AUTHED)//4
return "Certified Personnel"
- if(APOLLO_ACCESS_JOE)//4
+ if(APOLLO_ACCESS_JOE)//5
return "Working Joe"
- if(APOLLO_ACCESS_DEBUG)//5
+ if(APOLLO_ACCESS_DEBUG)//6
return "AI Service Technician"
// ------ Maintenance Controller UI ------ //
-/obj/structure/machinery/computer/working_joe/verb/eject_id()
- set category = "Object"
- set name = "Eject ID Card"
- set src in oview(1)
-
- if(!usr || usr.stat || usr.lying)
- return FALSE
-
- if(authenticator_id)
- authenticator_id.loc = get_turf(src)
- if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human))
- usr.put_in_hands(authenticator_id)
- if(operable()) // Powered. Console can response.
- visible_message("[SPAN_BOLD("[src]")] states, \"AUTH LOGOUT: Session end confirmed.\"")
- else
- to_chat(usr, "You remove [authenticator_id] from [src].")
- ticket_authenticated = FALSE // No card - no access
- authenticator_id = null
-
- else if(target_id)
- target_id.loc = get_turf(src)
- if(!usr.get_active_hand() && istype(usr,/mob/living/carbon/human))
- usr.put_in_hands(target_id)
- else
- to_chat(usr, "You remove [target_id] from [src].")
- target_id = null
-
- else
- to_chat(usr, "There is nothing to remove from the console.")
- return
-
-/obj/structure/machinery/computer/working_joe/attackby(obj/object, mob/user)
- if(istype(object, /obj/item/card/id))
- if(!ticket_console)
- to_chat(user, SPAN_WARNING("This console doesn't have an ID port!"))
- return FALSE
- if(!operable())
- to_chat(user, SPAN_NOTICE("You try to insert [object] but [src] remains silent."))
- return FALSE
- var/obj/item/card/id/idcard = object
- if((idcard.assignment == JOB_WORKING_JOE) || (ACCESS_ARES_DEBUG in idcard.access))
- if(!authenticator_id)
- if(user.drop_held_item())
- object.forceMove(src)
- authenticator_id = object
- authenticate(authenticator_id)
- else if(!target_id)
- if(user.drop_held_item())
- object.forceMove(src)
- target_id = object
- else
- to_chat(user, "Both slots are full already. Remove a card first.")
- return FALSE
- else
- if(!target_id)
- if(user.drop_held_item())
- object.forceMove(src)
- target_id = object
- else
- to_chat(user, "Both slots are full already. Remove a card first.")
- return FALSE
- else
- ..()
-
-/obj/structure/machinery/computer/working_joe/proc/authenticate(obj/item/card/id/id_card)
- if(!id_card)
- visible_message("[SPAN_BOLD("[src]")] states, \"AUTH ERROR: Authenticator card is missing!\"")
- return FALSE
-
- if((ACCESS_MARINE_AI in id_card.access) || (ACCESS_ARES_DEBUG in id_card.access))
- ticket_authenticated = TRUE
- visible_message("[SPAN_BOLD("[src]")] states, \"AUTH LOGIN: Welcome, [id_card.registered_name]. Access granted.\"")
- return TRUE
-
- visible_message("[SPAN_BOLD("[src]")] states, \"AUTH ERROR: Access denied.\"")
- return FALSE
-
-
-
-
/obj/structure/machinery/computer/working_joe/attack_hand(mob/user as mob)
if(..() || !allowed(usr) || inoperable())
return FALSE
@@ -730,7 +657,6 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/obj/structure/machinery/computer/working_joe/ui_data(mob/user)
var/list/data = list()
- data["ticket_console"] = ticket_console
data["current_menu"] = current_menu
data["last_page"] = last_menu
@@ -748,9 +674,6 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
data["apollo_log"] = list()
data["apollo_log"] += link.apollo_log
- data["authenticated"] = ticket_authenticated
-
-
var/list/logged_maintenance = list()
for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance)
if(!istype(maint_ticket))
@@ -775,10 +698,11 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
data["maintenance_tickets"] = logged_maintenance
var/list/logged_access = list()
+ var/list/requesting_access = list()
for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access)
var/lock_status = TICKET_OPEN
switch(access_ticket.ticket_status)
- if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED)
+ if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED)
lock_status = TICKET_CLOSED
var/list/current_ticket = list()
@@ -793,8 +717,10 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
current_ticket["lock_status"] = lock_status
current_ticket["ref"] = "\ref[access_ticket]"
logged_access += list(current_ticket)
- data["access_tickets"] = logged_access
+ if(lock_status == TICKET_OPEN)
+ requesting_access += access_ticket.ticket_name
+ data["access_tickets"] = logged_access
return data
@@ -864,9 +790,6 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
if("page_request")
last_menu = current_menu
current_menu = "access_requests"
- if("page_returns")
- last_menu = current_menu
- current_menu = "access_returns"
if("page_report")
last_menu = current_menu
current_menu = "maint_reports"
@@ -963,28 +886,122 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
return TRUE
if("new_access")
- var/priority_report = FALSE
- var/ticket_holder = tgui_input_text(operator, "Who is the ticket for?", "Ticket Holder", encode = FALSE)
+ var/obj/item/card/id/idcard = operator.get_active_hand()
+ var/has_id = FALSE
+ if(istype(idcard))
+ has_id = TRUE
+ else if(operator.wear_id)
+ idcard = operator.wear_id
+ if(istype(idcard))
+ has_id = TRUE
+ if(!has_id)
+ to_chat(operator, SPAN_WARNING("You require an ID card to request an access ticket!"))
+ playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
+ return FALSE
+ if(idcard.registered_name != last_login)
+ to_chat(operator, SPAN_WARNING("This ID card does not match the active login!"))
+ playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
+ return FALSE
+
+ var/ticket_holder = last_login
if(!ticket_holder)
return FALSE
var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE)
if(!details)
return FALSE
- if(authentication >= APOLLO_ACCESS_AUTHED)
- var/is_priority = tgui_alert(operator, "Is this a priority request?", "Priority designation", list("Yes", "No"))
- if(is_priority == "Yes")
- priority_report = TRUE
-
- var/confirm = alert(operator, "Please confirm the submission of your access ticket request. \n\n Priority: [priority_report ? "Yes" : "No"] \n Holder: '[ticket_holder]' \n Details: '[details]' \n\n Is this correct?", "Confirmation", "Yes", "No")
+ var/confirm = alert(operator, "Please confirm the submission of your access ticket request. \n\nHolder: '[ticket_holder]' \n Details: '[details]' \n\n Is this correct?", "Confirmation", "Yes", "No")
if(confirm != "Yes" || !link)
return FALSE
- var/datum/ares_ticket/access/access_ticket = new(last_login, ticket_holder, details, priority_report)
+ var/datum/ares_ticket/access/access_ticket = new(last_login, ticket_holder, details, FALSE, idcard.registered_gid)
+ link.waiting_ids += idcard
link.tickets_access += access_ticket
- if(priority_report)
- ares_apollo_talk("Priority Access Request: [ticket_holder] - ID [access_ticket.ticket_id]. Seek and resolve.")
log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Holder '[ticket_holder]' and Details of '[details]'.")
+ message_admins(SPAN_STAFF_IC("[key_name_admin(operator)] created a new ARES Access Ticket."), 1)
return TRUE
+ if("return_access")
+ playsound = FALSE
+ var/datum/ares_ticket/access/access_ticket
+ for(var/datum/ares_ticket/access/possible_ticket in link.tickets_access)
+ if(possible_ticket.ticket_status != TICKET_GRANTED)
+ continue
+ if(possible_ticket.ticket_name != last_login)
+ continue
+ access_ticket = possible_ticket
+ break
+
+ for(var/obj/item/card/id/identification in link.active_ids)
+ if(!istype(identification))
+ continue
+ if(identification.registered_gid != access_ticket.user_id_num)
+ continue
+
+ access_ticket.ticket_status = TICKET_RETURNED
+ identification.access -= ACCESS_MARINE_AI_TEMP
+ identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]."
+
+ to_chat(operator, SPAN_NOTICE("Temporary Access Ticket surrendered."))
+ playsound(src, 'sound/machines/chime.ogg', 15, 1)
+ ares_apollo_talk("[last_login] surrendered their access ticket.")
+
+ authentication = get_ares_access(identification)
+ if(authentication)
+ login_list += "[last_login] at [worldtime2text()], Surrendered Temporary Access Ticket."
+ return TRUE
+
+ to_chat(operator, SPAN_WARNING("This ID card does not have an access ticket!"))
+ playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
+ return FALSE
+
+ if("auth_access")
+ playsound = FALSE
+ var/datum/ares_ticket/access/access_ticket = locate(params["ticket"])
+ if(!access_ticket)
+ return FALSE
+ for(var/obj/item/card/id/identification in link.waiting_ids)
+ if(!istype(identification))
+ continue
+ if(identification.registered_gid != access_ticket.user_id_num)
+ continue
+ identification.handle_ares_access(last_login, operator)
+ access_ticket.ticket_status = TICKET_GRANTED
+ playsound(src, 'sound/machines/chime.ogg', 15, 1)
+ return TRUE
+ for(var/obj/item/card/id/identification in link.active_ids)
+ if(!istype(identification))
+ continue
+ if(identification.registered_gid != access_ticket.user_id_num)
+ continue
+ identification.handle_ares_access(last_login, operator)
+ access_ticket.ticket_status = TICKET_REVOKED
+ playsound(src, 'sound/machines/chime.ogg', 15, 1)
+ return TRUE
+ return FALSE
+
if(playsound)
playsound(src, "keyboard_alt", 15, 1)
+
+/obj/item/card/id/proc/handle_ares_access(logged_in, mob/user)
+ var/announce_text = "[logged_in] revoked core access from [registered_name]'s ID card."
+ var/operator = key_name(user)
+ var/datum/ares_link/link = GLOB.ares_link
+ if(logged_in == MAIN_AI_SYSTEM)
+ if(!user)
+ operator = "[MAIN_AI_SYSTEM] (Sensor Trip)"
+ else
+ operator = "[user.ckey]/([MAIN_AI_SYSTEM])"
+ if(ACCESS_MARINE_AI_TEMP in access)
+ access -= ACCESS_MARINE_AI_TEMP
+ link.active_ids -= src
+ modification_log += "Temporary AI access revoked by [operator]"
+ to_chat(user, SPAN_NOTICE("Access revoked from [registered_name]."))
+ else
+ access += ACCESS_MARINE_AI_TEMP
+ modification_log += "Temporary AI access granted by [operator]"
+ announce_text = "[logged_in] granted core access to [registered_name]'s ID card."
+ to_chat(user, SPAN_NOTICE("Access granted to [registered_name]."))
+ link.waiting_ids -= src
+ link.active_ids += src
+ ares_apollo_talk(announce_text)
+ return TRUE
diff --git a/code/game/machinery/ARES/ARES_records.dm b/code/game/machinery/ARES/ARES_records.dm
index 4e2b479e71a2..19751462bc37 100644
--- a/code/game/machinery/ARES/ARES_records.dm
+++ b/code/game/machinery/ARES/ARES_records.dm
@@ -32,13 +32,21 @@
/datum/ares_record/security
record_name = ARES_RECORD_SECURITY
-/datum/ares_record/antiair
+/datum/ares_record/security/antiair
record_name = ARES_RECORD_ANTIAIR
-/datum/ares_record/antiair/New(details, user)
+/datum/ares_record/security/antiair/New(details)
time = worldtime2text()
src.title = "AntiAir Adjustment"
src.details = details
+
+/datum/ares_record/flight
+ record_name = ARES_RECORD_FLIGHT
+
+/datum/ares_record/flight/New(details, user)
+ time = worldtime2text()
+ src.title = "Flight Log"
+ src.details = details
src.user = user
/datum/ares_record/bombardment
@@ -107,3 +115,17 @@
/datum/ares_ticket/access
ticket_type = ARES_RECORD_ACCESS
+ var/user_id_num
+
+/datum/ares_ticket/access/New(user, name, details, priority, global_id_num)
+ var/ref_holder = "\ref[src]"
+ var/pos = length(ref_holder)
+ var/new_id = "#[copytext("\ref[src]", pos - 4, pos)]"
+
+ ticket_time = worldtime2text()
+ ticket_submitter = user
+ ticket_details = details
+ ticket_name = name
+ ticket_priority = priority
+ ticket_id = new_id
+ user_id_num = global_id_num
diff --git a/code/game/machinery/ARES/ARES_step_triggers.dm b/code/game/machinery/ARES/ARES_step_triggers.dm
index a50aa40abd90..335a877f9f25 100644
--- a/code/game/machinery/ARES/ARES_step_triggers.dm
+++ b/code/game/machinery/ARES/ARES_step_triggers.dm
@@ -163,7 +163,18 @@
to_chat(passer, SPAN_BOLDWARNING("You hear a harsh buzzing sound as you cross the threshold!"))
ares_apollo_talk(broadcast_message)
if(idcard)
- idcard.access -= ACCESS_MARINE_AI_TEMP
+ /// Removes the access from the ID and updates the ID's modification log.
+ for(var/obj/item/card/id/identification in link.active_ids)
+ if(identification != idcard)
+ continue
+ idcard.access -= ACCESS_MARINE_AI_TEMP
+ link.active_ids -= idcard
+ idcard.modification_log += "Temporary AI access revoked by [MAIN_AI_SYSTEM]"
+ /// Updates the related access ticket.
+ for(var/datum/ares_ticket/access/access_ticket in link.tickets_access)
+ if(access_ticket.user_id_num != idcard.registered_gid)
+ continue
+ access_ticket.ticket_status = TICKET_REVOKED
COOLDOWN_START(src, sensor_cooldown, COOLDOWN_ARES_ACCESS_CONTROL)
if(alert_id && link)
for(var/obj/effect/step_trigger/ares_alert/sensor in link.linked_alerts)
diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm
index 28e045163f06..16512a944be1 100644
--- a/code/game/machinery/air_alarm.dm
+++ b/code/game/machinery/air_alarm.dm
@@ -136,8 +136,6 @@
/obj/structure/machinery/alarm/proc/first_run()
alarm_area = get_area(src)
- if (alarm_area.master)
- alarm_area = alarm_area.master
area_uid = alarm_area.uid
if (name == "alarm")
name = "[alarm_area.name] Air Alarm"
@@ -203,11 +201,10 @@
/obj/structure/machinery/alarm/proc/elect_master()
if(!alarm_area)
return 0
- for (var/area/A in alarm_area.related)
- for (var/obj/structure/machinery/alarm/AA in A)
- if (!(AA.inoperable()))
- alarm_area.master_air_alarm = AA
- return 1
+ for (var/obj/structure/machinery/alarm/AA in alarm_area)
+ if (!(AA.inoperable()))
+ alarm_area.master_air_alarm = AA
+ return 1
return 0
/obj/structure/machinery/alarm/proc/get_danger_level(current_value, list/danger_levels)
@@ -314,9 +311,8 @@
/obj/structure/machinery/alarm/proc/apply_mode()
//propagate mode to other air alarms in the area
//TODO: make it so that players can choose between applying the new mode to the room they are in (related area) vs the entire alarm area
- for (var/area/RA in alarm_area.related)
- for (var/obj/structure/machinery/alarm/AA in RA)
- AA.mode = mode
+ for (var/obj/structure/machinery/alarm/AA in alarm_area)
+ AA.mode = mode
switch(mode)
if(AALARM_MODE_SCRUBBING)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 7e548d02d919..3c2c81ff0ce7 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -90,7 +90,7 @@ update_flag
density = FALSE
update_icon()
-/obj/structure/machinery/portable_atmospherics/canister/bullet_act(obj/item/projectile/Proj)
+/obj/structure/machinery/portable_atmospherics/canister/bullet_act(obj/projectile/Proj)
if(Proj.ammo.damage)
update_health(round(Proj.ammo.damage / 2))
..()
diff --git a/code/game/machinery/bio-dome_floodlights.dm b/code/game/machinery/bio-dome_floodlights.dm
index 488cf1ed79cc..a1f028a79f30 100644
--- a/code/game/machinery/bio-dome_floodlights.dm
+++ b/code/game/machinery/bio-dome_floodlights.dm
@@ -60,9 +60,9 @@
spawn(rand(0,50))
if(F.is_lit) //Shut it down
- F.SetLuminosity(0)
+ F.set_light(0)
else
- F.SetLuminosity(F.lum_value)
+ F.set_light(F.lum_value)
F.is_lit = !(F.is_lit)
F.update_icon()
return 0
@@ -101,7 +101,6 @@
if(fswitch?.floodlist)
fswitch.floodlist -= src
fswitch = null
- SetLuminosity(0)
return ..()
/obj/structure/machinery/hydro_floodlight/update_icon()
@@ -130,7 +129,7 @@
user.visible_message(SPAN_NOTICE("[user] finishes welding [src]'s damage."), \
SPAN_NOTICE("You finish welding [src]'s damage."))
if(is_lit)
- SetLuminosity(lum_value)
+ set_light(lum_value)
update_icon()
return 1
else
@@ -161,7 +160,7 @@
if(do_after(user, 50, INTERRUPT_ALL, BUSY_ICON_HOSTILE) && !damaged) //Not when it's already damaged.
if(!src) return 0
damaged = 1
- SetLuminosity(0)
+ set_light(0)
user.visible_message(SPAN_DANGER("[user] slashes up [src]!"),
SPAN_DANGER("You slash up [src]!"))
playsound(src, 'sound/weapons/blade1.ogg', 25, 1)
diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index aff1efa3de66..116753093fe5 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -3,7 +3,8 @@
/obj/structure/machinery/bot
icon = 'icons/obj/structures/machinery/aibots.dmi'
layer = MOB_LAYER
- luminosity = 3
+ light_system = MOVABLE_LIGHT
+ light_range = 3
use_power = USE_POWER_NONE
var/obj/item/card/id/botcard // the ID card that the bot "holds"
var/on = 1
@@ -15,6 +16,12 @@
var/open = 0//Maint panel
var/locked = 1
+/obj/structure/machinery/bot/Initialize(mapload, ...)
+ . = ..()
+
+ if(light_range)
+ set_light_on(TRUE)
+
/obj/structure/machinery/bot/Destroy()
QDEL_NULL(botcard)
. = ..()
@@ -24,12 +31,12 @@
if(stat)
return 0
on = 1
- SetLuminosity(initial(luminosity))
+ set_light(initial(luminosity))
return 1
/obj/structure/machinery/bot/proc/turn_off()
on = 0
- SetLuminosity(0)
+ set_light(0)
/obj/structure/machinery/bot/proc/explode()
qdel(src)
@@ -38,10 +45,6 @@
if(health <= 0)
explode()
-/obj/structure/machinery/bot/Destroy()
- SetLuminosity(0)
- . = ..()
-
/obj/structure/machinery/bot/get_examine_text(mob/user)
. = ..()
if(health < maxhealth)
@@ -89,7 +92,7 @@
else
..()
-/obj/structure/machinery/bot/bullet_act(obj/item/projectile/Proj)
+/obj/structure/machinery/bot/bullet_act(obj/projectile/Proj)
health -= Proj.ammo.damage
..()
healthcheck()
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 20208a573c61..4d17e4a08803 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -79,7 +79,7 @@
network = list()
cameranet.removeCamera(src)
stat |= EMPED
- SetLuminosity(0)
+ set_light(0)
triggerCameraAlarm()
spawn(900)
network = previous_network
diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm
index 03dbe299b1f7..08de86581518 100644
--- a/code/game/machinery/computer/HolodeckControl.dm
+++ b/code/game/machinery/computer/HolodeckControl.dm
@@ -166,7 +166,7 @@
/obj/structure/holohoop/BlockedPassDirs(atom/movable/mover, target_dir)
if(istype(mover,/obj/item) && mover.throwing)
var/obj/item/I = mover
- if(istype(I, /obj/item/projectile))
+ if(istype(I, /obj/projectile))
return BLOCKED_MOVEMENT
if(prob(50))
I.forceMove(src.loc)
diff --git a/code/game/machinery/computer/almayer_control.dm b/code/game/machinery/computer/almayer_control.dm
index 7d63a2e8c3af..c3b17dbf8090 100644
--- a/code/game/machinery/computer/almayer_control.dm
+++ b/code/game/machinery/computer/almayer_control.dm
@@ -11,11 +11,11 @@
/// requesting a distress beacon
COOLDOWN_DECLARE(cooldown_request)
/// requesting evac
- COOLDOWN_DECLARE(cooldown_destruct)
+ COOLDOWN_DECLARE(cooldown_destruct)
/// messaging HC (admins)
COOLDOWN_DECLARE(cooldown_central)
/// making a ship announcement
- COOLDOWN_DECLARE(cooldown_message)
+ COOLDOWN_DECLARE(cooldown_message)
var/list/messagetitle = list()
var/list/messagetext = list()
@@ -164,11 +164,11 @@
if(!level_selected)
return
- set_security_level(seclevel2num(level_selected))
+ set_security_level(seclevel2num(level_selected), log = ARES_LOG_NONE)
log_game("[key_name(usr)] has changed the security level to [get_security_level()].")
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
var/datum/ares_link/link = GLOB.ares_link
- link.log_ares_security("Security Level Update", "[usr] has changed the security level to [get_security_level()].")
+ link.log_ares_security("Manual Security Update", "[usr] has changed the security level to [get_security_level()].")
. = TRUE
if("messageUSCM")
@@ -230,7 +230,7 @@
for(var/client/admin_client as anything in GLOB.admins)
if((R_ADMIN|R_MOD) & admin_client.admin_holder.rights)
admin_client << 'sound/effects/sos-morse-code.ogg'
- message_admins("[key_name(usr)] has requested a Distress Beacon! [CC_MARK(usr)] (SEND) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]")
+ SSticker.mode.request_ert(usr)
to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command."))
COOLDOWN_START(src, cooldown_request, COOLDOWN_COMM_REQUEST)
diff --git a/code/game/machinery/computer/area_air_control.dm b/code/game/machinery/computer/area_air_control.dm
index e3f16a988c86..22f4211aa8ee 100644
--- a/code/game/machinery/computer/area_air_control.dm
+++ b/code/game/machinery/computer/area_air_control.dm
@@ -139,14 +139,10 @@
var/turf/T_src = get_turf(src)
if(!T_src.loc) return 0
var/area/A_src = T_src.loc
- if (A_src.master)
- A_src = A_src.master
var/turf/T_scrub = get_turf(scrubber)
if(!T_scrub.loc) return 0
var/area/A_scrub = T_scrub.loc
- if (A_scrub.master)
- A_scrub = A_scrub.master
if(A_scrub != A_src)
return 0
@@ -160,14 +156,11 @@
var/turf/T = get_turf(src)
if(!T.loc) return
- var/area/A = T.loc
- if (A.master)
- A = A.master
for(var/obj/structure/machinery/portable_atmospherics/powered/scrubber/huge/scrubber in machines )
var/turf/T2 = get_turf(scrubber)
if(T2 && T2.loc)
- var/area/A2 = T2.loc
- if(istype(A2) && A2.master && A2.master == A )
+ var/area/A = T2.loc
+ if(istype(A) && A)
connectedscrubbers += scrubber
found = 1
diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm
index d4feca457f4a..281c548227b0 100644
--- a/code/game/machinery/computer/camera_console.dm
+++ b/code/game/machinery/computer/camera_console.dm
@@ -17,12 +17,12 @@
var/atom/movable/screen/map_view/cam_screen
var/atom/movable/screen/background/cam_background
- /// All turfs within range of the currently active camera
- var/list/range_turfs = list()
-
var/colony_camera_mapload = TRUE
var/admin_console = FALSE
+ /// All the plane masters that need to be applied.
+ var/list/cam_plane_masters
+
/obj/structure/machinery/computer/cameras/Initialize(mapload)
. = ..()
// Map name has to start and end with an A-Z character,
@@ -33,6 +33,16 @@
if(colony_camera_mapload && mapload && is_ground_level(z))
network = list(CAMERA_NET_COLONY)
+ cam_plane_masters = list()
+ for(var/plane in subtypesof(/atom/movable/screen/plane_master) - /atom/movable/screen/plane_master/blackness)
+ var/atom/movable/screen/plane_master/instance = new plane()
+ instance.assigned_map = map_name
+ instance.del_on_map_removal = FALSE
+ if(instance.blend_mode_override)
+ instance.blend_mode = instance.blend_mode_override
+ instance.screen_loc = "[map_name]:CENTER"
+ cam_plane_masters += instance
+
// Initialize map objects
cam_screen = new
cam_screen.icon = null
@@ -51,7 +61,6 @@
qdel(cam_screen)
QDEL_NULL(cam_background)
qdel(cam_background)
- range_turfs = null
last_camera_turf = null
concurrent_users = null
return ..()
@@ -74,6 +83,10 @@
if(inoperable())
return UI_DISABLED
+//Closes UI if you move away from console.
+/obj/structure/machinery/computer/cameras/ui_state(mob/user)
+ return GLOB.not_incapacitated_and_adjacent_strict_state
+
/obj/structure/machinery/computer/cameras/tgui_interact(mob/user, datum/tgui/ui)
// Update UI
ui = SStgui.try_update_ui(user, src, ui)
@@ -94,6 +107,8 @@
// Register map objects
user.client.register_map_obj(cam_screen)
user.client.register_map_obj(cam_background)
+ for(var/plane in cam_plane_masters)
+ user.client.register_map_obj(plane)
// Open UI
ui = new(user, src, "CameraConsole", name)
ui.open()
@@ -176,13 +191,8 @@
var/list/visible_things = current.isXRay() ? range(current.view_range, cam_location) : view(current.view_range, cam_location)
var/list/visible_turfs = list()
- range_turfs.Cut()
- var/area/A
for(var/turf/visible_turf in visible_things)
- range_turfs += visible_turf
- A = visible_turf.loc
- if(!A.lighting_use_dynamic || visible_turf.lighting_lumcount >= 1)
- visible_turfs += visible_turf
+ visible_turfs += visible_turf
var/list/bbox = get_bbox_of_atoms(visible_turfs)
var/size_x = bbox[3] - bbox[1] + 1
@@ -192,18 +202,6 @@
cam_background.icon_state = "clear"
cam_background.fill_rect(1, 1, size_x, size_y)
- START_PROCESSING(SSfastobj, src) // fastobj to somewhat keep pace with lighting updates
-
-/obj/structure/machinery/computer/cameras/process()
- if(current)
- var/list/visible_turfs = list()
- var/area/A
- for(var/turf/visible_turf as anything in range_turfs)
- A = visible_turf.loc
- if(!A.lighting_use_dynamic || visible_turf.lighting_lumcount >= 1)
- visible_turfs += visible_turf
- cam_screen.vis_contents = visible_turfs
-
/obj/structure/machinery/computer/cameras/ui_close(mob/user)
var/user_ref = WEAKREF(user)
var/is_living = isliving(user)
@@ -215,10 +213,8 @@
if(length(concurrent_users) == 0 && is_living)
current = null
last_camera_turf = null
- range_turfs = list()
if(use_power)
update_use_power(USE_POWER_IDLE)
- STOP_PROCESSING(SSfastobj, src)
user.unset_interaction()
/obj/structure/machinery/computer/cameras/proc/show_camera_static()
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index edc39faf3ddc..f7ea31fba36a 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -200,7 +200,7 @@
for(var/client/C in GLOB.admins)
if((R_ADMIN|R_MOD) & C.admin_holder.rights)
C << 'sound/effects/sos-morse-code.ogg'
- message_admins("[key_name(usr)] has requested a Distress Beacon! [CC_MARK(usr)] (SEND) (DENY) [ADMIN_JMP_USER(usr)] [CC_REPLY(usr)]")
+ SSticker.mode.request_ert(usr)
to_chat(usr, SPAN_NOTICE("A distress beacon request has been sent to USCM Central Command."))
cooldown_request = world.time
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 8fa0b9b86a0c..adce72f7d8b6 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -56,7 +56,7 @@
else
return
-/obj/structure/machinery/computer/bullet_act(obj/item/projectile/Proj)
+/obj/structure/machinery/computer/bullet_act(obj/projectile/Proj)
if(exproof)
visible_message("[Proj] ricochets off [src]!")
return 0
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index ed7335ea8778..eb9aed4f71e4 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -185,7 +185,6 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
flags_atom |= USES_HEARING
/obj/structure/machinery/cryopod/Destroy()
- SetLuminosity(0)
QDEL_NULL(occupant)
QDEL_NULL(announce)
. = ..()
@@ -368,7 +367,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
qdel(G)
icon_state = "body_scanner_open"
- SetLuminosity(0)
+ set_light(0)
if(occupant.key)
occupant.ghostize(0)
@@ -509,7 +508,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
mob.forceMove(src)
occupant = mob
icon_state = "body_scanner_closed"
- SetLuminosity(2)
+ set_light(2)
time_entered = world.time
start_processing()
@@ -532,7 +531,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
occupant = null
stop_processing()
icon_state = "body_scanner_open"
- SetLuminosity(0)
+ set_light(0)
playsound(src, 'sound/machines/pod_open.ogg', 30)
#ifdef OBJECTS_PROXY_SPEECH
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index e3e5fd3bee87..dc28cdca6f5c 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
else
return FALSE
-/obj/structure/machinery/door/airlock/bullet_act(obj/item/projectile/P)
+/obj/structure/machinery/door/airlock/bullet_act(obj/projectile/P)
bullet_ping(P)
if(P.damage)
if(P.ammo.flags_ammo_behavior & AMMO_ROCKET)
diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm
index b6b9a6133a84..78fc05d8e0d0 100644
--- a/code/game/machinery/doors/alarmlock.dm
+++ b/code/game/machinery/doors/alarmlock.dm
@@ -33,8 +33,6 @@
var/alert = signal.data["alert"]
var/area/our_area = get_area(src)
- if (our_area.master)
- our_area = our_area.master
if(alarm_area == our_area.name)
switch(alert)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index b54658b24245..578ef368f5d9 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -49,7 +49,7 @@
/obj/structure/machinery/door/Destroy()
. = ..()
if(filler && width > 1)
- filler.SetOpacity(0)// Ehh... let's hope there are no walls there. Must fix this
+ filler.set_opacity(0)// Ehh... let's hope there are no walls there. Must fix this
filler = null
density = FALSE
@@ -64,12 +64,12 @@
bound_width = width * world.icon_size
bound_height = world.icon_size
filler = get_step(src,EAST)
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
else
bound_width = world.icon_size
bound_height = width * world.icon_size
filler = get_step(src,NORTH)
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
//process()
//return
@@ -222,9 +222,9 @@
operating = TRUE
do_animate("opening")
icon_state = "door0"
- SetOpacity(FALSE)
+ set_opacity(FALSE)
if(filler)
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed)
return TRUE
@@ -255,9 +255,9 @@
/obj/structure/machinery/door/proc/finish_close()
update_icon()
if(visible && !glass)
- SetOpacity(TRUE)
+ set_opacity(TRUE)
if(filler)
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
operating = FALSE
/obj/structure/machinery/door/proc/requiresID()
@@ -279,15 +279,15 @@
if(dir in list(EAST, WEST))
bound_width = width * world.icon_size
bound_height = world.icon_size
- filler.SetOpacity(0)
+ filler.set_opacity(0)
filler = (get_step(src,EAST)) //Find new turf
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
else
bound_width = world.icon_size
bound_height = width * world.icon_size
- filler.SetOpacity(0)
+ filler.set_opacity(0)
filler = (get_step(src,NORTH)) //Find new turf
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
/obj/structure/machinery/door/morgue
diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm
index 2a49b8696a9f..6123d56b8f23 100644
--- a/code/game/machinery/doors/multi_tile.dm
+++ b/code/game/machinery/doors/multi_tile.dm
@@ -66,6 +66,7 @@
icon = 'icons/obj/structures/doors/Door2x1research.dmi'
opacity = FALSE
glass = 1
+ req_one_access = list(ACCESS_MARINE_RESEARCH, ACCESS_WY_RESEARCH, ACCESS_WY_EXEC)
/obj/structure/machinery/door/airlock/multi_tile/research/colony
req_access = null
@@ -178,7 +179,7 @@
/obj/structure/machinery/door/airlock/multi_tile/almayer/medidoor/research
name = "\improper Research Airlock"
- req_one_access = list(ACCESS_MARINE_RESEARCH)
+ req_one_access = list(ACCESS_MARINE_RESEARCH, ACCESS_WY_RESEARCH, ACCESS_WY_EXEC)
masterkey_resist = TRUE
/obj/structure/machinery/door/airlock/multi_tile/almayer/medidoor/research/colony
@@ -235,11 +236,11 @@
//We have to find these again since these doors are used on shuttles a lot so the turfs changes
/obj/structure/machinery/door/airlock/multi_tile/almayer/proc/update_filler_turfs()
for(var/turf/T in multi_filler)
- T.SetOpacity(null)
+ T.set_opacity(null)
multi_filler = list()
for(var/turf/T in get_filler_turfs())
- T.SetOpacity(opacity)
+ T.set_opacity(opacity)
multi_filler += list(T)
/obj/structure/machinery/door/airlock/multi_tile/proc/get_filler_turfs()
@@ -271,6 +272,7 @@
unacidable = TRUE
no_panel = 1
not_weldable = 1
+ var/queen_pryable = TRUE
/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/ex_act(severity)
return
@@ -285,6 +287,9 @@
if(xeno.hive_pos != XENO_QUEEN)
return ..()
+ if(!queen_pryable)
+ return ..()
+
if(!locked)
return ..()
@@ -316,6 +321,7 @@
locked = TRUE
opacity = FALSE
glass = TRUE
+ queen_pryable = FALSE
var/throw_dir = EAST
/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/try_to_activate_door(mob/user)
@@ -353,8 +359,8 @@
/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override)
. = ..()
- if(istype(port, /obj/docking_port/mobile/lifeboat))
- var/obj/docking_port/mobile/lifeboat/lifeboat = port
+ if(istype(port, /obj/docking_port/mobile/crashable/lifeboat))
+ var/obj/docking_port/mobile/crashable/lifeboat/lifeboat = port
lifeboat.doors += src
/// External airlock that is part of the lifeboat dock
@@ -377,7 +383,8 @@
/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/blastdoor/proc/vacate_premises()
for(var/turf/self_turf as anything in locs)
var/turf/near_turf = get_step(self_turf, throw_dir)
- var/turf/projected = get_ranged_target_turf(near_turf, throw_dir, 50)
+ var/turf/space_turf = get_step(near_turf, throw_dir)
+ var/turf/projected = get_ranged_target_turf(space_turf, EAST, 50)
for(var/atom/movable/atom_movable in near_turf)
if(ismob(atom_movable) && !isobserver(atom_movable))
var/mob/mob = atom_movable
@@ -389,7 +396,9 @@
continue
else
continue
- INVOKE_ASYNC(atom_movable, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE)
+ atom_movable.forceMove(space_turf)
+ INVOKE_ASYNC(atom_movable, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE, HIGH_LAUNCH)
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), atom_movable), 3 SECONDS)
/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/blastdoor/proc/bolt_explosion()
var/turf/turf = get_step(src, throw_dir|dir)
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index da6137e5e8cb..b2d836ee476f 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -16,9 +16,9 @@
/obj/structure/machinery/door/poddoor/Initialize()
. = ..()
if(density)
- SetOpacity(1)
+ set_opacity(1)
else
- SetOpacity(0)
+ set_opacity(0)
update_icon()
/obj/structure/machinery/door/poddoor/update_icon()
@@ -42,7 +42,7 @@
operating = 1
flick("[base_icon_state]c0", src)
icon_state = "[base_icon_state]0"
- SetOpacity(0)
+ set_opacity(0)
sleep(15)
density = FALSE
operating = 0
@@ -84,7 +84,7 @@
playsound(loc, 'sound/machines/blastdoor.ogg', 20, 0)
flick("[base_icon_state]c0", src)
icon_state = "[base_icon_state]0"
- SetOpacity(0)
+ set_opacity(0)
addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed)
return TRUE
@@ -102,7 +102,7 @@
flick("[base_icon_state]c1", src)
icon_state = "[base_icon_state]1"
density = TRUE
- SetOpacity(initial(opacity))
+ set_opacity(initial(opacity))
addtimer(CALLBACK(src, PROC_REF(finish_close)), openspeed)
return
@@ -123,13 +123,13 @@
/obj/structure/machinery/door/poddoor/two_tile/proc/start_opening()
flick("[base_icon_state]c0", src)
icon_state = "[base_icon_state]0"
- SetOpacity(0)
- f1.SetOpacity(0)
- f2.SetOpacity(0)
+ set_opacity(0)
+ f1.set_opacity(0)
+ f2.set_opacity(0)
/obj/structure/machinery/door/poddoor/two_tile/four_tile/start_opening()
- f3.SetOpacity(0)
- f4.SetOpacity(0)
+ f3.set_opacity(0)
+ f4.set_opacity(0)
..()
/obj/structure/machinery/door/poddoor/two_tile/proc/open_fully()
@@ -169,14 +169,14 @@
..()
/obj/structure/machinery/door/poddoor/two_tile/proc/close_fully()
- SetOpacity(initial(opacity))
- f1.SetOpacity(initial(opacity))
- f2.SetOpacity(initial(opacity))
+ set_opacity(initial(opacity))
+ f1.set_opacity(initial(opacity))
+ f2.set_opacity(initial(opacity))
operating = 0
/obj/structure/machinery/door/poddoor/two_tile/four_tile/close_fully()
- f3.SetOpacity(initial(opacity))
- f4.SetOpacity(initial(opacity))
+ f3.set_opacity(initial(opacity))
+ f4.set_opacity(initial(opacity))
..()
/obj/structure/machinery/door/poddoor/two_tile
@@ -194,8 +194,8 @@
f2 = new/obj/structure/machinery/door/poddoor/filler_object (get_step(src,dir))
f1.density = density
f2.density = density
- f1.SetOpacity(opacity)
- f2.SetOpacity(opacity)
+ f1.set_opacity(opacity)
+ f2.set_opacity(opacity)
/obj/structure/machinery/door/poddoor/two_tile/Destroy()
QDEL_NULL(f1)
@@ -223,8 +223,8 @@
f4 = new/obj/structure/machinery/door/poddoor/filler_object (get_step(f3,dir))
f3.density = density
f4.density = density
- f3.SetOpacity(opacity)
- f4.SetOpacity(opacity)
+ f3.set_opacity(opacity)
+ f4.set_opacity(opacity)
/obj/structure/machinery/door/poddoor/two_tile/four_tile/Destroy()
QDEL_NULL(f3)
diff --git a/code/game/machinery/doors/railing.dm b/code/game/machinery/doors/railing.dm
index 8449d5d52256..c86adb2e970b 100644
--- a/code/game/machinery/doors/railing.dm
+++ b/code/game/machinery/doors/railing.dm
@@ -22,7 +22,7 @@
if(density)//Allows preset-open to work
layer = closed_layer
- SetOpacity(initial(opacity))
+ set_opacity(initial(opacity))
/obj/structure/machinery/door/poddoor/railing/update_icon()
if(density)
diff --git a/code/game/machinery/doors/runed_sandstone.dm b/code/game/machinery/doors/runed_sandstone.dm
index d67398baa305..4bf66dfdc8d8 100644
--- a/code/game/machinery/doors/runed_sandstone.dm
+++ b/code/game/machinery/doors/runed_sandstone.dm
@@ -100,7 +100,7 @@
operating = TRUE
do_animate("opening")
icon_state = "door0"
- SetOpacity(FALSE)
+ set_opacity(0)
addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed)
return
@@ -109,9 +109,9 @@
layer = open_layer
density = FALSE
update_icon()
- SetOpacity(0)
+ set_opacity(0)
if(filler)
- filler.SetOpacity(opacity)
+ filler.set_opacity(opacity)
if(operating)
operating = FALSE
@@ -130,7 +130,7 @@
operating = TRUE
density = TRUE
- SetOpacity(TRUE)
+ set_opacity(1)
layer = closed_layer
do_animate("closing")
diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm
index 39ecbd806e64..da904f255c40 100644
--- a/code/game/machinery/doors/shutters.dm
+++ b/code/game/machinery/doors/shutters.dm
@@ -26,7 +26,7 @@
icon_state = "[base_icon_state]0"
sleep(15)
density = FALSE
- SetOpacity(0)
+ set_opacity(0)
operating = 0
return
return
@@ -46,7 +46,7 @@
/obj/structure/machinery/door/poddoor/shutters/finish_open()
density = FALSE
layer = open_layer
- SetOpacity(0)
+ set_opacity(0)
if(operating) //emag again
operating = FALSE
@@ -63,7 +63,7 @@
layer = closed_layer
density = TRUE
if(visible)
- SetOpacity(1)
+ set_opacity(1)
playsound(loc, 'sound/machines/blastdoor.ogg', 25)
addtimer(CALLBACK(src, PROC_REF(finish_close)), openspeed)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index e9006a9f2fb4..2b57fbd0a44d 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -123,7 +123,7 @@
qdel(src)
return
-/obj/structure/machinery/door/window/bullet_act(obj/item/projectile/Proj)
+/obj/structure/machinery/door/window/bullet_act(obj/projectile/Proj)
bullet_ping(Proj)
if(Proj.ammo.damage)
take_damage(round(Proj.ammo.damage / 2))
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 556eab541363..75d0de56dec0 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -26,10 +26,10 @@
..()
if ( !(stat & NOPOWER) )
icon_state = "[base_state]1"
-// src.sd_SetLuminosity(2)
+// src.sd_set_light(2)
else
icon_state = "[base_state]1-p"
-// src.sd_SetLuminosity(0)
+// src.sd_set_light(0)
//Don't want to render prison breaks impossible
/obj/structure/machinery/flasher/attackby(obj/item/W as obj, mob/user as mob)
diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm
index 8eec83ed7b70..5f6cd02a4bf8 100644
--- a/code/game/machinery/floodlight.dm
+++ b/code/game/machinery/floodlight.dm
@@ -6,38 +6,40 @@
icon_state = "flood00"
density = TRUE
anchored = TRUE
- var/on = 0
var/obj/item/cell/cell = null
var/use = 0
var/unlocked = 0
var/open = 0
- var/brightness_on = 7 //can't remember what the maxed out value is
+ light_power = 2
unslashable = TRUE
unacidable = TRUE
+ var/on_light_range = 6
+
/obj/structure/machinery/floodlight/Initialize(mapload, ...)
. = ..()
cell = new /obj/item/cell(src)
+ if(light_on)
+ set_light(on_light_range)
/obj/structure/machinery/floodlight/Destroy()
QDEL_NULL(cell)
- SetLuminosity(0)
return ..()
+/obj/structure/machinery/floodlight/turn_light(mob/user, toggle_on)
+ . = ..()
+ if(. == NO_LIGHT_STATE_CHANGE)
+ return
+
+ if(toggle_on)
+ set_light(on_light_range)
+ else
+ set_light(0)
+
+
/obj/structure/machinery/floodlight/proc/updateicon()
- icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]"
-/*
-/obj/structure/machinery/floodlight/process()
- if(on && cell)
- if(cell.charge >= use)
- cell.use(use)
- else
- on = 0
- updateicon()
- SetLuminosity(0)
- src.visible_message(SPAN_WARNING("[src] shuts down due to lack of power!"))
- return
-*/
+ icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[light_on]"
+
/obj/structure/machinery/floodlight/attack_hand(mob/user as mob)
if(open && cell)
if(ishuman(user))
@@ -55,10 +57,9 @@
updateicon()
return
- if(on)
- on = 0
- to_chat(user, SPAN_NOTICE(" You turn off the light."))
- SetLuminosity(0)
+ if(light_on)
+ to_chat(user, SPAN_NOTICE("You turn off the light."))
+ turn_light(user, toggle_on = FALSE)
unslashable = TRUE
unacidable = TRUE
else
@@ -66,9 +67,8 @@
return
if(cell.charge <= 0)
return
- on = 1
- to_chat(user, SPAN_NOTICE(" You turn on the light."))
- SetLuminosity(brightness_on)
+ to_chat(user, SPAN_NOTICE("You turn on the light."))
+ turn_light(user, toggle_on = TRUE)
unacidable = FALSE
updateicon()
@@ -121,9 +121,8 @@
name = "Landing Light"
desc = "A powerful light stationed near landing zones to provide better visibility."
icon_state = "flood01"
- on = 1
+ light_on = TRUE
in_use = 1
- luminosity = 6
use_power = USE_POWER_NONE
/obj/structure/machinery/floodlight/landing/attack_hand()
diff --git a/code/game/machinery/groundmap_geothermal.dm b/code/game/machinery/groundmap_geothermal.dm
index 4be9c53f0094..808c717e8891 100644
--- a/code/game/machinery/groundmap_geothermal.dm
+++ b/code/game/machinery/groundmap_geothermal.dm
@@ -269,9 +269,9 @@
F.is_lit = !F.is_lit
if(!F.damaged)
if(F.is_lit) //Shut it down
- F.SetLuminosity(F.lum_value)
+ F.set_light(F.lum_value)
else
- F.SetLuminosity(0)
+ F.set_light(0)
F.update_icon()
return 0
@@ -315,7 +315,6 @@
health = 150
/obj/structure/machinery/colony_floodlight/Destroy()
- SetLuminosity(0)
if(fswitch)
fswitch.floodlist -= src
fswitch = null
@@ -362,7 +361,7 @@
user.visible_message(SPAN_NOTICE("[user] screws [src]'s maintenance hatch closed."), \
SPAN_NOTICE("You screw [src]'s maintenance hatch closed."))
if(is_lit)
- SetLuminosity(lum_value)
+ set_light(lum_value)
update_icon()
return TRUE
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 1acb47370d96..2f8f113ddd23 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -142,8 +142,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
hologram.anchored = TRUE//So space wind cannot drag it.
hologram.name = "[A.name] (Hologram)"//If someone decides to right click.
- hologram.SetLuminosity(2) //hologram lighting
- SetLuminosity(2) //pad lighting
+ hologram.set_light(2) //hologram lighting
+ set_light(2) //pad lighting
icon_state = "holopad1"
A.holo = src
master = A//AI is the master.
@@ -151,14 +151,14 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
return 1
/obj/structure/machinery/hologram/holopad/clear_holo()
-// hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted
+// hologram.set_light(0)//Clear lighting. //handled by the lighting controller when its ower is deleted
if(hologram)
qdel(hologram)//Get rid of hologram.
hologram = null
if(master.holo == src)
master.holo = null
master = null//Null the master, since no-one is using it now.
- SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
+ set_light(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted)
icon_state = "holopad0"
use_power = USE_POWER_IDLE//Passive power usage.
return 1
@@ -175,7 +175,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/area/holo_area = get_area(src)
var/area/eye_area = get_area(master.eyeobj)
- if(eye_area in holo_area.master.related)
+ if(eye_area == holo_area)
return 1
clear_holo()//If not, we want to get rid of the hologram.
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index 5564ed0220a7..33f75c50e341 100644
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -60,10 +60,10 @@
if ( !(stat & NOPOWER) && disable == 0 )
icon_state = "[base_state]"
-// src.sd_SetLuminosity(2)
+// src.sd_set_light(2)
else
icon_state = "[base_state]-p"
-// src.sd_SetLuminosity(0)
+// src.sd_set_light(0)
/obj/structure/machinery/sparker/attackby(obj/item/W as obj, mob/user as mob)
if (HAS_TRAIT(W, TRAIT_TOOL_SCREWDRIVER))
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index ecf63a2a7902..f52350aa8db3 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -520,7 +520,7 @@
return 0
/obj/structure/machinery/smartfridge/chemistry/antag
- req_one_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
/obj/structure/machinery/smartfridge/chemistry/virology
name = "\improper Smart Virus Storage"
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index ae57f27f2162..66eb0386713f 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -10,7 +10,6 @@
var/on = 1
var/area/area = null
var/otherarea = null
- // luminosity = 1
/obj/structure/machinery/light_switch/Initialize()
. = ..()
@@ -43,15 +42,14 @@
/obj/structure/machinery/light_switch/attack_hand(mob/user)
on = !on
- for(var/area/A in area.master.related)
- A.lightswitch = on
- A.updateicon()
+ area.lightswitch = on
+ area.updateicon()
- for(var/obj/structure/machinery/light_switch/L in A)
- L.on = on
- L.updateicon()
+ for(var/obj/structure/machinery/light_switch/L in area)
+ L.on = on
+ L.updateicon()
- area.master.power_change()
+ area.power_change()
/obj/structure/machinery/light_switch/power_change()
diff --git a/code/game/machinery/mining.dm b/code/game/machinery/mining.dm
index 4f663c5fbca7..0662817174fc 100644
--- a/code/game/machinery/mining.dm
+++ b/code/game/machinery/mining.dm
@@ -26,4 +26,4 @@
icon_state = "furnace"
density = TRUE
anchored = TRUE
- luminosity = 3
+ light_range = 3
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index ad8f5a189267..89c9e9277f4c 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -93,7 +93,6 @@ var/list/obj/structure/machinery/newscaster/allCasters = list() //Global list th
var/c_locked=0; //Will our new channel be locked to public submissions?
var/hitstaken = 0 //Death at 3 hits from an item with force>=15
var/datum/feed_channel/viewing_channel = null
- luminosity = 0
anchored = TRUE
@@ -111,7 +110,6 @@ var/list/obj/structure/machinery/newscaster/allCasters = list() //Global list th
/obj/structure/machinery/newscaster/security_unit/Destroy()
allCasters -= src
- SetLuminosity(0)
return ..()
/obj/structure/machinery/newscaster/update_icon()
diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm
index 47d4bb20849b..b327bd6fdf26 100644
--- a/code/game/machinery/telecomms/presets.dm
+++ b/code/game/machinery/telecomms/presets.dm
@@ -76,7 +76,7 @@
if(!on)
msg_admin_niche("Portable communication relay shut down for Z-Level [src.z] [ADMIN_JMP(src)]")
-/obj/structure/machinery/telecomms/relay/preset/tower/bullet_act(obj/item/projectile/P)
+/obj/structure/machinery/telecomms/relay/preset/tower/bullet_act(obj/projectile/P)
..()
if(istype(P.ammo, /datum/ammo/xeno/boiler_gas))
update_health(50)
@@ -340,6 +340,8 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
for(var/obj/effect/alien/weeds/weed in new_pylon.node.children)
weed.parent = new_pylon.node
+ weed.spread_on_semiweedable = TRUE
+ weed.weed_expand()
RegisterSignal(new_pylon, COMSIG_PARENT_QDELETING, PROC_REF(uncorrupt))
@@ -421,7 +423,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
id = "Receiver B"
network = "tcommsat"
autolinkers = list("receiverB") // link to relay
- freq_listening = list(COMM_FREQ, ENG_FREQ, SEC_FREQ, MED_FREQ, REQ_FREQ, SENTRY_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ)
+ freq_listening = list(COMM_FREQ, ENG_FREQ, SEC_FREQ, MED_FREQ, REQ_FREQ, SENTRY_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
//Common and other radio frequencies for people to freely use
/obj/structure/machinery/telecomms/receiver/preset/Initialize(mapload, ...)
@@ -433,7 +435,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
id = "CentComm Receiver"
network = "tcommsat"
autolinkers = list("receiverCent")
- freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, SOF_FREQ)
+ freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
//Buses
@@ -453,7 +455,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
/obj/structure/machinery/telecomms/bus/preset_three
id = "Bus 3"
network = "tcommsat"
- freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, SOF_FREQ)
+ freq_listening = list(SEC_FREQ, COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
autolinkers = list("processor3", "security", "command", "JTAC")
/obj/structure/machinery/telecomms/bus/preset_four
@@ -469,7 +471,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
/obj/structure/machinery/telecomms/bus/preset_cent
id = "CentComm Bus"
network = "tcommsat"
- freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, SOF_FREQ)
+ freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
autolinkers = list("processorCent", "centcomm")
//Processors
@@ -534,7 +536,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
/obj/structure/machinery/telecomms/server/presets/command
id = "Command Server"
- freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, SOF_FREQ)
+ freq_listening = list(COMM_FREQ, WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, JTAC_FREQ, INTEL_FREQ, WY_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
autolinkers = list("command")
/obj/structure/machinery/telecomms/server/presets/engineering
@@ -549,7 +551,7 @@ GLOBAL_LIST_EMPTY(all_static_telecomms_towers)
/obj/structure/machinery/telecomms/server/presets/centcomm
id = "CentComm Server"
- freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, SOF_FREQ)
+ freq_listening = list(WY_WO_FREQ, PMC_FREQ, DUT_FREQ, YAUT_FREQ, HC_FREQ, PVST_FREQ, SOF_FREQ)
autolinkers = list("centcomm")
diff --git a/code/game/machinery/vending/vendor_types/antag/antag_clothing.dm b/code/game/machinery/vending/vendor_types/antag/antag_clothing.dm
index df047d6cf5fb..85210e1aaa3f 100644
--- a/code/game/machinery/vending/vendor_types/antag/antag_clothing.dm
+++ b/code/game/machinery/vending/vendor_types/antag/antag_clothing.dm
@@ -5,7 +5,8 @@
name = "\improper Suspicious Automated Equipment Rack"
desc = "While similar in function to ColMarTech automated racks, this one is clearly not of USCM origin. Contains various equipment."
icon_state = "antag_clothing"
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
listed_products = list()
diff --git a/code/game/machinery/vending/vendor_types/antag/antag_gear.dm b/code/game/machinery/vending/vendor_types/antag/antag_gear.dm
index c2b27dc91ef1..3e847b4919de 100644
--- a/code/game/machinery/vending/vendor_types/antag/antag_gear.dm
+++ b/code/game/machinery/vending/vendor_types/antag/antag_gear.dm
@@ -5,7 +5,8 @@
desc = "While similar in function to ColMarTech automated racks, this one is clearly not of USCM origin. Contains various gear."
icon_state = "gear"
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
listed_products = list()
/obj/structure/machinery/cm_vending/gear/antag/Initialize()
@@ -49,9 +50,9 @@
/obj/effect/essentials_set/upp_heavy
spawned_gear_list = list(
- /obj/item/weapon/gun/minigun/upp,
- /obj/item/ammo_magazine/minigun,
- /obj/item/ammo_magazine/minigun,
+ /obj/item/weapon/gun/pkp,
+ /obj/item/ammo_magazine/pkp,
+ /obj/item/ammo_magazine/pkp,
)
/obj/effect/essentials_set/leader/upp
diff --git a/code/game/machinery/vending/vendor_types/antag/antag_guns_snowflake.dm b/code/game/machinery/vending/vendor_types/antag/antag_guns_snowflake.dm
index a2cd462cd6a2..73a2c7346a4c 100644
--- a/code/game/machinery/vending/vendor_types/antag/antag_guns_snowflake.dm
+++ b/code/game/machinery/vending/vendor_types/antag/antag_guns_snowflake.dm
@@ -4,7 +4,8 @@
name = "\improper Suspicious Automated Guns Rack"
desc = "While similar in function to ColMarTech automated racks, this one is clearly not of USCM origin. Contains various weapons, ammunition and explosives."
icon_state = "antag_guns"
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
use_snowflake_points = TRUE
diff --git a/code/game/machinery/vending/vendor_types/antag/antag_guns_sorted.dm b/code/game/machinery/vending/vendor_types/antag/antag_guns_sorted.dm
index 6267db911b09..ab319f1eca1d 100644
--- a/code/game/machinery/vending/vendor_types/antag/antag_guns_sorted.dm
+++ b/code/game/machinery/vending/vendor_types/antag/antag_guns_sorted.dm
@@ -4,7 +4,8 @@
name = "\improper Suspicious Automated Guns Rack"
desc = "While similar in function to ColMarTech automated racks, this one is clearly not of USCM origin. Contains various weapons."
icon_state = "antag_guns"
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
listed_products = list()
/obj/structure/machinery/cm_vending/sorted/cargo_guns/antag_guns/Initialize()
diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
index 0496530be861..8ddd8df4c3a2 100644
--- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm
+++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
@@ -232,6 +232,12 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list(
list("MP Cap", 12, /obj/item/clothing/head/beret/marine/mp/mpcap, null, VENDOR_ITEM_REGULAR),
list("RO Cap", 12, /obj/item/clothing/head/cmcap/req, null, VENDOR_ITEM_REGULAR),
list("Officer Cap", 12, /obj/item/clothing/head/cmcap/ro, null, VENDOR_ITEM_REGULAR),
+ list("Marine Helmet", 12, /obj/item/clothing/head/helmet/marine, null, VENDOR_ITEM_REGULAR),
+ list("Grey Marine Helmet", 12, /obj/item/clothing/head/helmet/marine/grey, null, VENDOR_ITEM_REGULAR),
+ list("Technician Helmet", 12, /obj/item/clothing/head/helmet/marine/tech, null, VENDOR_ITEM_REGULAR),
+ list("Corpsman Helmet", 12, /obj/item/clothing/head/helmet/marine/medic, null, VENDOR_ITEM_REGULAR),
+ list("Attachable Helmet Shield", 12, /obj/item/prop/helmetgarb/riot_shield, null, VENDOR_ITEM_REGULAR),
+
list("SUIT", 0, null, null, null),
list("Bomber Jacket, Brown", 12, /obj/item/clothing/suit/storage/bomber, null, VENDOR_ITEM_REGULAR),
@@ -303,7 +309,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list(
/obj/structure/machinery/cm_vending/own_points/experimental_tools/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/coin/marine/synth))
if(user.drop_inv_item_to_loc(W, src))
- available_points = 45
+ available_points = 30
available_points_to_display = available_points
to_chat(user, SPAN_NOTICE("You insert \the [W] into \the [src]."))
return
diff --git a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
index fb9b662be1bc..891a2a907b39 100644
--- a/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
+++ b/code/game/machinery/vending/vendor_types/crew/vehicle_crew.dm
@@ -306,7 +306,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_vehicle_crew, list(
list("Gloves", 0, /obj/item/clothing/gloves/yellow, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
list("Tanker Armor", 0, /obj/item/clothing/suit/storage/marine/tanker, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_MANDATORY),
list("M50 Tanker Helmet", 0, /obj/item/clothing/head/helmet/marine/tech/tanker, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
- list("SensorMate HUD", 0, /obj/item/clothing/glasses/hud/sensor, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
+ list("Medical Helmet Optic", 0, /obj/item/device/helmet_visor/medical, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
list("Welding Kit", 0, /obj/item/tool/weldpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
diff --git a/code/game/machinery/vending/vendor_types/engineering.dm b/code/game/machinery/vending/vendor_types/engineering.dm
index 2fe6962e93bb..1983365bd661 100644
--- a/code/game/machinery/vending/vendor_types/engineering.dm
+++ b/code/game/machinery/vending/vendor_types/engineering.dm
@@ -94,7 +94,8 @@
)
/obj/structure/machinery/cm_vending/sorted/tech/tool_storage/antag
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
/obj/structure/machinery/cm_vending/sorted/tech/electronics_storage
name = "\improper Electronics Vendor"
@@ -117,7 +118,8 @@
)
/obj/structure/machinery/cm_vending/sorted/tech/electronics_storage/antag
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
/obj/structure/machinery/cm_vending/sorted/tech/comp_storage
name = "\improper Component Storage Machine"
@@ -146,7 +148,8 @@
)
/obj/structure/machinery/cm_vending/sorted/tech/comp_storage/antag
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
//------COLONY-SPECIFIC VENDORS-------
diff --git a/code/game/machinery/vending/vendor_types/intelligence_officer.dm b/code/game/machinery/vending/vendor_types/intelligence_officer.dm
index a2afe897b495..ab38fcb1dfeb 100644
--- a/code/game/machinery/vending/vendor_types/intelligence_officer.dm
+++ b/code/game/machinery/vending/vendor_types/intelligence_officer.dm
@@ -14,8 +14,9 @@ GLOBAL_LIST_INIT(cm_vending_gear_intelligence_officer, list(
list("Fulton Recovery Device", 10, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED),
list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR),
+ list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 5, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Welding Goggles", 5, /obj/item/clothing/glasses/welding, null, VENDOR_ITEM_REGULAR),
- list("Sensor Medical HUD", 5, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
list("POUCHES", 0, null, null, null),
list("Large Magazine Pouch", 10, /obj/item/storage/pouch/magazine/large, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/medical.dm b/code/game/machinery/vending/vendor_types/medical.dm
index 70ac7701973b..7073dc383dcd 100644
--- a/code/game/machinery/vending/vendor_types/medical.dm
+++ b/code/game/machinery/vending/vendor_types/medical.dm
@@ -26,7 +26,6 @@
/obj/item/reagent_container/hypospray/autoinjector/oxycodone,
/obj/item/reagent_container/hypospray/autoinjector/tramadol,
/obj/item/reagent_container/hypospray/autoinjector/tricord,
- /obj/item/reagent_container/hypospray/autoinjector/emergency,
/obj/item/reagent_container/hypospray/autoinjector/skillless,
/obj/item/reagent_container/hypospray/autoinjector/skillless/tramadol,
@@ -227,7 +226,8 @@
/obj/structure/machinery/cm_vending/sorted/medical/antag
name = "\improper Medical Equipment Vendor"
desc = "A vending machine dispensing various pieces of medical equipment."
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
vendor_theme = VENDOR_THEME_CLF
/obj/structure/machinery/cm_vending/sorted/medical/marinemed
@@ -267,7 +267,8 @@
/obj/structure/machinery/cm_vending/sorted/medical/marinemed/antag
name = "\improper Basic Medical Supplies Vendor"
desc = "A vending machine dispensing basic medical supplies."
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
vendor_theme = VENDOR_THEME_CLF
/obj/structure/machinery/cm_vending/sorted/medical/blood
@@ -298,7 +299,8 @@
return
/obj/structure/machinery/cm_vending/sorted/medical/blood/antag
- req_access = list(ACCESS_ILLEGAL_PIRATE)
+ req_one_access = list(ACCESS_ILLEGAL_PIRATE, ACCESS_UPP_GENERAL, ACCESS_CLF_GENERAL)
+ req_access = null
vendor_theme = VENDOR_THEME_CLF
/obj/structure/machinery/cm_vending/sorted/medical/wall_med
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
index faff01f7f299..d43e53db4f0d 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_engineer.dm
@@ -54,7 +54,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_engi, list(
list("M56D Heavy Machine Gun", 24, /obj/item/storage/box/guncase/m56d, null, VENDOR_ITEM_REGULAR),
list("UTILITIES", 0, null, null, null),
- list("SensorMate Medical HUD", 12, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 12, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("M3 B12 Pattern Armor", 24, /obj/item/clothing/suit/storage/marine/leader, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
index 9757576e6d0b..935469b13b47 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_leader.dm
@@ -67,7 +67,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_leader, list(
list("Injector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 4, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_RECOMMENDED),
+ list("Medical Helmet Optic", 4, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_RECOMMENDED),
list("Roller Bed", 2, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("SPECIAL AMMUNITION", 0, null, null, null),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
index 7c9682985298..65169a7591ae 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_medic.dm
@@ -29,7 +29,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list(
list("Autoinjector (Oxycodone)", 2, /obj/item/reagent_container/hypospray/autoinjector/oxycodone, null, VENDOR_ITEM_REGULAR),
list("Autoinjector (Tramadol)", 1, /obj/item/reagent_container/hypospray/autoinjector/tramadol, null, VENDOR_ITEM_REGULAR),
list("Autoinjector (Tricord)", 1, /obj/item/reagent_container/hypospray/autoinjector/tricord, null, VENDOR_ITEM_REGULAR),
- list("Autoinjector (Emergency)", 2, /obj/item/reagent_container/hypospray/autoinjector/emergency, null, VENDOR_ITEM_REGULAR),
list("PILL BOTTLES", 0, null, null, null),
list("Pill Bottle (Bicaridine)", 5, /obj/item/storage/pill_bottle/bicaridine, null, VENDOR_ITEM_RECOMMENDED),
@@ -42,7 +41,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_medic, list(
list("MEDICAL UTILITIES", 0, null, null, null),
list("Health Analyzer", 4, /obj/item/device/healthanalyzer, null, VENDOR_ITEM_REGULAR),
- list("Medical HUD Glasses", 4, /obj/item/clothing/glasses/hud/health, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 4, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Stasis Bag", 6, /obj/item/bodybag/cryobag, null, VENDOR_ITEM_REGULAR),
list("Pressurized Reagent Canister Pouch (EMPTY)", 3, /obj/item/storage/pouch/pressurized_reagent_canister, null, VENDOR_ITEM_REGULAR),
@@ -110,7 +108,6 @@ GLOBAL_LIST_INIT(cm_vending_clothing_medic, list(
list("Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY),
list("Uniform", 0, /obj/item/clothing/under/marine/medic, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY),
list("Gloves", 0, /obj/item/clothing/gloves/marine, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY),
- list("Medical HUD Glasses", 0, /obj/item/clothing/glasses/hud/health, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_MANDATORY),
list("Headset", 0, /obj/item/device/radio/headset/almayer/marine, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY),
list("Helmet", 0, /obj/item/clothing/head/helmet/marine/medic, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_MANDATORY),
list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm
index d2e50aee9042..c02748fea509 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm
@@ -79,10 +79,10 @@
list("WEBBINGS", -1, null, null),
list("Brown Webbing Vest", round(scale * 1.25), /obj/item/clothing/accessory/storage/black_vest/brown_vest, VENDOR_ITEM_REGULAR),
- list("Black Webbing Vest", round(scale * 0.5), /obj/item/clothing/accessory/storage/black_vest, VENDOR_ITEM_REGULAR),
+ list("Black Webbing Vest", round(max(1,(scale * 0.5))), /obj/item/clothing/accessory/storage/black_vest, VENDOR_ITEM_REGULAR),
list("Webbing", round(scale * 2), /obj/item/clothing/accessory/storage/webbing, VENDOR_ITEM_REGULAR),
- list("Drop Pouch", round(scale * 0.5), /obj/item/clothing/accessory/storage/droppouch, VENDOR_ITEM_REGULAR),
- list("Shoulder Holster", round(scale * 0.5), /obj/item/clothing/accessory/storage/holster, VENDOR_ITEM_REGULAR),
+ list("Drop Pouch", round(max(1,(scale * 0.5))), /obj/item/clothing/accessory/storage/droppouch, VENDOR_ITEM_REGULAR),
+ list("Shoulder Holster", round(max(1,(scale * 0.5))), /obj/item/clothing/accessory/storage/holster, VENDOR_ITEM_REGULAR),
list("ARMOR", -1, null, null),
list("M3 Pattern Carrier Marine Armor", round(scale * 15), /obj/item/clothing/suit/storage/marine/carrier, VENDOR_ITEM_REGULAR),
@@ -107,7 +107,7 @@
list("RESTRICTED BACKPACKS", -1, null, null),
list("USCM Technician Welderpack", round(scale * 1.25), /obj/item/storage/backpack/marine/engineerpack, VENDOR_ITEM_REGULAR),
list("Technician Welder-Satchel", round(scale * 2), /obj/item/storage/backpack/marine/engineerpack/satchel, VENDOR_ITEM_REGULAR),
- list("Radio Telephone Backpack", round(scale * 0.5), /obj/item/storage/backpack/marine/satchel/rto, VENDOR_ITEM_REGULAR),
+ list("Radio Telephone Backpack", round(max(1,(scale * 0.5))), /obj/item/storage/backpack/marine/satchel/rto, VENDOR_ITEM_REGULAR),
list("BELTS", -1, null, null),
list("M276 Pattern Ammo Load Rig", round(scale * 15), /obj/item/storage/belt/marine, VENDOR_ITEM_REGULAR),
@@ -155,6 +155,8 @@
list("M10 Helmet Rain Cover", round(scale * 10), /obj/item/prop/helmetgarb/raincover, VENDOR_ITEM_REGULAR),
list("Firearm Lubricant", round(scale * 15), /obj/item/prop/helmetgarb/gunoil, VENDOR_ITEM_REGULAR),
list("USCM Flair", round(scale * 15), /obj/item/prop/helmetgarb/flair_uscm, VENDOR_ITEM_REGULAR),
+ list("Falling Falcons Shoulder Patch", round(scale * 15), /obj/item/clothing/accessory/patch/falcon, VENDOR_ITEM_REGULAR),
+ list("USCM Shoulder Patch", round(scale * 15), /obj/item/clothing/accessory/patch, VENDOR_ITEM_REGULAR),
)
//--------------SQUAD SPECIFIC VERSIONS--------------
@@ -272,11 +274,11 @@
list("Wirecutters", round(scale * 5), /obj/item/tool/wirecutters, VENDOR_ITEM_REGULAR),
list("Crowbar", round(scale * 5), /obj/item/tool/crowbar, VENDOR_ITEM_REGULAR),
list("Wrench", round(scale * 5), /obj/item/tool/wrench, VENDOR_ITEM_REGULAR),
- list("ME3 hand welder", round(scale * 2), /obj/item/tool/weldingtool/simple, VENDOR_ITEM_REGULAR),
+ list("Multitool", round(scale * 1), /obj/item/device/multitool, VENDOR_ITEM_REGULAR),
+ list("ME3 hand welder", round(scale * 1), /obj/item/tool/weldingtool/simple, VENDOR_ITEM_REGULAR),
list("FLARE AND LIGHT", -1, null, null),
list("Combat Flashlight", round(scale * 5), /obj/item/device/flashlight/combat, VENDOR_ITEM_REGULAR),
- list("Flashlight", round(scale * 5), /obj/item/device/flashlight/combat, VENDOR_ITEM_REGULAR),
list("Box of Flashlight", round(scale * 1), /obj/item/ammo_box/magazine/misc/flashlight, VENDOR_ITEM_REGULAR),
list("Box of Flares", round(scale * 1), /obj/item/ammo_box/magazine/misc/flares, VENDOR_ITEM_REGULAR),
list("M94 Marking Flare Pack", round(scale * 10), /obj/item/storage/box/m94, VENDOR_ITEM_REGULAR),
@@ -286,6 +288,8 @@
list("Toolkit", round(scale * 1), /obj/item/storage/firstaid/toolkit/empty, VENDOR_ITEM_REGULAR),
list("Map", round(scale * 5), /obj/item/map/current_map, VENDOR_ITEM_REGULAR),
list("Extinguisher", round(scale * 5), /obj/item/tool/extinguisher, VENDOR_ITEM_REGULAR),
+ list("Fire Extinguisher (Portable)", round(scale * 1), /obj/item/tool/extinguisher/mini, VENDOR_ITEM_REGULAR),
+ list("Roller Bed", round(scale * 1), /obj/item/roller, VENDOR_ITEM_REGULAR),
list("Machete Scabbard (Full)", round(scale * 5), /obj/item/storage/large_holster/machete/full, VENDOR_ITEM_REGULAR),
list("Binoculars", round(scale * 1), /obj/item/device/binoculars, VENDOR_ITEM_REGULAR),
list("MB-6 Folding Barricades (x3)", round(scale * 2), /obj/item/stack/folding_barricade/three, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
index d92eaabf52c1..09881536901e 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_rifleman.dm
@@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_marine, list(
list("Brown Webbing Vest", 15, /obj/item/clothing/accessory/storage/black_vest/brown_vest, null, VENDOR_ITEM_REGULAR),
list("Black Webbing Vest", 15, /obj/item/clothing/accessory/storage/black_vest, null, VENDOR_ITEM_REGULAR),
list("Drop Pouch", 15, /obj/item/clothing/accessory/storage/droppouch, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("B12 Pattern Marine Armor", 30, /obj/item/clothing/suit/storage/marine/leader, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
index 5560508ca4c1..d3a606ae6b41 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_smartgunner.dm
@@ -34,6 +34,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_smartgun, list(
list("Powerloader Certification", 45, /obj/item/pamphlet/skill/powerloader, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("RADIO KEYS", 0, null, null, null),
list("Engineering Radio Encryption Key", 5, /obj/item/device/encryptionkey/engi, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
index e0900c3fd3c8..b09ae4aa15c5 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_specialist.dm
@@ -38,7 +38,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_spec, list(
list("UTILITIES", 0, null, null, null),
list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
list("Fuel Tank Strap Pouch", 5, /obj/item/storage/pouch/flamertank, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
index ceef80ab6952..4f64ca7e81fa 100644
--- a/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
+++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_tl.dm
@@ -35,7 +35,9 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list(
list("Motion Detector", 15, /obj/item/device/motiondetector, null, VENDOR_ITEM_RECOMMENDED),
list("Plastic Explosive", 10, /obj/item/explosive/plastic, null, VENDOR_ITEM_REGULAR),
list("Breaching Charge", 10, /obj/item/explosive/plastic/breaching_charge, null, VENDOR_ITEM_REGULAR),
- list("SensorMate Medical HUD", 15, /obj/item/clothing/glasses/hud/sensor, null, VENDOR_ITEM_REGULAR),
+ list("Welding Visor", 5, /obj/item/device/helmet_visor/welding_visor, null, VENDOR_ITEM_REGULAR),
+ list("Medical Helmet Optic", 15, /obj/item/device/helmet_visor/medical, null, VENDOR_ITEM_REGULAR),
+ list("Welding Goggles", 5, /obj/item/clothing/glasses/welding, null, VENDOR_ITEM_REGULAR),
list("M2 Night Vision Goggles", 30, /obj/item/prop/helmetgarb/helmet_nvg, null, VENDOR_ITEM_RECOMMENDED),
list("Roller Bed", 5, /obj/item/roller, null, VENDOR_ITEM_REGULAR),
list("Fulton Device Stack", 5, /obj/item/stack/fulton, null, VENDOR_ITEM_REGULAR),
@@ -44,7 +46,6 @@ GLOBAL_LIST_INIT(cm_vending_gear_tl, list(
list("Machete Pouch (Full)", 15, /obj/item/storage/pouch/machete/full, null, VENDOR_ITEM_REGULAR),
list("Fire Extinguisher (Portable)", 5, /obj/item/tool/extinguisher/mini, null, VENDOR_ITEM_REGULAR),
list("Whistle", 5, /obj/item/device/whistle, null, VENDOR_ITEM_REGULAR),
- list("Welding Goggles", 5, /obj/item/clothing/glasses/welding, null, VENDOR_ITEM_REGULAR),
list("Powerloader Certification", 45, /obj/item/pamphlet/skill/powerloader, null, VENDOR_ITEM_REGULAR),
list("Insulated Gloves", 3, /obj/item/clothing/gloves/yellow, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/supplies.dm b/code/game/machinery/vending/vendor_types/supplies.dm
index 2a2f35de8c19..376edf7ffc5d 100644
--- a/code/game/machinery/vending/vendor_types/supplies.dm
+++ b/code/game/machinery/vending/vendor_types/supplies.dm
@@ -23,8 +23,6 @@
list("FOOD AND BEVERAGE", -1, null, null),
list("MRE", 25, /obj/item/storage/box/MRE, VENDOR_ITEM_REGULAR),
list("Water Bottle", 25, /obj/item/reagent_container/food/drinks/cans/waterbottle, VENDOR_ITEM_REGULAR),
- list("Aspen Beer", 10, /obj/item/storage/beer_pack, VENDOR_ITEM_REGULAR),//NOTE TO SELF, LOCK THIS ALCOHOL BEHIND SHIP ESCAPE
- list("Wey-Yu Sake", 5, /obj/item/reagent_container/food/drinks/bottle/sake, VENDOR_ITEM_REGULAR),
list("UTILITY", -1, null, null),
list("M94 Marking Flare Pack", 5, /obj/item/storage/box/m94, VENDOR_ITEM_REGULAR),
diff --git a/code/game/objects/effects/acid_hole.dm b/code/game/objects/effects/acid_hole.dm
index 549ab45953d2..415df0e7e5a7 100644
--- a/code/game/objects/effects/acid_hole.dm
+++ b/code/game/objects/effects/acid_hole.dm
@@ -165,7 +165,7 @@
F.forceMove(Target)
F.setDir(pick(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
step_away(F,src,rand(1,5))
- F.SetLuminosity(0)
+ F.set_light(0)
if(F.on && loc != user)
- F.SetLuminosity(F.brightness_on)
+ F.set_light_on(F.on)
return
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm
index b94ee6902321..49d758b52b19 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/effects/aliens.dm
@@ -332,7 +332,7 @@
if(!acids_area)
return
- if(SSweather.is_weather_event && locate(acids_area.master) in SSweather.weather_areas)
+ if(SSweather.is_weather_event && locate(acids_area) in SSweather.weather_areas)
acid_strength = acid_strength + (SSweather.weather_event_instance.fire_smothering_strength * 0.33) //smothering_strength is 1-10, acid strength is a multiplier
in_weather = SSweather.weather_event_instance.fire_smothering_strength
else
diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm
index 43c3500813a4..9cf2aa3d8e09 100644
--- a/code/game/objects/effects/decals/cleanable/misc.dm
+++ b/code/game/objects/effects/decals/cleanable/misc.dm
@@ -35,12 +35,8 @@
name = "glowing goo"
acid_damage = 1
icon_state = "greenglow"
- luminosity = 1
-
-/obj/effect/decal/cleanable/dirt/greenglow/Destroy()
- SetLuminosity(0)
- return ..()
-
+ light_range = 1
+ light_color = COLOUR_GREEN
/obj/effect/decal/cleanable/flour
name = "flour"
desc = "It's still good. Four second rule!"
@@ -58,7 +54,8 @@
density = FALSE
anchored = TRUE
layer = TURF_LAYER
- luminosity = 1
+ light_range = 1
+ light_color = COLOUR_GREEN
icon = 'icons/effects/effects.dmi'
icon_state = "greenglow"
@@ -68,10 +65,6 @@
. = ..()
QDEL_IN(WEAKREF(src), 2 MINUTES)
-/obj/effect/decal/cleanable/greenglow/Destroy()
- SetLuminosity(0)
- return ..()
-
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 5391ed2710a8..338f8b9a7e8e 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -79,7 +79,7 @@
deconstruct(FALSE)
return
-/obj/effect/decal/mecha_wreckage/bullet_act(obj/item/projectile/Proj)
+/obj/effect/decal/mecha_wreckage/bullet_act(obj/projectile/Proj)
return 1
/obj/effect/decal/mecha_wreckage/attack_alien(mob/living/carbon/xenomorph/M)
diff --git a/code/game/objects/effects/effect_system/chemsmoke.dm b/code/game/objects/effects/effect_system/chemsmoke.dm
index c2323c32c934..eeb17f7c98d0 100644
--- a/code/game/objects/effects/effect_system/chemsmoke.dm
+++ b/code/game/objects/effects/effect_system/chemsmoke.dm
@@ -199,10 +199,10 @@
smoke.pixel_x = -32 + rand(-8,8)
smoke.pixel_y = -32 + rand(-8,8)
walk_to(smoke, T)
- smoke.SetOpacity(1) //switching opacity on after the smoke has spawned, and then
+ smoke.set_opacity(1) //switching opacity on after the smoke has spawned, and then
sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner
if(smoke.opacity)
- smoke.SetOpacity(0)
+ smoke.set_opacity(0)
fadeOut(smoke)
qdel(smoke)
diff --git a/code/game/objects/effects/effect_system/foam.dm b/code/game/objects/effects/effect_system/foam.dm
index a7647dbd4489..f26736c8bfc4 100644
--- a/code/game/objects/effects/effect_system/foam.dm
+++ b/code/game/objects/effects/effect_system/foam.dm
@@ -188,7 +188,7 @@
/obj/structure/foamed_metal/ex_act(severity)
take_damage(severity * FOAMED_METAL_EXPLOSION_DMG)
-/obj/structure/foamed_metal/bullet_act(obj/item/projectile/P)
+/obj/structure/foamed_metal/bullet_act(obj/projectile/P)
if(P.ammo.damage_type == HALLOSS || P.ammo.damage_type == TOX || P.ammo.damage_type == CLONE || P.damage == 0)
return
diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm
index 2eb36930c542..78aa01b5dacb 100644
--- a/code/game/objects/effects/effect_system/smoke.dm
+++ b/code/game/objects/effects/effect_system/smoke.dm
@@ -36,7 +36,7 @@
/obj/effect/particle_effect/smoke/Destroy()
. = ..()
if(opacity)
- SetOpacity(0)
+ set_opacity(0)
active_smoke_effects -= src
cause_data = null
@@ -51,9 +51,10 @@
qdel(src)
return
else if(time_to_live == 1)
- alpha = 180
+ if(alpha > 180)
+ alpha = 180
amount = 0
- SetOpacity(0)
+ set_opacity(0)
apply_smoke_effect(get_turf(src))
@@ -63,8 +64,8 @@
/obj/effect/particle_effect/smoke/Crossed(atom/movable/M)
..()
- if(istype(M, /obj/item/projectile/beam))
- var/obj/item/projectile/beam/B = M
+ if(istype(M, /obj/projectile/beam))
+ var/obj/projectile/beam/B = M
B.damage = (B.damage/2)
if(iscarbon(M))
affect(M)
@@ -254,45 +255,79 @@
name = "CN20 nerve gas"
smokeranking = SMOKE_RANK_HIGH
color = "#80c7e4"
+ var/xeno_affecting = FALSE
+ opacity = FALSE
+ alpha = 75
+
+/obj/effect/particle_effect/smoke/cn20/xeno
+ name = "CN20-X nerve gas"
+ color = "#2da9da"
+ xeno_affecting = TRUE
/obj/effect/particle_effect/smoke/cn20/Move()
. = ..()
- for(var/mob/living/carbon/human/creature in get_turf(src))
- affect(creature)
-
-/obj/effect/particle_effect/smoke/cn20/affect(mob/living/carbon/human/creature)
+ if(!xeno_affecting)
+ for(var/mob/living/carbon/human/human in get_turf(src))
+ affect(human)
+ else
+ for(var/mob/living/carbon/creature in get_turf(src))
+ affect(creature)
+
+/obj/effect/particle_effect/smoke/cn20/affect(mob/living/carbon/creature)
+ var/mob/living/carbon/xenomorph/xeno_creature
+ var/mob/living/carbon/human/human_creature
+ if(isxeno(creature))
+ xeno_creature = creature
+ else if(ishuman(creature))
+ human_creature = creature
if(!istype(creature) || issynth(creature) || creature.stat == DEAD)
return FALSE
+ if(!xeno_affecting && xeno_creature)
+ return FALSE
if(isyautja(creature) && prob(75))
return FALSE
- if (creature.wear_mask && (creature.wear_mask.flags_inventory & BLOCKGASEFFECT))
+ if(creature.wear_mask && (creature.wear_mask.flags_inventory & BLOCKGASEFFECT))
+ return FALSE
+ if(human_creature && (human_creature.head && (human_creature.head.flags_inventory & BLOCKGASEFFECT)))
return FALSE
var/effect_amt = round(6 + amount*6)
- creature.apply_damage(12, OXY)
+ if(xeno_creature)
+ if(xeno_creature.interference < 4)
+ to_chat(xeno_creature, SPAN_XENOHIGHDANGER("Your awareness dims to a small area!"))
+ xeno_creature.interference = 10
+ xeno_creature.blinded = TRUE
+ else
+ creature.apply_damage(12, OXY)
creature.SetEarDeafness(max(creature.ear_deaf, round(effect_amt*1.5))) //Paralysis of hearing system, aka deafness
- if(!creature.eye_blind) //Eye exposure damage
+ if(!xeno_creature && !creature.eye_blind) //Eye exposure damage
to_chat(creature, SPAN_DANGER("Your eyes sting. You can't see!"))
- creature.SetEyeBlind(round(effect_amt/3))
- if(creature.coughedtime != 1 && !creature.stat) //Coughing/gasping
+ creature.SetEyeBlind(round(effect_amt/3))
+ if(!xeno_creature && creature.coughedtime != 1 && !creature.stat) //Coughing/gasping
creature.coughedtime = 1
if(prob(50))
creature.emote("cough")
else
creature.emote("gasp")
addtimer(VARSET_CALLBACK(creature, coughedtime, 0), 1.5 SECONDS)
- if (prob(20))
+ var/stun_chance = 20
+ if(xeno_affecting)
+ stun_chance = 35
+ if(prob(stun_chance))
creature.apply_effect(1, WEAKEN)
//Topical damage (neurotoxin on exposed skin)
- to_chat(creature, SPAN_DANGER("Your body is going numb, almost as if paralyzed!"))
+ if(xeno_creature)
+ to_chat(xeno_creature, SPAN_XENODANGER("You are struggling to move, it's as if you're paralyzed!"))
+ else
+ to_chat(creature, SPAN_DANGER("Your body is going numb, almost as if paralyzed!"))
if(prob(60 + round(amount*15))) //Highly likely to drop items due to arms/hands seizing up
creature.drop_held_item()
- if(ishuman(creature))
- creature.temporary_slowdown = max(creature.temporary_slowdown, 4) //One tick every two second
- creature.recalculate_move_delay = TRUE
+ if(human_creature)
+ human_creature.temporary_slowdown = max(human_creature.temporary_slowdown, 4) //One tick every two second
+ human_creature.recalculate_move_delay = TRUE
return TRUE
//////////////////////////////////////
@@ -595,6 +630,9 @@
/datum/effect_system/smoke_spread/cn20
smoke_type = /obj/effect/particle_effect/smoke/cn20
+/datum/effect_system/smoke_spread/cn20/xeno
+ smoke_type = /obj/effect/particle_effect/smoke/cn20/xeno
+
// XENO SMOKES
/datum/effect_system/smoke_spread/xeno_acid
diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm
index e54607d6f930..bebe0ec8b27f 100644
--- a/code/game/objects/effects/glowshroom.dm
+++ b/code/game/objects/effects/glowshroom.dm
@@ -39,13 +39,9 @@
else //if on the floor, glowshroom on-floor sprite
icon_state = "glowshroomf"
- SetLuminosity(round(potency/15))
+ set_light(round(potency/15))
lastTick = world.timeofday
-/obj/effect/glowshroom/Destroy()
- SetLuminosity(0)
- . = ..()
-
/obj/effect/glowshroom/proc/CalcDir(turf/location = loc)
set background = 1
var/direction = 16
diff --git a/code/game/objects/effects/landmarks/survivor_spawner.dm b/code/game/objects/effects/landmarks/survivor_spawner.dm
index d19bbbe49516..25cc1a80d0b4 100644
--- a/code/game/objects/effects/landmarks/survivor_spawner.dm
+++ b/code/game/objects/effects/landmarks/survivor_spawner.dm
@@ -142,25 +142,44 @@
/obj/effect/landmark/survivor_spawner/upp/soldier
equipment = /datum/equipment_preset/survivor/upp/soldier
synth_equipment = /datum/equipment_preset/synth/survivor/upp
- spawn_priority = SPAWN_PRIORITY_MEDIUM
+ intro_text = list("
Name | Role | State | Location | SL Distance | Filter |
---|