Skip to content

Commit

Permalink
Xeno strain resetting (#7841)
Browse files Browse the repository at this point in the history
# About the pull request
Allows xenos to reset their strain, first use is free after that it can
be used every 40 minutes
<!-- Remove this text and explain what the purpose of your PR is.

Mention if you have tested your changes. If you changed a map, make sure
you used the mapmerge tool.
If this is an Issue Correction, you can type "Fixes Issue #169420" to
link the PR to the corresponding Issue number #169420.

Remember: something that is self-evident to you might not be to others.
Explain your rationale fully, even if you feel it goes without saying.
-->

# Explain why it's good for the game
Allows players to change their strain if they do not enjoy playing it
anymore or the round has went on for long enough it became basically
useless - happier players >> profit. (You could also make a point for
new players that accidently clicked a strain out of curiosity and now
want to reset it)
# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Put screenshots and videos here with an empty line between the
screenshots and the `<details>` tags.

</details>


# Changelog
:cl:
add: Xenomorphs can now reset their strain, first use is free then it
can be done once every 40 minutes.
/:cl:

---------

Co-authored-by: Zenith <[email protected]>
Co-authored-by: Blundir <[email protected]>
Co-authored-by: cmss13-ci[bot] <180991813+cmss13-ci[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Jan 6, 2025
1 parent 37c75f2 commit 43bdced
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 62 deletions.
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

0 comments on commit 43bdced

Please sign in to comment.