diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm
index 3ee4e26a7a..8583628114 100644
--- a/code/_helpers/turfs.dm
+++ b/code/_helpers/turfs.dm
@@ -17,3 +17,18 @@
if(A.simulated)
return 0
return 1
+
+// Picks a turf without a mob from the given list of turfs, if one exists.
+// If no such turf exists, picks any random turf from the given list of turfs.
+/proc/pick_mobless_turf_if_exists(var/list/start_turfs)
+ if(!start_turfs.len)
+ return null
+
+ var/list/available_turfs = list()
+ for(var/start_turf in start_turfs)
+ var/mob/M = locate() in start_turf
+ if(!M)
+ available_turfs += start_turf
+ if(!available_turfs.len)
+ available_turfs = start_turfs
+ return pick(available_turfs)
diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm
index 9374de6a6a..c76b5fe185 100644
--- a/code/game/antagonist/alien/borer.dm
+++ b/code/game/antagonist/alien/borer.dm
@@ -45,7 +45,7 @@ var/datum/antagonist/xenos/borer/borers
var/obj/item/organ/external/head = host.get_organ("head")
borer.host = host
head.implants += borer
- borer.loc = head
+ borer.forceMove(head)
if(!borer.host_brain)
borer.host_brain = new(borer)
borer.host_brain.name = host.name
diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm
index 4603fc5d1c..08cbeebca9 100644
--- a/code/game/antagonist/alien/xenomorph.dm
+++ b/code/game/antagonist/alien/xenomorph.dm
@@ -44,4 +44,4 @@ var/datum/antagonist/xenos/xenomorphs
player.objectives += new /datum/objective/escape()
/datum/antagonist/xenos/place_mob(var/mob/living/player)
- player.loc = get_turf(pick(get_vents()))
+ player.forceMove(get_turf(pick(get_vents())))
diff --git a/code/game/antagonist/antagonist_place.dm b/code/game/antagonist/antagonist_place.dm
index db8c74a14f..b5f62868dc 100644
--- a/code/game/antagonist/antagonist_place.dm
+++ b/code/game/antagonist/antagonist_place.dm
@@ -23,4 +23,5 @@
/datum/antagonist/proc/place_mob(var/mob/living/mob)
if(!starting_locations || !starting_locations.len)
return
- mob.loc = pick(starting_locations)
\ No newline at end of file
+ var/turf/T = pick_mobless_turf_if_exists(mob)
+ mob.forceMove(T)
diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm
index 1fd3df90db..ea107824d5 100644
--- a/code/game/antagonist/antagonist_print.dm
+++ b/code/game/antagonist/antagonist_print.dm
@@ -45,7 +45,7 @@
return text
/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
- var/role = ply.special_role ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]"
+ var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]"
var/text = "
[ply.name] ([ply.key]) as \a [role] ("
if(ply.current)
if(ply.current.stat == DEAD)
diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
index 69794c9af3..0d9519504f 100644
--- a/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
+++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/HELPERS.dm
@@ -163,12 +163,14 @@
command_announcement.Announce(fulltext)
-// Proc: get_all_apcs()
+// Proc: get_unhacked_apcs()
// Parameters: None
-// Description: Returns a list of all APCs
-/proc/get_all_apcs()
+// Description: Returns a list of all unhacked APCs
+/proc/get_unhacked_apcs(var/mob/living/silicon/ai/user)
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
+ if(A.hacker && A.hacker == user)
+ continue
H.Add(A)
return H
diff --git a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
index d156e417f9..11f3c55ef5 100644
--- a/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
+++ b/code/game/gamemodes/malfunction/newmalf_ability_trees/tree_networking.dm
@@ -38,7 +38,7 @@
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
-/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_all_apcs())
+/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs(src))
set category = "Software"
set name = "Basic Encryption Hack"
set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station."
diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm
index 2afb02ffd9..c42f76623c 100644
--- a/code/modules/mob/language/language.dm
+++ b/code/modules/mob/language/language.dm
@@ -136,7 +136,7 @@
var/datum/language/new_language = all_languages[language]
- if(!istype(new_language) || new_language in languages)
+ if(!istype(new_language) || (new_language in languages))
return 0
languages.Add(new_language)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 0d4a5d77b4..d7a989756d 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -230,7 +230,7 @@
/mob/living/proc/handle_fire()
if(fire_stacks < 0)
- fire_stacks = min(0, fire_stacks++) //If we've doused ourselves in water to avoid fire, dry off slowly
+ fire_stacks = min(0, ++fire_stacks) //If we've doused ourselves in water to avoid fire, dry off slowly
if(!on_fire)
return 1
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 8e6f3207fb..f3d7ffd848 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -34,7 +34,7 @@ var/global/list/robot_modules = list(
var/list/obj/item/borg/upgrade/supported_upgrades = list()
// Bookkeeping
- var/list/added_languages = list()
+ var/list/original_languages = list()
var/list/added_networks = list()
/obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R)
@@ -69,7 +69,7 @@ var/global/list/robot_modules = list(
for(var/module in modules)
qdel(module)
for(var/synth in synths)
- qdel(synths)
+ qdel(synth)
modules.Cut()
synths.Cut()
qdel(emag)
@@ -105,14 +105,22 @@ var/global/list/robot_modules = list(
modules += O
/obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R)
+ // Stores the languages as they were before receiving the module, and whether they could be synthezized.
+ for(var/datum/language/language_datum in R.languages)
+ original_languages[language_datum] = (language_datum in R.speech_synthesizer_langs)
+
for(var/language in languages)
- if(R.add_language(language, languages[language]))
- added_languages |= language
+ R.add_language(language, languages[language])
/obj/item/weapon/robot_module/proc/remove_languages(var/mob/living/silicon/robot/R)
- for(var/language in added_languages)
+ // Clear all added languages, whether or not we originally had them.
+ for(var/language in languages)
R.remove_language(language)
- added_languages.Cut()
+
+ // Then add back all the original languages, and the relevant synthezising ability
+ for(var/original_language in original_languages)
+ R.add_language(original_language, original_languages[original_language])
+ original_languages.Cut()
/obj/item/weapon/robot_module/proc/add_camera_networks(var/mob/living/silicon/robot/R)
if(R.camera && (NETWORK_ROBOTS in R.camera.network))
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 25b321a9a7..44926a7dab 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -201,16 +201,22 @@
return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language
/mob/living/silicon/add_language(var/language, var/can_speak=1)
- if (..(language) && can_speak)
- speech_synthesizer_langs.Add(all_languages[language])
+ var/var/datum/language/added_language = all_languages[language]
+ if(!added_language)
+ return
+
+ . = ..(language)
+ if (can_speak && (added_language in languages) && !(added_language in speech_synthesizer_langs))
+ speech_synthesizer_langs += added_language
return 1
/mob/living/silicon/remove_language(var/rem_language)
- ..(rem_language)
+ var/var/datum/language/removed_language = all_languages[rem_language]
+ if(!removed_language)
+ return
- for (var/datum/language/L in speech_synthesizer_langs)
- if (L.name == rem_language)
- speech_synthesizer_langs -= L
+ ..(rem_language)
+ speech_synthesizer_langs -= removed_language
/mob/living/silicon/check_languages()
set name = "Check Known Languages"
diff --git a/interface/skin.dmf b/interface/skin.dmf
index 671573fdbc..879afcf3ae 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -71,6 +71,14 @@ macro "borghotkeymode"
name = "SOUTH+REP"
command = ".south"
is-disabled = false
+ elem
+ name = "INSERT"
+ command = "a-intent right"
+ is-disabled = false
+ elem
+ name = "DELETE"
+ command = "delete-key-pressed"
+ is-disabled = false
elem
name = "1"
command = "toggle-module 1"
@@ -103,14 +111,6 @@ macro "borghotkeymode"
name = "CTRL+4"
command = "a-intent left"
is-disabled = false
- elem
- name = "INSERT"
- command = "a-intent right"
- is-disabled = false
- elem
- name = "DELETE"
- command = "delete-key-pressed"
- is-disabled = false
elem
name = "5"
command = ".me"
@@ -359,7 +359,7 @@ macro "macro"
is-disabled = false
elem
name = "CTRL+4"
- command = "a-intent hurt"
+ command = "a-intent harm"
is-disabled = false
elem
name = "CTRL+A+REP"