Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xeno strain resetting #7841

Merged
merged 11 commits into from
Jan 6, 2025
1 change: 1 addition & 0 deletions code/__DEFINES/keybinding.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
15 changes: 15 additions & 0 deletions code/datums/keybinding/xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()
27 changes: 20 additions & 7 deletions code/modules/mob/living/carbon/xenomorph/Evolution.dm
Original file line number Diff line number Diff line change
Expand Up @@ -309,27 +309,39 @@

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)
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
Expand Down Expand Up @@ -363,7 +375,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
Expand Down
1 change: 1 addition & 0 deletions code/modules/mob/living/carbon/xenomorph/Xenomorph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
var/armor_integrity_modifier = 0

var/list/modifier_sources
COOLDOWN_DECLARE(next_strain_reset)

//////////////////////////////////////////////////////////////////
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
39 changes: 36 additions & 3 deletions code/modules/mob/living/carbon/xenomorph/strains/xeno_strain.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -99,15 +98,49 @@
// 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(!COOLDOWN_FINISHED(src, 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(tgui_alert(src, "Are you sure?", "Reset Strain", list("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)
return

new_xeno.xeno_jitter(1.5 SECONDS)
// If it applied successfully, add it to the logs.
log_strain("[new_xeno.name] reset their strain.")
COOLDOWN_START(new_xeno, next_strain_reset, 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
Expand Down
Loading