diff --git a/code/__DEFINES/keybinding.dm b/code/__DEFINES/keybinding.dm index 9345599dab2d..2c656212ae23 100644 --- a/code/__DEFINES/keybinding.dm +++ b/code/__DEFINES/keybinding.dm @@ -167,6 +167,7 @@ #define COMSIG_KB_XENO_HIDE "keybinding_hide" #define COMSIG_KB_XENO_EVOLVE "keybinding_evolve" #define COMSIG_KB_XENO_PURCHASE_STRAIN "keybinding_purchase_strain" +#define COMSIG_KB_XENO_RESET_STRAIN "keybinding_reset_strain" // Yautja diff --git a/code/datums/keybinding/xenomorph.dm b/code/datums/keybinding/xenomorph.dm index 64acd876b49f..92c11a0d19ad 100644 --- a/code/datums/keybinding/xenomorph.dm +++ b/code/datums/keybinding/xenomorph.dm @@ -221,3 +221,18 @@ var/mob/living/carbon/xenomorph/current_xeno = user?.mob current_xeno.purchase_strain() + +/datum/keybinding/xenomorph/reset_strain + hotkey_keys = list("Unbound") + classic_keys = list("Unbound") + name = "reset_strain" + full_name = "Reset Strain" + keybind_signal = COMSIG_KB_XENO_RESET_STRAIN + +/datum/keybinding/xenomorph/reset_strain/down(client/user) + . = ..() + if(.) + return + + var/mob/living/carbon/xenomorph/current_xeno = user?.mob + current_xeno.reset_strain() diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm index 33924c8a1963..6701a2648f45 100644 --- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm @@ -309,27 +309,38 @@ SEND_SIGNAL(src, COMSIG_XENO_DEEVOLVE) + var/mob/living/carbon/xenomorph/new_xeno = transmute(newcaste) + if(new_xeno) + log_game("EVOLVE: [key_name(src)] de-evolved into [new_xeno].") + + return + +/mob/living/carbon/xenomorph/proc/transmute(newcaste) + // We have to delete the organ before creating the new xeno because all old_xeno contents are dropped to the ground on Initalize() var/obj/item/organ/xeno/organ = locate() in src if(!isnull(organ)) qdel(organ) var/level_to_switch_to = get_vision_level() var/xeno_type = GLOB.RoleAuthority.get_caste_by_text(newcaste) - var/mob/living/carbon/xenomorph/new_xeno = new xeno_type(get_turf(src), src) - + if(!istype(new_xeno)) - //Something went horribly wrong! + //Something went horribly wrong to_chat(src, SPAN_WARNING("Something went terribly wrong here. Your new xeno is null! Tell a coder immediately!")) if(new_xeno) qdel(new_xeno) - return + if(organ_value != 0) + var/obj/item/organ/xeno/organ = new() + organ.forceMove(src) + organ.research_value = organ_value + organ.caste_origin = caste_type + organ.icon_state = get_organ_icon() + return FALSE new_xeno.built_structures = built_structures.Copy() built_structures = null - log_game("EVOLVE: [key_name(src)] de-evolved into [new_xeno].") - if(mind) mind.transfer_to(new_xeno) else @@ -363,7 +374,8 @@ SSround_recording.recorder.track_player(new_xeno) qdel(src) - return + + return new_xeno /mob/living/carbon/xenomorph/proc/can_evolve(castepick, potential_queens) var/selected_caste = GLOB.xeno_datum_list[castepick]?.type diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index 236ca482a1d2..3779da33f80d 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -208,6 +208,7 @@ var/armor_integrity_modifier = 0 var/list/modifier_sources + var/next_strain_reset ////////////////////////////////////////////////////////////////// // 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 c73a1d7e66cb..431893bb014c 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 @@ -63,61 +63,15 @@ SEND_SIGNAL(target_xeno, COMSIG_XENO_DEEVOLVE) - var/obj/item/organ/xeno/organ = locate() in target_xeno - if(!isnull(organ)) - qdel(organ) + var/mob/living/carbon/xenomorph/new_xeno = target_xeno.transmute(newcaste) - var/level_to_switch_to = target_xeno.get_vision_level() - var/xeno_type = GLOB.RoleAuthority.get_caste_by_text(newcaste) + if(new_xeno) + message_admins("[key_name_admin(user_xeno)] has deevolved [key_name_admin(target_xeno)]. Reason: [reason]") + log_admin("[key_name_admin(user_xeno)] has deevolved [key_name_admin(target_xeno)]. Reason: [reason]") - //From there, the new xeno exists, hopefully - var/mob/living/carbon/xenomorph/new_xeno = new xeno_type(get_turf(target_xeno), target_xeno) + if(user_xeno.hive.living_xeno_queen && user_xeno.hive.living_xeno_queen.observed_xeno == target_xeno) + user_xeno.hive.living_xeno_queen.overwatch(new_xeno) - if(!istype(new_xeno)) - //Something went horribly wrong! - to_chat(user_xeno, SPAN_WARNING("Something went terribly wrong here. Your new xeno is null! Tell a coder immediately!")) - if(new_xeno) - qdel(new_xeno) - return - - new_xeno.built_structures = target_xeno.built_structures.Copy() - target_xeno.built_structures = null - - if(target_xeno.mind) - target_xeno.mind.transfer_to(new_xeno) - else - new_xeno.key = target_xeno.key - if(new_xeno.client) - new_xeno.client.change_view(GLOB.world_view_size) - new_xeno.client.pixel_x = 0 - new_xeno.client.pixel_y = 0 - - //Regenerate the new mob's name now that our player is inside - new_xeno.generate_name() - if(new_xeno.client) - new_xeno.set_lighting_alpha(level_to_switch_to) - - // If the player has lost the Deevolve verb before, don't allow them to do it again - if(!(/mob/living/carbon/xenomorph/verb/Deevolve in target_xeno.verbs)) - remove_verb(new_xeno, /mob/living/carbon/xenomorph/verb/Deevolve) - - new_xeno.visible_message(SPAN_XENODANGER("A [new_xeno.caste.caste_type] emerges from the husk of \the [target_xeno]."), \ - SPAN_XENODANGER("[user_xeno] makes us regress into your previous form.")) - - if(user_xeno.hive.living_xeno_queen && user_xeno.hive.living_xeno_queen.observed_xeno == target_xeno) - user_xeno.hive.living_xeno_queen.overwatch(new_xeno) - - message_admins("[key_name_admin(user_xeno)] has deevolved [key_name_admin(target_xeno)]. Reason: [reason]") - log_admin("[key_name_admin(user_xeno)] has deevolved [key_name_admin(target_xeno)]. Reason: [reason]") - - target_xeno.transfer_observers_to(new_xeno) - - if(GLOB.round_statistics && !new_xeno.statistic_exempt) - GLOB.round_statistics.track_new_participant(target_xeno.faction, -1) //so an evolved xeno doesn't count as two. - SSround_recording.recorder.stop_tracking(target_xeno) - SSround_recording.recorder.track_player(new_xeno) - - qdel(target_xeno) return /datum/action/xeno_action/onclick/remove_eggsac/use_ability(atom/A) diff --git a/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm b/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm index 18f1f892ddfa..62545ae0c39d 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm @@ -61,7 +61,6 @@ // Override with custom behaviour. return - /mob/living/carbon/xenomorph/verb/purchase_strain() set name = "Purchase Strain" set desc = "Purchase a strain for yourself" @@ -99,15 +98,46 @@ // If it applied successfully, add it to the logs. log_strain("[name] purchased strain '[strain_instance.type]'") +/mob/living/carbon/xenomorph/verb/reset_strain() + set name = "Reset Strain" + set desc = "Reset your strain" + set category = "Alien" + + // Firstly, make sure the xeno is actually able to take a strain. + if(!can_take_strain(reset=TRUE)) + return + + if(world.time < next_strain_reset) + to_chat(src, SPAN_WARNING("We lack the strength to reset our strain. We will be able to reset it in [round((next_strain_reset - world.time) / 600, 1)] minutes")) + return + + // Show the user the strain's description, and double check that they want it. + if(alert(usr, "Are you sure?", "Reset Strain", "Yes", "No") != "Yes") + return + // One more time after they confirm. + if(!can_take_strain(reset=TRUE)) + return + + var/mob/living/carbon/xenomorph/new_xeno = transmute(caste_type) + if(new_xeno) + new_xeno.xeno_jitter(1.5 SECONDS) + // If it applied successfully, add it to the logs. + log_strain("[new_xeno.name] reset their strain.") + new_xeno.next_strain_reset = world.time + 40 MINUTES + /// Is this xeno currently able to take a strain? -/mob/living/carbon/xenomorph/proc/can_take_strain() +/mob/living/carbon/xenomorph/proc/can_take_strain(reset=FALSE) if(!length(caste.available_strains) || !check_state(TRUE)) return FALSE - if(strain) + if(strain && !reset) to_chat(src, SPAN_WARNING("We have already chosen a strain.")) return FALSE + if(!strain && reset) + to_chat(src, SPAN_WARNING("You must first pick a strain before resetting it.")) + return FALSE + if(is_ventcrawling) to_chat(src, SPAN_WARNING("This place is too constraining to take a strain.")) return FALSE