diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c21d96be8a3..0166c81efec 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -376,7 +376,8 @@ text += "YES|no" if (objectives.len==0) text += "
Objectives are empty! Randomize!" - if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) ) + var/datum/changelingprofile/firstprof = changeling.stored_profiles[1] + if(changeling && changeling.stored_profiles.len && (current.real_name != firstprof.name) ) text += "
Transform to initial appearance." else text += "yes|NO" @@ -971,12 +972,13 @@ usr << "The objectives for changeling [key] have been generated. You can edit them and anounce manually." if("initialdna") - if( !changeling || !changeling.absorbed_dna.len || !istype(current, /mob/living/carbon)) + if( !changeling || !changeling.stored_profiles.len || !istype(current, /mob/living/carbon)) usr << "Resetting DNA failed!" else var/mob/living/carbon/C = current - C.dna = changeling.absorbed_dna[1] - C.real_name = C.dna.real_name + var/datum/changelingprofile/prof = changeling.stored_profiles[1] + C.dna = prof.dna + C.real_name = prof.name updateappearance(C) domutcheck(C) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 697531b40f0..42c8ca83ebf 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -232,9 +232,9 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind) var/list/stored_profiles = list() //list of datum/changelingprofile - var/list/absorbed_dna = 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/list/absorbed_dna = list() + //var/list/protected_dna = list() //dna that is not lost when capacity is otherwise full + var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation. var/absorbedcount = 1 //We would require at least 1 sample of compatible DNA to have taken on the form of a human. var/chem_charges = 20 var/chem_storage = 50 @@ -263,7 +263,7 @@ 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 + stored_profiles.len = dna_max /datum/changeling/proc/regenerate(var/mob/living/carbon/the_ling) @@ -278,7 +278,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" /datum/changeling/proc/get_dna(dna_owner) for(var/datum/changelingprofile/prof in stored_profiles) - if(dna_owner == prof.real_name) + if(dna_owner == prof.name) return prof /datum/changeling/proc/has_dna(datum/dna/tDNA) @@ -307,7 +307,11 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" return return 1 -/datum/changeling/proc/add_profile(var/mob/living/human/H) +/datum/changeling/proc/add_profile(var/mob/living/carbon/human/H, var/mob/living/carbon/user, protect = 0) + if(stored_profiles.len > dna_max) + if(!push_out_profile()) + return + var/datum/changelingprofile/prof = new() H.dna.real_name = H.real_name //Set this again, just to be sure that it's properly set. @@ -320,6 +324,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" new_dna.blood_type = H.dna.blood_type prof.dna = new_dna prof.name = H.real_name + prof.protected = protect var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store") for(var/slot in slots) @@ -329,13 +334,132 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" prof.name_list[slot] = I.name prof.appearance_list[slot] = I.appearance prof.flags_cover_list[slot] = I.flags_cover - + stored_profiles += prof -/datum/changelingprofile - name = "a bug" +/datum/changeling/proc/remove_profile(var/mob/living/carbon/human/H, force = 0) + for(var/datum/changelingprofile/prof in stored_profiles) + if(H.real_name == prof.name) + if(prof.protected && !force) + continue + stored_profiles -= prof + qdel(prof) - var/datum/dna/DNA = null +/datum/changeling/proc/get_profile_to_remove() + for(var/datum/changelingprofile/prof in stored_profiles) + if(!prof.protected) + return prof + +/datum/changeling/proc/push_out_profile() + var/datum/changelingprofile/removeprofile = get_profile_to_remove() + if(removeprofile) + stored_profiles -= removeprofile + return 1 + return 0 + +/proc/changeling_transform(var/mob/living/carbon/human/user, var/datum/changelingprofile/chosen_prof) + user.dna = chosen_prof.dna + user.real_name = chosen_prof.name + hardset_dna(user, null, null, null, null, chosen_prof.dna.species.type, chosen_prof.dna.features) + //var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store") //just here as a reference. + + //im so sorry + if(!user.head) + var/obj/item/clothing/head/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["head"] + C.name = chosen_prof.name_list["head"] + C.flags_cover = chosen_prof.flags_cover_list["head"] + user.equip_to_slot_or_del(C, slot_head) + + if(!user.wear_mask) + var/obj/item/clothing/mask/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["wear_mask"] + C.name = chosen_prof.name_list["wear_mask"] + C.flags_cover = chosen_prof.flags_cover_list["wear_mask"] + user.equip_to_slot_or_del(C, slot_wear_mask) + + if(!user.back) + var/obj/item/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["back"] + C.name = chosen_prof.name_list["back"] + user.equip_to_slot_or_del(C, slot_back) + + if(!user.wear_suit) + var/obj/item/clothing/suit/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["wear_suit"] + C.name = chosen_prof.name_list["wear_suit"] + C.flags_cover = chosen_prof.flags_cover_list["wear_suit"] + user.equip_to_slot_or_del(C, slot_wear_suit) + + if(!user.w_uniform) + var/obj/item/clothing/under/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["w_uniform"] + C.name = chosen_prof.name_list["w_uniform"] + C.flags_cover = chosen_prof.flags_cover_list["w_uniform"] + user.equip_to_slot_or_del(C, slot_w_uniform) + + if(!user.shoes) + var/obj/item/clothing/shoes/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["shoes"] + C.name = chosen_prof.name_list["shoes"] + C.flags_cover = chosen_prof.flags_cover_list["shoes"] + user.equip_to_slot_or_del(C, slot_shoes) + + if(!user.belt) + var/obj/item/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["belt"] + C.name = chosen_prof.name_list["belt"] + user.equip_to_slot_or_del(C, slot_belt) + + if(!user.gloves) + var/obj/item/clothing/gloves/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["gloves"] + C.name = chosen_prof.name_list["gloves"] + C.flags_cover = chosen_prof.flags_cover_list["gloves"] + user.equip_to_slot_or_del(C, slot_gloves) + + if(!user.glasses) + var/obj/item/clothing/glasses/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["glasses"] + C.name = chosen_prof.name_list["glasses"] + C.flags_cover = chosen_prof.flags_cover_list["glasses"] + user.equip_to_slot_or_del(C, slot_glasses) + + if(!user.ears) + var/obj/item/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["ears"] + C.name = chosen_prof.name_list["ears"] + C.flags_cover = chosen_prof.flags_cover_list["ears"] + user.equip_to_slot_or_del(C, slot_ears) + + if(!user.wear_id) + var/obj/item/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["wear_id"] + C.name = chosen_prof.name_list["wear_id"] + C.flags_cover = chosen_prof.flags_cover_list["wear_id"] + user.equip_to_slot_or_del(C, slot_wear_id) + + if(!user.s_store) + var/obj/item/changeling/C = new(user) + C.appearance = chosen_prof.appearance_list["s_store"] + C.name = chosen_prof.name_list["s_store"] + C.flags_cover = chosen_prof.flags_cover_list["s_store"] + user.equip_to_slot_or_del(C, slot_s_store) + + + updateappearance(user) + domutcheck(user) + + +/datum/changelingprofile + var/name = "a bug" + + var/protected = 0 + + var/datum/dna/dna = null var/list/name_list = list() //associative list of slotname = itemname var/list/appearance_list = list() var/list/flags_cover_list = list() + +/datum/changelingprofile/Destroy() + qdel(dna) diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index 9269dc71be1..5b045cf6efc 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -371,7 +371,7 @@ var/list/sting_paths S.on_purchase(src) var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste - mind.changeling.absorbed_dna |= C.dna + mind.changeling.add_profile(C) return 1 /datum/changeling/proc/reset() diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 2b58025ddf3..f4b0ce929cf 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -54,7 +54,7 @@ target << "You are absorbed by the changeling!" if(!changeling.has_dna(target.dna)) - changeling.absorb_dna(target, user) + changeling.add_profile(target, user) if(user.nutrition < NUTRITION_LEVEL_WELL_FED) user.nutrition = min((user.nutrition + target.nutrition), NUTRITION_LEVEL_WELL_FED) @@ -88,7 +88,7 @@ changeling.chem_charges += min(target.mind.changeling.chem_charges, changeling.chem_storage) changeling.absorbedcount += (target.mind.changeling.absorbedcount) - target.mind.changeling.absorbed_dna.len = 1 + target.mind.changeling.stored_profiles.len = 1 target.mind.changeling.absorbedcount = 0 @@ -152,9 +152,8 @@ target << "[user] tightens their grip as a painful sensation invades your body." if(!changeling.has_dna(target.dna)) - changeling.absorb_dna(target, user) - changeling.protected_dna -= user.dna - changeling.absorbed_dna -= user.dna + changeling.add_profile(target, user) + changeling.remove_profile(user) var/mob/dead/observer/ghost = target.ghostize(0) user.mind.transfer_to(target) diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm index 69a795ad9c4..74bee7886f1 100644 --- a/code/game/gamemodes/changeling/powers/hivemind.dm +++ b/code/game/gamemodes/changeling/powers/hivemind.dm @@ -31,9 +31,9 @@ var/list/datum/dna/hivemind_bank = list() /obj/effect/proc_holder/changeling/hivemind_upload/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() - for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna)) - if(!(DNA in hivemind_bank)) - names += DNA.real_name + for(var/datum/changelingprofile/prof in changeling.stored_profiles) + if(!(prof in hivemind_bank)) + names += prof.name if(names.len <= 0) user << "The airwaves already have all of our DNA." @@ -43,7 +43,7 @@ var/list/datum/dna/hivemind_bank = list() if(!chosen_name) return - var/datum/dna/chosen_dna = changeling.get_dna(chosen_name) + var/datum/changelingprofile/chosen_dna = changeling.get_dna(chosen_name) if(!chosen_dna) return @@ -62,7 +62,8 @@ 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. + var/datum/changelingprofile/first_prof = changeling.stored_profiles[1] + if(first_prof.name == user.real_name)//If our current DNA is the stalest, we gotta ditch it. user << "We have reached our capacity to store genetic information! We must transform before absorbing more." return return 1 @@ -70,9 +71,9 @@ var/list/datum/dna/hivemind_bank = list() /obj/effect/proc_holder/changeling/hivemind_download/sting_action(mob/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() - for(var/datum/dna/DNA in hivemind_bank) - if(!(DNA in changeling.absorbed_dna)) - names[DNA.real_name] = DNA + for(var/datum/changelingprofile/prof in hivemind_bank) + if(!(prof in changeling.stored_profiles)) + names[prof.name] = prof if(names.len <= 0) user << "There's no new DNA to absorb from the air." @@ -80,13 +81,11 @@ var/list/datum/dna/hivemind_bank = list() var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names if(!S) return - var/datum/dna/chosen_dna = names[S] - if(!chosen_dna) + var/datum/changelingprofile/chosen_prof = names[S] + if(!chosen_prof) return - if(changeling.absorbed_dna.len) - changeling.absorbed_dna.Cut(1,2) - changeling.store_dna(chosen_dna, user) + changeling.add_profile(chosen_prof, user) user << "We absorb the DNA of [S] from the air." feedback_add_details("changeling_powers","HD") - return 1 \ No newline at end of file + return 1 diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 999aaf47bed..de246564451 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -11,25 +11,25 @@ /obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() - for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna)) - names += "[DNA.real_name]" + for(var/datum/changelingprofile/prof in changeling.stored_profiles) + names += "[prof.name]" var/chosen_name = input("Select the target DNA: ", "Target DNA", null) as null|anything in names if(!chosen_name) return - var/datum/dna/chosen_dna = changeling.get_dna(chosen_name) - if(!chosen_dna) + var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name) + if(!chosen_prof) return if(!user || user.notransform) return 0 user << "We transform our appearance." - user.dna = chosen_dna - user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPSRC),chosen_dna.real_name) + user.humanize((TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPDAMAGE | TR_KEEPSRC), chosen_prof.name) + + changeling_transform(user, chosen_prof) changeling.purchasedpowers -= src feedback_add_details("changeling_powers","LFT") qdel(user) return 1 - diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 576a4102baa..243c5c8724f 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -171,7 +171,7 @@ /obj/effect/proc_holder/changeling/sting/extract_dna/sting_action(mob/user, mob/living/carbon/human/target) add_logs(user, target, "stung", "extraction sting") if(!(user.mind.changeling.has_dna(target.dna))) - user.mind.changeling.absorb_dna(target, user) + user.mind.changeling.add_profile(target, user) feedback_add_details("changeling_powers","ED") return 1 diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index ebbaa467fc0..5505feecf8c 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -16,6 +16,10 @@ name = "flesh" flags = NODROP +/obj/item/clothing/glasses/changeling + name = "flesh" + flags = NODROP + /obj/item/clothing/head/changeling name = "flesh" flags = NODROP @@ -50,97 +54,7 @@ if(!chosen_prof) return - user.dna = chosen_prof.dna - user.real_name = chosen_prof.name - hardset_dna(user, null, null, null, null, chosen_dna.species.type, chosen_dna.features) - var/list/slots = list("head", "wear_mask", "back", "wear_suit", "w_uniform", "shoes", "belt", "gloves", "glasses", "ears", "wear_id", "s_store") - - //im so sorry - if(!user.head) - var/obj/item/clothing/head/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["head"] - C.name = chosen_prof.name_list["head"] - C.flags_cover = chosen_prof.flags_cover_list["head"] - user.equip_to_slot_or_del(C, slot_head) - - if(!user.wear_mask) - var/obj/item/clothing/mask/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["wear_mask"] - C.name = chosen_prof.name_list["wear_mask"] - C.flags_cover = chosen_prof.flags_cover_list["wear_mask"] - user.equip_to_slot_or_del(C, slot_wear_mask) - - if(!user.back) - var/obj/item/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["back"] - C.name = chosen_prof.name_list["back"] - user.equip_to_slot_or_del(C, slot_back) - - if(!user.wear_suit) - var/obj/item/clothing/suit/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["wear_suit"] - C.name = chosen_prof.name_list["wear_suit"] - C.flags_cover = chosen_prof.flags_cover_list["wear_suit"] - user.equip_to_slot_or_del(C, slot_wear_suit) - - if(!user.w_uniform) - var/obj/item/clothing/under/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["w_uniform"] - C.name = chosen_prof.name_list["w_uniform"] - C.flags_cover = chosen_prof.flags_cover_list["w_uniform"] - user.equip_to_slot_or_del(C, slot_w_uniform) - - if(!user.shoes) - var/obj/item/clothing/shoes/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["shoes"] - C.name = chosen_prof.name_list["shoes"] - C.flags_cover = chosen_prof.flags_cover_list["shoes"] - user.equip_to_slot_or_del(C, slot_shoes) - - if(!user.belt) - var/obj/item/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["belt"] - C.name = chosen_prof.name_list["belt"] - user.equip_to_slot_or_del(C, slot_belt) - - if(!user.gloves) - var/obj/item/clothing/gloves/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["gloves"] - C.name = chosen_prof.name_list["gloves"] - C.flags_cover = chosen_prof.flags_cover_list["gloves"] - user.equip_to_slot_or_del(C, slot_gloves) - - if(!user.glasses) - var/obj/item/clothing/glasses/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["glasses"] - C.name = chosen_prof.name_list["glasses"] - C.flags_cover = chosen_prof.flags_cover_list["glasses"] - user.equip_to_slot_or_del(C, slot_glasses) - - if(!user.ears) - var/obj/item/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["ears"] - C.name = chosen_prof.name_list["ears"] - C.flags_cover = chosen_prof.flags_cover_list["ears"] - user.equip_to_slot_or_del(C, slot_ears) - - if(!user.wear_id) - var/obj/item/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["wear_id"] - C.name = chosen_prof.name_list["wear_id"] - C.flags_cover = chosen_prof.flags_cover_list["wear_id"] - user.equip_to_slot_or_del(C, slot_wear_id) - - if(!user.s_store) - var/obj/item/changeling/C = new(user) - C.appearance = chosen_prof.appearance_list["s_store"] - C.name = chosen_prof.name_list["s_store"] - C.flags_cover = chosen_prof.flags_cover_list["s_store"] - user.equip_to_slot_or_del(C, slot_s_store) - - - updateappearance(user) - domutcheck(user) + changeling_transform(user, chosen_prof) feedback_add_details("changeling_powers","TR") return 1 diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 452288e8ffd..81b671284ef 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -590,7 +590,7 @@ var/global/list/possible_items_special = list() return target_amount /datum/objective/absorb/check_completion() - if(owner && owner.changeling && owner.changeling.absorbed_dna && (owner.changeling.absorbedcount >= target_amount)) + if(owner && owner.changeling && owner.changeling.stored_profiles && (owner.changeling.absorbedcount >= target_amount)) return 1 else return 0