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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworks the morph. Makes it a more stealth ambush oriented antag #15208

Merged
merged 23 commits into from Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ff48019
Reworks the morph
farie82 Dec 29, 2020
17f0424
Hunger points. Reproduce. Sprites. Other tweaks
farie82 Dec 29, 2020
bcb4c9b
vent open. Convert to spells. Valid checks. Minor tweaks
farie82 Dec 30, 2020
21a74ab
undo life hack
farie82 Dec 30, 2020
a833f71
Icons, Fixes, No more morphed lights
farie82 Dec 30, 2020
6f03f0c
Item eat fix. All eating takes 3 seconds
farie82 Jan 1, 2021
2e5cf41
Add sounds
farie82 Jan 2, 2021
f2aa4ed
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Jan 5, 2021
8cb99a3
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Jan 5, 2021
1d1d2b3
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Jan 6, 2021
4d1c379
Fixes and tweaks. Pass airlock ability. Ambush screen alert
farie82 Jan 7, 2021
9778078
Steel review fixes
farie82 Jan 7, 2021
ac3fb6f
New dead morph sprite from Pewtershmitz
farie82 Jan 8, 2021
0590466
Pass airlock sprite provided by Pewtershmitz
farie82 Jan 9, 2021
4e68145
No barsigns or cryo cells as mimic
farie82 Jan 10, 2021
9edb615
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Feb 24, 2021
aa88e13
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Mar 2, 2021
9a224a1
Gluttany ruin change
farie82 Mar 2, 2021
a263186
Color fix. No forms fix
farie82 Mar 7, 2021
822405a
Merge remote-tracking branch 'upstream/master' into morph-rework
farie82 Mar 7, 2021
c36e4db
fix the stupid icons
farie82 Mar 7, 2021
e40f9f8
Apply suggestions from code review
farie82 Mar 8, 2021
26234c6
Merge master
farie82 Nov 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions code/datums/spell.dm
Expand Up @@ -216,7 +216,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)
Expand All @@ -235,7 +235,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(overlay)
for(var/atom/target in targets)
var/location
Expand Down
4 changes: 2 additions & 2 deletions code/datums/spells/area_teleport.dm
Expand Up @@ -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)
Expand All @@ -35,7 +35,7 @@
var/area/thearea = GLOB.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
Expand Down
205 changes: 205 additions & 0 deletions code/datums/spells/mimic.dm
@@ -0,0 +1,205 @@
/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/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/M = target
if(M.bound_height > world.icon_size || M.bound_width > world.icon_size)
farie82 marked this conversation as resolved.
Show resolved Hide resolved
return FALSE // No multitile structures
farie82 marked this conversation as resolved.
Show resolved Hide resolved
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))
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)

farie82 marked this conversation as resolved.
Show resolved Hide resolved
var/old_name = "[user]"
if(ishuman(user))
// Not fully finished yet
var/mob/living/carbon/human/H = user
H.name_override = form.name

farie82 marked this conversation as resolved.
Show resolved Hide resolved
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sound still makes me physically cringe whenever I hear it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRUNCH

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()

farie82 marked this conversation as resolved.
Show resolved Hide resolved
else
user.name = initial(user.name)
user.desc = initial(user.desc)

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 he dies. Returning to his 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!")
farie82 marked this conversation as resolved.
Show resolved Hide resolved


/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>")