mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 06:00:16 +01:00
Mind Transfer is now a pointed spell (#50119)
* Mind Swap pointed spell * Cast safety, cleanup * Warning messages cleanup * Autodoc * Update code/game/objects/items/granters.dm Co-Authored-By: Rohesie <rohesie@gmail.com> * Update code/modules/spells/spell_types/mind_transfer.dm Co-Authored-By: Rohesie <rohesie@gmail.com> * Review fixes * Blind range check fix * Generic range check and cleanup Co-authored-by: Rohesie <rohesie@gmail.com>
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind", "/obj/effect/proc_holder/spell/targeted/genetic/blind")
|
||||
ranged_mousepointer = 'icons/effects/blind_target.dmi'
|
||||
action_icon_state = "blind"
|
||||
base_icon_state = "blind"
|
||||
active_msg = "You prepare to blind a target..."
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
|
||||
@@ -26,7 +25,8 @@
|
||||
sound = 'sound/magic/blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind/intercept_check(mob/user, atom/target)
|
||||
if(!..())
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!isliving(target))
|
||||
to_chat(user, "<span class='warning'>You can only blind living beings!</span>")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target."
|
||||
|
||||
desc = "This spell allows the user to switch bodies with a target next to him."
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
clothes_req = FALSE
|
||||
@@ -9,90 +8,111 @@
|
||||
invocation_type = "whisper"
|
||||
range = 1
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell
|
||||
var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell
|
||||
|
||||
ranged_mousepointer = 'icons/effects/mindswap_target.dmi'
|
||||
action_icon_state = "mindswap"
|
||||
active_msg = "You prepare to swap minds with a target..."
|
||||
/// For how long is the caster stunned for after the spell
|
||||
var/unconscious_amount_caster = 40 SECONDS
|
||||
/// For how long is the victim stunned for after the spell
|
||||
var/unconscious_amount_victim = 40 SECONDS
|
||||
|
||||
/*
|
||||
Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
|
||||
Make sure spells that are removed from spell_list are actually removed and deleted when mind transferring.
|
||||
Also, you never added distance checking after target is selected. I've went ahead and did that.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride, silent = FALSE)
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer/cast(list/targets, mob/living/user, silent = FALSE)
|
||||
if(!targets.len)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>No mind found!</span>")
|
||||
return
|
||||
|
||||
return FALSE
|
||||
if(targets.len > 1)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Too many minds! You're not a hive damnit!</span>")
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
var/mob/living/victim = targets[1] //The target of the spell whos body will be transferred to.
|
||||
if(!swap_check(user, victim, silent))
|
||||
return FALSE
|
||||
if(istype(victim, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/stand = victim
|
||||
if(stand.summoner)
|
||||
victim = stand.summoner
|
||||
|
||||
var/t_He = target.p_they(TRUE)
|
||||
var/t_is = target.p_are()
|
||||
//MIND TRANSFER BEGIN
|
||||
var/mob/dead/observer/ghost = victim.ghostize()
|
||||
user.mind.transfer_to(victim)
|
||||
|
||||
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
|
||||
ghost.mind.transfer_to(user)
|
||||
if(ghost.key)
|
||||
user.key = ghost.key //have to transfer the key since the mind was not active
|
||||
qdel(ghost)
|
||||
//MIND TRANSFER END
|
||||
|
||||
//Here we knock both mobs out for a time.
|
||||
user.Unconscious(unconscious_amount_caster)
|
||||
victim.Unconscious(unconscious_amount_victim)
|
||||
SEND_SOUND(user, sound('sound/magic/mandswap.ogg'))
|
||||
SEND_SOUND(victim, sound('sound/magic/mandswap.ogg')) // only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* swap_check: Checks if we are allowed and able to swap two minds
|
||||
*
|
||||
* Arguments:
|
||||
* * user - caster of the spell
|
||||
* * target - target of the spell
|
||||
* * silent - if set to TRUE, the spell will not produce any warning messages to the user if the spell fails
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer/proc/swap_check(mob/user, atom/target, silent = FALSE)
|
||||
if(!isliving(target))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[t_He] [t_is] too far away!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>You can only swap minds with living beings!</span>")
|
||||
return FALSE
|
||||
|
||||
if(ismegafauna(target))
|
||||
if(user == target)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can't swap minds with yourself!</span>")
|
||||
return FALSE
|
||||
|
||||
var/mob/living/victim = target
|
||||
var/t_He = victim.p_they(TRUE)
|
||||
|
||||
if(ismegafauna(victim))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>This creature is too powerful to control!</span>")
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(target.stat == DEAD)
|
||||
if(victim.stat == DEAD)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You don't particularly want to be dead!</span>")
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
if(!victim.key || !victim.mind)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>[t_He] appear[victim.p_s()] to be catatonic! Not even magic can affect [victim.p_their()] vacant mind.</span>")
|
||||
return FALSE
|
||||
|
||||
if(user.suiciding)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>")
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/datum/mind/TM = target.mind
|
||||
if(target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev) || target.key[1] == "@")
|
||||
var/datum/mind/VM = victim.mind
|
||||
if(victim.anti_magic_check(TRUE, FALSE) || VM.has_antag_datum(/datum/antagonist/wizard) || VM.has_antag_datum(/datum/antagonist/cult) || VM.has_antag_datum(/datum/antagonist/changeling) || VM.has_antag_datum(/datum/antagonist/rev) || victim.key[1] == "@")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[target.p_their(TRUE)] mind is resisting your spell!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>[victim.p_their(TRUE)] mind is resisting your spell!</span>")
|
||||
return FALSE
|
||||
|
||||
if(istype(target, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/stand = target
|
||||
if(istype(victim, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/stand = victim
|
||||
if(stand.summoner)
|
||||
if(stand.summoner == user)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Swapping minds with your own guardian would just put you back into your own head!</span>")
|
||||
return
|
||||
else
|
||||
target = stand.summoner
|
||||
return FALSE
|
||||
|
||||
var/mob/living/victim = target//The target of the spell whos body will be transferred to.
|
||||
var/mob/living/caster = user//The wizard/whomever doing the body transferring.
|
||||
|
||||
//MIND TRANSFER BEGIN
|
||||
var/mob/dead/observer/ghost = victim.ghostize()
|
||||
caster.mind.transfer_to(victim)
|
||||
|
||||
ghost.mind.transfer_to(caster)
|
||||
if(ghost.key)
|
||||
caster.key = ghost.key //have to transfer the key since the mind was not active
|
||||
qdel(ghost)
|
||||
|
||||
//MIND TRANSFER END
|
||||
|
||||
//Here we knock both mobs out for a time.
|
||||
caster.Unconscious(unconscious_amount_caster)
|
||||
victim.Unconscious(unconscious_amount_victim)
|
||||
SEND_SOUND(caster, sound('sound/magic/mandswap.ogg'))
|
||||
SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer/intercept_check(mob/user, atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!swap_check(user, target))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/obj/effect/proc_holder/spell/pointed
|
||||
name = "pointed spell"
|
||||
ranged_mousepointer = 'icons/effects/throw_target.dmi'
|
||||
action_icon_state = "projectile"
|
||||
/// Message showing to the spell owner upon deactivating pointed spell.
|
||||
var/deactive_msg = "You dispel the magic..."
|
||||
/// Message showing to the spell owner upon activating pointed spell.
|
||||
var/active_msg = "You prepare to use the spell on a target..."
|
||||
/// Default icon for the pointed spell, used for active/inactive states switching.
|
||||
var/base_icon_state = "projectile"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/Click()
|
||||
var/mob/living/user = usr
|
||||
@@ -20,56 +19,68 @@
|
||||
if(active)
|
||||
msg = "<span class='notice'>[deactive_msg]</span>"
|
||||
remove_ranged_ability(msg)
|
||||
on_deactivation(user)
|
||||
else
|
||||
msg = "<span class='notice'>[active_msg] <B>Left-click to activate spell on a target!</B></span>"
|
||||
add_ranged_ability(user, msg, TRUE)
|
||||
on_activation(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/remove_ranged_ability(msg)
|
||||
. = ..()
|
||||
on_deactivation(ranged_ability_user)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/add_ranged_ability(mob/living/user, msg, forced)
|
||||
. = ..()
|
||||
on_activation(user)
|
||||
|
||||
/**
|
||||
* on_activation: What happens upon pointed spell activation.
|
||||
*
|
||||
* What happens upon pointed spell activation.
|
||||
*
|
||||
* user mob The mob interacting owning the spell.
|
||||
*
|
||||
**/
|
||||
* Arguments:
|
||||
* * user The mob interacting owning the spell.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/on_activation(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
/**
|
||||
* on_activation: What happens upon pointed spell deactivation.
|
||||
*
|
||||
* What happens upon pointed spell deactivation.
|
||||
*
|
||||
* user mob The mob interacting owning the spell.
|
||||
*
|
||||
**/
|
||||
* Arguments:
|
||||
* * user The mob interacting owning the spell.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/on_deactivation(mob/user)
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/update_icon()
|
||||
if(!action)
|
||||
return
|
||||
action.button_icon_state = "[base_icon_state][active]"
|
||||
if(active)
|
||||
action.button_icon_state = "[action_icon_state]1"
|
||||
else
|
||||
action.button_icon_state = "[action_icon_state]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(!(target in view_or_range(range, ranged_ability_user, selection_type)))
|
||||
to_chat(ranged_ability_user, "<span class='warning'>[target.p_theyre(TRUE)] too far away!</span>")
|
||||
return TRUE
|
||||
if(!intercept_check(ranged_ability_user, target))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(!cast_check(user = ranged_ability_user))
|
||||
return FALSE
|
||||
return TRUE
|
||||
perform(list(target), user = ranged_ability_user)
|
||||
remove_ranged_ability()
|
||||
return TRUE
|
||||
return TRUE // Do not do any underlying actions after the spell cast
|
||||
|
||||
/**
|
||||
/**
|
||||
* intercept_check: Specific spell checks for InterceptClickOn() targets.
|
||||
*
|
||||
* Specific spell checks for InterceptClickOn() targets.
|
||||
*
|
||||
* user mob The mob using the ranged spell via intercept.
|
||||
* target atom The atom being targeted by the spell via intercept.
|
||||
*
|
||||
**/
|
||||
* Arguments:
|
||||
* * user The mob using the ranged spell via intercept.
|
||||
* * target The atom that is being targeted by the spell via intercept.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/intercept_check(mob/user, atom/target)
|
||||
if(!can_target(target))
|
||||
to_chat(user, "<span class='warning'>Invalid target!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
Reference in New Issue
Block a user