mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 03:27:05 +01:00
Reworks the morph. Makes it a more stealth ambush oriented antag (#15208)
* Reworks the morph * Hunger points. Reproduce. Sprites. Other tweaks * vent open. Convert to spells. Valid checks. Minor tweaks * undo life hack * Icons, Fixes, No more morphed lights * Item eat fix. All eating takes 3 seconds * Add sounds * Fixes and tweaks. Pass airlock ability. Ambush screen alert * Steel review fixes * New dead morph sprite from Pewtershmitz * Pass airlock sprite provided by Pewtershmitz * No barsigns or cryo cells as mimic * Gluttany ruin change * Color fix. No forms fix * fix the stupid icons * Apply suggestions from code review Co-authored-by: dearmochi <shenesis@gmail.com> Co-authored-by: joep van der velden <15887760+farie82@users.noreply.github.com> Co-authored-by: dearmochi <shenesis@gmail.com>
This commit is contained in:
co-authored by
dearmochi
joep van der velden
parent
34b40c7860
commit
c4cda0930f
@@ -225,7 +225,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
charge_counter = charge_max
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr, make_attack_logs = TRUE) //if recharge is started is important for the trigger spells
|
||||
before_cast(targets)
|
||||
before_cast(targets, user)
|
||||
invocation()
|
||||
if(user && user.ckey && make_attack_logs)
|
||||
add_attack_logs(user, targets, "cast the spell [name]", ATKLOG_ALL)
|
||||
@@ -244,7 +244,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
if(action)
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/proc/before_cast(list/targets, mob/user)
|
||||
if(vampire_ability)
|
||||
if(!before_cast_vampire(targets))
|
||||
return
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/sound2 = 'sound/weapons/zapbang.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1, mob/living/user = usr)
|
||||
var/thearea = before_cast(targets)
|
||||
var/thearea = before_cast(targets, user)
|
||||
if(!thearea || !cast_check(FALSE, FALSE, user))
|
||||
revert_cast()
|
||||
return
|
||||
@@ -21,7 +21,7 @@
|
||||
cast(targets,thearea)
|
||||
after_cast(targets)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets, mob/user)
|
||||
var/A = null
|
||||
|
||||
if(!randomise_selection)
|
||||
@@ -35,7 +35,7 @@
|
||||
var/area/thearea = SSmapping.teleportlocs[A]
|
||||
|
||||
if(thearea.tele_proof && !istype(thearea, /area/wizard_station))
|
||||
to_chat(usr, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.")
|
||||
to_chat(user, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.")
|
||||
return
|
||||
|
||||
return thearea
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic
|
||||
name = "Mimic"
|
||||
desc = "Learn a new form to mimic or become one of your known forms"
|
||||
clothes_req = FALSE
|
||||
charge_max = 3 SECONDS
|
||||
include_user = TRUE // To change forms
|
||||
action_icon_state = "genetic_morph"
|
||||
allowed_type = /atom/movable
|
||||
auto_target_single = FALSE
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='sinister'>Click on a target to remember it's form. Click on yourself to change form.</span>"
|
||||
create_logs = FALSE
|
||||
action_icon_state = "morph_mimic"
|
||||
/// Which form is currently selected
|
||||
var/datum/mimic_form/selected_form
|
||||
/// Which forms the user can become
|
||||
var/list/available_forms = list()
|
||||
/// How many forms the user can remember
|
||||
var/max_forms = 5
|
||||
/// Which index will be overriden next when the user wants to remember another form
|
||||
var/next_override_index = 1
|
||||
/// If a message is shown when somebody examines the user from close range
|
||||
var/perfect_disguise = FALSE
|
||||
|
||||
var/static/list/black_listed_form_types = list(/obj/screen, /obj/singularity, /obj/effect, /mob/living/simple_animal/hostile/megafauna, /atom/movable/lighting_object, /obj/machinery/dna_vault,
|
||||
/obj/machinery/power/bluespace_tap, /obj/structure/sign/barsign, /obj/machinery/atmospherics/unary/cryo_cell)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/valid_target(atom/target, user)
|
||||
if(is_type_in_list(target, black_listed_form_types))
|
||||
return FALSE
|
||||
if(istype(target, /atom/movable))
|
||||
var/atom/movable/AM = target
|
||||
if(AM.bound_height > world.icon_size || AM.bound_width > world.icon_size)
|
||||
return FALSE // No multitile structures
|
||||
if(user != target && istype(target, /mob/living/simple_animal/hostile/morph))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/cast(list/targets, mob/user)
|
||||
var/atom/movable/A = targets[1]
|
||||
if(A == user)
|
||||
INVOKE_ASYNC(src, .proc/pick_form, user)
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(src, .proc/remember_form, A, user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/remember_form(atom/movable/A, mob/user)
|
||||
if(A.name in available_forms)
|
||||
to_chat(user, "<span class='warning'>[A] is already an available form.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
if(length(available_forms) >= max_forms)
|
||||
to_chat(user, "<span class='warning'>You start to forget the form of [available_forms[next_override_index]] to learn a new one.</span>")
|
||||
|
||||
to_chat(user, "<span class='sinister'>You start remembering the form of [A].</span>")
|
||||
if(!do_after(user, 2 SECONDS, FALSE, user))
|
||||
to_chat(user, "<span class='warning'>You lose focus.</span>")
|
||||
return
|
||||
|
||||
// Forget the old form if needed
|
||||
if(length(available_forms) >= max_forms)
|
||||
qdel(available_forms[available_forms[next_override_index]]) // Delete the value using the key
|
||||
available_forms[next_override_index++] = A.name
|
||||
// Reset if needed
|
||||
if(next_override_index > max_forms)
|
||||
next_override_index = 1
|
||||
|
||||
available_forms[A.name] = new /datum/mimic_form(A, user)
|
||||
to_chat(user, "<span class='sinister'>You learn the form of [A].</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/pick_form(mob/user)
|
||||
if(!length(available_forms) && !selected_form)
|
||||
to_chat(user, "<span class='warning'>No available forms. Learn more forms by using this spell on other objects first.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
|
||||
var/list/forms = list()
|
||||
if(selected_form)
|
||||
forms += "Original Form"
|
||||
|
||||
forms += available_forms.Copy()
|
||||
var/what = input(user, "Which form do you want to become?", "Mimic") as null|anything in forms
|
||||
if(!what)
|
||||
to_chat(user, "<span class='notice'>You decide against changing forms.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
|
||||
if(what == "Original Form")
|
||||
restore_form(user)
|
||||
return
|
||||
to_chat(user, "<span class='sinister'>You start becoming [what].</span>")
|
||||
if(!do_after(user, 2 SECONDS, FALSE, user))
|
||||
to_chat(user, "<span class='warning'>You lose focus.</span>")
|
||||
return
|
||||
take_form(available_forms[what], user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/take_form(datum/mimic_form/form, mob/user)
|
||||
var/old_name = "[user]"
|
||||
if(ishuman(user))
|
||||
// Not fully finished yet
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.name_override = form.name
|
||||
else
|
||||
user.appearance = form.appearance
|
||||
user.transform = initial(user.transform)
|
||||
user.pixel_y = initial(user.pixel_y)
|
||||
user.pixel_x = initial(user.pixel_x)
|
||||
user.layer = MOB_LAYER // Avoids weirdness when mimicing something below the vent layer
|
||||
|
||||
playsound(user, "bonebreak", 75, TRUE)
|
||||
show_change_form_message(user, old_name, "[user]")
|
||||
user.create_log(MISC_LOG, "Mimicked into [user]")
|
||||
|
||||
if(!selected_form)
|
||||
RegisterSignal(user, COMSIG_PARENT_EXAMINE, .proc/examine_override)
|
||||
RegisterSignal(user, COMSIG_MOB_DEATH, .proc/on_death)
|
||||
|
||||
selected_form = form
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/show_change_form_message(mob/user, old_name, new_name)
|
||||
user.visible_message("<span class='warning'>[old_name] contorts and slowly becomes [new_name]!</span>", "<span class='sinister'>You take form of [new_name].</span>", "You hear loud cracking noises!")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/restore_form(mob/user, show_message = TRUE)
|
||||
selected_form = null
|
||||
var/old_name = "[user]"
|
||||
|
||||
user.cut_overlays()
|
||||
user.icon = initial(user.icon)
|
||||
user.icon_state = initial(user.icon_state)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.name_override = null
|
||||
H.regenerate_icons()
|
||||
else
|
||||
user.name = initial(user.name)
|
||||
user.desc = initial(user.desc)
|
||||
user.color = initial(user.color)
|
||||
|
||||
playsound(user, "bonebreak", 150, TRUE)
|
||||
if(show_message)
|
||||
show_restore_form_message(user, old_name, "[user]")
|
||||
|
||||
UnregisterSignal(user, list(COMSIG_PARENT_EXAMINE, COMSIG_MOB_DEATH))
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/show_restore_form_message(mob/user, old_name, new_name)
|
||||
user.visible_message("<span class='warning'>[old_name] shakes and contorts and quickly becomes [new_name]!</span>", "<span class='sinister'>You take return to your normal self.</span>", "You hear loud cracking noises!")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/examine_override(datum/source, mob/user, list/examine_list)
|
||||
examine_list.Cut()
|
||||
examine_list += selected_form.examine_text
|
||||
if(!perfect_disguise && get_dist(user, source) <= 3)
|
||||
examine_list += "<span class='warning'>It doesn't look quite right...</span>"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/on_death(mob/user, gibbed)
|
||||
if(!gibbed)
|
||||
restore_form(user, FALSE)
|
||||
show_death_message(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/proc/show_death_message(mob/user)
|
||||
user.visible_message("<span class='warning'>[user] shakes and contorts as [user.p_they()] die[user.p_s()], returning to [user.p_their()] true form!</span>", "<span class='deadsay'>Your disguise fails as your life forces drain away.</span>", "You hear loud cracking noises followed by a thud!")
|
||||
|
||||
|
||||
/datum/mimic_form
|
||||
/// How does the form look like?
|
||||
var/appearance
|
||||
/// What is the examine text paired with this form
|
||||
var/examine_text
|
||||
/// What the name of the form is
|
||||
var/name
|
||||
|
||||
/datum/mimic_form/New(atom/movable/form, mob/user)
|
||||
appearance = form.appearance
|
||||
examine_text = form.examine(user)
|
||||
name = form.name
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph
|
||||
action_background_icon_state = "bg_morph"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/valid_target(atom/target, user)
|
||||
if(target != user && istype(target, /mob/living/simple_animal/hostile/morph))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/take_form(datum/mimic_form/form, mob/living/simple_animal/hostile/morph/user)
|
||||
..()
|
||||
user.assume()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/restore_form(mob/living/simple_animal/hostile/morph/user, show_message = TRUE)
|
||||
..()
|
||||
user.restore()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/show_change_form_message(mob/user, old_name, new_name)
|
||||
user.visible_message("<span class='warning'>[old_name] suddenly twists and changes shape, becoming a copy of [new_name]!</span>", \
|
||||
"<span class='notice'>You twist your body and assume the form of [new_name].</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/show_restore_form_message(mob/user, old_name, new_name)
|
||||
user.visible_message("<span class='warning'>[old_name] suddenly collapses in on itself, dissolving into a pile of green flesh!</span>", \
|
||||
"<span class='notice'>You reform to your normal body.</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mimic/morph/show_death_message(mob/user)
|
||||
user.visible_message("<span class='warning'>[user] twists and dissolves into a pile of green flesh!</span>", \
|
||||
"<span class='userdanger'>Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--</span>")
|
||||
Reference in New Issue
Block a user