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/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/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/_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/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/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/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/skills.dm b/code/datums/skills.dm
index a2edde24b8d4..252ef07c4806 100644
--- a/code/datums/skills.dm
+++ b/code/datums/skills.dm
@@ -1673,7 +1673,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
@@ -1682,12 +1682,13 @@ 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_MEDICAL = SKILL_MEDICAL_MEDIC,
- SKILL_VEHICLE = SKILL_VEHICLE_DEFAULT,
+ SKILL_VEHICLE = SKILL_VEHICLE_LARGE,
SKILL_JTAC = SKILL_JTAC_EXPERT,
)
diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm
index becee89adb6d..bc6adc026b6e 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
diff --git a/code/game/machinery/ARES/ARES.dm b/code/game/machinery/ARES/ARES.dm
index 56165cbccb58..e2ca3995ee83 100644
--- a/code/game/machinery/ARES/ARES.dm
+++ b/code/game/machinery/ARES/ARES.dm
@@ -159,6 +159,7 @@
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)
diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm
index bfe4c9dee21e..d83e9280b6c7 100644
--- a/code/game/machinery/ARES/ARES_procs.dm
+++ b/code/game/machinery/ARES/ARES_procs.dm
@@ -69,14 +69,14 @@ 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/user, 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_bombardment(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_announcement(title, message)
interface.records_announcement.Add(new /datum/ares_record/announcement(title, message))
-/datum/ares_link/proc/log_ares_requisition(source, details, mob/user)
- interface.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user.name))
+/datum/ares_link/proc/log_ares_requisition(source, details, user)
+ interface.records_asrs.Add(new /datum/ares_record/requisition_log(source, details, user))
/datum/ares_link/proc/log_ares_security(title, details)
interface.records_security.Add(new /datum/ares_record/security(title, details))
@@ -84,8 +84,8 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/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(mob/user, details)
- interface.records_flight.Add(new /datum/ares_record/flight(details, user.name))
+/datum/ares_link/proc/log_ares_flight(user, details)
+ interface.records_flight.Add(new /datum/ares_record/flight(details, user))
// ------ End ARES Logging Procs ------ //
/proc/ares_apollo_talk(broadcast_message)
@@ -234,6 +234,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
@@ -530,16 +531,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")
diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm
index c55250fdc04d..78fc05d8e0d0 100644
--- a/code/game/machinery/doors/alarmlock.dm
+++ b/code/game/machinery/doors/alarmlock.dm
@@ -25,7 +25,6 @@
return ..()
/obj/structure/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
-/*
..()
if(inoperable())
return
@@ -33,6 +32,8 @@
var/alarm_area = signal.data["zone"]
var/alert = signal.data["alert"]
+ var/area/our_area = get_area(src)
+
if(alarm_area == our_area.name)
switch(alert)
if("severe")
@@ -41,4 +42,3 @@
if("minor", "clear")
autoclose = 0
open()
-*/
diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm
index f58d50f3a8cf..da4ad01c086b 100644
--- a/code/game/machinery/doors/multi_tile.dm
+++ b/code/game/machinery/doors/multi_tile.dm
@@ -377,7 +377,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 +390,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/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/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("
You are a member of a UPP recon force!
",\
+ "You ARE aware of the xenomorph threat.",\
+ "Your primary objective is to survive. You believe a second dropship crashed somewhere to the south east, which was carrying additional weapons")
+ story_text = "Your orders were simple, Recon the site, ascertain if there is a biological weapons program in the area, and if so to secure the colony and retrieve a sample. However your team failed to account for an active anti-air battery near the area. Both your craft and your sister ship crashed. Barely having a chance to catch your breath, you found yourself being assailed by vile xenomorphs! You and your team have barely held your ground, at the cost of four of your own, but more are coming and ammo is low. You believe an American rescue force is en route, but is the enemy of my enemy truly your friend?"
+ spawn_priority = SPAWN_PRIORITY_LOW
/obj/effect/landmark/survivor_spawner/upp_sapper
equipment = /datum/equipment_preset/survivor/upp/sapper
synth_equipment = /datum/equipment_preset/synth/survivor/upp
+ intro_text = list("
You are a member of a UPP recon force!
",\
+ "You ARE aware of the xenomorph threat.",\
+ "Your primary objective is to survive. You believe a second dropship crashed somewhere to the south east, which was carrying additional weapons")
+ story_text = "Your orders were simple, Recon the site, ascertain if there is a biological weapons program in the area, and if so to secure the colony and retrieve a sample. However your team failed to account for an active anti-air battery near the area. Both your craft and your sister ship crashed. Barely having a chance to catch your breath, you found yourself being assailed by vile xenomorphs! You and your team have barely held your ground, at the cost of four of your own, but more are coming and ammo is low. You believe an American rescue force is en route, but is the enemy of my enemy truly your friend?"
spawn_priority = SPAWN_PRIORITY_MEDIUM
/obj/effect/landmark/survivor_spawner/upp_medic
equipment = /datum/equipment_preset/survivor/upp/medic
synth_equipment = /datum/equipment_preset/synth/survivor/upp
- spawn_priority = SPAWN_PRIORITY_HIGH
+ intro_text = list("
You are a member of a UPP recon force!
",\
+ "You ARE aware of the xenomorph threat.",\
+ "Your primary objective is to survive. You believe a second dropship crashed somewhere to the south east, which was carrying additional weapons")
+ story_text = "Your orders were simple, Recon the site, ascertain if there is a biological weapons program in the area, and if so to secure the colony and retrieve a sample. However your team failed to account for an active anti-air battery near the area. Both your craft and your sister ship crashed. Barely having a chance to catch your breath, you found yourself being assailed by vile xenomorphs! You and your team have barely held your ground, at the cost of four of your own, but more are coming and ammo is low. You believe an American rescue force is en route, but is the enemy of my enemy truly your friend?"
+ spawn_priority = SPAWN_PRIORITY_MEDIUM
/obj/effect/landmark/survivor_spawner/upp_specialist
equipment = /datum/equipment_preset/survivor/upp/specialist
synth_equipment = /datum/equipment_preset/synth/survivor/upp
+ intro_text = list("
You are a member of a UPP recon force!
",\
+ "You ARE aware of the xenomorph threat.",\
+ "Your primary objective is to survive. You believe a second dropship crashed somewhere to the south east, which was carrying additional weapons")
+ story_text = "Your orders were simple, Recon the site, ascertain if there is a biological weapons program in the area, and if so to secure the colony and retrieve a sample. However your team failed to account for an active anti-air battery near the area. Both your craft and your sister ship crashed. Barely having a chance to catch your breath, you found yourself being assailed by vile xenomorphs! You and your team have barely held your ground, at the cost of four of your own, but more are coming and ammo is low. You believe an American rescue force is en route, but is the enemy of my enemy truly your friend?"
spawn_priority = SPAWN_PRIORITY_HIGH
/obj/effect/landmark/survivor_spawner/squad_leader
equipment = /datum/equipment_preset/survivor/upp/squad_leader
synth_equipment = /datum/equipment_preset/synth/survivor/upp
+ intro_text = list("
You are a member of a UPP recon force!
",\
+ "You ARE aware of the xenomorph threat.",\
+ "Your primary objective is to survive. You believe a second dropship crashed somewhere to the south east, which was carrying additional weapons")
+ story_text = "Your orders were simple, Recon the site, ascertain if there is a biological weapons program in the area, and if so to secure the colony and retrieve a sample. However your team failed to account for an active anti-air battery near the area. Both your craft and your sister ship crashed. Barely having a chance to catch your breath, you found yourself being assailed by vile xenomorphs! You and your team have barely held your ground, at the cost of four of your own, but more are coming and ammo is low. You believe an American rescue force is en route, but is the enemy of my enemy truly your friend?"
spawn_priority = SPAWN_PRIORITY_VERY_HIGH
-
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 4ab9e19d5ae1..dd5f0f88e6a7 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -850,7 +850,7 @@
/obj/item/device/radio/headset/distress/pmc/hvh
desc = "A special headset used by corporate personnel. Channels are as follows: :o - colony."
- initial_keys = list(/obj/item/device/encryptionkey/colony)
+ initial_keys = list(/obj/item/device/encryptionkey/colony, /obj/item/device/encryptionkey/WY)
misc_tracking = FALSE
/obj/item/device/radio/headset/distress/pmc/cct
@@ -1022,3 +1022,13 @@
initial_keys = list(/obj/item/device/encryptionkey/vc)
volume = RADIO_VOLUME_RAISED
multibroadcast_cooldown = HIGH_MULTIBROADCAST_COOLDOWN
+
+/obj/item/device/radio/headset/distress/UPP/recon
+ name = "\improper UPP headset"
+ desc = "A special headset used by recon elements of the UPP military."
+ frequency = UPP_FREQ
+ initial_keys = list(/obj/item/device/encryptionkey/upp)
+ volume = RADIO_VOLUME_QUIET
+ ignore_z = FALSE
+ has_hud = TRUE
+ hud_type = MOB_HUD_FACTION_UPP
diff --git a/code/game/objects/items/reagent_containers/hypospray.dm b/code/game/objects/items/reagent_containers/hypospray.dm
index 5014c85547aa..fcea8997f0b5 100644
--- a/code/game/objects/items/reagent_containers/hypospray.dm
+++ b/code/game/objects/items/reagent_containers/hypospray.dm
@@ -10,7 +10,7 @@
icon_state = "hypo"
amount_per_transfer_from_this = 5
volume = 30
- possible_transfer_amounts = list(5,10,15,30)
+ possible_transfer_amounts = list(3, 5, 10, 15, 30)
flags_atom = FPRINT|OPENCONTAINER
flags_equip_slot = SLOT_WAIST
flags_item = NOBLUDGEON
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index 50a6cc92cb5f..afeaff89ae07 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -51,6 +51,7 @@
/obj/item/storage/lockbox/loyalty
name = "\improper Wey-Yu equipment lockbox"
+ req_access = null
req_one_access = list(ACCESS_WY_EXEC, ACCESS_WY_SECURITY)
/obj/item/storage/lockbox/loyalty/fill_preset_inventory()
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 173182b6cc3e..d47537743111 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -629,15 +629,15 @@ ICEY GRASS. IT LOOKS LIKE IT'S MADE OF ICE.
/obj/structure/flora/jungle/vines/light_1
icon_state = "light_1"
- icon_tag = "light_1"
+ icon_tag = "light"
/obj/structure/flora/jungle/vines/light_2
icon_state = "light_2"
- icon_tag = "light_2"
+ icon_tag = "light"
/obj/structure/flora/jungle/vines/light_3
icon_state = "light_3"
- icon_tag = "light_3"
+ icon_tag = "light"
//heavy hide you
/obj/structure/flora/jungle/vines/heavy
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index 4d60c6c263cf..22a3f48c837e 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -1031,8 +1031,9 @@ var/datum/controller/supply/supply_controller = new()
var/pack_name = supply_pack.name
if(supply_pack.dollar_cost)
pack_source = "Unknown"
- pack_name = "Unknown"
- link.log_ares_requisition(pack_source, pack_name, usr)
+ if(prob(90))
+ pack_name = "Unknown"
+ link.log_ares_requisition(pack_source, pack_name, usr.name)
else
temp = "Not enough money left. "
temp += " BackMain Menu"
diff --git a/code/modules/admin/verbs/freeforghosts.dm b/code/modules/admin/verbs/freeforghosts.dm
index a2f3912030e5..24c261ee18f3 100644
--- a/code/modules/admin/verbs/freeforghosts.dm
+++ b/code/modules/admin/verbs/freeforghosts.dm
@@ -6,22 +6,27 @@
to_chat(src, "Only staff members may use this.")
return
- free_for_ghosts(M)
+ free_for_ghosts(M, notify = TRUE)
message_admins("[key_name_admin(usr)] freed [key_name(M)] for ghosts to take.")
-/client/proc/free_for_ghosts(mob/living/M in GLOB.living_mob_list)
+/client/proc/free_for_ghosts(mob/living/M in GLOB.living_mob_list, notify)
if(!ismob(M))
return
- M.free_for_ghosts()
+ M.free_for_ghosts(notify)
-/mob/proc/free_for_ghosts()
+/mob/proc/free_for_ghosts(notify)
if(mind || client)
ghostize(FALSE)
GLOB.freed_mob_list |= WEAKREF(src)
+ if(!notify)
+ return
+
+ notify_ghosts(header = "Freed Mob", message = "A mob is now available for ghosts. Name: [real_name], Job: [job ? job : ""]", enter_link = "claim_freed=[REF(src)]", source = src, action = NOTIFY_ORBIT)
+
/client/proc/free_all_mobs_in_view()
set name = "Free All Mobs"
set category = "Admin.InView"
@@ -34,6 +39,6 @@
return
for(var/mob/living/M in view())
- free_for_ghosts(M)
+ free_for_ghosts(M, notify = FALSE)
message_admins(WRAP_STAFF_LOG(usr, "freed all mobs in [get_area(usr)] ([usr.x],[usr.y],[usr.z])"), usr.x, usr.y, usr.z)
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 3722b32fb2b4..a7149c07d3e7 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -436,6 +436,9 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list(
//if(prefs.window_skin & TOGGLE_WINDOW_SKIN)
// set_night_skin()
+ if(!tooltips && prefs.tooltips)
+ tooltips = new(src)
+
load_player_data()
view = world_view_size
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 4f1161709657..76323a19ac8c 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -234,6 +234,9 @@ var/const/MAX_SAVE_SLOTS = 10
/// if this client has custom cursors enabled
var/custom_cursors = TRUE
+ /// if this client has tooltips enabled
+ var/tooltips = TRUE
+
/datum/preferences/New(client/C)
key_bindings = deepCopyList(GLOB.hotkey_keybinding_list_by_key) // give them default keybinds and update their movement keys
macros = new(C, src)
@@ -573,6 +576,7 @@ var/const/MAX_SAVE_SLOTS = 10
dat += "Ambient Occlusion:[toggle_prefs & TOGGLE_AMBIENT_OCCLUSION ? "Enabled" : "Disabled"] "
dat += "Fit Viewport:[auto_fit_viewport ? "Auto" : "Manual"] "
dat += "Adaptive Zoom:[adaptive_zoom ? "[adaptive_zoom * 2]x" : "Disabled"] "
+ dat += "Tooltips:[tooltips ? "Enabled" : "Disabled"] "
dat += "tgui Window Mode:[(tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"] "
dat += "tgui Window Placement:[(tgui_lock) ? "Primary monitor" : "Free (default)"] "
dat += "Play Admin Midis:[(toggles_sound & SOUND_MIDI) ? "Yes" : "No"] "
@@ -1862,6 +1866,17 @@ var/const/MAX_SAVE_SLOTS = 10
adaptive_zoom = 0
owner?.adaptive_zoom()
+ if("tooltips")
+ tooltips = !tooltips
+ save_preferences()
+
+ if(!tooltips)
+ closeToolTip()
+ return
+
+ if(!owner.tooltips)
+ owner.tooltips = new(owner)
+
if("inputstyle")
var/result = tgui_alert(user, "Which input style do you want?", "Input Style", list("Modern", "Legacy"))
if(!result)
diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm
index 0f482fa7f894..7d9a67c455a9 100644
--- a/code/modules/client/preferences_savefile.dm
+++ b/code/modules/client/preferences_savefile.dm
@@ -193,6 +193,7 @@
S["custom_cursors"] >> custom_cursors
S["autofit_viewport"] >> auto_fit_viewport
S["adaptive_zoom"] >> adaptive_zoom
+ S["tooltips"] >> tooltips
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, CONFIG_GET(string/ooc_color_default))
@@ -225,6 +226,7 @@
no_radial_labels_preference = sanitize_integer(no_radial_labels_preference, FALSE, TRUE, FALSE)
auto_fit_viewport = sanitize_integer(auto_fit_viewport, FALSE, TRUE, TRUE)
adaptive_zoom = sanitize_integer(adaptive_zoom, 0, 2, 0)
+ tooltips = sanitize_integer(tooltips, FALSE, TRUE, TRUE)
synthetic_name = synthetic_name ? sanitize_text(synthetic_name, initial(synthetic_name)) : initial(synthetic_name)
synthetic_type = sanitize_inlist(synthetic_type, PLAYER_SYNTHS, initial(synthetic_type))
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index a7844631051e..b31e6281dba1 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -140,6 +140,11 @@
req_skill_level = SKILL_RESEARCH_TRAINED
clothing_traits = list(TRAIT_REAGENT_SCANNER)
+/obj/item/clothing/glasses/science/prescription
+ name = "prescription reagent scanner HUD goggles"
+ desc = "These goggles are probably of use to someone who isn't holding a rifle and actively seeking to lower their combat life expectancy. Contains prescription lenses."
+ prescription = TRUE
+
/obj/item/clothing/glasses/science/get_examine_text(mob/user)
. = ..()
. += SPAN_INFO("While wearing them, you can examine items to see their reagent contents.")
diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm
index 593134642198..e8b95f7e1aae 100644
--- a/code/modules/cm_aliens/structures/special/pylon_core.dm
+++ b/code/modules/cm_aliens/structures/special/pylon_core.dm
@@ -21,6 +21,11 @@
var/protection_level = TURF_PROTECTION_CAS
+ /// How many lesser drone spawns this pylon is able to spawn currently
+ var/lesser_drone_spawns = 0
+ /// The maximum amount of lesser drone spawns this pylon can hold
+ var/lesser_drone_spawn_limit = 5
+
plane = FLOOR_PLANE
/obj/effect/alien/resin/special/pylon/Initialize(mapload, hive_ref)
@@ -42,6 +47,11 @@
QDEL_NULL(node)
. = ..()
+/obj/effect/alien/resin/special/pylon/process(delta_time)
+ if(lesser_drone_spawns < lesser_drone_spawn_limit)
+ // One every 10 seconds while on ovi, one every 120-ish seconds while off ovi
+ lesser_drone_spawns = min(lesser_drone_spawns + ((linked_hive.living_xeno_queen?.ovipositor ? 0.1 : 0.008) * delta_time), lesser_drone_spawn_limit)
+
/obj/effect/alien/resin/special/pylon/attack_alien(mob/living/carbon/xenomorph/M)
if(isxeno_builder(M) && M.a_intent == INTENT_HELP && M.hivenumber == linked_hive.hivenumber)
do_repair(M) //This handles the delay itself.
@@ -49,6 +59,20 @@
else
return ..()
+/obj/effect/alien/resin/special/pylon/get_examine_text(mob/user)
+ . = ..()
+
+ var/lesser_count = 0
+ for(var/mob/living/carbon/xenomorph/lesser_drone in linked_hive.totalXenos)
+ lesser_count++
+
+ . += "Currently holding [SPAN_NOTICE("[Floor(lesser_drone_spawns)]")]/[SPAN_NOTICE("[lesser_drone_spawn_limit]")] lesser drones."
+ . += "There are currently [SPAN_NOTICE("[lesser_count]")] lesser drones in the hive. The hive can support [SPAN_NOTICE("[linked_hive.lesser_drone_limit]")] lesser drones."
+
+/obj/effect/alien/resin/special/pylon/attack_ghost(mob/dead/observer/user)
+ . = ..()
+ spawn_lesser_drone(user)
+
/obj/effect/alien/resin/special/pylon/proc/do_repair(mob/living/carbon/xenomorph/xeno)
if(!istype(xeno))
return
@@ -94,6 +118,25 @@
pylon_node.resin_parent = src
return pylon_node
+/obj/effect/alien/resin/special/pylon/proc/spawn_lesser_drone(mob/xeno_candidate)
+ if(!linked_hive.can_spawn_as_lesser_drone(xeno_candidate, src))
+ return FALSE
+
+ if(tgui_alert(xeno_candidate, "Are you sure you want to become a lesser drone?", "Confirmation", list("Yes", "No")) != "Yes")
+ return FALSE
+
+ if(!linked_hive.can_spawn_as_lesser_drone(xeno_candidate, src))
+ return FALSE
+
+ var/mob/living/carbon/xenomorph/lesser_drone/new_drone = new(loc, null, linked_hive.hivenumber)
+ xeno_candidate.mind.transfer_to(new_drone, TRUE)
+ lesser_drone_spawns -= 1
+ new_drone.visible_message(SPAN_XENODANGER("A lesser drone emerges out of [src]!"), SPAN_XENODANGER("You emerge out of [src] and awaken from your slumber. For the Hive!"))
+ playsound(new_drone, 'sound/effects/xeno_newlarva.ogg', 25, TRUE)
+ new_drone.generate_name()
+
+ return TRUE
+
/obj/effect/alien/resin/special/pylon/endgame
cover_range = WEED_RANGE_CORE
var/activated = FALSE
@@ -189,6 +232,7 @@
protection_level = TURF_PROTECTION_OB
+ lesser_drone_spawn_limit = 10
/obj/effect/alien/resin/special/pylon/core/Initialize(mapload, datum/hive_status/hive_ref)
. = ..()
@@ -205,6 +249,7 @@
SSminimaps.add_marker(src, z, MINIMAP_FLAG_XENO, "core[health < (initial(health) * 0.5) ? "_warn" : "_passive"]")
/obj/effect/alien/resin/special/pylon/core/process()
+ . = ..()
update_minimap_icon()
// Handle spawning larva if core is connected to a hive
@@ -236,14 +281,13 @@
last_surge_time = world.time
linked_hive.stored_larva++
linked_hive.hijack_burrowed_left--
- announce_dchat("The hive has gained another burrowed larva! Use the Join As Xeno verb to take it.", src)
+ notify_ghosts(header = "Claim Xeno", message = "The Hive has gained another burrowed larva! Click to take it.", source = src, action = NOTIFY_JOIN_XENO, enter_link = "join_xeno")
if(surge_cooldown > 30 SECONDS) //mostly for sanity purposes
surge_cooldown = surge_cooldown - surge_incremental_reduction //ramps up over time
if(linked_hive.hijack_burrowed_left < 1)
linked_hive.hijack_burrowed_surge = FALSE
xeno_message(SPAN_XENOANNOUNCE("The hive's power wanes. You will no longer gain pooled larva over time."), 3, linked_hive.hivenumber)
-
// Hive core can repair itself over time
if(health < maxhealth && last_healed <= world.time)
health += min(heal_amount, maxhealth-health)
@@ -400,22 +444,5 @@
// Tell admins that this condition is reached so they know what has happened if it fails somehow
return
-/obj/effect/alien/resin/special/pylon/core/proc/spawn_lesser_drone(mob/xeno_candidate)
- if(!linked_hive.can_spawn_as_lesser_drone(xeno_candidate))
- return FALSE
-
- var/mob/living/carbon/xenomorph/lesser_drone/new_drone = new /mob/living/carbon/xenomorph/lesser_drone(loc, null, linked_hive.hivenumber)
- xeno_candidate.mind.transfer_to(new_drone, TRUE)
- new_drone.visible_message(SPAN_XENODANGER("A lesser drone emerges out of [src]!"), SPAN_XENODANGER("You emerge out of [src] and awaken from your slumber. For the Hive!"))
- playsound(new_drone, 'sound/effects/xeno_newlarva.ogg', 25, TRUE)
- new_drone.generate_name()
-
- return TRUE
-
-/obj/effect/alien/resin/special/pylon/core/attack_ghost(mob/dead/observer/user)
- . = ..()
- if(SSticker.mode.check_xeno_late_join(user))
- SSticker.mode.attempt_to_join_as_lesser_drone(user)
-
#undef PYLON_REPAIR_TIME
#undef PYLON_WEEDS_REGROWTH_TIME
diff --git a/code/modules/cm_marines/equipment/guncases.dm b/code/modules/cm_marines/equipment/guncases.dm
index a9a3855a53e4..aa01535ff888 100644
--- a/code/modules/cm_marines/equipment/guncases.dm
+++ b/code/modules/cm_marines/equipment/guncases.dm
@@ -315,16 +315,16 @@
//M44 Combat Revolver
/obj/item/storage/box/guncase/m44
name = "\improper M44 Combat Revolver case"
- desc = "A gun case containing an M44 Combat Revolver."
+ desc = "A gun case containing an M44 Combat Revolver loaded with marksman ammo."
storage_slots = 5
can_hold = list(/obj/item/attachable/flashlight, /obj/item/weapon/gun/revolver/m44, /obj/item/ammo_magazine/revolver)
/obj/item/storage/box/guncase/m44/fill_preset_inventory()
new /obj/item/attachable/flashlight(src)
- new /obj/item/weapon/gun/revolver/m44(src)
- new /obj/item/ammo_magazine/revolver(src)
- new /obj/item/ammo_magazine/revolver(src)
- new /obj/item/ammo_magazine/revolver(src)
+ new /obj/item/weapon/gun/revolver/m44/mp(src)
+ new /obj/item/ammo_magazine/revolver/marksman(src)
+ new /obj/item/ammo_magazine/revolver/marksman(src)
+ new /obj/item/ammo_magazine/revolver/marksman(src)
//M4A3 Service Pistol
/obj/item/storage/box/guncase/m4a3
diff --git a/code/modules/cm_marines/overwatch.dm b/code/modules/cm_marines/overwatch.dm
index 070cf1f6c1cf..aa8de9dccf56 100644
--- a/code/modules/cm_marines/overwatch.dm
+++ b/code/modules/cm_marines/overwatch.dm
@@ -1,3 +1,5 @@
+#define MAX_SAVED_COORDINATES 3
+
#define HIDE_ALMAYER 2
#define HIDE_GROUND 1
#define HIDE_NONE 0
@@ -28,10 +30,18 @@
var/datum/tacmap/tacmap
var/minimap_type = MINIMAP_FLAG_USCM
+
+ ///List of saved coordinates, format of ["x", "y", "comment"]
+ var/list/saved_coordinates = list()
+ ///Currently selected UI theme
+ var/ui_theme = "crtblue"
+
+
/obj/structure/machinery/computer/overwatch/Initialize()
. = ..()
tacmap = new(src, minimap_type)
+
/obj/structure/machinery/computer/overwatch/Destroy()
QDEL_NULL(tacmap)
return ..()
@@ -57,437 +67,345 @@
to_chat(user, SPAN_WARNING("You don't have the training to use [src]."))
return
- user.set_interaction(src)
- var/dat = ""
+ tgui_interact(user)
- if(!operator)
- dat += " Operator:---------- "
- else
- dat += " Operator:[operator.name] "
- dat += " Stop Overwatch "
- dat += ""
-
- switch(state)
- if(0) // Base menu
- dat += get_base_menu_text()
- if(1) //Info screen.
- dat += get_info_screen_text()
- if(2)
- dat += get_supply_drop_menu_text()
- if(3)
- dat += get_orbital_bombardment_control_text()
-
- show_browser(user, dat, "Overwatch Console", "overwatch", "size=550x550")
- return
+/obj/structure/machinery/computer/overwatch/get_examine_text(mob/user)
+ . = ..()
-/obj/structure/machinery/computer/overwatch/proc/get_base_menu_text()
- var/dat = ""
+ . += SPAN_NOTICE("Alt-Click this machine to change the UI theme.")
- if(!current_squad) //No squad has been set yet. Pick one.
- dat += "Current Squad: ---------- "
- return dat;
+/obj/structure/machinery/computer/overwatch/clicked(mob/user, list/mods)
- dat += "Current Squad: [current_squad.name] Squad "
- dat += "Message Squad