diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 7c9d7f4a85c..e85b3f9290f 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -79,17 +79,17 @@
var/mob/living/carbon/human/zealot_master = null
/datum/mind/proc/transfer_to(mob/living/new_character)
+ var/datum/atom_hud/antag/hud_to_transfer = antag_hud //we need this because leave_hud() will clear this list
if(!istype(new_character))
log_to_dd("## DEBUG: transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn")
if(current) //remove ourself from our old body's mind variable
current.mind = null
+ leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
nanomanager.user_transferred(current, new_character)
if(new_character.mind) //remove any mind currently in our new body's mind variable
new_character.mind.current = null
- var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list
- leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
current = new_character //link ourself to our new body
new_character.mind = src //and link our new body to ourself
transfer_antag_huds(hud_to_transfer) //inherit the antag HUD
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index d812296b916..9fb2402f889 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -224,7 +224,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
var/list/absorbed_dna = list()
var/list/absorbed_languages = list()
var/list/protected_dna = list() //DNA that is not lost when capacity is otherwise full.
- var/dna_max = 4 //How many extra DNA strands the changeling can store for transformation.
+ var/dna_max = 5 //How many total DNA strands the changeling can store for transformation.
var/absorbedcount = 1 //Would require at least 1 sample to take on the form of a human
var/chem_charges = 20
var/chem_recharge_rate = 0.5
@@ -253,7 +253,6 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
changelingID = "[honorific] [changelingID]"
else
changelingID = "[honorific] [rand(1,999)]"
- absorbed_dna.len = dna_max
/datum/changeling/proc/regenerate()
chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
@@ -265,14 +264,35 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
if(dna_owner == DNA.real_name)
return DNA
-/datum/changeling/proc/has_dna(var/datum/dna/tDNA)
+/datum/changeling/proc/find_dna(var/datum/dna/tDNA)
for(var/datum/dna/D in (absorbed_dna + protected_dna))
if(tDNA.unique_enzymes == D.unique_enzymes && tDNA.uni_identity == D.uni_identity && tDNA.species == D.species)
- return 1
+ return D
+ return null
+
+/datum/changeling/proc/has_dna(var/datum/dna/tDNA)
+ if(find_dna(tDNA))
+ return 1
return 0
+// A changeling's DNA is "stale" if their current form's DNA is the oldest DNA in a full list
+/datum/changeling/proc/using_stale_dna(var/mob/living/carbon/user)
+ var/current_dna = find_dna(user.dna)
+ if(absorbed_dna.len < dna_max)
+ return 0 // Still more room for DNA
+ if(!current_dna || !(current_dna in absorbed_dna))
+ return 1 // Oops, our current DNA was somehow not absorbed; force a transformation
+ if(absorbed_dna[1] == current_dna)
+ return 1 // Oldest DNA is the current DNA
+ return 0
+
+/datum/changeling/proc/trim_dna()
+ absorbed_dna -= null
+ if(absorbed_dna.len > dna_max)
+ absorbed_dna.Cut(1, (absorbed_dna.len - dna_max) + 1)
+
/datum/changeling/proc/can_absorb_dna(var/mob/living/carbon/user, var/mob/living/carbon/target)
- if(absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it.
+ if(using_stale_dna(user))//If our current DNA is the stalest, we gotta ditch it.
to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.")
return
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 8e8e824d85e..6d03a864692 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -73,12 +73,6 @@
return 0
return 1
-/obj/effect/proc_holder/changeling/proc/transfer_changeling_powers(var/mob/living/carbon/user, var/mob/living/carbon/target)
- if(istype(target, /mob/living/carbon)) // so we don't runtime, I don't even know why it's necessary as it needs a grab
- var/datum/changeling/c = user.mind.changeling
- var/datum/changeling/t = target.mind.changeling
- c.purchasedpowers = t.purchasedpowers
-
//used in /mob/Stat()
/obj/effect/proc_holder/changeling/proc/can_be_used_by(var/mob/user)
if(!ishuman(user))
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index 7efcb3f09a1..43f08584823 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -376,6 +376,7 @@ var/list/sting_paths
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
mind.changeling.absorbed_dna |= C.dna
+ mind.changeling.trim_dna()
return 1
//Used to dump the languages from the changeling datum into the actual mob.
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 6dbcc48dc2f..3800597709a 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -86,8 +86,6 @@
//Absorbs the target DNA.
/datum/changeling/proc/absorb_dna(mob/living/carbon/T, var/mob/user)
- if(absorbed_dna.len)
- absorbed_dna.Cut(1,2)
T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set.
var/datum/dna/new_dna = T.dna.Clone()
//Steal all of their languages!
@@ -104,4 +102,5 @@
if(E.target_real_name == new_dna.real_name)
protected_dna |= new_dna
return
- absorbed_dna |= new_dna
\ No newline at end of file
+ absorbed_dna |= new_dna
+ trim_dna()
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index 1032f84635f..0976f0da36d 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -62,7 +62,7 @@ var/list/datum/dna/hivemind_bank = list()
if(!..())
return
var/datum/changeling/changeling = user.mind.changeling
- if(changeling.absorbed_dna[1] == user.dna)//If our current DNA is the stalest, we gotta ditch it.
+ if(changeling.using_stale_dna(user))//If our current DNA is the stalest, we gotta ditch it.
to_chat(user, "We have reached our capacity to store genetic information! We must transform before absorbing more.")
return
return 1
@@ -84,8 +84,6 @@ var/list/datum/dna/hivemind_bank = list()
if(!chosen_dna)
return
- if(changeling.absorbed_dna.len)
- changeling.absorbed_dna.Cut(1,2)
changeling.store_dna(chosen_dna, user)
to_chat(user, "We absorb the DNA of [S] from the air.")
feedback_add_details("changeling_powers","HD")
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index 188c5fb437b..ce8bda64d03 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -38,10 +38,12 @@
to_chat(target, "[user] tightens their grip as a painful sensation invades your body.")
+ changeling.absorbed_dna -= changeling.find_dna(user.dna)
+ changeling.protected_dna -= changeling.find_dna(user.dna)
+ changeling.absorbedcount -= 1
if(!changeling.has_dna(target.dna))
changeling.absorb_dna(target, user)
- changeling.protected_dna -= user.dna
- changeling.absorbed_dna -= user.dna
+ changeling.trim_dna()
var/mob/dead/observer/ghost = target.ghostize(0)
user.mind.transfer_to(target)
@@ -52,6 +54,6 @@
user.Paralyse(2)
target.add_language("Changeling")
user.remove_language("Changeling")
- transfer_changeling_powers(user, target)
to_chat(target, "Our genes cry out as we swap our [user] form for [target].")
+ return 1
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index eec1b92e63d..9c880666f4e 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -82,11 +82,12 @@
// Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget().
// Calling it in the overriden Login, such as /mob/living/Login() doesn't cause this.
/mob/proc/update_interface()
- if(client)
- if(winget(src, "mainwindow.hotkey_toggle", "is-checked") == "true")
- update_hotkey_mode()
- else
- update_normal_mode()
+ spawn() // Spawn off so winget/winset don't delay callers.
+ if(client)
+ if(winget(src, "mainwindow.hotkey_toggle", "is-checked") == "true")
+ update_hotkey_mode()
+ else
+ update_normal_mode()
/mob/proc/update_hotkey_mode()
var/hotkeyname = "hotkeymode"
@@ -94,7 +95,7 @@
var/hotkeys = client.hotkeylist[client.hotkeytype]
hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]
client.hotkeyon = 1
- winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0")
+ winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0")
/mob/proc/update_normal_mode()
var/hotkeyname = "macro"
@@ -102,4 +103,4 @@
var/hotkeys = client.hotkeylist[client.hotkeytype]//get the list containing the hotkey names
hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]//get the name of the hotkey, to not clutter winset() to much
client.hotkeyon = 0
- winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5")
+ winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5")