diff --git a/citadel.dme b/citadel.dme index 91f744d9f41..3bf1db94f73 100644 --- a/citadel.dme +++ b/citadel.dme @@ -106,6 +106,7 @@ #include "code\__DEFINES\tgs.dm" #include "code\__DEFINES\tgui.dm" #include "code\__DEFINES\time.dm" +#include "code\__DEFINES\transform.dm" #include "code\__DEFINES\turfs.dm" #include "code\__DEFINES\typeids.dm" #include "code\__DEFINES\unit_tests.dm" @@ -5281,6 +5282,8 @@ #include "code\modules\species\holosphere\health.dm" #include "code\modules\species\holosphere\holosphere.dm" #include "code\modules\species\holosphere\holosphere_shell.dm" +#include "code\modules\species\holosphere\transform.dm" +#include "code\modules\species\holosphere\verbs.dm" #include "code\modules\species\outsider\celestials.dm" #include "code\modules\species\outsider\replicant.dm" #include "code\modules\species\outsider\scori.dm" diff --git a/code/__DEFINES/transform.dm b/code/__DEFINES/transform.dm new file mode 100644 index 00000000000..729731a99a5 --- /dev/null +++ b/code/__DEFINES/transform.dm @@ -0,0 +1,5 @@ +// defines for transformation states +// per the custom_transform component +#define STATE_TRANSFORMED "transformed" +#define STATE_NOT_TRANSFORMED "not_transformed" +#define STATE_UNKNOWN_TRANSFORM "unknown" diff --git a/code/datums/components/custom_transform.dm b/code/datums/components/custom_transform.dm index a879db70be2..c15246f6f75 100644 --- a/code/datums/components/custom_transform.dm +++ b/code/datums/components/custom_transform.dm @@ -30,7 +30,7 @@ owner.visible_message("[owner] [transform_text]") /datum/component/custom_transform/proc/try_transform(silent = FALSE) - if(transformed.loc == parent) + if(get_current_transform_state() == STATE_NOT_TRANSFORMED) transform(silent) return TRUE return FALSE @@ -45,8 +45,7 @@ owner.visible_message("[owner] [untransform_text]") /datum/component/custom_transform/proc/try_untransform(silent = FALSE) - var/mob/owner = parent - if(owner.loc == transformed) + if(get_current_transform_state() == STATE_TRANSFORMED) untransform(silent) return TRUE return FALSE @@ -102,3 +101,11 @@ S.mob_radio = null H.forceMove(get_turf(M)) M.transfer_client_to(H) + +/datum/component/custom_transform/proc/get_current_transform_state() + var/mob/M = parent + if(transformed.loc == M) + return STATE_NOT_TRANSFORMED + if(M.loc == transformed) + return STATE_TRANSFORMED + return STATE_UNKNOWN_TRANSFORM diff --git a/code/modules/species/holosphere/health.dm b/code/modules/species/holosphere/health.dm index 7cec17706c7..18c9466c357 100644 --- a/code/modules/species/holosphere/health.dm +++ b/code/modules/species/holosphere/health.dm @@ -1,51 +1,30 @@ -/datum/species/shapeshifter/holosphere/handle_death(var/mob/living/carbon/human/H, gibbed) - last_death_time = world.time +/datum/species/shapeshifter/holosphere/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt) + // handle_crit does not transform the shell on crit, it does everything else (the message, stun, automatic attempt to revive) + if(holosphere_shell.hologram.is_in_critical()) + handle_crit(H) + // handles when you are forced to change state between transformed/untransformed (i.e. due to dying or being in crit) + handle_transform_state() + + handle_regen(H) + +/datum/species/shapeshifter/holosphere/handle_death(var/mob/living/carbon/human/H, gibbed) if(gibbed) QDEL_NULL(holosphere_shell) return +/datum/species/shapeshifter/holosphere/proc/handle_crit(mob/living/carbon/human/H) + if(get_current_transform_state() == STATE_TRANSFORMED) + return + var/deathmsg = "Systems critically damaged. Emitters temporarily offline." - to_chat(H, deathmsg) - try_transform(force = TRUE) + to_chat(holosphere_shell, deathmsg) holosphere_shell.afflict_stun(hologram_death_duration) spawn(hologram_death_duration) try_revive(H) -/// same way shapeshifter species heals but it does not work if you have no nutrition -/datum/species/shapeshifter/holosphere/handle_environment_special(mob/living/carbon/human/H, datum/gas_mixture/environment, dt) - if(!actively_healing || H.nutrition <= 0) - return - if(H.fire_stacks >= 0 && heal_rate > 0) - if(H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss()) - var/nutrition_cost = 0 - var/nutrition_debt = H.getBruteLoss() - var/starve_mod = 1 - if(H.nutrition <= 25) - starve_mod = 0.75 - H.adjustBruteLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getBruteLoss() - - nutrition_debt = H.getFireLoss() - H.adjustFireLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getFireLoss() - - nutrition_debt = H.getOxyLoss() - H.adjustOxyLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getOxyLoss() - - nutrition_debt = H.getToxLoss() - H.adjustToxLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getToxLoss() - H.nutrition -= (heal_nutrition_multiplier * nutrition_cost) //Costs Nutrition when damage is being repaired, corresponding to the amount of damage being repaired. - H.nutrition = max(0, H.nutrition) //Ensure it's not below 0. - try_revive(H, TRUE) - -/datum/species/shapeshifter/holosphere/proc/get_revive_cost() - return max_nutrition / 4 - /datum/species/shapeshifter/holosphere/proc/can_revive(mob/living/carbon/human/H, revive_cost) - if(H.stat != DEAD) + if(H.stat != DEAD && !H.is_in_critical()) return FALSE if(holosphere_shell.stat == DEAD) return FALSE @@ -56,14 +35,35 @@ return FALSE return TRUE +/datum/species/shapeshifter/holosphere/proc/get_revive_cost() + return max_nutrition / 4 + /datum/species/shapeshifter/holosphere/proc/try_revive(mob/living/carbon/human/H, silent_failure = FALSE) var/revive_cost = get_revive_cost() if(can_revive(H, revive_cost)) H.nutrition -= revive_cost try_untransform(force = TRUE) - H.revive(full_heal = TRUE, restore_nutrition = FALSE) + if(IS_DEAD(H)) + H.revive(full_heal = TRUE, restore_nutrition = FALSE) + else + H.rejuvenate(TRUE, restore_nutrition = FALSE) var/regenmsg = "Emitters have returned online. Systems functional." to_chat(H, regenmsg) else if(!silent_failure) var/failuremsg = "Emitters unable to turn online due to insufficient battery." to_chat(holosphere_shell, failuremsg) + +/datum/species/shapeshifter/holosphere/proc/handle_regen(mob/living/carbon/human/H) + var/nutrition_cost = heal_nutrition_multiplier * heal_rate + if(H.getBruteLoss() && H.nutrition >= nutrition_cost) + H.nutrition -= nutrition_cost + H.adjustBruteLoss(-heal_rate, TRUE) + if(H.getFireLoss() && H.nutrition >= nutrition_cost) + H.nutrition -= nutrition_cost + H.adjustFireLoss(-heal_rate, TRUE) + if(H.getOxyLoss() && H.nutrition >= nutrition_cost) + H.nutrition -= nutrition_cost + H.adjustOxyLoss(-heal_rate) + if(H.getToxLoss() && H.nutrition >= nutrition_cost) + H.nutrition -= nutrition_cost + H.adjustToxLoss(-heal_rate) diff --git a/code/modules/species/holosphere/holosphere.dm b/code/modules/species/holosphere/holosphere.dm index 7660c7b0d0d..ae8e5bbcf1e 100644 --- a/code/modules/species/holosphere/holosphere.dm +++ b/code/modules/species/holosphere/holosphere.dm @@ -25,9 +25,9 @@ species_appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR | HAS_BODY_ALPHA | HAS_HAIR_ALPHA species_flags = NO_SCAN | NO_SLIP | NO_MINOR_CUT | NO_HALLUCINATION | NO_INFECT | NO_PAIN | CONTAMINATION_IMMUNE | NO_BLOOD | NO_NUTRITION_GAIN - total_health = 20 + total_health = 200 death_health = 0 - crit_health = -100 // never happens because you hit death health first, and cant go into crit while dead + crit_health = 180 // they turn into their shell at crit, so effectively they have 20 health hunger_factor = 0 // doesn't get hungry naturally, but instead when healing they use nutrition @@ -156,34 +156,6 @@ remove_chameleon_gear() -/datum/species/shapeshifter/holosphere/proc/try_transform(force = FALSE) - if(force || !IS_DEAD(holosphere_shell)) - if(holosphere_shell.hologram.incapacitated(INCAPACITATION_ALL)) - to_chat(holosphere_shell.hologram, SPAN_WARNING("You can't do that right now!")) - return - - holosphere_shell.name = holosphere_shell.hologram.name - try_exit_recharge_station() - if(transform_component.try_transform()) - holosphere_shell.hologram.drop_held_items() - holosphere_shell.regenerate_icons() - -/datum/species/shapeshifter/holosphere/proc/try_untransform(force = FALSE) - if(force || !IS_DEAD(holosphere_shell.hologram)) - try_exit_recharge_station() - transform_component.try_untransform() - -/mob/living/carbon/human/proc/disable_hologram() - set name = "Disable Hologram (Holosphere)" - set desc = "Disable your hologram." - set category = VERB_CATEGORY_IC - - var/datum/species/shapeshifter/holosphere/holosphere_species = species - if(!istype(holosphere_species)) - return - - holosphere_species.try_transform() - /datum/species/shapeshifter/holosphere/apply_survival_gear(mob/living/carbon/for_target, list/into_box, list/into_inv) into_box?.Add(/obj/item/tool/prybar/red) into_box?.Add(/obj/item/flashlight/flare/survival) @@ -204,6 +176,7 @@ SPECIES_MONKEY_TAJ, SPECIES_MONKEY_AKULA, SPECIES_MONKEY_VULPKANIN, SPECIES_MONKEY_SERGAL, SPECIES_MONKEY_NEVREAN, ) + /datum/species/shapeshifter/holosphere/proc/try_exit_recharge_station() var/obj/machinery/recharge_station/shell_station = holosphere_shell.loc var/obj/machinery/recharge_station/hologram_station = holosphere_shell.hologram.loc diff --git a/code/modules/species/holosphere/holosphere_shell.dm b/code/modules/species/holosphere/holosphere_shell.dm index a1b7cd847dd..5190eb445ea 100644 --- a/code/modules/species/holosphere/holosphere_shell.dm +++ b/code/modules/species/holosphere/holosphere_shell.dm @@ -166,6 +166,7 @@ hologram.adjust_nutrition(got) return (got * SYNTHETIC_NUTRITION_KJ_PER_UNIT) / GLOB.cellrate / SYNTHETIC_NUTRITION_INDUCER_CHEAT_FACTOR +// support the shell having accents (hissing) if the hologram has it /mob/living/simple_mob/holosphere_shell/proc/handle_hologram_shell_speech(datum/source, list/message_args) var/message = message_args["message"] var/language_name = message_args["language_name"] diff --git a/code/modules/species/holosphere/transform.dm b/code/modules/species/holosphere/transform.dm new file mode 100644 index 00000000000..574a61d20b6 --- /dev/null +++ b/code/modules/species/holosphere/transform.dm @@ -0,0 +1,41 @@ +/datum/species/shapeshifter/holosphere/proc/try_transform(force = FALSE) + if(!force && holosphere_shell.hologram.incapacitated(INCAPACITATION_ALL)) + to_chat(holosphere_shell.hologram, SPAN_WARNING("You can't do that right now!")) + return + if(force || !IS_DEAD(holosphere_shell)) + holosphere_shell.name = holosphere_shell.hologram.name + try_exit_recharge_station() + if(transform_component.try_transform()) + holosphere_shell.hologram.drop_held_items() + holosphere_shell.regenerate_icons() + +/datum/species/shapeshifter/holosphere/proc/try_untransform(force = FALSE) + if(force || (!IS_DEAD(holosphere_shell.hologram) && !holosphere_shell.hologram.is_in_critical())) + try_exit_recharge_station() + transform_component.try_untransform() + +/datum/species/shapeshifter/holosphere/proc/get_current_transform_state() + return transform_component.get_current_transform_state() + +/datum/species/shapeshifter/holosphere/proc/get_expected_transform_state(var/current_transform_state) + // if hologram is in critical, you should be in your shell + if(holosphere_shell.hologram.is_in_critical()) + return STATE_TRANSFORMED + // if hologram or shell is dead, you should be in your shell + if(IS_DEAD(holosphere_shell) || IS_DEAD(holosphere_shell.hologram)) + return STATE_TRANSFORMED + // otherwise we can be our current state + return current_transform_state + +// compares current and expected state +// transforms/untransforms to move to the expected state +/datum/species/shapeshifter/holosphere/proc/handle_transform_state() + var/current_transform_state = get_current_transform_state() + var/expected_transform_state = get_expected_transform_state(current_transform_state) + if(current_transform_state == expected_transform_state) + return + + if(expected_transform_state == STATE_TRANSFORMED) + try_transform(force = TRUE) // transform even if dead + else if(expected_transform_state == STATE_NOT_TRANSFORMED) + try_untransform(force = TRUE) // untransform even if dead diff --git a/code/modules/species/holosphere/verbs.dm b/code/modules/species/holosphere/verbs.dm new file mode 100644 index 00000000000..432bf291992 --- /dev/null +++ b/code/modules/species/holosphere/verbs.dm @@ -0,0 +1,10 @@ +/mob/living/carbon/human/proc/disable_hologram() + set name = "Disable Hologram (Holosphere)" + set desc = "Disable your hologram." + set category = VERB_CATEGORY_IC + + var/datum/species/shapeshifter/holosphere/holosphere_species = species + if(!istype(holosphere_species)) + return + + holosphere_species.try_transform()