diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral_ch.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral_ch.dm index 422fc6f621..05ee8802fa 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral_ch.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral_ch.dm @@ -79,3 +79,13 @@ ), autohiss_exempt = list("Vespinae")) excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_unathi) + +/datum/trait/neutral/gargoyle + name = "Gargoyle" + desc = "You turn into a statue at will, but also whenever you run out of energy. Being a statue replenishes your energy slowly." + cost = 0 + custom_only = FALSE //should this be custom only?? + +/datum/trait/neutral/gargoyle/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.LoadComponent(/datum/component/gargoyle) diff --git a/modular_chomp/code/datums/components/gargoyle.dm b/modular_chomp/code/datums/components/gargoyle.dm index b8b5f73c3e..e19737b339 100644 --- a/modular_chomp/code/datums/components/gargoyle.dm +++ b/modular_chomp/code/datums/components/gargoyle.dm @@ -8,16 +8,13 @@ var/mob/living/carbon/human/gargoyle //easy reference var/obj/structure/gargoyle/statue //another easy ref - var/fireloss - var/bruteloss - var/sleeping - var/paralysis - var/blinded - /datum/component/gargoyle/Initialize() if (!ishuman(parent)) return COMPONENT_INCOMPATIBLE - var/mob/living/carbon/human/gargoyle = parent + gargoyle = parent + gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_transformation + gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_pause + gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_checkenergy START_PROCESSING(SSprocessing, src) /datum/component/gargoyle/process() @@ -25,36 +22,74 @@ return if (paused && gargoyle.loc != paused_loc) paused = FALSE - energy -= 20 + energy = max(energy - 5, 0) if (energy > 0) if (!transformed && !paused) energy = max(0,energy-0.05) - else - paused = 0 - + else if (!transformed && isturf(gargoyle.loc)) + gargoyle.gargoyle_transformation() if (transformed) if (!statue) transformed = FALSE - statue.health = min(gargoyle.max_health + 100, statue.health + 0.5) + statue.damage(-0.5) energy = min(energy+0.3, 100) - fireloss = max(fireloss - 0.5, 0) - bruteloss = max(bruteloss - 0.5, 0) -/mob/living/carbon/human/verb/gargoyle_transformation() - set name = "Gargoyle Petrification" +/datum/component/gargoyle/proc/unpause() + if (!paused || transformed) + paused = FALSE + paused_loc = null + UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING) + return + if (gargoyle?.loc != paused_loc) + paused = FALSE + paused_loc = null + energy = max(energy - 5, 0) + if (energy == 0) + gargoyle.gargoyle_transformation() + UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING) + +//verbs or action buttons...? +/mob/living/carbon/human/proc/gargoyle_transformation() + set name = "Gargoyle - Petrification" set category = "Abilities" - set desc = "Turn yourself into (or out of) being a gargoyle." + set desc = "Turn yourself into (or back from) being a gargoyle." if (stat == DEAD) return var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) - if (comp?.cooldown > world.time) - var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS) - to_chat(src, "You can't activate that ability right now! Wait for another [round(time_to_wait,0.1)] seconds!") - + if (comp) + if (comp.energy <= 0 && isturf(loc)) + to_chat(src, "You suddenly turn into a statue as you run out of energy!") + else if (comp.cooldown > world.time) + var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS) + to_chat(src, "You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!") + return if (istype(loc, /obj/structure/gargoyle)) var/obj/structure/gargoyle/statue = loc - statue.unpetrify() + qdel(statue) else if (isturf(loc)) - var/obj/structure/gargoyle/statue = new(loc, src) \ No newline at end of file + new /obj/structure/gargoyle(loc, src) + +/mob/living/carbon/human/proc/gargoyle_pause() + set name = "Gargoyle - Pause" + set category = "Abilities" + set desc = "Pause your energy while standing still, so you don't use up any more, though you will lose a small amount upon moving again." + + if (stat) + return + + var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) + if (comp && !comp.transformed) + comp.paused = TRUE + comp.paused_loc = loc + comp.RegisterSignal(src, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause) + +/mob/living/carbon/human/proc/gargoyle_checkenergy() + set name = "Gargoyle - Check Energy" + set category = "Abilities" + set desc = "Check how much energy you have remaining as a gargoyle." + + var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) + if (comp) + to_chat(src, "You have [round(comp.energy,0.01)] energy remaining. It is currently [comp.paused ? "stable" : (comp.transformed ? "increasing" : "decreasing")].") diff --git a/modular_chomp/code/game/objects/structures/gargoyle.dm b/modular_chomp/code/game/objects/structures/gargoyle.dm index 9e5290f1bc..1379749d42 100644 --- a/modular_chomp/code/game/objects/structures/gargoyle.dm +++ b/modular_chomp/code/game/objects/structures/gargoyle.dm @@ -6,27 +6,157 @@ var/mob/living/carbon/human/gargoyle var/initial_sleep var/initial_blind + var/initial_is_shifted + var/initial_lying + var/initial_lying_prev + var/wagging + var/flapping + var/obj_integrity = 100 + var/original_int = 100 + var/max_integrity = 100 + var/stored_examine -/obj/structure/gargoyle/Initialize(var/location, var/mob/living/carbon/human/H) +/obj/structure/gargoyle/Initialize(mapload, var/mob/living/carbon/human/H) . = ..() - if (!location || !istype(H)) + if (isspace(loc) || isopenspace(loc)) + anchored = FALSE + if (!istype(H) || !isturf(H.loc)) return + var/datum/component/gargoyle/comp = H.GetComponent(/datum/component/gargoyle) + if (comp) + comp.cooldown = world.time + (15 SECONDS) + comp.statue = src + comp.transformed = TRUE + comp.paused = FALSE gargoyle = H + + max_integrity = H.getMaxHealth() + 100 + obj_integrity = H.health + 100 + original_int = obj_integrity + name = "statue of [H.name]" + desc = "A very lifelike statue of [H.name]." + stored_examine = H.examine() + description_fluff = H.get_description_fluff() + if (H.buckled) H.buckled.unbuckle_mob(H, TRUE) - H.click_intercept = src - initial_sleep = H.sleeping - intial_blind = H.eye_blind - transform = H.transform - layer = H.layer - pixel_x = H.pixel_x - pixel_y = H.pixel_y - dir = H.dir - H.disabilites |= MUTE - H.forceMove(src) - H.setBlinded(0) - H.setSleeping(0) - H.status_flags |= GODMODE - H.updatehealth() - H.canmove = 0 + icon = H.icon + copy_overlays(H) + color = list(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0)) + initial_sleep = H.sleeping + initial_blind = H.eye_blind + initial_is_shifted = H.is_shifted + transform = H.transform + layer = H.layer + pixel_x = H.pixel_x + pixel_y = H.pixel_y + dir = H.dir + initial_lying = H.lying + initial_lying_prev = H.lying_prev + H.sdisabilities |= MUTE + if (H.appearance_flags & PIXEL_SCALE) + appearance_flags |= PIXEL_SCALE + wagging = H.wagging + H.transforming = TRUE + flapping = H.flapping + H.toggle_tail(FALSE, FALSE) + H.toggle_wing(FALSE, FALSE) + H.visible_message("[H]'s skin rapidly turns to stone!", "Your skin abruptly hardens as you turn to stone!") + H.forceMove(src) + H.SetBlinded(0) + H.SetSleeping(0) + H.status_flags |= GODMODE + H.updatehealth() + H.canmove = 0 +/obj/structure/gargoyle/Destroy() + unpetrify() + . = ..() + +/obj/structure/gargoyle/get_description_info() + if (gargoyle) + if (isspace(loc) || isopenspace(loc)) + return + return "It can be [anchored ? "un" : ""]anchored with a wrench." + +/obj/structure/gargoyle/examine(mob/user) + if (gargoyle && stored_examine) + return stored_examine + return ..() + +/obj/structure/gargoyle/proc/unpetrify() + if (!gargoyle) + return + var/datum/component/gargoyle/comp = gargoyle.GetComponent(/datum/component/gargoyle) + if (comp) + comp.cooldown = world.time + (15 SECONDS) + comp.statue = null + comp.transformed = FALSE + gargoyle.forceMove(loc) + gargoyle.transform = transform + gargoyle.pixel_x = pixel_x + gargoyle.pixel_y = pixel_y + gargoyle.is_shifted = initial_is_shifted + gargoyle.dir = dir + gargoyle.lying = initial_lying + gargoyle.lying_prev = initial_lying_prev + gargoyle.toggle_tail(wagging, FALSE) + gargoyle.toggle_wing(flapping, FALSE) + gargoyle.sdisabilities &= ~MUTE //why is there no ADD_TRAIT etc here that's actually ussssed + gargoyle.status_flags &= ~GODMODE + gargoyle.SetBlinded(initial_blind) + gargoyle.SetSleeping(initial_sleep) + gargoyle.transforming = FALSE + gargoyle.canmove = 1 + gargoyle.update_canmove() + var/hurtmessage = "" + if (obj_integrity < original_int) + var/f = (original_int - obj_integrity) / 10 + for (var/x in 1 to 10) + gargoyle.adjustBruteLoss(f) + hurtmessage = " You feel your body take the damage that was dealt while being stone!" + gargoyle.updatehealth() + alpha = 0 + gargoyle.visible_message("[gargoyle]'s skin rapidly softens, returning them to normal!", "Your skin softens, freeing your movement once more![hurtmessage]") + +/obj/structure/gargoyle/return_air() + return return_air_for_internal_lifeform() + +/obj/structure/gargoyle/return_air_for_internal_lifeform(var/mob/living/lifeform) + var/air_type = /datum/gas_mixture/belly_air + if(istype(lifeform)) + air_type = lifeform.get_perfect_belly_air_type() + var/air = new air_type(1000) + return air + +/obj/structure/gargoyle/proc/damage(var/damage) + obj_integrity = min(obj_integrity-damage, max_integrity) + if(obj_integrity <= 0) + qdel(src) + +/obj/structure/gargoyle/take_damage(var/damage) + damage(damage) + +/obj/structure/gargoyle/attack_generic(var/mob/user, var/damage, var/attack_message = "hits") + user.do_attack_animation(src) + visible_message("[user] [attack_message] the [src]!") + damage(damage) + +/obj/structure/gargoyle/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if(W.is_wrench()) + if (isspace(loc) || isopenspace(loc)) + to_chat(user, "You can't anchor that here!") + anchored = FALSE + return ..() + playsound(src, W.usesound, 50, 1) + if (do_after(user, (2 SECONDS) * W.toolspeed, target = src)) + to_chat("You [anchored ? "un" : ""]anchor the [src].") + anchored = !anchored + else if (!(W.flags & NOBLUDGEON)) + user.setClickCooldown(user.get_attack_speed(W)) + if(W.damtype == BRUTE || W.damtype == BURN) + user.do_attack_animation(src) + playsound(src, W.hitsound, 50, 1) + damage(W.force) + else + return ..() \ No newline at end of file