diff --git a/code/__DEFINES/defenses.dm b/code/__DEFINES/defenses.dm
index 57eb0c86f939..db615c2a0c78 100644
--- a/code/__DEFINES/defenses.dm
+++ b/code/__DEFINES/defenses.dm
@@ -8,7 +8,7 @@
// Defines for barricade upgrades
#define BARRICADE_UPGRADE_BURN "Biohazard Upgrade (+Burn)"
#define BARRICADE_UPGRADE_BRUTE "Reinforced Upgrade (+Brute)"
-#define BARRICADE_UPGRADE_EXPLOSIVE "Explosive Upgrade (+Explosive)"
+#define BARRICADE_UPGRADE_ANTIFF "Composite Upgrade (++Explosive, ++Projectile, ++Fire)"
// Defines for defense stats
#define DEFENSE_FUNCTIONAL 0
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 495b5fb472c5..ba928e202cf0 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -11,8 +11,6 @@
#define OVEREAT_TIME 200
//=================================================
-#define ALIEN_SELECT_AFK_BUFFER 1 // How many minutes that a person can be AFK before not being allowed to be an alien.
-
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point
diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm
index 6d6bd64ea918..7741beecedef 100644
--- a/code/__DEFINES/xeno.dm
+++ b/code/__DEFINES/xeno.dm
@@ -154,6 +154,22 @@
#define WEED_BASE_GROW_SPEED (5 SECONDS)
#define WEED_BASE_DECAY_SPEED (10 SECONDS)
+/// The time you must be dead to join as a xeno larva
+#define XENO_JOIN_DEAD_LARVA_TIME (2.5 MINUTES)
+/// The time you must be dead to join as xeno (not larva)
+#define XENO_JOIN_DEAD_TIME (5 MINUTES)
+/// The time of inactivity you cannot exceed to join as a xeno
+#define XENO_JOIN_AFK_TIME_LIMIT (5 MINUTES)
+/// The amount of time after round start before buried larva spawns are disallowed
+#define XENO_BURIED_LARVA_TIME_LIMIT (30 MINUTES)
+
+/// The time against away_timer when an AFK xeno larva can be replaced
+#define XENO_LEAVE_TIMER_LARVA 80 //80 seconds
+/// The time against away_timer when an AFK xeno (not larva) can be replaced
+#define XENO_LEAVE_TIMER 300 //300 seconds
+/// The time against away_timer when an AFK xeno gets listed in the available list so ghosts can get ready
+#define XENO_AVAILABLE_TIMER 60 //60 seconds
+
/// Between 2% to 10% of explosion severity
#define WEED_EXPLOSION_DAMAGEMULT rand(2, 10)*0.01
diff --git a/code/__HELPERS/_time.dm b/code/__HELPERS/_time.dm
index 85acafa0e2f6..b929ae8636b3 100644
--- a/code/__HELPERS/_time.dm
+++ b/code/__HELPERS/_time.dm
@@ -15,10 +15,6 @@
#define DECISECONDS_TO_HOURS /36000
-#define XENO_LEAVE_TIMER_LARVA 80 //80 seconds
-#define XENO_LEAVE_TIMER 300 //300 seconds
-#define XENO_AVAILABLE_TIMER 60 //60 seconds, when to add a xeno to the avaliable list so ghosts can get ready
-
var/midnight_rollovers = 0
var/rollovercheck_last_timeofday = 0
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index 4ca0edcf43d0..888e3c2ce657 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -57,3 +57,12 @@ var/atom/cmp_dist_origin=null
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
+
+/// Compares mobs based on their timeofdeath value in ascending order
+/proc/cmp_mob_deathtime_asc(mob/A, mob/B)
+ return A.timeofdeath - B.timeofdeath
+
+/// Compares observers based on their larva_queue_time value in ascending order
+/// Assumes the client on the observer is not null
+/proc/cmp_obs_larvaqueuetime_asc(mob/dead/observer/A, mob/dead/observer/B)
+ return A.client.larva_queue_time - B.client.larva_queue_time
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index a0bb9dd98423..61976f4dc903 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -241,35 +241,70 @@
else
return get_step(start, EAST)
-// Same as above but for alien candidates.
-/proc/get_alien_candidates()
+/// Get a list of observers that can be alien candidates, optionally sorted by larva_queue_time
+/proc/get_alien_candidates(sorted = TRUE)
var/list/candidates = list()
- for(var/i in GLOB.observer_list)
- var/mob/dead/observer/O = i
+ for(var/mob/dead/observer/cur_obs as anything in GLOB.observer_list)
+ // Preference check
+ if(!cur_obs.client || !cur_obs.client.prefs || !(cur_obs.client.prefs.be_special & BE_ALIEN_AFTER_DEATH))
+ continue
+
// Jobban check
- if(!O.client || !O.client.prefs || !(O.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) || jobban_isbanned(O, JOB_XENOMORPH))
+ if(jobban_isbanned(cur_obs, JOB_XENOMORPH))
continue
//players that can still be revived are skipped
- if(O.mind && O.mind.original && ishuman(O.mind.original))
- var/mob/living/carbon/human/H = O.mind.original
- if (H.check_tod() && H.is_revivable())
+ if(cur_obs.mind && cur_obs.mind.original && ishuman(cur_obs.mind.original))
+ var/mob/living/carbon/human/cur_human = cur_obs.mind.original
+ if(cur_human.check_tod() && cur_human.is_revivable())
continue
// copied from join as xeno
- var/deathtime = world.time - O.timeofdeath
- if(deathtime < 3000 && ( !O.client.admin_holder || !(O.client.admin_holder.rights & R_ADMIN)) )
+ 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)) )
continue
- // Admins and AFK players cannot be drafted
- if(O.client.inactivity / 600 > ALIEN_SELECT_AFK_BUFFER + 5 || (O.client.admin_holder && (O.client.admin_holder.rights & R_MOD)) && O.adminlarva == 0)
+ // AFK players cannot be drafted
+ if(cur_obs.client.inactivity > XENO_JOIN_AFK_TIME_LIMIT)
continue
- candidates += O
+ // Mods with larva protection cannot be drafted
+ if((cur_obs.client.admin_holder && (cur_obs.client.admin_holder.rights & R_MOD)) && !cur_obs.adminlarva)
+ continue
+
+ candidates += cur_obs
+
+ // Optionally sort by larva_queue_time
+ if(sorted && length(candidates))
+ candidates = sort_list(candidates, GLOBAL_PROC_REF(cmp_obs_larvaqueuetime_asc))
return candidates
+/**
+ * Messages observers that are currently candidates an update on the queue.
+ *
+ * Arguments:
+ * * candidates - The list of observers from get_alien_candidates()
+ * * dequeued - How many candidates to skip messaging because they were dequeued
+ * * cache_only - Whether to not actually send a to_chat message and instead only update larva_queue_cached_message
+ */
+/proc/message_alien_candidates(list/candidates, dequeued, cache_only = FALSE)
+ var/new_players = 0
+ for(var/i in (1 + dequeued) to candidates.len)
+ var/mob/dead/observer/cur_obs = candidates[i]
+
+ // Generate the messages
+ var/cached_message = SPAN_XENONOTICE("You are currently [i-dequeued]\th in the larva queue. There are [new_players] ahead of you that have yet to play this round.")
+ cur_obs.larva_queue_cached_message = cached_message
+ if(!cache_only)
+ var/chat_message = dequeued ? replacetext(cached_message, "currently", "now") : cached_message
+ to_chat(candidates[i], chat_message)
+
+ // Count how many are prioritized
+ if(cur_obs.client.larva_queue_time < 2) // 0 and 1 because facehuggers/t-domers are slightly deprioritized
+ new_players++
+
/proc/convert_k2c(temp)
return ((temp - T0C))
diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm
index 187f179094b2..e2203aadce0c 100644
--- a/code/_globalvars/lists/mobs.dm
+++ b/code/_globalvars/lists/mobs.dm
@@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY_TYPED(alive_human_list, /mob/living/carbon/human) // list of a
GLOBAL_LIST_EMPTY_TYPED(xeno_mob_list, /mob/living/carbon/xenomorph)
GLOBAL_LIST_EMPTY_TYPED(living_xeno_list, /mob/living/carbon/xenomorph)
GLOBAL_LIST_EMPTY_TYPED(xeno_cultists, /mob/living/carbon/human)
+GLOBAL_LIST_EMPTY_TYPED(player_embryo_list, /obj/item/alien_embryo)
GLOBAL_LIST_EMPTY_TYPED(hellhound_list, /mob/living/carbon/xenomorph/hellhound)
GLOBAL_LIST_EMPTY_TYPED(zombie_list, /mob/living/carbon/human)
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index ad2f305790d2..affbc28cdd45 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -71,7 +71,9 @@
return
// Click handled elsewhere. (These clicks are not affected by the next_move cooldown)
- if (click(A, mods) || A.clicked(src, mods, location, params))
+ if(click(A, mods))
+ return
+ if(A.clicked(src, mods, location, params))
return
// Default click functions from here on.
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 21ac66e5f222..5acfe74f2965 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -45,11 +45,11 @@
return FALSE
var/deathtime = world.time - timeofdeath
- if(deathtime < 2.5 MINUTES)
+ if(deathtime < XENO_JOIN_DEAD_LARVA_TIME)
var/message = "You have been dead for [DisplayTimeText(deathtime)]."
message = SPAN_WARNING("[message]")
to_chat(src, message)
- to_chat(src, SPAN_WARNING("You must wait 2.5 minutes before rejoining the game!"))
+ to_chat(src, SPAN_WARNING("You must wait atleast 2.5 minutes before rejoining the game!"))
ManualFollow(target)
return FALSE
diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm
index a8ed20f5c4b3..9c9784286d09 100644
--- a/code/_onclick/other_mobs.dm
+++ b/code/_onclick/other_mobs.dm
@@ -34,4 +34,4 @@
Have no reason to click on anything at all.
*/
/mob/new_player/click()
- return 1
+ return
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 58910c45af75..0e23b99a9cc2 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -424,7 +424,7 @@ SUBSYSTEM_DEF(ticker)
for(var/mob/living/carbon/human/player in GLOB.human_mob_list)
if(player.mind)
- if(player.job == "Commanding Officers")
+ if(player.job == JOB_CO)
captainless = FALSE
if(player.job)
RoleAuthority.equip_role(player, RoleAuthority.roles_by_name[player.job], late_join = FALSE)
diff --git a/code/datums/effects/neurotoxin.dm b/code/datums/effects/neurotoxin.dm
index 0405c87bec8b..836fccf49ca3 100644
--- a/code/datums/effects/neurotoxin.dm
+++ b/code/datums/effects/neurotoxin.dm
@@ -21,9 +21,8 @@
/// Stamina damage per tick. Major balance number.
var/stam_dam = 7
-/datum/effects/neurotoxin/New(atom/thing)
- ..(thing)
- cause_data = create_cause_data("neurotoxic gas")
+/datum/effects/neurotoxin/New(atom/thing, mob/from = null)
+ ..(thing, from, effect_name)
/datum/effects/neurotoxin/validate_atom(atom/thing)
if(isxeno(thing) || isobj(thing))
@@ -36,9 +35,10 @@
var/mob/living/carbon/affected_mob = affected_atom
if(!.)
return FALSE
- if(affected_mob.stat)
+ if(affected_mob.stat == DEAD)
return
// General effects
+ affected_mob.last_damage_data = cause_data
affected_mob.apply_stamina_damage(stam_dam)
affected_mob.make_dizzy(12)
diff --git a/code/datums/fluff_emails.dm b/code/datums/fluff_emails.dm
index 6dd8cd590860..f7083541dd5a 100644
--- a/code/datums/fluff_emails.dm
+++ b/code/datums/fluff_emails.dm
@@ -93,9 +93,9 @@
/datum/fluff_email/almayer/themajor
title = "The Major?"
entry_text = {"
- I keep forgetting what the new Major's name is. I got quizzed by one of the jackass staff officers last week about the captain's name,
- and I absolutely spilled my marbles. PCF Mable was watching too, and she probably thinks I've got rocks in my head. I know it's been weeks
- since the new captain took over, but for some reason the name keeps escaping me when it matters. Either the cryo-sleepers are juicing my
+ I keep forgetting what the new Major's name is. I got quizzed by one of the jackass staff officers last week about the Major's name,
+ and I absolutely spilled my marbles. PFC Mable was watching too, and she probably thinks I've got rocks in my head. I know it's been weeks
+ since the new Major took over, but for some reason the name keeps escaping me when it matters. Either the cryo-sleepers are juicing my
memory capacity or the CO keeps changing their name and not telling anybody. Maybe next jump I'll scrawl it on a sticky note and plaster it
to the inside of my sleeper pod. I can't be the only one having this problem.
@@ -105,7 +105,8 @@
/datum/fluff_email/almayer/tunes
title = "RE: Tunes"
entry_text = {"
- Cryosleep is killing me, man. Inside and outside. I mean really, they expect us to sit in that tube for god only knows how long, and when we wake up? It's all 'grab a crappy protein bar and grab your gear, you're going to war, Marine!' Bullshit.
+ Cryosleep is killing me, man. Inside and outside. I mean really, they expect us to sit in that tube for god only knows how long, and when we wake up?
+ It's all 'grab a crappy protein bar and grab your gear, you're going to war, Marine!' Bullshit.
Anywho, I've been thinking how to make the whole thing more bearable. Tried to take a plush from the bunks with me inside. That dickwad MP took it away from me though, said it was against Operating Procedure. Like I care. Can't do anything fun around here, right?
@@ -113,82 +114,81 @@
I don't usually use these things, and frankly that vendor near Medbay has waaay too many cassettes to choose from. Not that I know most songs on them anywho.
- I saw you with a Walkman from time to time, so... any chances you could recommend a tape to me? Or two, I'm not gonna be picky. Just anything to start out with, I just want some nice sounds. Please, I'm gonna go mad if I don't do something about my cryophobia or whatever. This might just help with that.
+ I saw you with a Walkman from time to time, so... any chances you could recommend a tape to me? Or two, I'm not gonna be picky.
+ Just anything to start out with, I just want some nice sounds. Please, I'm gonna go mad if I don't do something about my cryophobia or whatever.
+ This might just help with that.
"}
-/datum/fluff_email/almayer/lasergun
- title = "RE: Lasergun"
+/datum/fluff_email/almayer/lasergun1
+ title = "Prototype Weapon"
entry_text = {"
- Hey REDACTED. Thanks for letting me test out the laser gun. That thing is a factual blast to use. It literally set the targets down range on fire! Those cooling coils work wonders. Used it a good few times and the barrel didn't explode!
+ This thing is an absolute blast to use.
+ It disintegrated some of the targets down range but you're going to need to work on those cooling coils.
+ I used it a few times and I'm seeing the front barrel glow red.
- Hell, it's even pretty accurate too. I know there's like, a couple of prototypes issued to some USCM detachments but we got to have this shit in production one day. It's just good. Now, I don't think it's gonna replace the old Mark two's but it would be a nice addition for some of our grunts that prefer the high tech approach. You know the ones, all nerdy and gadget loving geeks in the corps. Hell I can already hear them glossing over this thing in their sleep.
+ Surprisingly accurate too despite being a prototype.
+ I know there's like, a couple of prototypes issued to some USCM detachments, but we got to have this shit in production one day.
- Anyway, I've already attached the weapon report you wanted on this thing back to the email. Hopefully you guys in R&D will get some useful info out of it.
+ Even as a prototype, it's leagues better than some of the junk we're issued.
+ Now, I don't think it's going to replace the old Mark Twos, but it would be a nice addition for some of our grunts that prefer the high-tech approach.
- Alright see you when I see you
- REDACTED
-
- RE:RE: The Plasma Gun (It's called the XM99 Phased Plasma Pulse Rifle)
- Hey REDACTED, REDACTED here. Thanks for the report but I'm going to need you to send the Phased Plasma Pulse Rifle back to me. Apparently we're not allowed to ship them out for testing... I guess I must've missed that memo. The memo came three days after I shipped it out to you. Sorry for the inconvenience. You know where to send it back to and how to. I did tell you how right? There was a small pamphlet in the casing if you forgot.
-
-
- Don't think this is going to be issued en masse for a while, it's still going under trials and when I got the weapon report you sent me, they sent in a new updated design for the gun which invalidated most of the things in the report, shame. Looks more promising than the last one though.
-
-
- Okay, I'll hopefully be seeing the XM99 Phased Plasma Pulse Rifle in the lab soon.
-
-
- REDACTED RE:RE:RE: The Plasma Gun (It's called the XM99 Phased Plasma Pulse Rifle)
-
- Holy shit, what the fuck did you do to the damned thing? When I opened the case, I could see fractures and scratches everywhere! Did you give this to the entire platoon to try out? And from the data I'm reading, you fired over 178 shots with this. I only gave you two batteries for the thing.
-
-
- How the hell did you recharge it?! The prototype can't take any other forms of power other than those two batteries. And even then, you can't recharge those specially made batteries either without the equipment back in the lab here. And the inside of the barrel is all messed up man. The cooling coils expired and there're bits of the barrel loose inside of it. How the hell did you not notice bits of the inside of the barrel spewing out from the muzzle man?!
-
-
- Right. They've threatened to drop me from the project if something like this happens again. In the rare case that I send another prototype out, it had better come back in one piece. And I mean in pristine condition, you got that?
-
-
Regards,
-
REDACTED
+ You know the ones, all nerdy and gadget loving geeks in the corps. Hell, I can already hear them glossing over this thing in their sleep.
+ My report has been sent back to you and I'm really excited to see how this turns out.
+
+ "}
+
+
+/datum/fluff_email/almayer/lasergun2
+ title = "New Prototype Design"
+ entry_text = {"
+ Thanks for sending the report in, we've been mulling over the data you sent over.
+ We've updated the design for the prototype which solves most of the problems everyone has encountered.
+ This one looks more promising than the last one.
+ And as much as everyone wants this done and shippped, I don't think this is going to be issued en masse for a good while.
"}
/datum/fluff_email/almayer/beatup
- title = "RE: Beat Up"
+ title = "Beat Up"
entry_text = {"
- Yo.
-
-
- Man, last mission was an absolute shit show. The USS Heyst got their shit kicked in with a missile and we got our cargo hold set on fire by that damn suicide craft. They even blew up most of our good ammo too! Now we're left with the soft point backup munitions. Shit, most of 1st platoon is pretty much out of action. Lotta folks are in sickbay and the rest of us are heading off to cryosleep, well what's left of us.
-
-
- When the comms got cut and we were cut off from command; Squad Foxtrot was immediately ambushed on the logistics route to get supplies in and out of the combat zone. I suspect they were taping into your comms to find the literal perfect moment to fuck with our logistics. Thankfully those trucks of ours had their engines tricked out by the techies back on LV-176 in the civilian garage. Those guys hosted rally races around their colony and Sergeant DATA EXPUNGED won a few races for us. Instead of taking their trophy, he pulled a few favors to get our trucks pimped out with better engines. We owe our lives to Sarge for winning one for the corps.
-
-
- Hell, at least we're all going back to Chinook Station to get resupplied. Hopefully the wounded wake up to the docs on station rather than our poor and cramped excuse for a medical bay. The number of times the medbay has been packed with wounded where even the damn front lobby had bodies lining up on the sides of the walls waiting for treatment; it still amazes. Worse still was the stench from all the blood and guts, it made it hell for the maint. techs to clean up afterwards.
-
- I'm still surprised those doctors we had on hand took care of most of them so quickly, even if most of them are still injured heading to the fridge.
-
-
- I read the After-Action Report which the Heyst's XO did, and they're leaving out a few details. When it came to that city, they left out how we had to DATA EXPUNGED. The entire building collapsed with them in it too. Damn shame we couldn't save them.
-
-
- The only damn silver lining i see in this shit is that the AI is going to cycle cryo again and we ain't waking to deal with whatever bullshit is happening next time. 2nd Platoon is dealing with that, cause 1st platoon is undermanned as is with our casualties. I heard they have a few screws loose, not that ours are entirely in either! But I don't care, it's their problem now y'know?
-
-
- Worst case scenario, we don't wake up at all.
-
- Right, see you back on station friend.
-
-
- Regards,
-
- REDACTED
+ Man last mission was an absolute shit show.
+
+ The USS Heyst got their shit kicked in with a missile and we got our cargo hold set on fire. And most of our good ammo is gone too!
+ Now we're left with the FMJs and the older AP munitions. What's worse is that most of 1st platoon is pretty much out of action.
+ Lotta folks are in the sickbay and the rest of us are heading off to cryosleep, well what's left of us. There's not many of the old guard left I'm afraid.
+ Until we get reinforced with more bodies, command has given the go ahead to merge 2nd platoon into 1st for the time being.
+
+ "}
+
+
+/datum/fluff_email/almayer/rallyrace
+ title = "Rally Racing"
+ entry_text = {"
+ Hey, remember last shore leave on LV-179? Man, that was one crazy night. The folks at the colony had setup a rally race with their tractors all stripped of non-essentials.
+ LCPL Millard got pretty friendly with the locals and got himself into the competition.
+ We all put in a little wager to see if he'd even get close to first place or even survive to the finish line.
+ Now most of the boys bet a fair amount against him since he was pretty new to our outfit, yet I've been out on detail with the guy.
+
+
+ Millard grew up on one of those shake and bake colonies and used to drive the big daisies around.
+ He knew the ins and outs of what made them tick. The few of us who had faith in him reaped everyone else's
+ paycheck for the week with Millard finishing first place by a near country mile.
"}
+
+/datum/fluff_email/almayer/missing
+ title = "Missing Personnel"
+ entry_text = {"
+ Has anyone seen Mendoza around? He owes me half of his paycheck from last month's poker game.
+ Everyone's payday was a week ago and we're all set to head back to Chinook station.
+ Could have sworn I saw him near the cargo elevator yesterday.
+ I'll catch him back at base once we've docked because I need that money to pay off my tab at the bar.
+
+ "}
+
diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm
index 8237fc63b7e2..2f6dc6e38118 100644
--- a/code/game/gamemodes/cm_initialize.dm
+++ b/code/game/gamemodes/cm_initialize.dm
@@ -354,7 +354,7 @@ Additional game mode variables.
var/datum/hive_status/hive
for(var/hivenumber in GLOB.hive_datum)
hive = GLOB.hive_datum[hivenumber]
- if(!hive.hardcore && hive.stored_larva && (hive.hive_location || (world.time < 30 MINUTES + SSticker.round_start_time)))
+ if(!hive.hardcore && hive.stored_larva && (hive.hive_location || (world.time < XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time)))
if(SSticker.mode && (SSticker.mode.flags_round_type & MODE_RANDOM_HIVE))
available_xenos |= "any buried larva"
LAZYADD(available_xenos["any buried larva"], hive)
@@ -364,7 +364,27 @@ Additional game mode variables.
available_xenos[larva_option] = list(hive)
if(!available_xenos.len || (instant_join && !available_xenos_non_ssd.len))
- to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae. You can try getting spawned as a chestburster larva by toggling your Xenomorph candidacy in Preferences -> Toggle SpecialRole Candidacy."))
+ if(!xeno_candidate.client || !xeno_candidate.client.prefs || !(xeno_candidate.client.prefs.be_special & BE_ALIEN_AFTER_DEATH))
+ to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae. You can try getting spawned as a chestburster larva by toggling your Xenomorph candidacy in Preferences -> Toggle SpecialRole Candidacy."))
+ return FALSE
+ to_chat(xeno_candidate, SPAN_WARNING("There aren't any available xenomorphs or burrowed larvae."))
+
+ // Give the player a cached message of their queue status if they are an observer
+ var/mob/dead/observer/candidate_observer = xeno_candidate
+ if(istype(candidate_observer))
+ if(candidate_observer.larva_queue_cached_message)
+ to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message)
+ return FALSE
+
+ // No cache, lets check now then
+ message_alien_candidates(get_alien_candidates(), dequeued = 0, cache_only = TRUE)
+ if(candidate_observer.larva_queue_cached_message)
+ to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message)
+ return FALSE
+
+ // We aren't in queue yet, lets teach them about the queue then
+ candidate_observer.larva_queue_cached_message = SPAN_XENONOTICE("You are currently still awaiting assignment in the larva queue. Priority is given to players who have yet to play in the round, but otherwise the ordering is based on your time of death. When you have been dead long enough and are not inactive, you will periodically receive messages where you are in the queue relative to other currently valid xeno candidates. Note: Playing as a facehugger or in the thunderdome will not alter your time of death. This means you won't lose your relative place in queue if you step away, disconnect, play as a facehugger, or play in the thunderdome.")
+ to_chat(xeno_candidate, candidate_observer.larva_queue_cached_message)
return FALSE
var/mob/living/carbon/xenomorph/new_xeno
@@ -377,11 +397,11 @@ Additional game mode variables.
if(!xeno_bypass_timer)
var/deathtime = world.time - xeno_candidate.timeofdeath
if(isnewplayer(xeno_candidate))
- deathtime = 2.5 MINUTES //so new players don't have to wait to latejoin as xeno in the round's first 5 mins.
- if(deathtime < 2.5 MINUTES && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE))
+ deathtime = XENO_JOIN_DEAD_LARVA_TIME //so new players don't have to wait to latejoin as xeno in the round's first 5 mins.
+ if(deathtime < XENO_JOIN_DEAD_LARVA_TIME && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE))
var/message = SPAN_WARNING("You have been dead for [DisplayTimeText(deathtime)].")
to_chat(xeno_candidate, message)
- to_chat(xeno_candidate, SPAN_WARNING("You must wait 2.5 minutes before rejoining the game as a buried larva!"))
+ to_chat(xeno_candidate, SPAN_WARNING("You must wait 2 minutes and 30 seconds before rejoining the game as a buried larva!"))
return FALSE
for(var/mob_name in picked_hive.banished_ckeys)
@@ -393,7 +413,7 @@ Additional game mode variables.
noob.close_spawn_windows()
if(picked_hive.hive_location)
picked_hive.hive_location.spawn_burrowed_larva(xeno_candidate)
- else if((world.time < 30 MINUTES + SSticker.round_start_time))
+ else if((world.time < XENO_BURIED_LARVA_TIME_LIMIT + SSticker.round_start_time))
picked_hive.do_buried_larva_spawn(xeno_candidate)
else
to_chat(xeno_candidate, SPAN_WARNING("Seems like something went wrong. Try again?"))
@@ -417,8 +437,8 @@ Additional game mode variables.
if(!xeno_bypass_timer)
var/deathtime = world.time - xeno_candidate.timeofdeath
if(istype(xeno_candidate, /mob/new_player))
- deathtime = 5 MINUTES //so new players don't have to wait to latejoin as xeno in the round's first 5 mins.
- if(deathtime < 5 MINUTES && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE))
+ deathtime = XENO_JOIN_DEAD_TIME //so new players don't have to wait to latejoin as xeno in the round's first 5 mins.
+ if(deathtime < XENO_JOIN_DEAD_TIME && !check_client_rights(xeno_candidate.client, R_ADMIN, FALSE))
var/message = "You have been dead for [DisplayTimeText(deathtime)]."
message = SPAN_WARNING("[message]")
to_chat(xeno_candidate, message)
diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm
index ce5e9a743bc5..a25293aebbd3 100644
--- a/code/game/machinery/telecomms/presets.dm
+++ b/code/game/machinery/telecomms/presets.dm
@@ -60,7 +60,7 @@
return TRUE
return FALSE
-/obj/structure/machinery/telecomms/relay/preset/tower/tcomms_startup()
+/obj/structure/machinery/telecomms/relay/preset/tower/update_state()
. = ..()
if(on)
playsound(src, 'sound/machines/tcomms_on.ogg', vol = 80, vary = FALSE, sound_range = 16, falloff = 0.5)
diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
index bd403c65c31b..1d8e5e289066 100644
--- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm
+++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm
@@ -244,6 +244,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list(
list("Labcoat", 12, /obj/item/clothing/suit/storage/labcoat, null, VENDOR_ITEM_REGULAR),
list("Labcoat, Researcher", 12, /obj/item/clothing/suit/storage/labcoat/researcher, null, VENDOR_ITEM_REGULAR),
list("RO Jacket", 12, /obj/item/clothing/suit/storage/RO, null, VENDOR_ITEM_REGULAR),
+ list("USCM Poncho", 12, /obj/item/clothing/accessory/poncho, null, VENDOR_ITEM_REGULAR),
list("BACKPACK", 0, null, null, null),
list("Backpack, Industrial", 12, /obj/item/storage/backpack/industrial, null, VENDOR_ITEM_REGULAR),
diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm
index 250a998f38bf..838b21a00e6f 100644
--- a/code/game/machinery/vending/vendor_types/requisitions.dm
+++ b/code/game/machinery/vending/vendor_types/requisitions.dm
@@ -426,6 +426,7 @@
list("ARMOR", -1, null, null),
list("M10 Pattern Marine Helmet", 20, /obj/item/clothing/head/helmet/marine, VENDOR_ITEM_REGULAR),
list("M10 Pattern Technician Helmet", 20, /obj/item/clothing/head/helmet/marine/tech, VENDOR_ITEM_REGULAR),
+ list("M10 Pattern Corpman Helmet", 20, /obj/item/clothing/head/helmet/marine/medic, VENDOR_ITEM_REGULAR),
list("M3 Pattern Carrier Marine Armor", 20, /obj/item/clothing/suit/storage/marine/carrier, VENDOR_ITEM_REGULAR),
list("M3 Pattern Padded Marine Armor", 20, /obj/item/clothing/suit/storage/marine/padded, VENDOR_ITEM_REGULAR),
list("M3 Pattern Padless Marine Armor", 20, /obj/item/clothing/suit/storage/marine/padless, VENDOR_ITEM_REGULAR),
diff --git a/code/game/objects/effects/effect_system/chemsmoke.dm b/code/game/objects/effects/effect_system/chemsmoke.dm
index 8ecdb2c07db9..c2323c32c934 100644
--- a/code/game/objects/effects/effect_system/chemsmoke.dm
+++ b/code/game/objects/effects/effect_system/chemsmoke.dm
@@ -40,7 +40,8 @@
// Culls the selected turfs to a (roughly) circle shape, then calls smokeFlow() to make
// sure the smoke can actually path to the turfs. This culls any turfs it can't reach.
//------------------------------------------
-/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, n = 10, c = 0, loca, direct)
+/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, n = 10, c = 0, loca, direct, datum/cause_data/new_cause_data)
+ cause_data = istype(new_cause_data) ? new_cause_data : cause_data
range = n * 0.3
cardinals = c
carry.copy_to(chemholder, carry.total_volume)
diff --git a/code/game/objects/effects/effect_system/smoke.dm b/code/game/objects/effects/effect_system/smoke.dm
index a02069087412..9f7a9c8143c7 100644
--- a/code/game/objects/effects/effect_system/smoke.dm
+++ b/code/game/objects/effects/effect_system/smoke.dm
@@ -283,14 +283,14 @@
var/gas_damage = 20
/obj/effect/particle_effect/smoke/xeno_burn/Initialize(mapload, amount, datum/cause_data/cause_data)
- var/mob/living/carbon/xenomorph/xeno = cause_data?.resolve_mob()
- if (istype(xeno) && xeno.hivenumber)
- hivenumber = xeno.hivenumber
-
- set_hive_data(src, hivenumber)
-
- . = ..()
+ if(istype(cause_data))
+ var/datum/ui_state/hive_state/cause_data_hive_state = GLOB.hive_state[cause_data.faction]
+ var/new_hive_number = cause_data_hive_state?.hivenumber
+ if(new_hive_number)
+ hivenumber = new_hive_number
+ set_hive_data(src, new_hive_number)
+ return ..()
/obj/effect/particle_effect/smoke/xeno_burn/apply_smoke_effect(turf/T)
..()
@@ -387,7 +387,7 @@
if(!issynth(moob))
var/datum/effects/neurotoxin/neuro_effect = locate() in moob.effects_list
if(!neuro_effect)
- neuro_effect = new /datum/effects/neurotoxin(moob)
+ neuro_effect = new(moob, cause_data.resolve_mob())
neuro_effect.strength = effect_amt
neuro_effect.duration += neuro_dose
if(moob.coughedtime != 1 && !moob.stat) //Coughing/gasping
diff --git a/code/game/objects/structures/barricade/barricade.dm b/code/game/objects/structures/barricade/barricade.dm
index 6905a734b915..eac5f154e26e 100644
--- a/code/game/objects/structures/barricade/barricade.dm
+++ b/code/game/objects/structures/barricade/barricade.dm
@@ -30,6 +30,8 @@
var/brute_multiplier = 1
var/burn_multiplier = 1
var/explosive_multiplier = 1
+ var/brute_projectile_multiplier = 1
+ var/burn_flame_multiplier = 1
var/repair_materials = list()
var/metallic = TRUE
@@ -42,12 +44,12 @@
addtimer(CALLBACK(src, PROC_REF(update_icon)), 0)
starting_maxhealth = maxhealth
-/obj/structure/barricade/initialize_pass_flags(datum/pass_flags_container/PF)
+/obj/structure/barricade/initialize_pass_flags(datum/pass_flags_container/pass_flags)
..()
- if (PF)
- PF.flags_can_pass_all = NONE
- PF.flags_can_pass_front = NONE
- PF.flags_can_pass_behind = PASS_OVER^(PASS_OVER_ACID_SPRAY|PASS_OVER_THROW_MOB)
+ if (pass_flags)
+ pass_flags.flags_can_pass_all = NONE
+ pass_flags.flags_can_pass_front = NONE
+ pass_flags.flags_can_pass_behind = PASS_OVER^(PASS_OVER_ACID_SPRAY|PASS_OVER_THROW_MOB)
flags_can_pass_front_temp = PASS_OVER_THROW_MOB
flags_can_pass_behind_temp = PASS_OVER_THROW_MOB
@@ -95,7 +97,7 @@
overlays += image('icons/obj/structures/barricades.dmi', icon_state = "+burn_upgrade_[damage_state]")
if(BARRICADE_UPGRADE_BRUTE)
overlays += image('icons/obj/structures/barricades.dmi', icon_state = "+brute_upgrade_[damage_state]")
- if(BARRICADE_UPGRADE_EXPLOSIVE)
+ if(BARRICADE_UPGRADE_ANTIFF)
overlays += image('icons/obj/structures/barricades.dmi', icon_state = "+explosive_upgrade_[damage_state]")
if(is_wired)
@@ -106,34 +108,34 @@
..()
-/obj/structure/barricade/hitby(atom/movable/AM)
- if(AM.throwing && is_wired)
- if(iscarbon(AM))
- var/mob/living/carbon/C = AM
- if(C.mob_size <= MOB_SIZE_XENO)
- C.visible_message(SPAN_DANGER("The barbed wire slices into [C]!"),
+/obj/structure/barricade/hitby(atom/movable/atom_movable)
+ if(atom_movable.throwing && is_wired)
+ if(iscarbon(atom_movable))
+ var/mob/living/carbon/living_carbon = atom_movable
+ if(living_carbon.mob_size <= MOB_SIZE_XENO)
+ living_carbon.visible_message(SPAN_DANGER("The barbed wire slices into [living_carbon]!"),
SPAN_DANGER("The barbed wire slices into you!"))
- C.apply_damage(10)
- C.apply_effect(2, WEAKEN) //Leaping into barbed wire is VERY bad
- playsound(C, "bonk", 75, FALSE)
+ living_carbon.apply_damage(10)
+ living_carbon.apply_effect(2, WEAKEN) //Leaping into barbed wire is VERY bad
+ playsound(living_carbon, "bonk", 75, FALSE)
..()
-/obj/structure/barricade/Collided(atom/movable/AM)
+/obj/structure/barricade/Collided(atom/movable/atom_movable)
..()
- if(istype(AM, /mob/living/carbon/xenomorph/crusher))
- var/mob/living/carbon/xenomorph/crusher/C = AM
+ if(istype(atom_movable, /mob/living/carbon/xenomorph/crusher))
+ var/mob/living/carbon/xenomorph/crusher/living_carbon = atom_movable
- if (!C.throwing)
+ if (!living_carbon.throwing)
return
if(crusher_resistant)
- visible_message(SPAN_DANGER("[C] smashes into [src]!"))
+ visible_message(SPAN_DANGER("[living_carbon] smashes into [src]!"))
take_damage(150)
playsound(src, barricade_hitsound, 25, TRUE)
- else if(!C.stat)
- visible_message(SPAN_DANGER("[C] smashes through [src]!"))
+ else if(!living_carbon.stat)
+ visible_message(SPAN_DANGER("[living_carbon] smashes through [src]!"))
deconstruct(FALSE)
playsound(src, barricade_hitsound, 25, TRUE)
@@ -163,8 +165,8 @@
if(closed)
return NO_BLOCKED_MOVEMENT
- var/obj/structure/S = locate(/obj/structure) in get_turf(mover)
- if(S && S.climbable && !(S.flags_atom & ON_BORDER) && climbable && isliving(mover)) //Climbable objects allow you to universally climb over others
+ var/obj/structure/structure = locate(/obj/structure) in get_turf(mover)
+ if(structure && structure.climbable && !(structure.flags_atom & ON_BORDER) && climbable && isliving(mover)) //Climbable objects allow you to universally climb over others
return NO_BLOCKED_MOVEMENT
return ..()
@@ -180,33 +182,33 @@
/obj/structure/barricade/attack_animal(mob/user as mob)
return attack_alien(user)
-/obj/structure/barricade/attackby(obj/item/W, mob/user)
- if(istype(W, /obj/item/weapon/zombie_claws))
+/obj/structure/barricade/attackby(obj/item/item, mob/user)
+ if(istype(item, /obj/item/weapon/zombie_claws))
user.visible_message(SPAN_DANGER("The zombie smashed at the [src.barricade_type] barricade!"),
SPAN_DANGER("You smack the [src.barricade_type] barricade!"))
if(barricade_hitsound)
playsound(src, barricade_hitsound, 35, 1)
- hit_barricade(W)
+ hit_barricade(item)
return
- for(var/obj/effect/xenomorph/acid/A in src.loc)
- if(A.acid_t == src)
+ for(var/obj/effect/xenomorph/acid/acid in src.loc)
+ if(acid.acid_t == src)
to_chat(user, "You can't get near that, it's melting!")
return
- if(istype(W, /obj/item/stack/barbed_wire))
- var/obj/item/stack/barbed_wire/B = W
+ if(istype(item, /obj/item/stack/barbed_wire))
+ var/obj/item/stack/barbed_wire/barbed_wire = item
if(can_wire)
- user.visible_message(SPAN_NOTICE("[user] starts setting up [W.name] on [src]."),
- SPAN_NOTICE("You start setting up [W.name] on [src]."))
+ user.visible_message(SPAN_NOTICE("[user] starts setting up [item.name] on [src]."),
+ SPAN_NOTICE("You start setting up [item.name] on [src]."))
if(do_after(user, 20, INTERRUPT_NO_NEEDHAND|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD, src) && can_wire)
// Make sure there's still enough wire in the stack
- if(!B.use(1))
+ if(!barbed_wire.use(1))
return
playsound(src.loc, 'sound/effects/barbed_wire_movement.ogg', 25, 1)
- user.visible_message(SPAN_NOTICE("[user] sets up [W.name] on [src]."),
- SPAN_NOTICE("You set up [W.name] on [src]."))
+ user.visible_message(SPAN_NOTICE("[user] sets up [item.name] on [src]."),
+ SPAN_NOTICE("You set up [item.name] on [src]."))
maxhealth += 50
update_health(-50)
@@ -218,7 +220,7 @@
update_icon()
return
- if(HAS_TRAIT(W, TRAIT_TOOL_WIRECUTTERS))
+ if(HAS_TRAIT(item, TRAIT_TOOL_WIRECUTTERS))
if(is_wired)
user.visible_message(SPAN_NOTICE("[user] begin removing the barbed wire on [src]."),
SPAN_NOTICE("You begin removing the barbed wire on [src]."))
@@ -240,27 +242,27 @@
new/obj/item/stack/barbed_wire( src.loc )
return
- if(W.force > force_level_absorption)
+ if(item.force > force_level_absorption)
..()
if(barricade_hitsound)
playsound(src, barricade_hitsound, 35, 1)
- hit_barricade(W)
+ hit_barricade(item)
-/obj/structure/barricade/bullet_act(obj/item/projectile/P)
- bullet_ping(P)
+/obj/structure/barricade/bullet_act(obj/item/projectile/bullet)
+ bullet_ping(bullet)
- if(P.ammo.damage_type == BURN)
- P.damage = P.damage * burn_multiplier
+ if(bullet.ammo.damage_type == BURN)
+ bullet.damage = bullet.damage * burn_multiplier
else
- P.damage = P.damage * brute_multiplier
+ bullet.damage = bullet.damage * brute_projectile_multiplier
- if(istype(P.ammo, /datum/ammo/xeno/boiler_gas))
+ if(istype(bullet.ammo, /datum/ammo/xeno/boiler_gas))
take_damage(round(50 * burn_multiplier))
- else if(P.ammo.flags_ammo_behavior & AMMO_ANTISTRUCT)
- take_damage(P.damage * ANTISTRUCT_DMG_MULT_BARRICADES)
+ else if(bullet.ammo.flags_ammo_behavior & AMMO_ANTISTRUCT)
+ take_damage(bullet.damage * ANTISTRUCT_DMG_MULT_BARRICADES)
- take_damage(P.damage)
+ take_damage(bullet.damage)
return TRUE
@@ -282,11 +284,11 @@
/obj/structure/barricade/ex_act(severity, direction, cause_data)
- for(var/obj/structure/barricade/B in get_step(src,dir)) //discourage double-stacking barricades by removing health from opposing barricade
- if(B.dir == reverse_direction(dir))
+ for(var/obj/structure/barricade/barricade in get_step(src,dir)) //discourage double-stacking barricades by removing health from opposing barricade
+ if(barricade.dir == reverse_direction(dir))
spawn(1)
- if(B)
- B.ex_act(severity, direction)
+ if(barricade)
+ barricade.ex_act(severity, direction)
if(health <= 0)
var/location = get_turf(src)
handle_debris(severity, direction)
@@ -321,15 +323,15 @@
new /datum/effects/acid(src, null, null)
/obj/structure/barricade/flamer_fire_act(dam = BURN_LEVEL_TIER_1)
- take_damage(dam * burn_multiplier)
+ take_damage(dam * burn_flame_multiplier)
-/obj/structure/barricade/proc/hit_barricade(obj/item/I)
- take_damage(I.force * 0.5 * brute_multiplier)
+/obj/structure/barricade/proc/hit_barricade(obj/item/item)
+ take_damage(item.force * 0.5 * brute_multiplier)
/obj/structure/barricade/proc/take_damage(damage)
- for(var/obj/structure/barricade/B in get_step(src,dir)) //discourage double-stacking barricades by removing health from opposing barricade
- if(B.dir == reverse_direction(dir))
- B.update_health(damage)
+ for(var/obj/structure/barricade/barricade in get_step(src,dir)) //discourage double-stacking barricades by removing health from opposing barricade
+ if(barricade.dir == reverse_direction(dir))
+ barricade.update_health(damage)
update_health(damage)
@@ -357,12 +359,12 @@
if(50 to 75) damage_state = BARRICADE_DMG_SLIGHT
if(75 to INFINITY) damage_state = BARRICADE_DMG_NONE
-/obj/structure/barricade/proc/weld_cade(obj/item/tool/weldingtool/WT, mob/user)
+/obj/structure/barricade/proc/weld_cade(obj/item/tool/weldingtool/welder, mob/user)
if(!metallic)
user.visible_message(SPAN_WARNING("You can't weld \the [src]!"))
return FALSE
- if(!(WT.remove_fuel(2, user)))
+ if(!(welder.remove_fuel(2, user)))
return FALSE
user.visible_message(SPAN_NOTICE("[user] begins repairing damage to [src]."),
@@ -413,20 +415,20 @@
return ..()
-/obj/structure/barricade/proc/try_nailgun_usage(obj/item/W, mob/user)
- if(length(repair_materials) == 0 || health >= maxhealth || !istype(W, /obj/item/weapon/gun/smg/nailgun))
+/obj/structure/barricade/proc/try_nailgun_usage(obj/item/item, mob/user)
+ if(length(repair_materials) == 0 || health >= maxhealth || !istype(item, /obj/item/weapon/gun/smg/nailgun))
return FALSE
- var/obj/item/weapon/gun/smg/nailgun/NG = W
+ var/obj/item/weapon/gun/smg/nailgun/nailgun = item
- if(!NG.in_chamber || !NG.current_mag || NG.current_mag.current_rounds < 3)
+ if(!nailgun.in_chamber || !nailgun.current_mag || nailgun.current_mag.current_rounds < 3)
to_chat(user, SPAN_WARNING("You require at least 4 nails to complete this task!"))
return FALSE
// Check if either hand has a metal stack by checking the weapon offhand
// Presume the material is a sheet until proven otherwise.
var/obj/item/stack/sheet/material = null
- if(user.l_hand == NG)
+ if(user.l_hand == nailgun)
material = user.r_hand
else
material = user.l_hand
@@ -445,8 +447,8 @@
to_chat(user, SPAN_WARNING("You'll need some adequate repair material in your other hand to patch up [src]!"))
return FALSE
- var/soundchannel = playsound(src, NG.repair_sound, 25, 1)
- if(!do_after(user, NG.nailing_speed, INTERRUPT_ALL, BUSY_ICON_FRIENDLY, src))
+ var/soundchannel = playsound(src, nailgun.repair_sound, 25, 1)
+ if(!do_after(user, nailgun.nailing_speed, INTERRUPT_ALL, BUSY_ICON_FRIENDLY, src))
playsound(src, null, channel = soundchannel)
return FALSE
@@ -454,7 +456,7 @@
to_chat(user, SPAN_WARNING("You seems to have misplaced the repair material!"))
return FALSE
- if(!NG.in_chamber || !NG.current_mag || NG.current_mag.current_rounds < 3)
+ if(!nailgun.in_chamber || !nailgun.current_mag || nailgun.current_mag.current_rounds < 3)
to_chat(user, SPAN_WARNING("You require at least 4 nails to complete this task!"))
return FALSE
@@ -462,7 +464,7 @@
to_chat(user, SPAN_WARNING("You nail [material] to [src], restoring some of its integrity!"))
update_damage_state()
material.use(1)
- NG.current_mag.current_rounds -= 3
- NG.in_chamber = null
- NG.load_into_chamber()
+ nailgun.current_mag.current_rounds -= 3
+ nailgun.in_chamber = null
+ nailgun.load_into_chamber()
return TRUE
diff --git a/code/game/objects/structures/barricade/metal.dm b/code/game/objects/structures/barricade/metal.dm
index 40f784b064e4..4056ac9021f8 100644
--- a/code/game/objects/structures/barricade/metal.dm
+++ b/code/game/objects/structures/barricade/metal.dm
@@ -39,12 +39,12 @@
. += SPAN_NOTICE("The cade is protected by a biohazardous upgrade.")
if(BARRICADE_UPGRADE_BRUTE)
. += SPAN_NOTICE("The cade is protected by a reinforced upgrade.")
- if(BARRICADE_UPGRADE_EXPLOSIVE)
- . += SPAN_NOTICE("The cade is protected by an explosive upgrade.")
+ if(BARRICADE_UPGRADE_ANTIFF)
+ . += SPAN_NOTICE("The cade is protected by a composite upgrade.")
-/obj/structure/barricade/metal/attackby(obj/item/W, mob/user)
- if(iswelder(W))
- if(!HAS_TRAIT(W, TRAIT_TOOL_BLOWTORCH))
+/obj/structure/barricade/metal/attackby(obj/item/item, mob/user)
+ if(iswelder(item))
+ if(!HAS_TRAIT(item, TRAIT_TOOL_BLOWTORCH))
to_chat(user, SPAN_WARNING("You need a stronger blowtorch!"))
return
if(user.action_busy)
@@ -52,7 +52,7 @@
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_TRAINED))
to_chat(user, SPAN_WARNING("You're not trained to repair [src]..."))
return
- var/obj/item/tool/weldingtool/WT = W
+ var/obj/item/tool/weldingtool/welder = item
if(damage_state == BARRICADE_DMG_HEAVY)
to_chat(user, SPAN_WARNING("[src] has sustained too much structural damage to be repaired."))
return
@@ -61,10 +61,10 @@
to_chat(user, SPAN_WARNING("[src] doesn't need repairs."))
return
- weld_cade(WT, user)
+ weld_cade(welder, user)
return
- if(try_nailgun_usage(W, user))
+ if(try_nailgun_usage(item, user))
return
for(var/obj/effect/xenomorph/acid/A in src.loc)
@@ -74,7 +74,7 @@
switch(build_state)
if(BARRICADE_BSTATE_SECURED) //Fully constructed step. Use screwdriver to remove the protection panels to reveal the bolts
- if(HAS_TRAIT(W, TRAIT_TOOL_SCREWDRIVER))
+ if(HAS_TRAIT(item, TRAIT_TOOL_SCREWDRIVER))
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
to_chat(user, SPAN_WARNING("You are not trained to touch [src]..."))
return
@@ -88,16 +88,16 @@
build_state = BARRICADE_BSTATE_UNSECURED
return
- if(istype(W, /obj/item/stack/sheet/metal))
+ if(istype(item, /obj/item/stack/sheet/metal))
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
to_chat(user, SPAN_WARNING("You are not trained to touch [src]..."))
return
if(upgraded)
to_chat(user, SPAN_NOTICE("This barricade is already upgraded."))
return
- var/obj/item/stack/sheet/metal/M = W
+ var/obj/item/stack/sheet/metal/metal = item
if(user.client?.prefs?.no_radials_preference)
- var/choice = tgui_input_list(user, "Choose an upgrade to apply to the barricade", "Apply Upgrade", list(BARRICADE_UPGRADE_BURN, BARRICADE_UPGRADE_BRUTE, BARRICADE_UPGRADE_EXPLOSIVE))
+ var/choice = tgui_input_list(user, "Choose an upgrade to apply to the barricade", "Apply Upgrade", list(BARRICADE_UPGRADE_BURN, BARRICADE_UPGRADE_BRUTE, BARRICADE_UPGRADE_ANTIFF))
if(!choice)
return
if(!user.Adjacent(src))
@@ -106,33 +106,37 @@
if(upgraded)
to_chat(user, SPAN_NOTICE("This barricade is already upgraded."))
return
- if(M.get_amount() < 2)
+ if(metal.get_amount() < 2)
to_chat(user, SPAN_NOTICE("You lack the required metal."))
return
- if((usr.get_active_hand()) != M)
- to_chat(user, SPAN_WARNING("You must be holding the [M] to upgrade \the [src]!"))
+ if((usr.get_active_hand()) != metal)
+ to_chat(user, SPAN_WARNING("You must be holding the [metal] to upgrade \the [src]!"))
return
switch(choice)
if(BARRICADE_UPGRADE_BURN)
burn_multiplier = 0.75
+ burn_flame_multiplier = 0.75
upgraded = BARRICADE_UPGRADE_BURN
to_chat(user, SPAN_NOTICE("You applied a biohazardous upgrade."))
if(BARRICADE_UPGRADE_BRUTE)
brute_multiplier = 0.75
+ brute_projectile_multiplier = 0.75
upgraded = BARRICADE_UPGRADE_BRUTE
to_chat(user, SPAN_NOTICE("You applied a reinforced upgrade."))
- if(BARRICADE_UPGRADE_EXPLOSIVE)
- explosive_multiplier = 0.75
- upgraded = BARRICADE_UPGRADE_EXPLOSIVE
- to_chat(user, SPAN_NOTICE("You applied an explosive upgrade."))
+ if(BARRICADE_UPGRADE_ANTIFF)
+ explosive_multiplier = 0.5
+ brute_projectile_multiplier = 0.5
+ burn_flame_multiplier = 0.5
+ upgraded = BARRICADE_UPGRADE_ANTIFF
+ to_chat(user, SPAN_NOTICE("You applied a composite upgrade."))
- M.use(2)
+ metal.use(2)
user.count_niche_stat(STATISTICS_NICHE_UPGRADE_CADES)
update_icon()
return
else
- var/static/list/cade_types = list(BARRICADE_UPGRADE_EXPLOSIVE = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "explosive_obj"), BARRICADE_UPGRADE_BRUTE = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "brute_obj"), BARRICADE_UPGRADE_BURN = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "burn_obj"))
+ var/static/list/cade_types = list(BARRICADE_UPGRADE_ANTIFF = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "explosive_obj"), BARRICADE_UPGRADE_BRUTE = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "brute_obj"), BARRICADE_UPGRADE_BURN = image(icon = 'icons/obj/structures/barricades.dmi', icon_state = "burn_obj"))
var/choice = show_radial_menu(user, src, cade_types, require_near = TRUE)
if(!choice)
return
@@ -142,33 +146,37 @@
if(upgraded)
to_chat(user, SPAN_NOTICE("This barricade is already upgraded."))
return
- if(M.get_amount() < 2)
+ if(metal.get_amount() < 2)
to_chat(user, SPAN_NOTICE("You lack the required metal."))
return
- if((usr.get_active_hand()) != M)
- to_chat(user, SPAN_WARNING("You must be holding the [M] to upgrade \the [src]!"))
+ if((usr.get_active_hand()) != metal)
+ to_chat(user, SPAN_WARNING("You must be holding the [metal] to upgrade \the [src]!"))
return
switch(choice)
if(BARRICADE_UPGRADE_BURN)
burn_multiplier = 0.75
+ burn_flame_multiplier = 0.75
upgraded = BARRICADE_UPGRADE_BURN
to_chat(user, SPAN_NOTICE("You applied a biohazardous upgrade."))
if(BARRICADE_UPGRADE_BRUTE)
brute_multiplier = 0.75
+ brute_projectile_multiplier = 0.75
upgraded = BARRICADE_UPGRADE_BRUTE
to_chat(user, SPAN_NOTICE("You applied a reinforced upgrade."))
- if(BARRICADE_UPGRADE_EXPLOSIVE)
- explosive_multiplier = 0.75
- upgraded = BARRICADE_UPGRADE_EXPLOSIVE
- to_chat(user, SPAN_NOTICE("You applied an explosive upgrade."))
+ if(BARRICADE_UPGRADE_ANTIFF)
+ explosive_multiplier = 0.5
+ brute_projectile_multiplier = 0.5
+ burn_flame_multiplier = 0.5
+ upgraded = BARRICADE_UPGRADE_ANTIFF
+ to_chat(user, SPAN_NOTICE("You applied a composite upgrade."))
- M.use(2)
+ metal.use(2)
user.count_niche_stat(STATISTICS_NICHE_UPGRADE_CADES)
update_icon()
return
- if(HAS_TRAIT(W, TRAIT_TOOL_MULTITOOL))
+ if(HAS_TRAIT(item, TRAIT_TOOL_MULTITOOL))
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
to_chat(user, SPAN_WARNING("You are not trained to touch [src]..."))
return
@@ -181,13 +189,15 @@
upgraded = null
explosive_multiplier = initial(explosive_multiplier)
brute_multiplier = initial(brute_multiplier)
+ brute_projectile_multiplier = initial(brute_projectile_multiplier)
burn_multiplier = initial(burn_multiplier)
+ burn_flame_multiplier = initial(burn_flame_multiplier)
new stack_type (loc, 1)
update_icon()
return
if(BARRICADE_BSTATE_UNSECURED) //Protection panel removed step. Screwdriver to put the panel back, wrench to unsecure the anchor bolts
- if(HAS_TRAIT(W, TRAIT_TOOL_SCREWDRIVER))
+ if(HAS_TRAIT(item, TRAIT_TOOL_SCREWDRIVER))
if(user.action_busy)
return
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
@@ -199,7 +209,7 @@
SPAN_NOTICE("You set [src]'s protection panel back."))
build_state = BARRICADE_BSTATE_SECURED
return
- if(HAS_TRAIT(W, TRAIT_TOOL_WRENCH))
+ if(HAS_TRAIT(item, TRAIT_TOOL_WRENCH))
if(user.action_busy)
return
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
@@ -214,7 +224,7 @@
update_icon() //unanchored changes layer
return
if(BARRICADE_BSTATE_MOVABLE) //Anchor bolts loosened step. Apply crowbar to unseat the panel and take apart the whole thing. Apply wrench to resecure anchor bolts
- if(HAS_TRAIT(W, TRAIT_TOOL_WRENCH))
+ if(HAS_TRAIT(item, TRAIT_TOOL_WRENCH))
if(user.action_busy)
return
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
@@ -224,8 +234,8 @@
if(B != src && B.dir == dir)
to_chat(user, SPAN_WARNING("There's already a barricade here."))
return
- var/turf/open/T = loc
- if(!(istype(T) && T.allow_construction))
+ var/turf/open/turf = loc
+ if(!(istype(turf) && turf.allow_construction))
to_chat(user, SPAN_WARNING("[src] must be secured on a proper surface!"))
return
playsound(src.loc, 'sound/items/Ratchet.ogg', 25, 1)
@@ -236,7 +246,7 @@
anchored = TRUE
update_icon() //unanchored changes layer
return
- if(HAS_TRAIT(W, TRAIT_TOOL_CROWBAR))
+ if(HAS_TRAIT(item, TRAIT_TOOL_CROWBAR))
if(user.action_busy)
return
if(!skillcheck(user, SKILL_CONSTRUCTION, SKILL_CONSTRUCTION_TRAINED))
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
index 52aae50a966a..c7a7664af3e8 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm
@@ -203,6 +203,9 @@
message_admins(SPAN_DANGER("ERROR: Non-admin [key_name(usr)] attempted to execute a SDQL query!"))
log_admin("non-admin attempted to execute a SDQL query!")
return FALSE
+ var/prompt = tgui_alert(usr, "Run SDQL2 Query?", "SDQL2", list("Yes", "Cancel"))
+ if (prompt != "Yes")
+ return
var/list/results = world.SDQL2_query(query_text, key_name_admin(usr), "[key_name(usr)]")
if(length(results) == 3)
for(var/I in 1 to 3)
diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm
index be8a5693df6e..700d42808a07 100644
--- a/code/modules/admin/verbs/deadsay.dm
+++ b/code/modules/admin/verbs/deadsay.dm
@@ -23,7 +23,7 @@
stafftype = "[admin_holder.rank]"
msg = strip_html(msg)
- log_admin("[key_name(src)] : [msg]")
+ log_admin("DEAD: [key_name(src)] : [msg]")
if (!msg)
return
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 8f0939474427..fbec4aa13f36 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -26,6 +26,8 @@
var/adminobs = null
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
+ /// The descriminator for larva queue ordering: Generally set to timeofdeath except for facehuggers/admin z-level play
+ var/larva_queue_time
var/donator = 0
var/adminhelped = 0
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index e51a904cfdac..d2d69d095dbd 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1228,8 +1228,9 @@ var/const/MAX_SAVE_SLOTS = 10
if("pred_gender")
predator_gender = predator_gender == MALE ? FEMALE : MALE
if("pred_age")
- var/new_predator_age = tgui_input_number(user, "Choose your Predator's age(20 to 10000):", "Character Preference", 1234, 10000, 20)
- if(new_predator_age) predator_age = max(min( round(text2num(new_predator_age)), 10000),20)
+ var/new_predator_age = tgui_input_number(user, "Choose your Predator's age(175 to 3000):", "Character Preference", 1234, 3000, 175)
+ if(new_predator_age)
+ predator_age = max(min( round(text2num(new_predator_age)), 3000),175)
if("pred_trans_type")
var/new_translator_type = tgui_input_list(user, "Choose your translator type.", "Translator Type", PRED_TRANSLATORS)
if(!new_translator_type)
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index 1c74080a928f..c621f112d7fc 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -297,3 +297,7 @@
/obj/item/device/walkman,
)
+/obj/item/clothing/suit/storage/snow_suit/liaison
+ name = "liaison's winter coat"
+ desc = "A Weyland-Yutani winter coat. Only the best comfort for the liaison in a cold environment."
+ icon_state = "snowsuit_liaison"
diff --git a/code/modules/clothing/under/marine_uniform.dm b/code/modules/clothing/under/marine_uniform.dm
index 17b98d9b9326..540c311f9221 100644
--- a/code/modules/clothing/under/marine_uniform.dm
+++ b/code/modules/clothing/under/marine_uniform.dm
@@ -777,12 +777,22 @@
icon_state = "liaison_regular"
worn_state = "liaison_regular"
+/obj/item/clothing/under/liaison_suit/charcoal
+ name = "liaison's charcoal suit"
+ desc = "A stiff, stylish charcoal suit commonly worn by businessmen from the Weyland-Yutani corporation. Expertly crafted to make you look like a prick."
+ icon_state = "liaison_charcoal"
+ worn_state = "liaison_charcoal"
+
/obj/item/clothing/under/liaison_suit/outing
name = "liaison's outfit"
desc = "A casual outfit consisting of a collared shirt and a vest. Looks like something you might wear on the weekends, or on a visit to a derelict colony."
icon_state = "liaison_outing"
worn_state = "liaison_outing"
+/obj/item/clothing/under/liaison_suit/outing/red
+ icon_state = "liaison_outing_red"
+ worn_state = "liaison_outing_red"
+
/obj/item/clothing/under/liaison_suit/formal
name = "liaison's white suit"
desc = "A formal, white suit. Looks like something you'd wear to a funeral, a Weyland-Yutani corporate dinner, or both. Stiff as a board, but makes you feel like rolling out of a Rolls-Royce."
@@ -795,6 +805,12 @@
icon_state = "liaison_suspenders"
worn_state = "liaison_suspenders"
+/obj/item/clothing/under/liaison_suit/blazer
+ name = "liaison's blue blazer"
+ desc = "A stiff but casual blue blazer. Similar can be found in any Weyland-Yutani office. Only the finest wear for the galaxy's most cunning."
+ icon_state = "liaison_blue_blazer"
+ worn_state = "liaison_blue_blazer"
+
/obj/item/clothing/under/marine/reporter
name = "combat correspondent uniform"
desc = "A relaxed and robust uniform fit for any potential reporting needs."
diff --git a/code/modules/cm_aliens/structures/special/pylon_core.dm b/code/modules/cm_aliens/structures/special/pylon_core.dm
index 9376e2b6e914..c38e540efb30 100644
--- a/code/modules/cm_aliens/structures/special/pylon_core.dm
+++ b/code/modules/cm_aliens/structures/special/pylon_core.dm
@@ -108,6 +108,7 @@
var/last_healed = 0
var/last_attempt = 0 // logs time of last attempt to prevent spam. if you want to destroy it, you must commit.
var/last_larva_time = 0
+ var/last_larva_queue_time = 0
var/last_surge_time = 0
var/spawn_cooldown = 30 SECONDS
var/surge_cooldown = 90 SECONDS
@@ -135,25 +136,40 @@
// Handle spawning larva if core is connected to a hive
if(linked_hive)
- for(var/mob/living/carbon/xenomorph/larva/L in range(2, src))
- if(!L.ckey && L.burrowable && !QDELETED(L))
- visible_message(SPAN_XENODANGER("[L] quickly burrows into \the [src]."))
- linked_hive.stored_larva++
- linked_hive.hive_ui.update_burrowed_larva()
- qdel(L)
-
- if((last_larva_time + spawn_cooldown) < world.time && can_spawn_larva()) // every minute
+ for(var/mob/living/carbon/xenomorph/larva/worm in range(2, src))
+ if((!worm.ckey || worm.stat == DEAD) && worm.burrowable && (worm.hivenumber == linked_hive.hivenumber) && !QDELETED(worm))
+ visible_message(SPAN_XENODANGER("[worm] quickly burrows into \the [src]."))
+ if(!worm.banished)
+ // Goob job bringing her back home, but no doubling please
+ linked_hive.stored_larva++
+ linked_hive.hive_ui.update_burrowed_larva()
+ qdel(worm)
+
+ var/spawning_larva = can_spawn_larva() && (last_larva_time + spawn_cooldown) < world.time
+ if(spawning_larva)
last_larva_time = world.time
+ if(spawning_larva || (last_larva_queue_time + spawn_cooldown * 4) < world.time)
+ last_larva_queue_time = world.time
var/list/players_with_xeno_pref = get_alien_candidates()
- if(players_with_xeno_pref && players_with_xeno_pref.len && can_spawn_larva())
- spawn_burrowed_larva(pick(players_with_xeno_pref))
+ if(players_with_xeno_pref && players_with_xeno_pref.len)
+ if(spawning_larva && spawn_burrowed_larva(players_with_xeno_pref[1]))
+ // We were in spawning_larva mode and successfully spawned someone
+ message_alien_candidates(players_with_xeno_pref, dequeued = 1)
+ else
+ // Just time to update everyone their queue status (or the spawn failed)
+ message_alien_candidates(players_with_xeno_pref, dequeued = 0)
if(linked_hive.hijack_burrowed_surge && (last_surge_time + surge_cooldown) < world.time)
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)
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)
diff --git a/code/modules/cm_marines/marines_consoles.dm b/code/modules/cm_marines/marines_consoles.dm
index 21f8a461a016..3539a43e6c15 100644
--- a/code/modules/cm_marines/marines_consoles.dm
+++ b/code/modules/cm_marines/marines_consoles.dm
@@ -177,7 +177,7 @@
if(!authenticated || !target_id_card)
return
- var/new_name = params["name"] // reject_bad_name() can be added here
+ var/new_name = strip_html(params["name"])
if(!new_name)
visible_message(SPAN_NOTICE("[src] buzzes rudely."))
return
@@ -191,7 +191,7 @@
return
if(target == "Custom")
- var/custom_name = params["custom_name"]
+ var/custom_name = strip_html(params["custom_name"])
if(custom_name)
target_id_card.assignment = custom_name
else
diff --git a/code/modules/cm_marines/orbital_cannon.dm b/code/modules/cm_marines/orbital_cannon.dm
index 431b03fb31d3..14e990809f4f 100644
--- a/code/modules/cm_marines/orbital_cannon.dm
+++ b/code/modules/cm_marines/orbital_cannon.dm
@@ -484,14 +484,13 @@ var/list/ob_type_fuel_requirements
var/list/turf_list = list()
for(var/turf/T in range(range_num, target))
- if(protected_by_pylon(TURF_PROTECTION_OB, T))
- continue
-
turf_list += T
for(var/i = 1 to total_amount)
for(var/k = 1 to instant_amount)
var/turf/U = pick(turf_list)
+ if(protected_by_pylon(TURF_PROTECTION_OB, U)) //If the turf somehow gained OB protection while the cluster was firing
+ continue
fire_in_a_hole(U)
sleep(delay_between_clusters)
diff --git a/code/modules/mentor/mentorhelp.dm b/code/modules/mentor/mentorhelp.dm
index 8413b6d118e6..84dacf4f8bfb 100644
--- a/code/modules/mentor/mentorhelp.dm
+++ b/code/modules/mentor/mentorhelp.dm
@@ -108,28 +108,28 @@
sound_to(recipient, 'sound/effects/mhelp.ogg')
to_chat(recipient, wrap_message(msg, sender))
- for(var/client/C in GLOB.admins)
+ for(var/client/admin_client in GLOB.admins)
var/formatted = msg
var/soundfile
- if(!C || C == recipient)
+ if(!admin_client || admin_client == recipient)
continue
// Initial broadcast
- else if(!staff_only && !recipient && CLIENT_HAS_RIGHTS(C, R_MENTOR))
+ else if(!staff_only && !recipient && CLIENT_HAS_RIGHTS(admin_client, R_MENTOR))
formatted = wrap_message(formatted, sender)
soundfile = 'sound/effects/mhelp.ogg'
- // Staff eavesdrop
- else if(CLIENT_HAS_RIGHTS(C, R_MENTOR) && CLIENT_IS_STAFF(C))
+ // Eavesdrop
+ else if(CLIENT_HAS_RIGHTS(admin_client, R_MENTOR) && (!staff_only || CLIENT_IS_STAFF(admin_client)) && admin_client != sender)
if(include_keys)
formatted = SPAN_MENTORHELP(key_name(sender, TRUE) + " -> " + key_name(recipient, TRUE) + ": ") + msg
else continue
- if(soundfile && with_sound && (C.prefs?.toggles_sound & SOUND_ADMINHELP))
- sound_to(C, soundfile)
- to_chat(C, formatted)
+ if(soundfile && with_sound && (admin_client.prefs?.toggles_sound & SOUND_ADMINHELP))
+ sound_to(admin_client, soundfile)
+ to_chat(admin_client, formatted)
return
// Makes the sender input a message and sends it
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 47e747d4cd5c..fcb95a6fd783 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -33,8 +33,8 @@
plane = GHOST_PLANE
layer = ABOVE_FLY_LAYER
stat = DEAD
- var/adminlarva = 0
- var/ghostvision = 1
+ var/adminlarva = FALSE
+ var/ghostvision = TRUE
var/can_reenter_corpse
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
//If you died in the game and are a ghost - this will remain as null.
@@ -45,7 +45,7 @@
"Squad HUD" = FALSE,
"Xeno Status HUD" = FALSE
)
- universal_speak = 1
+ universal_speak = TRUE
var/updatedir = TRUE //Do we have to update our dir as the ghost moves around?
var/atom/movable/following = null
var/datum/orbit_menu/orbit_menu
@@ -55,6 +55,8 @@
var/own_orbit_size = 0
var/observer_actions = list(/datum/action/observer_action/join_xeno)
var/datum/action/minimap/observer/minimap
+ var/larva_queue_cached_message
+
alpha = 127
/mob/dead/observer/verb/toggle_ghostsee()
@@ -327,8 +329,8 @@ Works together with spawning an observer, noted above.
ghost.langchat_make_image()
SStgui.on_transfer(src, ghost)
- if(is_admin_level(z))
- ghost.timeofdeath = 0 // Bypass respawn limit if you die on the admin zlevel
+ if(is_admin_level((get_turf(src))?.z)) // Gibbed humans ghostize the brain in their head which itself is z 0
+ ghost.timeofdeath = 1 // Bypass respawn limit if you die on the admin zlevel
ghost.key = key
ghost.mind = mind
@@ -363,6 +365,12 @@ Works together with spawning an observer, noted above.
if(ghost.client.player_data)
ghost.client.player_data.load_timestat_data()
+ // Larva queue: We use the larger of their existing queue time or the new timeofdeath except for facehuggers
+ // We don't change facehugger timeofdeath because they are still on cooldown if they died as a hugger
+ // Facehuggers are atleast 1 because they did get some action compared to those at 0 timeofdeath
+ var/new_tod = isfacehugger(src) ? 1 : ghost.timeofdeath
+ ghost.client.larva_queue_time = max(ghost.client.larva_queue_time, new_tod)
+
ghost.set_huds_from_prefs()
return ghost
@@ -405,6 +413,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/mob/dead/observer/ghost = ghostize((is_nested && nest && !QDELETED(nest))) //FALSE parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
if(ghost && !is_admin_level(z))
ghost.timeofdeath = world.time
+ ghost.client?.larva_queue_time = world.time
if(is_nested && nest && !QDELETED(nest))
ghost.can_reenter_corpse = FALSE
nest.ghost_of_buckled_mob = ghost
diff --git a/code/modules/mob/living/carbon/xenomorph/Embryo.dm b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
index e03f225ccade..29779480f143 100644
--- a/code/modules/mob/living/carbon/xenomorph/Embryo.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Embryo.dm
@@ -12,6 +12,8 @@
var/hivenumber = XENO_HIVE_NORMAL
var/faction = FACTION_XENOMORPH
var/flags_embryo = FALSE // Used in /ciphering/predator property
+ /// The ckey of any player hugger that made this embryo
+ var/hugger_ckey
/obj/item/alien_embryo/Initialize(mapload, ...)
. = ..()
@@ -33,6 +35,7 @@
C.med_hud_set_status()
STOP_PROCESSING(SSobj, src)
affected_mob = null
+ GLOB.player_embryo_list -= src
. = ..()
/obj/item/alien_embryo/process()
@@ -145,19 +148,33 @@
var/mob/picked
// If the bursted person themselves has Xeno enabled, they get the honor of first dibs on the new larva.
- if((!isyautja(affected_mob) || (isyautja(affected_mob) && prob(20))) && istype(affected_mob.buckled, /obj/structure/bed/nest))
+ if((!isyautja(affected_mob) || (isyautja(affected_mob) && prob(20))) && istype(affected_mob.buckled, /obj/structure/bed/nest))
if(affected_mob.first_xeno || (affected_mob.client && affected_mob.client.prefs && (affected_mob.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) && !jobban_isbanned(affected_mob, JOB_XENOMORPH)))
picked = affected_mob
else if(affected_mob.mind && affected_mob.mind.ghost_mob && affected_mob.client && affected_mob.client.prefs && (affected_mob.client.prefs.be_special & BE_ALIEN_AFTER_DEATH) && !jobban_isbanned(affected_mob, JOB_XENOMORPH))
picked = affected_mob.mind.ghost_mob
-
if(!picked)
// Get a candidate from observers
var/list/candidates = get_alien_candidates()
-
if(candidates && candidates.len)
- picked = pick(candidates)
+ // If they were facehugged by a player thats still in queue, they get second dibs on the new larva.
+ if(hugger_ckey)
+ for(var/mob/dead/observer/cur_obs as anything in candidates)
+ if(cur_obs.ckey == hugger_ckey)
+ picked = cur_obs
+ candidates -= cur_obs
+ message_alien_candidates(candidates, dequeued = 0)
+ for(var/obj/item/alien_embryo/embryo as anything in GLOB.player_embryo_list)
+ if(embryo.hugger_ckey == cur_obs.ckey && embryo != src)
+ // Skipping src just in case an admin wants to quickly check before this thing fully deletes
+ // If this nulls out any embryo, wow
+ embryo.hugger_ckey = null
+ break
+
+ if(!picked)
+ picked = candidates[1]
+ message_alien_candidates(candidates, dequeued = 1)
// Spawn the larva
var/mob/living/carbon/xenomorph/larva/new_xeno
diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm
index 1f88643db764..4806f7528582 100644
--- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm
@@ -140,6 +140,7 @@
if(3)
hive.tier_3_xenos |= new_xeno
+ log_game("EVOLVE: [key_name(src)] evolved into [new_xeno].")
if(mind)
mind.transfer_to(new_xeno)
else
@@ -327,6 +328,7 @@
qdel(new_xeno)
return
+ log_game("EVOLVE: [key_name(src)] de-evolved into [new_xeno].")
if(mind)
mind.transfer_to(new_xeno)
else
diff --git a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm
index 121a231b7bf8..8b3b1d54f26d 100644
--- a/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/Facehuggers.dm
@@ -209,6 +209,11 @@
if(stat == UNCONSCIOUS)
return
+ // Force reset throw now because [/atom/movable/proc/launch_impact] only does that later on
+ // If we DON'T, step()'s move below can collide, rebound, trigger this proc again, into infinite recursion
+ throwing = FALSE
+ rebounding = FALSE
+
if(leaping && can_hug(L, hivenumber))
attach(L)
else if(L.density)
@@ -241,46 +246,46 @@
throw_atom(target, 3, SPEED_FAST)
return TRUE
-/obj/item/clothing/mask/facehugger/proc/attach(mob/living/M, silent = FALSE, knockout_mod = 1)
- if(attached || !can_hug(M, hivenumber))
+/obj/item/clothing/mask/facehugger/proc/attach(mob/living/living_mob, silent = FALSE, knockout_mod = 1, hugger_ckey = null)
+ if(attached || !can_hug(living_mob, hivenumber))
return FALSE
// This is always going to be valid because of the can_hug check above
- var/mob/living/carbon/human/H = M
+ var/mob/living/carbon/human/human = living_mob
if(!silent)
- H.visible_message(SPAN_DANGER("[src] leaps at [H]'s face!"))
+ human.visible_message(SPAN_DANGER("[src] leaps at [human]'s face!"))
if(isxeno(loc)) //Being carried? Drop it
var/mob/living/carbon/xenomorph/X = loc
X.drop_inv_item_on_ground(src)
- if(isturf(H.loc))
- forceMove(H.loc)//Just checkin
+ if(isturf(human.loc))
+ forceMove(human.loc)//Just checkin
- if(!H.handle_hugger_attachment(src))
+ if(!human.handle_hugger_attachment(src))
return FALSE
attached = TRUE
- forceMove(H)
+ forceMove(human)
icon_state = initial(icon_state)
- H.equip_to_slot(src, WEAR_FACE)
- H.update_inv_wear_mask()
- H.disable_lights()
- H.disable_special_items()
- if(ishuman_strict(H))
- playsound(loc, H.gender == "male" ? 'sound/misc/facehugged_male.ogg' : 'sound/misc/facehugged_female.ogg' , 25, 0)
- else if(isyautja(H))
+ human.equip_to_slot(src, WEAR_FACE)
+ human.update_inv_wear_mask()
+ human.disable_lights()
+ human.disable_special_items()
+ if(ishuman_strict(human))
+ playsound(loc, human.gender == "male" ? 'sound/misc/facehugged_male.ogg' : 'sound/misc/facehugged_female.ogg' , 25, 0)
+ else if(isyautja(human))
playsound(loc, 'sound/voice/pred_facehugged.ogg', 65, FALSE)
if(!sterile)
- if(!H.species || !(H.species.flags & IS_SYNTHETIC)) //synthetics aren't paralyzed
- H.apply_effect(MIN_IMPREGNATION_TIME * 0.5 * knockout_mod, PARALYZE) //THIS MIGHT NEED TWEAKS
+ if(!human.species || !(human.species.flags & IS_SYNTHETIC)) //synthetics aren't paralyzed
+ human.apply_effect(MIN_IMPREGNATION_TIME * 0.5 * knockout_mod, PARALYZE) //THIS MIGHT NEED TWEAKS
- addtimer(CALLBACK(src, PROC_REF(impregnate), H), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME))
+ addtimer(CALLBACK(src, PROC_REF(impregnate), human, hugger_ckey), rand(MIN_IMPREGNATION_TIME, MAX_IMPREGNATION_TIME))
return TRUE
-/obj/item/clothing/mask/facehugger/proc/impregnate(mob/living/carbon/human/target)
+/obj/item/clothing/mask/facehugger/proc/impregnate(mob/living/carbon/human/target, hugger_ckey = null)
if(!target || target.wear_mask != src) //Was taken off or something
return
if(SEND_SIGNAL(target, COMSIG_HUMAN_IMPREGNATE, src) & COMPONENT_NO_IMPREGNATE)
@@ -295,6 +300,8 @@
if(!embryos)
var/obj/item/alien_embryo/embryo = new /obj/item/alien_embryo(target)
embryo.hivenumber = hivenumber
+ embryo.hugger_ckey = hugger_ckey
+ GLOB.player_embryo_list += embryo
embryo.flags_embryo = flags_embryo
flags_embryo = NO_FLAGS
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm
index e745e8940063..dff6c82efbf8 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/boiler/boiler_powers.dm
@@ -139,7 +139,8 @@
spicy_gas = new /datum/effect_system/smoke_spread/xeno_weaken
else
CRASH("Globber has unknown ammo [xeno.ammo]! Oh no!")
- spicy_gas.set_up(1, 0, get_turf(xeno), null, 6)
+ var/datum/cause_data/cause_data = create_cause_data("acid shroud gas", owner)
+ spicy_gas.set_up(1, 0, get_turf(xeno), null, 6, new_cause_data = cause_data)
spicy_gas.start()
to_chat(xeno, SPAN_XENOHIGHDANGER("You dump your acid through your pores, creating a shroud of gas!"))
for (var/action_type in action_types_to_cd)
@@ -166,9 +167,9 @@
if(!actually_moving)
return
- var/obj/effect/particle_effect/smoke/S = new /obj/effect/particle_effect/smoke/xeno_burn(get_turf(mover), 1, create_cause_data(initial(mover.caste_type), mover))
- S.time_to_live = 3
- S.spread_speed = 1000000
+ var/obj/effect/particle_effect/smoke/xeno_burn/smoke_effect = new(get_turf(mover), 1, create_cause_data("dumped acid gas", mover))
+ smoke_effect.time_to_live = 3
+ smoke_effect.spread_speed = 1000000
/datum/action/xeno_action/onclick/dump_acid/remove_from()
remove_speed_buff()
@@ -283,27 +284,25 @@
apply_cooldown()
return ..()
-/datum/action/xeno_action/activable/acid_shotgun/use_ability(atom/A)
- var/mob/living/carbon/xenomorph/X = owner
- if (!istype(X))
+/datum/action/xeno_action/activable/acid_shotgun/use_ability(atom/target)
+ var/mob/living/carbon/xenomorph/xeno = owner
+ if (!istype(xeno))
return
if (!action_cooldown_check())
return
- if(!A || A.layer >= FLY_LAYER || !isturf(X.loc) || !X.check_state())
+ if(!target || target.layer >= FLY_LAYER || !isturf(xeno.loc) || !xeno.check_state())
return
- X.visible_message(SPAN_XENOWARNING("The [X] fires a blast of acid at [A]!"), SPAN_XENOWARNING("You fire a blast of acid at [A]!"))
-
- var/turf/target = locate(A.x, A.y, A.z)
- var/obj/item/projectile/P = new /obj/item/projectile(X.loc, create_cause_data(initial(X.caste_type), X))
+ xeno.visible_message(SPAN_XENOWARNING("The [xeno] fires a blast of acid at [target]!"), SPAN_XENOWARNING("You fire a blast of acid at [target]!"))
+ var/turf/target_turf = locate(target.x, target.y, target.z)
+ var/obj/item/projectile/proj = new(xeno.loc, create_cause_data("acid shotgun", xeno))
var/datum/ammo/ammoDatum = new ammo_type()
- P.generate_bullet(ammoDatum)
-
- P.fire_at(target, X, X, ammoDatum.max_range, ammoDatum.shell_speed)
+ proj.generate_bullet(ammoDatum)
+ proj.fire_at(target_turf, xeno, xeno, ammoDatum.max_range, ammoDatum.shell_speed)
apply_cooldown()
return ..()
@@ -347,7 +346,7 @@
else if(stabbing_xeno.ammo == GLOB.ammo_list[/datum/ammo/xeno/boiler_gas])
var/datum/effects/neurotoxin/neuro_effect = locate() in carbon_target.effects_list
if(!neuro_effect)
- neuro_effect = new /datum/effects/neurotoxin(carbon_target)
+ neuro_effect = new(carbon_target, owner)
neuro_effect.duration += 16
to_chat(carbon_target,SPAN_HIGHDANGER("You are injected with something from [stabbing_xeno]'s tailstab!"))
else
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
index 1712ba739748..921b61a23bc9 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm
@@ -766,12 +766,12 @@
SPAN_XENOWARNING("You spit a [xeno.ammo.name] at [atom]!") )
playsound(xeno.loc, sound_to_play, 25, 1)
+ var/obj/item/projectile/proj = new (current_turf, create_cause_data(xeno.ammo.name, xeno))
+ proj.generate_bullet(xeno.ammo)
+ proj.permutated += xeno
+ proj.def_zone = xeno.get_limbzone_target()
+ proj.fire_at(spit_target, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
- var/obj/item/projectile/Proj = new (current_turf, create_cause_data(initial(xeno.caste_type), xeno))
- Proj.generate_bullet(xeno.ammo)
- Proj.permutated += xeno
- Proj.def_zone = xeno.get_limbzone_target()
- Proj.fire_at(spit_target, xeno, xeno, xeno.ammo.max_range, xeno.ammo.shell_speed)
spitting = FALSE
SEND_SIGNAL(xeno, COMSIG_XENO_POST_SPIT)
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
index 46e8807e8ade..65ea443c133c 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
@@ -472,22 +472,6 @@
user_xeno.hive.banished_ckeys.Remove(banished_name)
return ..()
-/datum/action/xeno_action/activable/secrete_resin/remote/queen/use_ability(atom/A)
- . = ..()
- if(!.)
- return
-
- if(!boosted)
- return
- var/mob/living/carbon/xenomorph/X = owner
- var/datum/hive_status/HS = X.hive
- if(!HS || !HS.hive_location)
- return
- // 5 screen radius
- if(get_dist(A, HS.hive_location) > 35)
- // Apply the normal cooldown if not building near the hive
- apply_cooldown_override(initial(xeno_cooldown))
-
/datum/action/xeno_action/onclick/eye
name = "Enter Eye Form"
action_icon_state = "queen_eye"
diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
index 9eb8601bb6dc..246e2d2809db 100644
--- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
+++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm
@@ -287,6 +287,9 @@
SPAN_DANGER("You nudge your head against [src]."), null, 5, CHAT_TYPE_XENO_FLUFF)
/mob/living/proc/is_xeno_grabbable()
+ if(stat == DEAD)
+ return FALSE
+
return TRUE
/mob/living/carbon/human/is_xeno_grabbable()
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm
index d9ab8a1e849d..1b8ac2ee05dc 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm
@@ -143,9 +143,9 @@
/mob/living/carbon/xenomorph/facehugger/proc/handle_hug(mob/living/carbon/human/human)
var/obj/item/clothing/mask/facehugger/hugger = new /obj/item/clothing/mask/facehugger(loc, hivenumber)
- var/did_hug = hugger.attach(human, TRUE, 0.5)
+ var/did_hug = hugger.attach(human, TRUE, 0.5, client?.ckey)
if(client)
- client?.player_data?.adjust_stat(PLAYER_STAT_FACEHUGS, STAT_CATEGORY_XENO, 1)
+ client.player_data?.adjust_stat(PLAYER_STAT_FACEHUGS, STAT_CATEGORY_XENO, 1)
var/area/hug_area = get_area(src)
if(hug_area)
for(var/mob/dead/observer/observer as anything in GLOB.observer_list)
@@ -155,6 +155,7 @@
for(var/mob/dead/observer/observer as anything in GLOB.observer_list)
to_chat(observer, SPAN_DEADSAY("[human] has been facehugged by [src]" + " [OBSERVER_JMP(observer, human)]"))
to_chat(src, SPAN_DEADSAY("[human] has been facehugged by [src]"))
+ timeofdeath = 1 // Ever so slightly deprioritized for larva queue
qdel(src)
if(hug_area)
xeno_message(SPAN_XENOMINORWARNING("You sense that [src] has facehugged a host at \the [hug_area]!"), 1, src.hivenumber)
diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm b/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm
index 04b7e04c2da5..4cf0ff113615 100644
--- a/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm
+++ b/code/modules/mob/living/carbon/xenomorph/castes/Larva.dm
@@ -170,3 +170,5 @@
/mob/living/carbon/xenomorph/larva/emote(act, m_type, message, intentional, force_silence)
playsound(loc, "alien_roar_larva", 15)
+/mob/living/carbon/xenomorph/larva/is_xeno_grabbable()
+ return TRUE
diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm
index e1a84c087a3b..fe4b4cca2fb1 100644
--- a/code/modules/mob/living/carbon/xenomorph/death.dm
+++ b/code/modules/mob/living/carbon/xenomorph/death.dm
@@ -37,12 +37,13 @@
if(GLOB.hive_datum[hivenumber].stored_larva)
GLOB.hive_datum[hivenumber].stored_larva = round(GLOB.hive_datum[hivenumber].stored_larva * 0.5) //Lose half on dead queen
- var/turf/larva_spawn
+
var/list/players_with_xeno_pref = get_alien_candidates()
- while(GLOB.hive_datum[hivenumber].stored_larva > 0 && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core)) // stil some left
- larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location)
- if(players_with_xeno_pref && players_with_xeno_pref.len)
- var/mob/xeno_candidate = pick(players_with_xeno_pref)
+ if(players_with_xeno_pref && istype(GLOB.hive_datum[hivenumber].hive_location, /obj/effect/alien/resin/special/pylon/core))
+ var/turf/larva_spawn = get_turf(GLOB.hive_datum[hivenumber].hive_location)
+ var/count = 0
+ while(GLOB.hive_datum[hivenumber].stored_larva > 0 && count < length(players_with_xeno_pref)) // still some left
+ var/mob/xeno_candidate = players_with_xeno_pref[++count]
var/mob/living/carbon/xenomorph/larva/new_xeno = new /mob/living/carbon/xenomorph/larva(larva_spawn)
new_xeno.set_hive_and_update(hivenumber)
@@ -50,11 +51,14 @@
if(!SSticker.mode.transfer_xeno(xeno_candidate, new_xeno))
qdel(new_xeno)
return
+
new_xeno.visible_message(SPAN_XENODANGER("A larva suddenly burrows out of the ground!"),
SPAN_XENODANGER("You burrow out of the ground after feeling an immense tremor through the hive, which quickly fades into complete silence..."))
- GLOB.hive_datum[hivenumber].stored_larva--
- GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva()
+ GLOB.hive_datum[hivenumber].stored_larva--
+ GLOB.hive_datum[hivenumber].hive_ui.update_burrowed_larva()
+ if(count)
+ message_alien_candidates(players_with_xeno_pref, dequeued = count)
if(hive && hive.living_xeno_queen == src)
xeno_message(SPAN_XENOANNOUNCE("A sudden tremor ripples through the hive... the Queen has been slain! Vengeance!"),3, hivenumber)
@@ -136,10 +140,10 @@
switch(caste.caste_type) //This will need to be changed later, when we have proper xeno pathing. Might do it on caste or something.
if(XENO_CASTE_BOILER)
- var/mob/living/carbon/xenomorph/boiler/B = src
+ var/mob/living/carbon/xenomorph/boiler/src_boiler = src
visible_message(SPAN_DANGER("[src] begins to bulge grotesquely, and explodes in a cloud of corrosive gas!"))
- B.smoke.set_up(2, 0, get_turf(src))
- B.smoke.start()
+ src_boiler.smoke.set_up(2, 0, get_turf(src), new_cause_data = src_boiler.smoke.cause_data)
+ src_boiler.smoke.start()
remains.icon_state = "gibbed-a-corpse"
if(XENO_CASTE_RUNNER)
remains.icon_state = "gibbed-a-corpse-runner"
diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm
index b5431720e14a..5d3ee0b04ba7 100644
--- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm
+++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm
@@ -285,6 +285,8 @@
var/larva_gestation_multiplier = 1
var/bonus_larva_spawn_chance = 1
var/hijack_burrowed_surge = FALSE //at hijack, start spawning lots of burrowed
+ /// how many burrowed is going to spawn during larva surge
+ var/hijack_burrowed_left = 0
var/ignore_slots = FALSE
var/dynamic_evolution = TRUE
@@ -877,6 +879,8 @@
/datum/hive_status/proc/abandon_on_hijack()
var/area/hijacked_dropship = get_area(living_xeno_queen)
+ var/shipside_humans_weighted_count = 0
+ var/xenos_count = 0
for(var/name_ref in hive_structures)
for(var/obj/effect/alien/resin/special/S in hive_structures[name_ref])
if(get_area(S) == hijacked_dropship)
@@ -885,6 +889,10 @@
qdel(S)
for(var/mob/living/carbon/xenomorph/xeno as anything in totalXenos)
if(get_area(xeno) != hijacked_dropship && xeno.loc && is_ground_level(xeno.loc.z))
+ if(isfacehugger(xeno))
+ to_chat(xeno, SPAN_XENOANNOUNCE("The Queen has left without you, you quickly find a hiding place to enter hibernation as you lose touch with the hive mind."))
+ qdel(xeno)
+ continue
if(xeno.hunter_data.hunted && !isqueen(xeno))
to_chat(xeno, SPAN_XENOANNOUNCE("The Queen has left without you, seperating you from her hive! You must defend yourself from the headhunter before you can enter hibernation..."))
xeno.set_hive_and_update(XENO_HIVE_FORSAKEN)
@@ -895,6 +903,9 @@
xeno.handle_stomach_contents()
qdel(xeno)
stored_larva++
+ continue
+ if(!isfacehugger(xeno))
+ xenos_count++
for(var/i in GLOB.alive_mob_list)
var/mob/living/potential_host = i
if(!(potential_host.status_flags & XENO_HOST))
@@ -907,7 +918,13 @@
for(var/obj/item/alien_embryo/embryo in potential_host)
embryo.hivenumber = XENO_HIVE_FORSAKEN
potential_host.update_med_icon()
+ for(var/mob/living/carbon/human/current_human as anything in GLOB.alive_human_list)
+ if((isspecieshuman(current_human) || isspeciessynth(current_human)) && current_human.job)
+ var/turf/turf = get_turf(current_human)
+ if(is_mainship_level(turf?.z))
+ shipside_humans_weighted_count += RoleAuthority.calculate_role_weight(current_human.job)
hijack_burrowed_surge = TRUE
+ hijack_burrowed_left = max(n_ceil(shipside_humans_weighted_count * 0.5) - xenos_count, 5)
hivecore_cooldown = FALSE
xeno_message(SPAN_XENOBOLDNOTICE("The weeds have recovered! A new hive core can be built!"),3,hivenumber)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 7803c15da523..0c182fb0fe9c 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -843,7 +843,7 @@ note dizziness decrements automatically in the mob's Life() proc.
return FALSE
to_chat(src, SPAN_WARNING("You attempt to get a good grip on [selection] in your body."))
else
- if(get_active_hand())
+ if(usr.get_active_hand())
to_chat(usr, SPAN_WARNING("You need an empty hand for this!"))
return FALSE
to_chat(usr, SPAN_WARNING("You attempt to get a good grip on [selection] in [src]'s body."))
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index 81296f346d50..39cc5b25e519 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -141,10 +141,9 @@
X.visible_message(SPAN_WARNING("[X] devours [pulled]!"), \
SPAN_WARNING("You devour [pulled]!"), null, 5)
- //IMPORTANT CODER NOTE: Due to us using the old lighting engine, we need to hacky hack hard to get this working properly
- //So we're just going to get the lights out of here by forceMoving them to a far-away place
- //They will be recovered when regurgitating, since this also calls forceMove
- pulled.moveToNullspace()
+ if(ishuman(pulled))
+ var/mob/living/carbon/human/pulled_human = pulled
+ pulled_human.disable_lights()
//Then, we place the mob where it ought to be
X.stomach_contents.Add(pulled)
diff --git a/code/modules/projectiles/ammo_datums.dm b/code/modules/projectiles/ammo_datums.dm
index 05a4256efb49..d8b158485501 100644
--- a/code/modules/projectiles/ammo_datums.dm
+++ b/code/modules/projectiles/ammo_datums.dm
@@ -2740,7 +2740,7 @@
return
var/datum/effects/neurotoxin/neuro_effect = locate() in moob.effects_list
if(!neuro_effect)
- neuro_effect = new /datum/effects/neurotoxin(moob)
+ neuro_effect = new /datum/effects/neurotoxin(moob, proj.firer)
neuro_effect.duration += 5
moob.apply_effect(3, DAZE)
to_chat(moob, SPAN_HIGHDANGER("Neurotoxic liquid spreads all over you and immediately soaks into your pores and orifices! Oh fuck!")) // Fucked up but have a chance to escape rather than being game-ended
@@ -2763,9 +2763,10 @@
/datum/ammo/xeno/boiler_gas/proc/drop_nade(turf/turf, obj/item/projectile/proj)
var/lifetime_mult = 1.0
+ var/datum/cause_data
if(isboiler(proj.firer))
- smoke_system.cause_data = proj.weapon_cause_data
- smoke_system.set_up(smokerange, 0, turf)
+ cause_data = proj.weapon_cause_data
+ smoke_system.set_up(smokerange, 0, turf, new_cause_data = cause_data)
smoke_system.lifetime = 12 * lifetime_mult
smoke_system.start()
turf.visible_message(SPAN_DANGER("A glob of acid lands with a splat and explodes into noxious fumes!"))
diff --git a/code/modules/projectiles/gun_helpers.dm b/code/modules/projectiles/gun_helpers.dm
index 2cfd827b1fc2..d8ea29cd92f8 100644
--- a/code/modules/projectiles/gun_helpers.dm
+++ b/code/modules/projectiles/gun_helpers.dm
@@ -143,7 +143,7 @@ As sniper rifles have both and weapon mods can change them as well. ..() deals w
/obj/item/weapon/gun/dropped(mob/user)
. = ..()
- turn_off_light(user)
+ disconnect_light_from_mob(user)
var/delay_left = (last_fired + fire_delay + additional_fire_group_delay) - world.time
if(fire_delay_group && delay_left > 0)
@@ -160,16 +160,28 @@ As sniper rifles have both and weapon mods can change them as well. ..() deals w
for(var/group in fire_delay_group)
LAZYSET(user.fire_delay_next_fire, group, world.time + delay_left)
-/obj/item/weapon/gun/proc/turn_off_light(mob/bearer)
+/// This function disconnects the luminosity from the mob and back to the gun
+/obj/item/weapon/gun/proc/disconnect_light_from_mob(mob/bearer)
if (!(flags_gun_features & GUN_FLASHLIGHT_ON))
return FALSE
for (var/slot in attachments)
var/obj/item/attachable/attachment = attachments[slot]
if (!attachment || !attachment.light_mod)
continue
+ bearer.SetLuminosity(0, FALSE, src)
+ SetLuminosity(attachment.light_mod)
+ return TRUE
+ return FALSE
+/// This function actually turns the lights on the gun off
+/obj/item/weapon/gun/proc/turn_off_light(mob/bearer)
+ if (!(flags_gun_features & GUN_FLASHLIGHT_ON))
+ return FALSE
+ for (var/slot in attachments)
+ var/obj/item/attachable/attachment = attachments[slot]
+ if (!attachment || !attachment.light_mod)
+ continue
attachment.activate_attachment(src, bearer)
-
return TRUE
return FALSE
diff --git a/code/modules/projectiles/magazines/flamer.dm b/code/modules/projectiles/magazines/flamer.dm
index 782b6bfe8910..787a0585640a 100644
--- a/code/modules/projectiles/magazines/flamer.dm
+++ b/code/modules/projectiles/magazines/flamer.dm
@@ -58,6 +58,7 @@
reagents.clear_reagents()
+ playsound(loc, 'sound/effects/refill.ogg', 25, 1, 3)
to_chat(usr, SPAN_NOTICE("You empty out [src]"))
update_icon()
@@ -71,22 +72,21 @@
G.update_icon()
/obj/item/ammo_magazine/flamer_tank/afterattack(obj/target, mob/user , flag) //refuel at fueltanks when we run out of ammo.
- if(!istype(target, /obj/structure/reagent_dispensers/fueltank) && !istype(target, /obj/item/tool/weldpack) && !istype(target, /obj/item/storage/backpack/marine/engineerpack))
- return ..()
if(get_dist(user,target) > 1)
return ..()
+ if(!istype(target, /obj/structure/reagent_dispensers/fueltank) && !istype(target, /obj/item/tool/weldpack) && !istype(target, /obj/item/storage/backpack/marine/engineerpack))
+ return ..()
- var/obj/O = target
- if(!O.reagents || O.reagents.reagent_list.len < 1)
- to_chat(user, SPAN_WARNING("[O] is empty!"))
+ if(!target.reagents || target.reagents.reagent_list.len < 1)
+ to_chat(user, SPAN_WARNING("[target] is empty!"))
return
if(!reagents)
create_reagents(max_rounds)
- var/datum/reagent/to_add = O.reagents.reagent_list[1]
+ var/datum/reagent/to_add = target.reagents.reagent_list[1]
- if(!istype(to_add) || (length(reagents.reagent_list) && flamer_chem != to_add.id) || length(O.reagents.reagent_list) > 1)
+ if(!istype(to_add) || (length(reagents.reagent_list) && flamer_chem != to_add.id) || length(target.reagents.reagent_list) > 1)
to_chat(user, SPAN_WARNING("You can't mix fuel mixtures!"))
return
@@ -96,10 +96,11 @@
var/fuel_amt_to_remove = Clamp(to_add.volume, 0, max_rounds - reagents.get_reagent_amount(to_add.id))
if(!fuel_amt_to_remove)
- to_chat(user, SPAN_WARNING("[O] is empty!"))
+ if(!max_rounds)
+ to_chat(user, SPAN_WARNING("[target] is empty!"))
return
- O.reagents.remove_reagent(to_add.id, fuel_amt_to_remove)
+ target.reagents.remove_reagent(to_add.id, fuel_amt_to_remove)
reagents.add_reagent(to_add.id, fuel_amt_to_remove)
playsound(loc, 'sound/effects/refill.ogg', 25, 1, 3)
caliber = to_add.name
diff --git a/code/modules/shuttle/dropship_hijack.dm b/code/modules/shuttle/dropship_hijack.dm
index 1e5e401f1e0f..ce151c14324c 100644
--- a/code/modules/shuttle/dropship_hijack.dm
+++ b/code/modules/shuttle/dropship_hijack.dm
@@ -1,3 +1,5 @@
+#define HIJACK_CRASH_SITE_OFFSET_X -5
+#define HIJACK_CRASH_SITE_OFFSET_Y -11
/datum/dropship_hijack
var/obj/docking_port/mobile/shuttle
@@ -90,9 +92,10 @@
var/obj/docking_port/stationary/marine_dropship/crash_site/target_site = new()
crash_site = target_site
- crash_site.x = target.x - 5
- crash_site.y = target.y - 11
- crash_site.z = target.z
+ var/turf/offset_target = locate(target.x + HIJACK_CRASH_SITE_OFFSET_X, target.y + HIJACK_CRASH_SITE_OFFSET_Y, target.z)
+ if(!offset_target)
+ offset_target = target // Welp the offsetting failed so...
+ target_site.forceMove(offset_target)
target_site.name = "[shuttle] crash site"
target_site.id = "crash_site_[shuttle.id]"
@@ -116,7 +119,10 @@
remaining_crash_sites -= target_ship_section
var/new_target_ship_section = pick(remaining_crash_sites)
var/turf/target = get_crashsite_turf(new_target_ship_section)
- crash_site.Move(target)
+ var/turf/offset_target = locate(target.x + HIJACK_CRASH_SITE_OFFSET_X, target.y + HIJACK_CRASH_SITE_OFFSET_Y, target.z)
+ if(!offset_target)
+ offset_target = target // Welp the offsetting failed so...
+ crash_site.forceMove(offset_target)
marine_announcement("A hostile aircraft on course for the [target_ship_section] has been successfully deterred.", "IX-50 MGAD System", logging = ARES_LOG_SECURITY)
target_ship_section = new_target_ship_section
// TODO mobs not alerted
@@ -217,3 +223,6 @@
else
CRASH("Crash site [ship_section] unknown.")
return pick(turfs)
+
+#undef HIJACK_CRASH_SITE_OFFSET_X
+#undef HIJACK_CRASH_SITE_OFFSET_Y
diff --git a/code/modules/shuttle/helpers.dm b/code/modules/shuttle/helpers.dm
index 14cfcc3cd691..1d841581faa0 100644
--- a/code/modules/shuttle/helpers.dm
+++ b/code/modules/shuttle/helpers.dm
@@ -8,7 +8,8 @@
/datum/door_controller/aggregate/Destroy(force, ...)
. = ..()
- QDEL_NULL_LIST(door_controllers)
+ QDEL_LIST_ASSOC_VAL(door_controllers)
+ door_controllers = null
/datum/door_controller/aggregate/proc/set_label(label)
for(var/datum/door_controller/single/cont in door_controllers)
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 77ba9681ebb6..7e181ed470cb 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -628,15 +628,15 @@
/obj/docking_port/mobile/proc/intoTheSunset()
// Loop over mobs
- for(var/t in return_turfs())
- var/turf/T = t
- for(var/mob/living/L in T.GetAllContents())
+ for(var/turf/turf as anything in return_turfs())
+ for(var/mob/living/mob in turf.GetAllContents())
// Ghostize them and put them in nullspace stasis (for stat & possession checks)
- //L.notransform = TRUE
- var/mob/dead/observer/O = L.ghostize(FALSE)
- if(O)
- O.timeofdeath = world.time
- L.moveToNullspace()
+ //mob.notransform = TRUE
+ var/mob/dead/observer/obs = mob.ghostize(FALSE)
+ if(obs)
+ obs.timeofdeath = world.time
+ obs.client?.larva_queue_time = world.time
+ mob.moveToNullspace()
// Now that mobs are stowed, delete the shuttle
jumpToNullSpace()
diff --git a/html/changelogs/AutoChangeLog-pr-3666.yml b/html/changelogs/AutoChangeLog-pr-3666.yml
new file mode 100644
index 000000000000..d7d8860c237e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3666.yml
@@ -0,0 +1,4 @@
+author: "Morrow"
+delete-after: True
+changes:
+ - balance: "Xenos no longer can pull dead xenos"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3683.yml b/html/changelogs/AutoChangeLog-pr-3683.yml
deleted file mode 100644
index 74f16d9344af..000000000000
--- a/html/changelogs/AutoChangeLog-pr-3683.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "harryob"
-delete-after: True
-changes:
- - server: "server's can now support using a cdn for web assets"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3717.yml b/html/changelogs/AutoChangeLog-pr-3717.yml
new file mode 100644
index 000000000000..6d6327ea63a7
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3717.yml
@@ -0,0 +1,4 @@
+author: "Drathek"
+delete-after: True
+changes:
+ - bugfix: "Fixed the crashsite offset for a hijack shuttle that gets deterred by the MGAD System"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3718.yml b/html/changelogs/AutoChangeLog-pr-3718.yml
new file mode 100644
index 000000000000..41f5322a2493
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3718.yml
@@ -0,0 +1,4 @@
+author: "TheGamerdk"
+delete-after: True
+changes:
+ - balance: "Queen boosted building no longer has 2 second cooldown when far from hive"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3723.yml b/html/changelogs/AutoChangeLog-pr-3723.yml
new file mode 100644
index 000000000000..987b7eeec708
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3723.yml
@@ -0,0 +1,4 @@
+author: "TheGamerdk"
+delete-after: True
+changes:
+ - bugfix: "Communications intel objective now actually works"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3730.yml b/html/changelogs/AutoChangeLog-pr-3730.yml
new file mode 100644
index 000000000000..9ae18e6bc788
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3730.yml
@@ -0,0 +1,4 @@
+author: "fira"
+delete-after: True
+changes:
+ - bugfix: "Fixed a MC crash related to NPC huggers rebounding logic."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3731.yml b/html/changelogs/AutoChangeLog-pr-3731.yml
new file mode 100644
index 000000000000..21fd76664d2b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3731.yml
@@ -0,0 +1,4 @@
+author: "blackdragonTOW"
+delete-after: True
+changes:
+ - maptweak: "Added a small light to unlit rooms."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3736.yml b/html/changelogs/AutoChangeLog-pr-3736.yml
new file mode 100644
index 000000000000..c1eba0beabfd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3736.yml
@@ -0,0 +1,4 @@
+author: "Morrow"
+delete-after: True
+changes:
+ - rscdel: "Removed toxin mags on shivas"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-3742.yml b/html/changelogs/AutoChangeLog-pr-3742.yml
new file mode 100644
index 000000000000..7319ac52f8d9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-3742.yml
@@ -0,0 +1,6 @@
+author: "SpartanBobby"
+delete-after: True
+changes:
+ - maptweak: "Minor decal changes to LV522"
+ - maptweak: "Buffed sec armory on LV522"
+ - maptweak: "LV522 Breaching charge moved to the PROP APC made UNACIDABLE"
\ No newline at end of file
diff --git a/html/changelogs/archive/2023-06.yml b/html/changelogs/archive/2023-06.yml
index 53b779e0fab1..71aeb035f4b8 100644
--- a/html/changelogs/archive/2023-06.yml
+++ b/html/changelogs/archive/2023-06.yml
@@ -315,3 +315,71 @@
- bugfix: Flashlight gun attachments turn off when they should
sg2002:
- bugfix: XM88 now correctly notifies the user on the hit streak end.
+2023-06-23:
+ harryob:
+ - server: server's can now support using a cdn for web assets
+2023-06-24:
+ Drathek:
+ - rscadd: The selection to become a xeno larva is now based on timeofdeath rather
+ than random and also sends a message to all candidates when the queue moves.
+ Playing as a facehugger or on admin z-levels (thunderdome) will not affect your
+ relative place in queue. The join xeno action will also display the last queue
+ message for you when you allow xeno candidacy.
+ - bugfix: Fixed gibbed humans not properly setting their timeofdeath when on an
+ admin z-level.
+ - bugfix: Fixed a bad del on shuttle doors when a shuttle deletes (such as intoTheSunset).
+ - bugfix: Fixed erroneous is empty messages when inserting tanks into a flamer pack.
+ - soundadd: Added the refill sfx when using the empty canister verb on flamer tanks.
+ Morrow:
+ - bugfix: Prevented some light bugs with devouring marines
+ - bugfix: Fixed two gun light attachment issues
+ Steelpoint:
+ - rscadd: Synthetics may now vend Ponchos.
+ realforest2001:
+ - admin: Improves logging for admin deadchat.
+ - admin: Adds logging for xeno evolution.
+ theselfish:
+ - qol: Added the Corpsman Helmet to Req's surplus vendor.
+2023-06-25:
+ Sargeantmuffinman:
+ - rscadd: Added two new emails to the Almayer's personal computers and rewrote 3
+ other emails.
+ Segrain:
+ - bugfix: Hive core now always correctly absorbs hive's dead larvas.
+ - bugfix: Preview dummy in character setup once again can be rotated.
+2023-06-26:
+ Drathek:
+ - bugfix: Fixed the yank object verb not testing who is actually performing the
+ action has a free hand
+ - rscadd: Player facehugging gets 2nd dibs on the burst (the original marine gets
+ first dibs still)
+ - bugfix: Fix a possibility of banished larva refunding double the larva
+ blackdragonTOW:
+ - spellcheck: multiple typos and grammar changes in the round start tooltips.
+2023-06-27:
+ TeDGamer Drathek:
+ - bugfix: Boilers from other hives generate proper colored IFFed gas
+ - bugfix: Fixes some death causes with boiler acid gas (for bombard, shroud, and
+ gibbing), neurotoxin gas/stabs, acid shotgun, and xeno spits
+ - balance: Neurotoxin stops processing only in dead mobs
+ TheGamerdk:
+ - bugfix: The game will no longer falsely claim there is no CO
+ realforest2001:
+ - rscadd: Changed min and max Predator ages from 20 - 10000 to 175 - 3000
+2023-06-28:
+ Drathek:
+ - admin: Mentors can now eavesdrop on mentor messages, and the responder to a mhelp
+ doesn't get double logging from eavesdropping.
+ Morrow, Thwomper:
+ - rscadd: Added three new uniforms and a snow jacket for the CL.
+ TheGamerdk:
+ - balance: Cluster OBs will now no longer hit turfs that have gotten OB protection
+ after the initial OB was fired.
+ ihatethisengine:
+ - balance: larva surge is limited by marines/xenos ratio
+ - bugfix: xenos no longer get free larva from abandoned facehuggers during hijack
+ - balance: explosive barricade upgrade provides better protection against explosions
+ (25% to 50%)
+ - balance: explosive barricade upgrade provides strong protection against brute-based
+ projectiles (50%)
+ - balance: explosive barricade upgrade provides strong protection against fire (50%)
diff --git a/icons/mob/humans/onmob/suit_0.dmi b/icons/mob/humans/onmob/suit_0.dmi
index 4d63b7abd7f1..5cccc4c2e0e0 100644
Binary files a/icons/mob/humans/onmob/suit_0.dmi and b/icons/mob/humans/onmob/suit_0.dmi differ
diff --git a/icons/mob/humans/onmob/uniform_0.dmi b/icons/mob/humans/onmob/uniform_0.dmi
index 4973a59a69c4..cac9869c9034 100644
Binary files a/icons/mob/humans/onmob/uniform_0.dmi and b/icons/mob/humans/onmob/uniform_0.dmi differ
diff --git a/icons/obj/items/clothing/suits.dmi b/icons/obj/items/clothing/suits.dmi
index 47d06bc2cc10..cff4b5d48c17 100644
Binary files a/icons/obj/items/clothing/suits.dmi and b/icons/obj/items/clothing/suits.dmi differ
diff --git a/icons/obj/items/clothing/uniforms.dmi b/icons/obj/items/clothing/uniforms.dmi
index 132f193fbf40..254c9e8b67c9 100644
Binary files a/icons/obj/items/clothing/uniforms.dmi and b/icons/obj/items/clothing/uniforms.dmi differ
diff --git a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm
index 2ca8c7083cfa..a431aa368702 100644
--- a/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm
+++ b/maps/map_files/Ice_Colony_v3/Shivas_Snowball.dmm
@@ -8762,8 +8762,6 @@
"cSn" = (
/obj/structure/closet/secure_closet/guncabinet,
/obj/item/weapon/gun/rifle/m41aMK1,
-/obj/item/ammo_magazine/rifle/m41aMK1/toxin,
-/obj/item/ammo_magazine/rifle/m41aMK1/toxin,
/obj/item/ammo_magazine/rifle/m41aMK1,
/obj/item/ammo_magazine/rifle/m41aMK1,
/obj/item/ammo_magazine/rifle/m41aMK1,
@@ -19747,7 +19745,6 @@
pixel_x = -10;
pixel_y = 13
},
-/obj/item/ammo_magazine/rifle/toxin,
/turf/open/asphalt/cement,
/area/shiva/interior/warehouse)
"oYw" = (
@@ -21979,7 +21976,6 @@
/area/shiva/interior/colony/research_hab)
"ril" = (
/obj/structure/closet/secure_closet/freezer/fridge,
-/obj/item/ammo_magazine/rifle/m41aMK1/toxin,
/turf/open/floor/shiva{
icon_state = "multi_tiles"
},
@@ -24859,7 +24855,6 @@
},
/area/shiva/interior/colony/medseceng)
"ukJ" = (
-/obj/item/ammo_magazine/rifle/m41aMK1/toxin,
/turf/open/floor/shiva,
/area/shiva/interior/colony/research_hab)
"ukU" = (
diff --git a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm
index 01df2b7e136e..34eecc574c9c 100644
--- a/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm
+++ b/maps/map_files/LV522_Chances_Claim/LV522_Chances_Claim.dmm
@@ -998,8 +998,8 @@
/obj/structure/closet/crate/weapon,
/obj/item/weapon/gun/rifle/l42a,
/obj/item/weapon/gun/rifle/l42a,
-/obj/item/ammo_magazine/rifle/l42a,
-/obj/item/ammo_magazine/rifle/l42a,
+/obj/item/weapon/gun/rifle/l42a,
+/obj/item/weapon/gun/rifle/l42a,
/turf/open/floor/prison,
/area/lv522/indoors/a_block/security)
"aIp" = (
@@ -4661,12 +4661,11 @@
/turf/open/floor/corsat,
/area/lv522/atmos/east_reactor/west)
"cKF" = (
-/obj/structure/cargo_container/kelland/left,
/obj/item/explosive/plastic/breaching_charge{
- layer = 5
+ unacidable = 1
},
/turf/open/auto_turf/shale/layer0,
-/area/lv522/outdoors/colony_streets/east_central_street)
+/area/lv522/outdoors/n_rockies)
"cKG" = (
/turf/closed/wall/strata_ice/dirty,
/area/lv522/outdoors/nw_rockies)
@@ -9745,6 +9744,21 @@
icon_state = "plate"
},
/area/lv522/atmos/east_reactor/east)
+"eWF" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/firstaid/adv{
+ layer = 3.1;
+ pixel_x = 3;
+ pixel_y = -2
+ },
+/obj/structure/surface/rack,
+/obj/item/storage/firstaid/adv{
+ pixel_y = 14
+ },
+/turf/open/floor/prison{
+ icon_state = "darkredfull2"
+ },
+/area/lv522/indoors/a_block/security)
"eWK" = (
/obj/structure/pipes/standard/manifold/hidden/green{
dir = 4
@@ -10683,6 +10697,12 @@
/obj/item/prop/colony/used_flare,
/turf/open/floor/prison,
/area/lv522/indoors/a_block/dorms)
+"fuw" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "W"
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"fuQ" = (
/obj/structure/pipes/standard/manifold/hidden/green{
dir = 1
@@ -13641,6 +13661,7 @@
"gLV" = (
/obj/structure/prop/server_equipment/yutani_server/broken{
density = 0;
+ layer = 3.5;
pixel_y = 16
},
/obj/effect/decal/cleanable/dirt,
@@ -13746,10 +13767,9 @@
/area/lv522/atmos/east_reactor)
"gOC" = (
/obj/structure/pipes/vents/pump,
-/obj/structure/surface/rack,
-/obj/item/weapon/shield/riot,
-/obj/item/weapon/classic_baton,
/obj/effect/decal/cleanable/dirt,
+/obj/structure/surface/table/almayer,
+/obj/item/ammo_box/magazine/shotgun/beanbag/empty,
/turf/open/floor/prison{
icon_state = "darkredfull2"
},
@@ -19773,10 +19793,10 @@
},
/area/lv522/indoors/c_block/cargo)
"jmd" = (
-/obj/item/weapon/shield/riot,
-/obj/item/weapon/classic_baton,
-/obj/structure/surface/rack,
/obj/effect/decal/cleanable/dirt,
+/obj/structure/surface/rack,
+/obj/item/weapon/gun/revolver/cmb,
+/obj/item/ammo_magazine/revolver/cmb,
/turf/open/floor/prison{
icon_state = "darkredfull2"
},
@@ -20728,13 +20748,13 @@
/turf/open/auto_turf/shale/layer1,
/area/lv522/outdoors/colony_streets/north_west_street)
"jGj" = (
-/obj/structure/surface/rack,
-/obj/item/weapon/gun/revolver/cmb,
-/obj/item/ammo_magazine/revolver/cmb,
-/turf/open/floor/prison{
- icon_state = "darkredfull2"
+/obj/effect/decal/cleanable/dirt,
+/obj/item/maintenance_jack,
+/turf/open/floor/strata{
+ dir = 4;
+ icon_state = "white_cyan1"
},
-/area/lv522/indoors/a_block/security)
+/area/lv522/indoors/a_block/corpo)
"jGm" = (
/obj/structure/barricade/handrail{
dir = 4
@@ -21364,6 +21384,10 @@
},
/turf/closed/wall/mineral/bone_resin,
/area/lv522/oob)
+"jUg" = (
+/obj/item/ammo_box/magazine/l42a/ap/empty,
+/turf/open/floor/prison,
+/area/lv522/indoors/a_block/security)
"jUk" = (
/turf/open/floor/prison{
dir = 10;
@@ -22373,6 +22397,13 @@
/obj/structure/platform_decoration{
dir = 4
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "S"
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "E";
+ pixel_x = 1
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -25126,6 +25157,13 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/prison,
/area/lv522/indoors/a_block/dorms)
+"lsG" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "E";
+ pixel_x = 1
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"lsR" = (
/obj/structure/fence{
layer = 2.9
@@ -26235,6 +26273,13 @@
icon_state = "floor_marked"
},
/area/lv522/indoors/lone_buildings/outdoor_bot)
+"lUh" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "N";
+ pixel_y = 1
+ },
+/turf/open/auto_turf/shale/layer1,
+/area/lv522/outdoors/colony_streets/north_west_street)
"lUi" = (
/obj/structure/bed/chair/comfy{
dir = 1
@@ -27097,6 +27142,12 @@
/obj/structure/platform_decoration{
dir = 8
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "S"
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "W"
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -27108,6 +27159,13 @@
icon_state = "darkpurplefull2"
},
/area/lv522/indoors/a_block/dorms)
+"mnU" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/item/ammo_magazine/rifle/l42a/extended{
+ current_rounds = 0
+ },
+/turf/open/floor/prison,
+/area/lv522/indoors/a_block/security/glass)
"mnX" = (
/obj/item/weapon/gun/rifle/m41a{
current_mag = null
@@ -28488,6 +28546,13 @@
/area/lv522/outdoors/colony_streets/south_east_street)
"mUG" = (
/obj/structure/platform_decoration,
+/obj/effect/decal/warning_stripes{
+ icon_state = "N";
+ pixel_y = 1
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "W"
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -28507,6 +28572,10 @@
/area/lv522/indoors/a_block/kitchen)
"mVi" = (
/obj/structure/platform,
+/obj/effect/decal/warning_stripes{
+ icon_state = "N";
+ pixel_y = 1
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -29045,6 +29114,9 @@
/obj/structure/platform{
dir = 4
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "W"
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -30273,21 +30345,14 @@
/turf/open/asphalt/cement,
/area/lv522/outdoors/colony_streets/north_street)
"nKo" = (
-/obj/structure/surface/table/almayer,
-/obj/structure/machinery/door_control/brbutton/alt{
- id = "Secure_Master_Armoury";
- name = "remote door-control"
- },
-/obj/item/limb/hand/l_hand{
- dir = 1;
- pixel_x = 9;
- pixel_y = 3
+/obj/structure/pipes/standard/simple/hidden/green{
+ dir = 4
},
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/prison{
- icon_state = "darkredfull2"
+/obj/item/weapon/gun/rifle/l42a{
+ current_mag = null
},
-/area/lv522/indoors/a_block/security)
+/turf/open/floor/plating/plating_catwalk/prison,
+/area/lv522/indoors/a_block/security/glass)
"nKK" = (
/obj/structure/platform{
dir = 8
@@ -30376,6 +30441,7 @@
"nMt" = (
/obj/structure/surface/table/almayer,
/obj/effect/decal/cleanable/dirt,
+/obj/item/ammo_box/magazine/l42a,
/turf/open/floor/prison{
icon_state = "darkredfull2"
},
@@ -34987,6 +35053,14 @@
/obj/structure/platform_decoration{
dir = 1
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "N";
+ pixel_y = 1
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "E";
+ pixel_x = 1
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -36438,6 +36512,13 @@
},
/turf/open/floor/plating,
/area/lv522/outdoors/colony_streets/central_streets)
+"qma" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "NW-out";
+ pixel_y = 1
+ },
+/turf/open/auto_turf/shale/layer1,
+/area/lv522/outdoors/colony_streets/north_west_street)
"qml" = (
/obj/structure/pipes/standard/simple/hidden/green{
dir = 4
@@ -36686,9 +36767,17 @@
/turf/open/floor/plating/plating_catwalk/prison,
/area/lv522/indoors/a_block/bridges/op_centre)
"qqD" = (
-/obj/item/ammo_box/magazine/shotgun/buckshot/empty,
/obj/structure/surface/table/almayer,
/obj/effect/decal/cleanable/dirt,
+/obj/structure/machinery/door_control/brbutton/alt{
+ id = "Sec-Armoury-Lockdown";
+ name = "remote door-control"
+ },
+/obj/item/limb/hand/l_hand{
+ dir = 1;
+ pixel_x = 9;
+ pixel_y = 3
+ },
/turf/open/floor/prison{
icon_state = "darkredfull2"
},
@@ -36816,6 +36905,10 @@
/obj/structure/platform{
dir = 8
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "E";
+ pixel_x = 1
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -37353,6 +37446,14 @@
icon_state = "blue_plate"
},
/area/lv522/indoors/a_block/hallway)
+"qDl" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "NE-out";
+ pixel_x = 1;
+ pixel_y = 1
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"qDr" = (
/obj/item/ammo_magazine/rifle/heap{
current_rounds = 0
@@ -39297,6 +39398,12 @@
icon_state = "floor_plate"
},
/area/lv522/indoors/a_block/hallway)
+"rmX" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "S"
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"rng" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/machinery/camera/autoname{
@@ -39624,12 +39731,8 @@
/turf/open/floor/prison,
/area/lv522/indoors/a_block/dorms)
"ruj" = (
-/obj/structure/machinery/door_control{
- id = "UD6";
- name = "Cargo Shutter Control"
- },
/turf/closed/shuttle/dropship2/tornado/typhoon{
- icon_state = "53"
+ icon_state = "59"
},
/area/lv522/landing_zone_forecon/UD6_Typhoon)
"rus" = (
@@ -40104,18 +40207,12 @@
},
/area/lv522/landing_zone_forecon/UD6_Typhoon)
"rDu" = (
-/obj/structure/closet/crate/ammo,
-/obj/item/ammo_magazine/m56d,
-/obj/item/ammo_magazine/m56d,
-/obj/item/device/m56d_gun,
-/obj/structure/barricade/handrail{
- dir = 4
- },
-/obj/structure/barricade/handrail{
- dir = 8
+/obj/structure/machinery/door_control{
+ id = "UD6";
+ name = "Cargo Shutter Control"
},
-/turf/open/shuttle/dropship{
- icon_state = "rasputin15"
+/turf/closed/shuttle/dropship2/tornado/typhoon{
+ icon_state = "53"
},
/area/lv522/landing_zone_forecon/UD6_Typhoon)
"rDz" = (
@@ -41363,6 +41460,9 @@
/obj/structure/machinery/light{
dir = 8
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "W"
+ },
/turf/open/auto_turf/shale/layer0,
/area/lv522/outdoors/colony_streets/north_west_street)
"seA" = (
@@ -44799,6 +44899,9 @@
/obj/structure/platform{
dir = 1
},
+/obj/effect/decal/warning_stripes{
+ icon_state = "S"
+ },
/turf/open/floor/prison{
icon_state = "floor_plate"
},
@@ -47329,6 +47432,13 @@
"uAa" = (
/turf/open/floor/prison,
/area/lv522/outdoors/colony_streets/north_street)
+"uAb" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "SE-out";
+ pixel_x = 1
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"uAd" = (
/turf/open/floor/corsat{
dir = 1;
@@ -47394,7 +47504,7 @@
/turf/open/floor/prison,
/area/lv522/indoors/a_block/security)
"uDs" = (
-/obj/item/clothing/head/beret/sec/hos,
+/obj/item/clothing/head/CMB,
/obj/effect/decal/cleanable/blood,
/turf/open/floor/plating/plating_catwalk/prison,
/area/lv522/indoors/a_block/security)
@@ -47602,6 +47712,12 @@
icon_state = "blue_plate"
},
/area/lv522/indoors/a_block/hallway)
+"uGd" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "SW-out"
+ },
+/turf/open/auto_turf/shale/layer0,
+/area/lv522/outdoors/colony_streets/north_west_street)
"uGl" = (
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/prison{
@@ -54463,7 +54579,7 @@
},
/area/lv522/indoors/b_block/hydro)
"xwO" = (
-/obj/structure/cargo_container/watatsumi/leftmid,
+/obj/structure/cargo_container/seegson/left,
/turf/open/floor/prison,
/area/lv522/outdoors/colony_streets/north_west_street)
"xwZ" = (
@@ -54514,7 +54630,7 @@
/turf/open/floor/plating,
/area/lv522/indoors/c_block/mining)
"xxJ" = (
-/obj/structure/cargo_container/watatsumi/rightmid,
+/obj/structure/cargo_container/seegson/mid,
/obj/effect/decal/warning_stripes{
icon_state = "E";
pixel_x = 1
@@ -54530,7 +54646,7 @@
/turf/open/floor/prison,
/area/lv522/indoors/a_block/admin)
"xxV" = (
-/obj/structure/cargo_container/watatsumi/right,
+/obj/structure/cargo_container/seegson/right,
/turf/open/asphalt/cement{
icon_state = "cement1"
},
@@ -55007,13 +55123,16 @@
/turf/open/floor/plating,
/area/lv522/indoors/lone_buildings/engineering)
"xKc" = (
-/obj/structure/largecrate/supply/supplies/mre,
/obj/structure/barricade/handrail{
- dir = 4
+ dir = 8
},
/obj/structure/barricade/handrail{
- dir = 8
+ dir = 4
},
+/obj/structure/closet/crate/ammo,
+/obj/item/ammo_magazine/m56d,
+/obj/item/ammo_magazine/m56d,
+/obj/item/device/m56d_gun,
/turf/open/shuttle/dropship{
icon_state = "rasputin15"
},
@@ -55994,9 +56113,8 @@
},
/area/lv522/outdoors/colony_streets/north_west_street)
"ydD" = (
-/obj/item/weapon/shield/riot,
-/obj/item/weapon/classic_baton,
-/obj/structure/surface/rack,
+/obj/structure/surface/table/almayer,
+/obj/item/ammo_box/magazine/shotgun/buckshot/empty,
/turf/open/floor/prison{
icon_state = "darkredfull2"
},
@@ -64934,11 +65052,11 @@ slO
hJZ
hJZ
hJZ
-hJZ
-hJZ
-hJZ
-hJZ
-hJZ
+uAb
+lsG
+lsG
+lsG
+qDl
clY
vjG
kCJ
@@ -65161,11 +65279,11 @@ slO
hJZ
clY
hJZ
-hJZ
+rmX
xkO
xkO
xkO
-clY
+lUh
clY
clY
oTd
@@ -65388,11 +65506,11 @@ slO
hJZ
clY
clY
-hJZ
+rmX
xkO
sKj
xkO
-clY
+lUh
clY
clY
srQ
@@ -65615,11 +65733,11 @@ eUt
hJZ
hJZ
clY
-hJZ
+rmX
xkO
xWx
xkO
-clY
+lUh
clY
clY
oNQ
@@ -65842,11 +65960,11 @@ eUt
clY
hJZ
hJZ
-hJZ
+uGd
sek
-hJZ
+fuw
sek
-clY
+qma
clY
hJZ
oNQ
@@ -68540,7 +68658,7 @@ cpy
cpy
fgf
cpy
-yim
+cKF
hzA
ihy
yim
@@ -75861,8 +75979,8 @@ kRb
kBk
iJu
uDs
-uDb
-nKo
+jUg
+uVj
sjy
ogK
oud
@@ -76085,10 +76203,10 @@ wdi
sjy
sjy
jmd
-jmd
+eWF
oLW
mbF
-jGj
+jft
xbj
sjy
mNR
@@ -77214,7 +77332,7 @@ sjy
sjy
sjy
lhK
-azl
+nKo
mqH
ybt
sjy
@@ -77442,7 +77560,7 @@ sjy
sjy
lhK
azl
-mqH
+mnU
xhu
sjy
vHU
@@ -78108,7 +78226,7 @@ iPZ
uSv
jyx
uQF
-jyx
+jGj
wwy
jPw
qgr
@@ -79450,7 +79568,7 @@ saC
saC
saC
saC
-cpy
+saC
saC
ien
ien
@@ -79675,9 +79793,9 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
+saC
+saC
+saC
saC
saC
ien
@@ -79901,11 +80019,11 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
-cpy
-cpy
+saC
+saC
+saC
+saC
+saC
saC
ien
rxI
@@ -80127,11 +80245,11 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
-cpy
-cpy
+saC
+saC
+saC
+saC
+saC
saC
ien
ien
@@ -80355,10 +80473,10 @@ saC
saC
saC
saC
-cpy
-cpy
saC
-cpy
+saC
+saC
+saC
saC
saC
ien
@@ -80585,7 +80703,7 @@ saC
saC
saC
saC
-cpy
+saC
saC
ien
ien
@@ -85353,7 +85471,7 @@ saC
saC
saC
saC
-cpy
+saC
saC
saC
saC
@@ -85579,9 +85697,9 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
+saC
+saC
+saC
saC
saC
saC
@@ -85806,11 +85924,11 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
-cpy
-cpy
+saC
+saC
+saC
+saC
+saC
saC
saC
bUN
@@ -86034,11 +86152,11 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
-cpy
-cpy
+saC
+saC
+saC
+saC
+saC
ien
cGd
rtI
@@ -86262,10 +86380,10 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
-cpy
+saC
+saC
+saC
+saC
ien
rhh
rtX
@@ -86489,9 +86607,9 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
+saC
+saC
+saC
ien
ien
ien
@@ -86717,9 +86835,9 @@ saC
saC
saC
saC
-cpy
-cpy
-cpy
+saC
+saC
+saC
ien
qSH
qSH
@@ -86945,8 +87063,8 @@ saC
saC
saC
saC
-cpy
-cpy
+saC
+saC
ien
qSH
qSH
@@ -94500,7 +94618,7 @@ tTD
tTD
tSm
rnB
-cKF
+oXZ
uKR
rnB
rnB
diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm
index 7644e139bc67..63562239f4dc 100644
--- a/maps/map_files/USS_Almayer/USS_Almayer.dmm
+++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm
@@ -1007,6 +1007,9 @@
/obj/structure/closet,
/obj/item/clothing/suit/armor/riot/marine/vintage_riot,
/obj/item/clothing/head/helmet/riot/vintage_riot,
+/obj/structure/machinery/light/small{
+ dir = 1
+ },
/turf/open/floor/almayer{
icon_state = "plate"
},
@@ -4886,16 +4889,6 @@
icon_state = "orange"
},
/area/almayer/engineering/engineering_workshop/hangar)
-"apQ" = (
-/obj/structure/surface/table/reinforced/almayer_B,
-/obj/structure/machinery/door/window/southleft{
- desc = "A window, that is also a door. A windoor if you will. This one is stronger.";
- health = 500;
- name = "Reinforced Glass door";
- req_one_access_txt = "2;35"
- },
-/turf/open/floor/almayer,
-/area/almayer/engineering/engineering_workshop/hangar)
"apR" = (
/obj/structure/surface/rack,
/obj/item/storage/box/beakers{
@@ -6540,6 +6533,9 @@
pixel_x = 8;
pixel_y = -32
},
+/obj/structure/machinery/light/small{
+ dir = 4
+ },
/turf/open/floor/almayer{
icon_state = "plate"
},
@@ -19415,6 +19411,39 @@
icon_state = "test_floor4"
},
/area/almayer/hallways/starboard_hallway)
+"bBi" = (
+/obj/structure/closet/cabinet,
+/obj/item/clothing/under/liaison_suit/formal,
+/obj/item/clothing/under/liaison_suit,
+/obj/item/clothing/under/liaison_suit/outing,
+/obj/item/clothing/under/liaison_suit/suspenders,
+/obj/item/clothing/under/blackskirt{
+ desc = "A stylish skirt, in a business-black and red colour scheme.";
+ name = "liaison's skirt"
+ },
+/obj/item/clothing/under/suit_jacket/charcoal{
+ desc = "A professional black suit and blue tie. A combination popular among government agents and corporate Yes-Men alike.";
+ name = "liaison's black suit"
+ },
+/obj/item/clothing/under/suit_jacket/navy{
+ desc = "A navy suit and red tie, intended for the Almayer's finest. And accountants.";
+ name = "liaison's navy suit"
+ },
+/obj/item/clothing/under/suit_jacket/trainee,
+/obj/item/clothing/under/liaison_suit/charcoal,
+/obj/item/clothing/under/liaison_suit/outing/red,
+/obj/item/clothing/under/liaison_suit/blazer,
+/obj/item/clothing/suit/storage/snow_suit/liaison,
+/obj/item/clothing/gloves/black,
+/obj/item/clothing/gloves/marine/dress,
+/obj/item/clothing/glasses/sunglasses/big,
+/obj/item/clothing/accessory/blue,
+/obj/item/clothing/accessory/red,
+/obj/structure/machinery/status_display{
+ pixel_x = -32
+ },
+/turf/open/floor/wood/ship,
+/area/almayer/command/corporateliason)
"bBl" = (
/obj/structure/machinery/light{
dir = 4
@@ -20040,22 +20069,6 @@
icon_state = "orange"
},
/area/almayer/engineering/lower_engineering)
-"bEk" = (
-/obj/structure/machinery/door/airlock/almayer/marine/requisitions{
- dir = 1;
- name = "\improper Requisitions Storage"
- },
-/obj/structure/machinery/door/firedoor/border_only/almayer{
- dir = 1
- },
-/obj/structure/disposalpipe/up/almayer{
- dir = 4;
- id = "almayerlink_OT1_req"
- },
-/turf/open/floor/almayer{
- icon_state = "test_floor4"
- },
-/area/almayer/squads/req)
"bEl" = (
/obj/structure/machinery/computer/supply_drop_console/limited,
/turf/closed/wall/almayer,
@@ -28576,6 +28589,9 @@
"cBd" = (
/obj/structure/surface/rack,
/obj/item/reagent_container/food/snacks/wrapped/chunk,
+/obj/structure/machinery/light/small{
+ dir = 4
+ },
/turf/open/floor/almayer{
icon_state = "cargo"
},
@@ -34000,6 +34016,9 @@
dir = 8
},
/obj/effect/decal/cleanable/blood,
+/obj/structure/machinery/light/small{
+ dir = 4
+ },
/turf/open/floor/almayer{
icon_state = "plate"
},
@@ -37213,14 +37232,6 @@
icon_state = "redfull"
},
/area/almayer/hull/lower_hull/l_f_s)
-"gkg" = (
-/obj/structure/disposalpipe/sortjunction{
- dir = 4;
- negdir = 4;
- posdir = 1
- },
-/turf/closed/wall/almayer,
-/area/almayer/squads/req)
"gks" = (
/obj/structure/largecrate/random/secure,
/turf/open/floor/plating,
@@ -38781,6 +38792,13 @@
/obj/structure/pipes/standard/manifold/hidden/supply,
/turf/open/floor/plating/plating_catwalk,
/area/almayer/lifeboat_pumps/north2)
+"gVA" = (
+/obj/structure/disposalpipe/down/almayer{
+ dir = 8;
+ id = "almayerlink_OT1_req"
+ },
+/turf/open/floor/almayer,
+/area/almayer/lifeboat_pumps/south1)
"gVF" = (
/obj/structure/pipes/standard/manifold/hidden/supply{
dir = 1
@@ -38810,6 +38828,12 @@
icon_state = "plate"
},
/area/almayer/hull/lower_hull/l_f_p)
+"gXh" = (
+/obj/structure/machinery/light/small{
+ dir = 8
+ },
+/turf/open/floor/plating/plating_catwalk,
+/area/almayer/hull/upper_hull/u_m_s)
"gXl" = (
/obj/structure/closet/secure_closet/personal/cabinet{
req_access_txt = "5"
@@ -39088,6 +39112,12 @@
icon_state = "plate"
},
/area/almayer/living/cryo_cells)
+"hcC" = (
+/obj/structure/disposalpipe/up/almayer{
+ id = "almayerlink_OT_req"
+ },
+/turf/closed/wall/almayer,
+/area/almayer/engineering/engineering_workshop/hangar)
"hcI" = (
/obj/structure/machinery/cryopod{
pixel_y = 6
@@ -39152,12 +39182,6 @@
icon_state = "plate"
},
/area/almayer/hull/lower_hull/l_f_s)
-"hdV" = (
-/obj/structure/disposalpipe/segment{
- dir = 4
- },
-/turf/open/floor/almayer,
-/area/almayer/lifeboat_pumps/south1)
"hee" = (
/turf/open/floor/almayer{
dir = 4;
@@ -42601,13 +42625,6 @@
icon_state = "silver"
},
/area/almayer/command/cichallway)
-"iJH" = (
-/obj/structure/disposalpipe/down/almayer{
- dir = 4;
- id = "almayerlink_OT_req"
- },
-/turf/open/floor/almayer,
-/area/almayer/lifeboat_pumps/south1)
"iJS" = (
/obj/structure/machinery/cm_vending/gear/tl{
density = 0;
@@ -42920,13 +42937,6 @@
icon_state = "plate"
},
/area/almayer/hull/lower_hull/l_m_s)
-"iRh" = (
-/obj/structure/disposalpipe/down/almayer{
- dir = 8;
- id = "almayerlink_OT1_req"
- },
-/turf/open/floor/almayer,
-/area/almayer/lifeboat_pumps/south1)
"iRr" = (
/obj/structure/machinery/light{
dir = 1
@@ -45149,6 +45159,16 @@
icon_state = "plate"
},
/area/almayer/living/bridgebunks)
+"jUn" = (
+/obj/structure/surface/table/reinforced/almayer_B,
+/obj/structure/machinery/door/window/southleft{
+ desc = "A window, that is also a door. A windoor if you will. This one is stronger.";
+ health = 500;
+ name = "Reinforced Glass door";
+ req_one_access_txt = "2;35"
+ },
+/turf/open/floor/almayer,
+/area/almayer/engineering/engineering_workshop/hangar)
"jUs" = (
/obj/effect/decal/warning_stripes{
icon_state = "NE-out";
@@ -47857,6 +47877,12 @@
/obj/structure/pipes/standard/simple/hidden/supply,
/turf/open/floor/almayer,
/area/almayer/shipboard/navigation)
+"ley" = (
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/turf/open/floor/almayer,
+/area/almayer/lifeboat_pumps/south1)
"leY" = (
/obj/structure/bed/sofa/south/white/left,
/turf/open/floor/almayer{
@@ -49066,6 +49092,10 @@
},
/turf/open/floor/almayer,
/area/almayer/squads/alpha_bravo_shared)
+"lEW" = (
+/obj/structure/disposalpipe/segment,
+/turf/closed/wall/almayer,
+/area/almayer/engineering/engineering_workshop/hangar)
"lFb" = (
/obj/structure/pipes/standard/simple/hidden/supply{
dir = 4
@@ -51905,6 +51935,14 @@
},
/turf/open/floor/almayer,
/area/almayer/hull/upper_hull/u_f_p)
+"mYv" = (
+/obj/structure/disposalpipe/sortjunction{
+ dir = 4;
+ negdir = 4;
+ posdir = 1
+ },
+/turf/closed/wall/almayer,
+/area/almayer/squads/req)
"mYw" = (
/obj/structure/sign/safety/escapepod{
pixel_x = -17;
@@ -54054,6 +54092,22 @@
"nXP" = (
/turf/closed/wall/almayer/outer,
/area/almayer/hull/lower_hull/l_f_s)
+"nXU" = (
+/obj/structure/machinery/door/airlock/almayer/marine/requisitions{
+ dir = 1;
+ name = "\improper Requisitions Storage"
+ },
+/obj/structure/machinery/door/firedoor/border_only/almayer{
+ dir = 1
+ },
+/obj/structure/disposalpipe/up/almayer{
+ dir = 4;
+ id = "almayerlink_OT1_req"
+ },
+/turf/open/floor/almayer{
+ icon_state = "test_floor4"
+ },
+/area/almayer/squads/req)
"nYc" = (
/obj/effect/decal/warning_stripes{
icon_state = "N";
@@ -60504,6 +60558,13 @@
icon_state = "green"
},
/area/almayer/hallways/port_hallway)
+"qYC" = (
+/obj/structure/disposalpipe/down/almayer{
+ dir = 4;
+ id = "almayerlink_OT_req"
+ },
+/turf/open/floor/almayer,
+/area/almayer/lifeboat_pumps/south1)
"qYG" = (
/turf/open/floor/almayer{
icon_state = "mono"
@@ -60831,10 +60892,6 @@
icon_state = "test_floor4"
},
/area/almayer/hull/upper_hull/u_m_s)
-"rfi" = (
-/obj/structure/disposalpipe/segment,
-/turf/closed/wall/almayer,
-/area/almayer/engineering/engineering_workshop/hangar)
"rfI" = (
/obj/structure/sign/safety/airlock{
pixel_y = -32
@@ -63986,36 +64043,6 @@
icon_state = "silvercorner"
},
/area/almayer/hallways/aft_hallway)
-"sDL" = (
-/obj/structure/closet/cabinet,
-/obj/item/clothing/under/liaison_suit/formal,
-/obj/item/clothing/under/liaison_suit,
-/obj/item/clothing/under/liaison_suit/outing,
-/obj/item/clothing/under/liaison_suit/suspenders,
-/obj/item/clothing/under/blackskirt{
- desc = "A stylish skirt, in a business-black and red colour scheme.";
- name = "liaison's skirt"
- },
-/obj/item/clothing/under/suit_jacket/charcoal{
- desc = "A professional black suit and blue tie. A combination popular among government agents and corporate Yes-Men alike.";
- name = "liaison's black suit"
- },
-/obj/item/clothing/under/suit_jacket/navy{
- desc = "A navy suit and red tie, intended for the Almayer's finest. And accountants.";
- name = "liaison's navy suit"
- },
-/obj/item/clothing/under/suit_jacket/trainee,
-/obj/item/clothing/gloves/black,
-/obj/item/clothing/gloves/marine/dress,
-/obj/item/clothing/glasses/sunglasses/big,
-/obj/item/clothing/accessory/blue,
-/obj/item/clothing/accessory/red,
-/obj/item/clothing/shoes/dress,
-/obj/structure/machinery/status_display{
- pixel_x = -32
- },
-/turf/open/floor/wood/ship,
-/area/almayer/command/corporateliason)
"sDM" = (
/turf/open/floor/almayer{
dir = 9;
@@ -67350,12 +67377,6 @@
},
/turf/open/floor/plating/plating_catwalk,
/area/almayer/lifeboat_pumps/south2)
-"uda" = (
-/obj/structure/disposalpipe/up/almayer{
- id = "almayerlink_OT_req"
- },
-/turf/closed/wall/almayer,
-/area/almayer/engineering/engineering_workshop/hangar)
"udi" = (
/turf/open/floor/almayer{
icon_state = "red"
@@ -70400,6 +70421,14 @@
icon_state = "dark_sterile"
},
/area/almayer/engineering/laundry)
+"vqO" = (
+/obj/structure/machinery/light/small{
+ dir = 4
+ },
+/turf/open/floor/almayer{
+ icon_state = "plate"
+ },
+/area/almayer/hull/upper_hull/u_a_p)
"vqW" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -73623,6 +73652,9 @@
desc = "A small coin, bearing the falling falcons insignia.";
name = "falling falcons challenge coin"
},
+/obj/structure/machinery/light/small{
+ dir = 8
+ },
/turf/open/floor/almayer{
icon_state = "plate"
},
@@ -103218,8 +103250,8 @@ gfW
bUe
cbR
ccr
-uda
-rfi
+hcC
+lEW
aqd
bWM
bWM
@@ -103422,7 +103454,7 @@ iRx
iEb
bHa
apm
-apQ
+jUn
avT
bWM
bWM
@@ -106786,7 +106818,7 @@ yfv
bit
baw
baw
-iJH
+qYC
kwo
trb
aag
@@ -106989,7 +107021,7 @@ abg
ajC
baw
vbB
-hdV
+ley
kwo
trb
aag
@@ -107192,7 +107224,7 @@ avn
aim
baw
dBp
-iRh
+gVA
tQV
tQV
aah
@@ -110843,7 +110875,7 @@ awE
vGk
xCX
vGk
-csz
+hoX
qVM
csz
qVM
@@ -111041,7 +111073,7 @@ fAo
awE
bhM
wQv
-sDL
+bBi
awE
ieH
qVM
@@ -111655,7 +111687,7 @@ awE
csz
iid
csz
-csz
+hoX
qVM
noV
csz
@@ -117081,7 +117113,7 @@ aag
lYA
aao
aap
-aap
+gXh
aao
aap
aap
@@ -118027,7 +118059,7 @@ bNQ
bNQ
bNQ
bNQ
-bEk
+nXU
bKA
jac
bCA
@@ -118230,7 +118262,7 @@ bNP
bmD
bNP
bmD
-gkg
+mYv
doP
jac
isS
@@ -124647,7 +124679,7 @@ vuv
vuv
cxo
cxo
-cxo
+vqO
sXK
tbD
qMu
diff --git a/strings/marinetips.txt b/strings/marinetips.txt
index 620dc8710400..cf808884f1e5 100644
--- a/strings/marinetips.txt
+++ b/strings/marinetips.txt
@@ -28,7 +28,7 @@ Examine your gun and click [See combat statistics] to view information such as d
Xenomorphs who resist while on fire are stunned for some time and emit light. Use that time to catch up and finish them off!
When you have shrapnel embedded, take out your boot knife and use it in your hand to rip them out of your body.
If your weapon has a bayonet, you can manually pry open unpowered doors by clicking on them with the gun. Click on the door again to close it. UPP bayonets can pry them open quicker.
-Items on the floor can be shot. Shoot a misthrown HEDP away to save your buddies!
+Items on the floor can be shot. Shoot a poorly thrown HEDP away to save your buddies!
You can hold a bayonet or throwing knife on your mask slot. Always be prepared.
Xenomorphs can't apply huggers to marines if they're on fire.
Dragging a Nanomed onto yourself instantly gives a Health Analyzer report. Always know what's wrong with you.
@@ -46,18 +46,18 @@ By right clicking your medical belt and selecting "toggle belt mode", you can ta
You can put screwdrivers, cigarettes, and some other things in your second ear slot!
Pilots : there is one of each engine upgrade in the hangar at the start of the round, saving you the point cost of having to print out a pair of each.
You can use a hand labeler (as found in squad prep rooms) to name your equipment and make it less likely to be stolen.
-You can use a health analyser in hand (Z key) to check the last scan readout from it.
+You can use a health analyzer in hand (Z key) to check the last scan readout from it.
Holocards are a useful triage tool for doctors and medics. Ensure you assign them (examine the marine with shift-click and select an appropriate holocard) to marines who have taken damage that cannot be healed without surgery. (Hint : major organ damage or larval infection = red card!)
Escape pods are designed for only three occupants - more than that, or if a larger xenomorph is in the pod, and it will malfunction and blow up on launch.
A misloaded OB can deviate severely from the intended target area - ensure you load them correctly!
-The XO and CO are trained in powerloader use and engineering, and can load the OB.
+The XO and CO are trained in Power Loader use and engineering, and can load the OB.
You can change what your SL tracker beacon is tracking by right clicking on your headset and clicking "Switch Tracker Target".
Boilers emit light - not every glow from around the corner is friendly!
You can carry a variety of items inside your helmet - from gauze and cigarettes to flares and screwdrivers.
CIC staff can track every USCM-aligned person via the suit sensors console and overwatch console - useful for finding escaped prisoners or dead marines.
When the M7 RPG is fired, it creates a substantial shockwave behind it that can stun and harm marines standing too close. Watch your backblast!
Remember that you need to put a defibrillator's paddles away in order to store it.
-W-Y PMCs do not have marine IFF. Don't fire smartguns through them!
+W-Y PMCs do not have marine IFF. Don't fire Smartguns through them!
To talk on multiple radio channels at once, put a COMMA [,] before your message and add up to four prefixes. E.g, ,abcd talks on all squad channels at once.
Put .w or :w before your message to whisper. Another way to whisper is to use the verb "whisper" in the IC tab or command bar.
For Vehicle Crewmen : it is often safer to repair the parts of your APC or tank inside the vehicle than outside it.
@@ -75,13 +75,13 @@ Intel Officers can be put in a squad by going to CIC and requesting it.
Any marine can perform CPR. On dead marines, this will increase the time they have until they become unrevivable.
If you've been pounced on and your squad is unloading into the target, you can hit the 'rest' button to stay down so you don't get filled with lead after getting up.
You can check the landing zone as a marine in the status panel.
-Functioning night vision goggles can be recharged with batteries. Broken night vision goggles can be repaired by an Engineer with a screwdriver. Not the loadout ones though, those are unfixable and unchargeable.
-You can put a pistol belt on your suit slot. (Just grab a rifle instead..)
+Functioning night vision goggles can be recharged with batteries. Broken night vision goggles can be repaired by an Engineer with a screwdriver. Not the loadout ones though, those cannot be fixed.
+You can put a pistol belt on your suit slot. (Just grab a rifle instead.)
Alt-clicking the Squad Leader tracker lets you track your fireteam leader instead.
-Armor has a randomized reduction in effectiveness, and does not protect the digits. Take the wiki damage values as a best case scenario.
+Armor has a randomized reduction in effectiveness, and does not protect the digits. Take the wiki damage values as a best-case scenario.
You can click on your Security Access Tuner (multitool) in your hand to locate the area's APC if there is one.
Clicking on your sprite with help intent will let you check your body, seeing where your fractures and other wounds are.
Armor has insulative properties - taking it off will help you cool off and take less damage faster if you've been set on fire.
-Both foldable cades & plasteel cades if loosened and folded down can be transported in crates! In this way, you can use the crate as a portable breach-repair kit, or dragged (or carried via Powerloader) to an unsecure area for quick defensive set up.
+Both foldable cades & plasteel cades if loosened and folded down can be transported in crates! In this way, you can use the crate as a portable breach-repair kit, or dragged (or carried via Power Loader) to an unsecure area for quick defensive set up.
The fuel tank pouch doesn't just carry fuel for an incinerator- they can also carry full-size extinguishers. Toolbelts & tool pouches also may hold miniature extinguishers.
-The M2C heavy machinegunner belt rig can also carry C4, breaching charges, and most tools.
+The M2C heavy machine gunner belt rig can also carry C4, breaching charges, and most tools.
diff --git a/strings/metatips.txt b/strings/metatips.txt
index 4b69af764aeb..f694da02b5bf 100644
--- a/strings/metatips.txt
+++ b/strings/metatips.txt
@@ -1,13 +1,13 @@
-Remember hotkeys and marcos can be customized to your liking. Hotkeys can be accessed in your preferences, and macros can be edited in the Byond macro editor, available in the top left drop down menu (click the Byond logo in the corner of the game window).
-If you're unsure about a gameplay mechanic, use the 'mentorhelp' verb in the Admins tab to ask veteran players on the subject.
+Remember hotkeys and macros can be customized to your liking. Hotkeys can be accessed in your preferences, and macros can be edited in the Byond macro editor, available in the top left drop down menu (click the Byond logo in the corner of the game window).
+If you're unsure about a gameplay mechanic, use the 'mentorhelp' verb in the Admin tab to ask veteran players on the subject.
Try not to get too mad about dying. We’re all here to have fun.
After dying, ask yourself what you did wrong and make a mental note to not make the same mistake again.
Communication, be it from a marine to a marine, a drone to the queen, or command to everyone, is vital and information on flanks can change how the entire round plays out.
As an alien or marine, be careful of the flank, regardless of if the push is going well or stalling out.
Half of getting good is knowing to be aggressive. The other half is knowing when not to be aggressive.
-Alt-click a storage item to draw the last item in it (last non-weapon if it's a weapon belt). Middle-click a storage item to inmediately open it, and middle-click structures to attempt to vault them.
+Alt-click a storage item to draw the last item in it (last non-weapon if it's a weapon belt). Middle-click a storage item to immediately open it, and middle-click structures to attempt to vault them.
Use "North, South, West, East" when referring to locations in-game rather than "up, down, left, right".
You shouldn't ignore what your allies are up to. Sometimes they can be organizing a flank in hivemind/radio, sometimes they can be walking up behind you with a slug-loaded shotgun. Either way, it pays to be alert to what they're doing, as much to as what the enemies are.
-The Wiki (https://cm-ss13.com/wiki) is a very useful repository of information about the game, such as weapons, equipment, xenomorph castes and their strains. It may not be fully up to date the majority of the time, but the basics are usually accurate.
+The Wiki (https://cm-ss13.com/wiki) is a very useful repository of information about the game, such as weapons, equipment, xenomorph castes and their strains. It may not be fully up to date much of the time, but the basics are usually accurate.
As an observer, you may see how much remaining hijack time is left in the status panel.
Embrace the suck.
diff --git a/strings/xenotips.txt b/strings/xenotips.txt
index 4e98be577a61..2ca2964ae2d5 100644
--- a/strings/xenotips.txt
+++ b/strings/xenotips.txt
@@ -1,6 +1,6 @@
Acid pillars can be sneakily placed next to a door in order to surprise marines.
-Alien structures like clusters, walls, or pillars are absolutely vital to your victory, be it as cover or to delay and funnel marines.
-Always thank your drones and hivelords for supporting the hive!
+Alien structures like clusters, walls, or pillars are vital to your victory, be it as cover or to delay and funnel marines.
+Always thank your drones and Hivelords for supporting the hive!
Don't underestimate survivors. They have no armor but that makes them very fast, they're inherently hardier than marines and have various tricks up their sleeves.
While the Queen is de-ovied, the hive does not gain evolution points.
Try out new castes or strains that you might have passed up initially. You might find them to be surprisingly fun.
@@ -16,21 +16,21 @@ If a fellow alien is stunned, be sure to drag them to safety.
On help intent, click a xenomorph who is on fire to pat them out. This works on marines too!
Frenzy increases your speed and damage, Recovery increases your health regeneration, and Warding increases the time you have until you bleed out in critical health.
Remember that, as a Xenomorph, you can fully disable your night-vision. This helps put into perspective how hidden your position is to marines onscreen.
-You can devour bursted corpses in order to transport them to the Spawn Pool or Egg Morpher easier.
+You can devour burst corpses in order to transport them to the Spawn Pool or Egg Morpher easier.
The bigger you are, the more time it'll take to enter a tunnel.
-Drag yourself onto a hole in a wall as a medium-sized or smaller xeno to pass through it.
+Drag yourself onto a hole in a wall as a medium-sized or smaller Xeno to pass through it.
Claymores have directional explosions. Set them off early by slashing them from behind.
If you have difficulty clicking marines, try using Directional Slashing, though there's no directional slashing for abilities.
You can diagonally pounce through the corners of fire as a Lurker or Runner without getting ignited.
-When playing as xeno, consider aiming at the limbs instead of the chest. Marine armour doesn't protect the arms and legs as well as it does the body.
-As xeno, you can break Night-Vision goggles that some marines wear on their helmets. Just aim for the head and slash until the goggles shatter.
+When playing as Xeno, consider aiming at the limbs instead of the chest. Marine armor doesn't protect the arms and legs as well as it does the body.
+As Xeno, you can break Night-Vision goggles that some marines wear on their helmets. Just aim for the head and slash until the goggles shatter.
Pounces are ineffective on marines who are laying down.
-You may rest inmediately during a pounce to pounce straight through mobs. It's not very practical or useful though.
-Pouncing someone who is buckled to a chair will still stun them, but you won't jump into their tile and they will not be knocked to the grund.
-Starshell dust from said grenades is just as meltable as normal flares.
-You can join the hive as a living facehugger by clicking on the hive's eggmorpher. This works on other hives too..
-Playable facehuggers can leap onto targets with a one-second windup, but this will only infect them if they are adjacent to it. Otherwise, it will simply knock them down for a small duration.
-As a facehugger, you cannot talk in hivemind, but you can still open Hive Status and overwatch your sisters. This can be useful if you're locating other facehuggers, flanker castes, or trying to learn from experienced facehugger players.
+You may rest immediately during a pounce to pounce straight through mobs. It's not very practical or useful though.
+Pouncing someone who is buckled to a chair will still stun them, but you won't jump into their tile and they will not be knocked to the ground.
+Star shell dust from said grenades is just as meltable as normal flares.
+You can join the hive as a living Facehugger by clicking on the hive's Eggmorpher. This works on other hives too..
+Playable Facehuggers can leap onto targets with a one-second windup, but this will only infect them if they are adjacent to it. Otherwise, it will simply knock them down for a small duration.
+As a Facehugger, you cannot talk in hivemind, but you can still open Hive Status and overwatch your sisters. This can be useful if you're locating other Facehuggers, flanker castes, or trying to learn from experienced Facehugger players.
Shift-clicking the Queen indicator will tell you what area you are in, on the map.
-Resisting on a water tile will inmediately put out fires. Make sure you're alone though - It's usually better to let a friendly Xenomorph pat you out than it is to expose yourself to open water.
+Resisting on a water tile will immediately put out fires. Make sure you're alone though - It's usually better to let a friendly Xenomorph pat you out than it is to expose yourself to open water.
You can filter out the Xenomorphs displayed in hive status by health, allowing you to look only for wounded sisters.