mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-10 14:44:05 +01:00
Makes most targeted spells select a target on click with a radius (#13220)
* Basis * Make most targeted spells use a click with radius instead of a list * Fixes * Selection code * return ..() * Auto targeting * Forgot a comment change * Merge issue fix
This commit is contained in:
+2
-2
@@ -1102,8 +1102,8 @@
|
||||
special_role = null
|
||||
to_chat(current,"<span class='userdanger'>Your infernal link has been severed! You are no longer a devil!</span>")
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/infernal_jaunt)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/fireball/hellish)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/summon_contract)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/click/fireball/hellish)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/click/summon_contract)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/greater)
|
||||
RemoveSpell(/obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/ascended)
|
||||
|
||||
+157
-68
@@ -24,6 +24,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
user.face_atom(A)
|
||||
return FALSE
|
||||
|
||||
/datum/click_intercept/proc_holder
|
||||
var/obj/effect/proc_holder/spell
|
||||
|
||||
/datum/click_intercept/proc_holder/New(client/C, obj/effect/proc_holder/spell_to_cast)
|
||||
. = ..()
|
||||
spell = spell_to_cast
|
||||
|
||||
/datum/click_intercept/proc_holder/InterceptClickOn(user, params, atom/object)
|
||||
spell.InterceptClickOn(user, params, object)
|
||||
|
||||
/datum/click_intercept/proc_holder/quit()
|
||||
spell.remove_ranged_ability(spell.ranged_ability_user)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, var/msg)
|
||||
if(!user || !user.client)
|
||||
return
|
||||
@@ -32,7 +46,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
user.ranged_ability.remove_ranged_ability(user)
|
||||
user.ranged_ability = src
|
||||
ranged_ability_user = user
|
||||
user.client.click_intercept = user.ranged_ability
|
||||
user.client.click_intercept = new /datum/click_intercept/proc_holder(user.client, user.ranged_ability)
|
||||
add_mousepointer(user.client)
|
||||
active = TRUE
|
||||
if(msg)
|
||||
@@ -48,15 +62,17 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
C.mouse_pointer_icon = initial(C.mouse_pointer_icon)
|
||||
|
||||
/obj/effect/proc_holder/proc/remove_ranged_ability(mob/living/user, var/msg)
|
||||
if(!user || !user.client || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
|
||||
if(!user || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
|
||||
return
|
||||
user.ranged_ability = null
|
||||
ranged_ability_user = null
|
||||
user.client.click_intercept = null
|
||||
remove_mousepointer(user.client)
|
||||
active = FALSE
|
||||
if(msg)
|
||||
to_chat(user, msg)
|
||||
if(user.client)
|
||||
qdel(user.client.click_intercept)
|
||||
user.client.click_intercept = null
|
||||
remove_mousepointer(user.client)
|
||||
if(msg)
|
||||
to_chat(user, msg)
|
||||
update_icon()
|
||||
|
||||
/obj/effect/proc_holder/spell
|
||||
@@ -114,10 +130,14 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
var/sound = null //The sound the spell makes when it is cast
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
||||
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
||||
return 0
|
||||
/* Checks if the user can cast the spell
|
||||
* @param charge_check If the proc should do the cooldown check
|
||||
* @param start_recharge If the proc should set the cooldown
|
||||
* @param user The caster of the spell
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/proc/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
if(!can_cast(user, charge_check, TRUE))
|
||||
return FALSE
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/caster = user
|
||||
@@ -126,49 +146,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
caster.reset_perspective(0)
|
||||
return 0
|
||||
|
||||
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
||||
return 0
|
||||
|
||||
if(!skipcharge)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
to_chat(user, still_recharging_msg)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
to_chat(user, "<span class='notice'>[name] has no charges left.</span>")
|
||||
return 0
|
||||
|
||||
if(!ghost)
|
||||
if(user.stat && !stat_allowed)
|
||||
to_chat(user, "<span class='notice'>You can't cast this spell while incapacitated.</span>")
|
||||
return 0
|
||||
if(ishuman(user) && (invocation_type == "whisper" || invocation_type == "shout") && user.is_muzzled())
|
||||
to_chat(user, "Mmmf mrrfff!")
|
||||
return 0
|
||||
|
||||
var/obj/effect/proc_holder/spell/noclothes/clothes_spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list()))
|
||||
if((ishuman(user) && clothes_req) && !istype(clothes_spell))//clothes check
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/clothing/robe = H.wear_suit
|
||||
var/obj/item/clothing/hat = H.head
|
||||
var/obj/item/clothing/shoes = H.shoes
|
||||
if(!robe || !hat || !shoes)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't complete, you should put on your robe and wizard hat, as well as sandals.</span>")
|
||||
return 0
|
||||
if(!robe.magical || !hat.magical || !shoes.magical)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't magical enough, you should put on your robe and wizard hat, as well as your sandals.</span>")
|
||||
return 0
|
||||
else if(!ishuman(user))
|
||||
if(clothes_req || human_req)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
|
||||
return 0
|
||||
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
|
||||
return 0
|
||||
|
||||
if(!skipcharge)
|
||||
if(start_recharge)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
charge_counter = 0 //doesn't start recharging until the targets selecting ends
|
||||
@@ -442,6 +420,100 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click
|
||||
var/click_radius = 1 // How big the radius around the clicked atom is to find a suitable target. -1 is only the selected atom is considered
|
||||
var/selection_activated_message = "<span class='notice'>Click on a target to cast the spell.</span>"
|
||||
var/selection_deactivated_message = "<span class='notice'>You choose to not cast this spell.</span>"
|
||||
var/allowed_type = /mob/living // Which type the targets have to be
|
||||
var/auto_target_single = TRUE // If the spell should auto select a target if only one is found
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/Click()
|
||||
var/mob/living/user = usr
|
||||
if(!istype(user))
|
||||
return
|
||||
|
||||
if(active)
|
||||
remove_ranged_ability(user, selection_deactivated_message)
|
||||
else
|
||||
if(cast_check(TRUE, FALSE, user))
|
||||
if(auto_target_single && attempt_auto_target(user))
|
||||
return
|
||||
|
||||
add_ranged_ability(user, selection_activated_message)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src] is not ready to be used yet.</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/proc/attempt_auto_target(mob/user)
|
||||
var/atom/target
|
||||
for(var/atom/A in view_or_range(range, user, selection_type))
|
||||
if(valid_target(A, user))
|
||||
if(target)
|
||||
return FALSE // Two targets found. ABORT
|
||||
target = A
|
||||
|
||||
if(target && cast_check(TRUE, TRUE, user)) // Singular target found. Cast it instantly
|
||||
to_chat(user, "<span class='warning'>Only one target found. Casting [src] on [target]!</span>")
|
||||
perform(list(target), user = user)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/InterceptClickOn(mob/living/user, params, atom/A)
|
||||
if(..() || !cast_check(TRUE, TRUE, user))
|
||||
remove_ranged_ability(user)
|
||||
revert_cast(user)
|
||||
return TRUE
|
||||
|
||||
var/list/targets = list()
|
||||
if(valid_target(A, user))
|
||||
targets.Add(A)
|
||||
|
||||
if((!max_targets || max_targets > targets.len) && click_radius >= 0)
|
||||
var/list/found_others = list()
|
||||
for(var/atom/target in range(click_radius, A))
|
||||
if(valid_target(target, user))
|
||||
found_others |= target
|
||||
if(!max_targets)
|
||||
targets.Add(found_others)
|
||||
else
|
||||
if(max_targets <= found_others.len + targets.len)
|
||||
targets.Add(found_others)
|
||||
else
|
||||
switch(random_target_priority) //Add in the rest
|
||||
if(TARGET_RANDOM)
|
||||
while(targets.len < max_targets && found_others.len) // Add the others
|
||||
targets.Add(pick_n_take(found_others))
|
||||
if(TARGET_CLOSEST)
|
||||
var/list/distances = list()
|
||||
for(var/target in found_others)
|
||||
distances[target] = get_dist(user, target)
|
||||
sortTim(distances, /proc/cmp_numeric_asc, TRUE) // Sort on distance
|
||||
for(var/target in distances)
|
||||
targets.Add(target)
|
||||
if(targets.len >= max_targets)
|
||||
break
|
||||
|
||||
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='warning'>No suitable target found.</span>")
|
||||
revert_cast(user)
|
||||
return FALSE
|
||||
|
||||
perform(targets, user = user)
|
||||
remove_ranged_ability(user)
|
||||
return TRUE
|
||||
|
||||
/* Checks if a target is valid
|
||||
* Should not include to_chats or other types of messages since this is used often on tons of targets.
|
||||
* @param target The target to check
|
||||
* @param user The user of the spell
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/targeted/click/proc/valid_target(target, user)
|
||||
return istype(target, allowed_type) && (include_user || target != user) && \
|
||||
(target in view_or_range(range, user, selection_type))
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/choose_targets(mob/living/user, atom/A) // Not used
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr)
|
||||
var/list/targets = list()
|
||||
|
||||
@@ -475,30 +547,39 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
qdel(dummy)
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
||||
return 0
|
||||
|
||||
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
||||
return 0
|
||||
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
return 0
|
||||
|
||||
if(user.stat && !stat_allowed)
|
||||
return 0
|
||||
if(charge_check)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
if(show_message)
|
||||
to_chat(user, still_recharging_msg)
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>[name] has no charges left.</span>")
|
||||
return 0
|
||||
if(!ghost)
|
||||
if(user.stat && !stat_allowed)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>You can't cast this spell while incapacitated.</span>")
|
||||
return 0
|
||||
if(ishuman(user) && (invocation_type == "whisper" || invocation_type == "shout") && user.is_muzzled())
|
||||
if(show_message)
|
||||
to_chat(user, "Mmmf mrrfff!")
|
||||
return 0
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
|
||||
return 0
|
||||
|
||||
var/clothcheck = locate(/obj/effect/proc_holder/spell/noclothes) in user.mob_spell_list
|
||||
var/clothcheck2 = user.mind && (locate(/obj/effect/proc_holder/spell/noclothes) in user.mind.spell_list)
|
||||
if(clothes_req && !clothcheck && !clothcheck2) //clothes check
|
||||
@@ -506,12 +587,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
|
||||
var/obj/item/clothing/hat = H.head
|
||||
var/obj/item/clothing/shoes = H.shoes
|
||||
if(!robe || !hat || !shoes)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't complete, you should put on your robe and wizard hat, as well as sandals.</span>")
|
||||
return 0
|
||||
if(!robe.magical || !hat.magical || !shoes.magical)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>Your outfit isn't magical enough, you should put on your robe and wizard hat, as well as your sandals.</span>")
|
||||
return 0
|
||||
else
|
||||
if(clothes_req || human_req)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
|
||||
return 0
|
||||
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1, mob/living/user = usr)
|
||||
var/thearea = before_cast(targets)
|
||||
if(!thearea || !cast_check(1))
|
||||
if(!thearea || !cast_check(TRUE, FALSE, user))
|
||||
revert_cast()
|
||||
return
|
||||
invocation(thearea)
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/chaplain_bless
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless
|
||||
name = "Bless"
|
||||
desc = "Blesses a single person."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
|
||||
max_targets = 1
|
||||
include_user = 0
|
||||
humans_only = 1
|
||||
|
||||
include_user = FALSE
|
||||
allowed_type = /mob/living/carbon/human
|
||||
selection_activated_message = "<span class='notice'>You prepare a blessing. Click on a target to start blessing.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>The crew will be blessed another time.</span>"
|
||||
range = 1
|
||||
click_radius = -1 // Only precision clicking
|
||||
cooldown_min = 20
|
||||
action_icon_state = "shield"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/chaplain_bless/cast(list/targets, mob/living/user = usr, distanceoverride)
|
||||
return target.mind && target.ckey && !target.stat
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/chaplain_bless/cast(list/targets, mob/living/user = usr)
|
||||
if(!istype(user))
|
||||
to_chat(user, "Somehow, you are not a living mob. This should never happen. Report this bug.")
|
||||
revert_cast()
|
||||
@@ -35,32 +41,7 @@
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/target = targets[range]
|
||||
|
||||
if(!istype(target))
|
||||
to_chat(user, "No target.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
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.
|
||||
to_chat(user, "[target] is too far away!")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(!target.mind)
|
||||
to_chat(user, "[target] appears to be catatonic. Your blessing would have no effect.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(!target.ckey)
|
||||
to_chat(user, "[target] appears to be too out of it to benefit from this.")
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "[target] is already dead. There is no point.")
|
||||
revert_cast()
|
||||
return
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
spawn(0) // allows cast to complete even if recipient ignores the prompt
|
||||
if(alert(target, "[user] wants to bless you, in the name of [user.p_their()] religion. Accept?", "Accept Blessing?", "Yes", "No") == "Yes") // prevents forced conversions
|
||||
|
||||
@@ -21,13 +21,18 @@
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract
|
||||
name = "Summon infernal contract"
|
||||
desc = "Skip making a contract by hand, just do it by magic."
|
||||
invocation_type = "whisper"
|
||||
invocation = "Just sign on the dotted line."
|
||||
include_user = 0
|
||||
selection_activated_message = "<span class='notice'>You prepare a detailed contract. Click on a target to summon the contract in his hands.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You archive the contract for later use.</span>"
|
||||
include_user = FALSE
|
||||
range = 5
|
||||
auto_target_single = FALSE // Prevent an accidental contract from summoning
|
||||
click_radius = -1 // Precision clicking required
|
||||
allowed_type = /mob/living/carbon
|
||||
clothes_req = FALSE
|
||||
school = "conjuration"
|
||||
charge_max = 150
|
||||
@@ -35,8 +40,9 @@
|
||||
action_icon_state = "spell_default"
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract/cast(list/targets, mob/user = usr)
|
||||
for(var/target in targets)
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.mind && user.mind)
|
||||
if(C.stat == DEAD)
|
||||
if(user.drop_item())
|
||||
@@ -63,7 +69,7 @@
|
||||
to_chat(user,"<span class='notice'>[C] seems to not be sentient. You are unable to summon a contract for them.</span>")
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/hellish
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/hellish
|
||||
name = "Hellfire"
|
||||
desc = "This spell launches hellfire at the target."
|
||||
school = "evocation"
|
||||
@@ -74,7 +80,7 @@
|
||||
fireball_type = /obj/item/projectile/magic/fireball/infernal
|
||||
action_background_icon_state = "bg_demon"
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/hellish/cast(list/targets, mob/living/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/hellish/cast(list/targets, mob/living/user = usr)
|
||||
add_attack_logs(user, targets, "has fired a Hellfire ball", ATKLOG_FEW)
|
||||
.=..()
|
||||
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask
|
||||
/obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
name = "Curse of the Horseman"
|
||||
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
|
||||
school = "transmutation"
|
||||
charge_type = "recharge"
|
||||
charge_max = 150
|
||||
charge_counter = 0
|
||||
clothes_req = 0
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
|
||||
invocation_type = "shout"
|
||||
range = 7
|
||||
cooldown_min = 30 //30 deciseconds reduction per rank
|
||||
selection_type = "range"
|
||||
|
||||
selection_activated_message = "<span class='notice'>You start to quietly neigh an incantation. Click on or near a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You stop neighing to yourself.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
action_icon_state = "barn"
|
||||
sound = 'sound/magic/HorseHead_curse.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/horsemask/cast(list/targets, mob/user = usr)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='notice'>No target found in range.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/target = targets[1]
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='notice'>It'd be stupid to curse [target] with a horse's head!</span>")
|
||||
return
|
||||
|
||||
if(!(target in oview(range)))//If they are not in overview after selection.
|
||||
to_chat(user, "<span class='notice'>They are too far away!</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
|
||||
magichead.flags |= NODROP | DROPDEL //curses!
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/Click()
|
||||
if(!ready && start_time == 0)
|
||||
if(cast_check())
|
||||
if(cast_check(TRUE, FALSE, usr))
|
||||
StartChargeup()
|
||||
else
|
||||
if(ready && cast_check(skipcharge=1))
|
||||
if(ready && cast_check(TRUE, TRUE, usr))
|
||||
choose_targets()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/magnet/Click()
|
||||
if(!ready && start_time == 0)
|
||||
if(cast_check())
|
||||
if(cast_check(TRUE, FALSE, usr))
|
||||
StartChargeup()
|
||||
else
|
||||
if(ready && cast_check(skipcharge=1))
|
||||
if(ready && cast_check(TRUE, TRUE, usr))
|
||||
choose_targets()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target."
|
||||
|
||||
@@ -8,33 +8,29 @@
|
||||
invocation = "GIN'YU CAPAN"
|
||||
invocation_type = "whisper"
|
||||
range = 1
|
||||
click_radius = 0 // Still gotta be pretty accurate
|
||||
selection_activated_message = "<span class='notice'>You prepare to transfer your mind. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>You decide that your current form is good enough.</span>"
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
|
||||
var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell
|
||||
var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell
|
||||
action_icon_state = "mindswap"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer/valid_target(mob/living/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return target.stat != DEAD && target.key && target.mind
|
||||
|
||||
/*
|
||||
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 transfering.
|
||||
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/user = usr, distanceoverride)
|
||||
/obj/effect/proc_holder/spell/targeted/click/mind_transfer/cast(list/targets, mob/user = usr)
|
||||
|
||||
var/mob/living/target = targets[range]
|
||||
|
||||
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.
|
||||
to_chat(user, "They are too far away!")
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user, "You don't particularly want to be dead.")
|
||||
return
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
to_chat(user, "[target.p_they(TRUE)] appear[target.p_s()] to be catatonic. Not even magic can affect [target.p_their()] vacant mind.")
|
||||
return
|
||||
|
||||
if(user.suiciding)
|
||||
to_chat(user, "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>")
|
||||
return
|
||||
|
||||
@@ -308,76 +308,50 @@
|
||||
duration = 300
|
||||
sound = 'sound/magic/blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
name = "Fireball"
|
||||
desc = "This spell fires a fireball at a target and does not require wizard garb."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
invocation = "ONI SOMA"
|
||||
invocation_type = "shout"
|
||||
auto_target_single = FALSE // Having this true won't ever find a single target and is just lost processing power
|
||||
range = 20
|
||||
cooldown_min = 20 //10 deciseconds reduction per rank
|
||||
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>You extinguish your fireball...for now.</span>"
|
||||
allowed_type = /atom // FIRE AT EVERYTHING
|
||||
|
||||
var/fireball_type = /obj/item/projectile/magic/fireball
|
||||
action_icon_state = "fireball0"
|
||||
sound = 'sound/magic/fireball.ogg'
|
||||
|
||||
active = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/Click()
|
||||
var/mob/living/user = usr
|
||||
if(!istype(user))
|
||||
return
|
||||
|
||||
var/msg
|
||||
|
||||
if(!can_cast(user))
|
||||
msg = "<span class='warning'>You can no longer cast Fireball.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
return
|
||||
|
||||
if(active)
|
||||
msg = "<span class='notice'>You extinguish your fireball...for now.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
else
|
||||
msg = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
|
||||
add_ranged_ability(user, msg)
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/update_icon()
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/update_icon()
|
||||
if(!action)
|
||||
return
|
||||
action.button_icon_state = "fireball[active]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/InterceptClickOn(mob/living/user, params, atom/target)
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
if(!cast_check(0, user))
|
||||
remove_ranged_ability(user)
|
||||
return FALSE
|
||||
|
||||
var/list/targets = list(target)
|
||||
perform(targets, user = user)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/cast(list/targets, mob/living/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/fireball/cast(list/targets, mob/living/user = usr)
|
||||
var/target = targets[1] //There is only ever one target for fireball
|
||||
var/turf/T = user.loc
|
||||
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
|
||||
if(!isturf(U) || !isturf(T))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/obj/item/projectile/magic/fireball/FB = new fireball_type(user.loc)
|
||||
FB.current = get_turf(user)
|
||||
FB.preparePixelProjectile(target, get_turf(target), user)
|
||||
FB.fire()
|
||||
user.newtonian_move(get_dir(U, T))
|
||||
remove_ranged_ability(user)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse
|
||||
name = "Repulse"
|
||||
|
||||
@@ -123,13 +123,13 @@
|
||||
instability = GENE_INSTABILITY_MODERATE
|
||||
mutation = CRYO
|
||||
|
||||
spelltype = /obj/effect/proc_holder/spell/targeted/cryokinesis
|
||||
spelltype = /obj/effect/proc_holder/spell/targeted/click/cryokinesis
|
||||
|
||||
/datum/dna/gene/basic/grant_spell/cryo/New()
|
||||
..()
|
||||
block = GLOB.cryoblock
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/cryokinesis
|
||||
/obj/effect/proc_holder/spell/targeted/click/cryokinesis
|
||||
name = "Cryokinesis"
|
||||
desc = "Drops the bodytemperature of another person."
|
||||
panel = "Abilities"
|
||||
@@ -137,45 +137,44 @@
|
||||
charge_type = "recharge"
|
||||
charge_max = 1200
|
||||
|
||||
clothes_req = 0
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
|
||||
click_radius = 0
|
||||
auto_target_single = FALSE // Give the clueless geneticists a way out and to have them not target themselves
|
||||
selection_activated_message = "<span class='notice'>Your mind grow cold. Click on a target to cast the spell.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind returns to normal.</span>"
|
||||
allowed_type = /mob/living/carbon
|
||||
invocation_type = "none"
|
||||
range = 7
|
||||
selection_type = "range"
|
||||
include_user = 1
|
||||
include_user = TRUE
|
||||
var/list/compatible_mobs = list(/mob/living/carbon/human)
|
||||
|
||||
action_icon_state = "genetic_cryo"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/cryokinesis/cast(list/targets, mob/user = usr)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='notice'>No target found in range.</span>")
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/cryokinesis/cast(list/targets, mob/user = usr)
|
||||
|
||||
var/mob/living/carbon/C = targets[1]
|
||||
|
||||
if(!iscarbon(C))
|
||||
to_chat(user, "<span class='warning'>This will only work on normal organic beings.</span>")
|
||||
return
|
||||
|
||||
if(COLDRES in C.mutations)
|
||||
C.visible_message("<span class='warning'>A cloud of fine ice crystals engulfs [C.name], but disappears almost instantly!</span>")
|
||||
return
|
||||
var/handle_suit = 0
|
||||
var/handle_suit = FALSE
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(istype(H.head, /obj/item/clothing/head/helmet/space))
|
||||
if(istype(H.wear_suit, /obj/item/clothing/suit/space))
|
||||
handle_suit = 1
|
||||
handle_suit = TRUE
|
||||
if(H.internal)
|
||||
H.visible_message("<span class='warning'>[user] sprays a cloud of fine ice crystals, engulfing [H]!</span>",
|
||||
"<span class='notice'>[user] sprays a cloud of fine ice crystals over your [H.head]'s visor.</span>")
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
else
|
||||
H.visible_message("<span class='warning'>[user] sprays a cloud of fine ice crystals engulfing, [H]!</span>",
|
||||
"<span class='warning'>[user] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.</span>")
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
|
||||
H.bodytemperature = max(0, H.bodytemperature - 100)
|
||||
add_attack_logs(user, C, "Cryokinesis")
|
||||
if(!handle_suit)
|
||||
C.bodytemperature = max(0, C.bodytemperature - 200)
|
||||
C.ExtinguishMob()
|
||||
@@ -454,7 +453,7 @@
|
||||
name = "Polymorphism"
|
||||
desc = "Enables the subject to reconfigure their appearance to mimic that of others."
|
||||
|
||||
spelltype =/obj/effect/proc_holder/spell/targeted/polymorph
|
||||
spelltype =/obj/effect/proc_holder/spell/targeted/click/polymorph
|
||||
//cooldown = 1800
|
||||
activation_messages = list("You don't feel entirely like yourself somehow.")
|
||||
deactivation_messages = list("You feel secure in your identity.")
|
||||
@@ -465,34 +464,36 @@
|
||||
..()
|
||||
block = GLOB.polymorphblock
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/polymorph
|
||||
/obj/effect/proc_holder/spell/targeted/click/polymorph
|
||||
name = "Polymorph"
|
||||
desc = "Mimic the appearance of others!"
|
||||
panel = "Abilities"
|
||||
charge_max = 1800
|
||||
|
||||
clothes_req = 0
|
||||
human_req = 1
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
|
||||
click_radius = -1 // Precision required
|
||||
auto_target_single = FALSE // Safety to not turn into monkey (420)
|
||||
selection_activated_message = "<span class='notice'>You body becomes unstable. Click on a target to cast transform into them.</span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your body calms down again.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
invocation_type = "none"
|
||||
range = 1
|
||||
selection_type = "range"
|
||||
|
||||
action_icon_state = "genetic_poly"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/polymorph/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/M = targets[1]
|
||||
if(!ishuman(M))
|
||||
to_chat(usr, "<span class='warning'>You can only change your appearance to that of another human.</span>")
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/polymorph/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'>[user]'s body shifts and contorts.</span>")
|
||||
|
||||
spawn(10)
|
||||
if(M && user)
|
||||
if(target && user)
|
||||
playsound(user.loc, 'sound/goonstation/effects/gib.ogg', 50, 1)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/mob/living/carbon/human/target = M
|
||||
H.UpdateAppearance(target.dna.UI)
|
||||
H.real_name = target.real_name
|
||||
H.name = target.name
|
||||
|
||||
@@ -92,7 +92,7 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
var/form = BASIC_DEVIL
|
||||
var/exists = 0
|
||||
var/static/list/dont_remove_spells = list(
|
||||
/obj/effect/proc_holder/spell/targeted/summon_contract,
|
||||
/obj/effect/proc_holder/spell/targeted/click/summon_contract,
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/violin,
|
||||
/obj/effect/proc_holder/spell/targeted/summon_dancefloor)
|
||||
var/ascendable = FALSE
|
||||
@@ -326,12 +326,12 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
owner.RemoveSpell(S)
|
||||
|
||||
/datum/devilinfo/proc/give_summon_contract()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/summon_contract(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/summon_contract(null))
|
||||
|
||||
|
||||
/datum/devilinfo/proc/give_base_spells(give_summon_contract = 0)
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork(null))
|
||||
if(give_summon_contract)
|
||||
give_summon_contract()
|
||||
@@ -343,13 +343,13 @@ GLOBAL_LIST_INIT(lawlorify, list (
|
||||
/datum/devilinfo/proc/give_lizard_spells()
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/infernal_jaunt(null))
|
||||
|
||||
/datum/devilinfo/proc/give_true_spells()
|
||||
remove_spells()
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/pitchfork/greater(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/infernal_jaunt(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/sintouch(null))
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
else
|
||||
name = "[initial(name)] ([cast_amount]E)"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr)
|
||||
/obj/effect/proc_holder/spell/aoe_turf/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(user.inhibited)
|
||||
return 0
|
||||
if(charge_counter < charge_max)
|
||||
|
||||
@@ -18,80 +18,56 @@
|
||||
return 0
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
|
||||
name = "Glare"
|
||||
desc = "Stuns and mutes a target for a decent duration. Duration depends on the proximity to the target."
|
||||
panel = "Shadowling Abilities"
|
||||
charge_max = 300
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
range = 10 //has no effect beyond this range, so setting this makes invalid/useless targets not show up in popup
|
||||
action_icon_state = "glare"
|
||||
humans_only = 1 //useless since we override chose_targets, but might be used for other code later??? Might remove, idk
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare/choose_targets(mob/user)
|
||||
var/list/possible_targets = list()
|
||||
for(var/mob/living/carbon/human/target in view_or_range(range, user, "view"))
|
||||
if(target.stat)
|
||||
continue
|
||||
if(is_shadow_or_thrall(target))
|
||||
continue
|
||||
possible_targets += target
|
||||
var/mob/living/carbon/human/M
|
||||
var/list/targets = list()
|
||||
if(possible_targets.len == 1)//no choice involved
|
||||
targets = possible_targets
|
||||
else
|
||||
M = input("Choose the target for the spell.", "Targeting") as mob in possible_targets
|
||||
if(M in view_or_range(range, user, "view"))
|
||||
targets += M
|
||||
selection_activated_message = "<span class='notice'>Your prepare to your eyes for a stunning glare! <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your eyes relax... for now.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr)
|
||||
if(!shadowling_check(user))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
if(!targets.len) //doesn't waste the spell
|
||||
revert_cast(user)
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !target.stat && !is_shadow_or_thrall(target)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/H = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'><b>[user]'s eyes flash a blinding red!</b></span>")
|
||||
var/distance = get_dist(H, user)
|
||||
if (distance <= 1) //Melee glare
|
||||
H.visible_message("<span class='danger'>[H] freezes in place, [H.p_their()] eyes glazing over...</span>", \
|
||||
"<span class='userdanger'>Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...</span>")
|
||||
H.Stun(10)
|
||||
H.AdjustSilence(10)
|
||||
else //Distant glare
|
||||
var/loss = 10 - distance
|
||||
var/duration = 10 - loss
|
||||
if(loss <= 0)
|
||||
to_chat(user, "<span class='danger'>Your glare had no effect over a such long distance!</span>")
|
||||
return
|
||||
H.slowed = duration
|
||||
H.AdjustSilence(10)
|
||||
to_chat(H, "<span class='userdanger'>A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..</span>")
|
||||
addtimer(CALLBACK(src, .proc/do_stun, H, user, loss), duration SECONDS)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/glare/proc/do_stun(mob/living/carbon/human/target, user, stun_time)
|
||||
if(!istype(target) || target.stat)
|
||||
return
|
||||
|
||||
perform(targets, user = user)
|
||||
return
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/glare/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You may only glare at humans!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>[target] must be conscious!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='danger'>You don't see why you would want to paralyze an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/mob/living/carbon/human/M = target
|
||||
user.visible_message("<span class='warning'><b>[user]'s eyes flash a blinding red!</b></span>")
|
||||
var/distance = get_dist(target, user)
|
||||
if (distance <= 1) //Melee glare
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
|
||||
to_chat(target, "<span class='userdanger'>Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...</span>")
|
||||
target.Stun(10)
|
||||
M.AdjustSilence(10)
|
||||
else //Distant glare
|
||||
var/loss = 10 - distance
|
||||
var/duration = 10 - loss
|
||||
if(loss <= 0)
|
||||
to_chat(user, "<span class='danger'>Your glare had no effect over a such long distance!</span>")
|
||||
return
|
||||
target.slowed = duration
|
||||
M.AdjustSilence(10)
|
||||
to_chat(target, "<span class='userdanger'>A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..</span>")
|
||||
sleep(duration*10)
|
||||
target.Stun(loss)
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
|
||||
to_chat(target, "<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...</span>")
|
||||
target.Stun(stun_time)
|
||||
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>",\
|
||||
"<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...</span>")
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/veil
|
||||
name = "Veil"
|
||||
@@ -228,96 +204,80 @@
|
||||
M.reagents.add_reagent("frostoil", 15) //Half of a cryosting
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties
|
||||
name = "Enthrall"
|
||||
desc = "Allows you to enslave a conscious, non-braindead, non-catatonic human to your will. This takes some time to cast."
|
||||
panel = "Shadowling Abilities"
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
range = 1 //Adjacent to user
|
||||
var/enthralling = 0
|
||||
var/enthralling = FALSE
|
||||
action_icon_state = "enthrall"
|
||||
humans_only = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets, mob/user = usr)
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>Your prepare your mind to entrall a mortal. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(enthralling || !shadowling_check(user))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return target.key && target.mind && !target.stat && !is_shadow_or_thrall(target) && target.client
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/enthrall/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/ling = user
|
||||
listclearnulls(SSticker.mode.shadowling_thralls)
|
||||
if(!(ling.mind in SSticker.mode.shadows))
|
||||
return
|
||||
if(!isshadowling(ling))
|
||||
if(SSticker.mode.shadowling_thralls.len >= 5)
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(!in_range(user, target))
|
||||
to_chat(user, "<span class='warning'>You need to be closer to enthrall [target].</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.key || !target.mind)
|
||||
to_chat(user, "<span class='warning'>The target has no mind.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>The target must be conscious.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>You can not enthrall allies.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You can only enthrall humans.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(enthralling)
|
||||
to_chat(user, "<span class='warning'>You are already enthralling!</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.client)
|
||||
to_chat(user, "<span class='warning'>[target]'s mind is vacant of activity.</span>")
|
||||
enthralling = 1
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the enthralling.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] stares at you. You feel your head begin to pulse.</span>")
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
enthralling = TRUE
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the enthralling.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] stares at you. You feel your head begin to pulse.</span>")
|
||||
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You place your hands to [target]'s head...</span>")
|
||||
user.visible_message("<span class='warning'>[user] places [user.p_their()] hands onto the sides of [target]'s head!</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin preparing [target]'s mind as a blank slate...</span>")
|
||||
user.visible_message("<span class='warning'>[user]'s palms flare a bright red against [target]'s temples!</span>")
|
||||
to_chat(target, "<span class='danger'>A terrible red light floods your mind. You collapse as conscious thought is wiped away.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>They have a mindshield implant. You begin to deactivate it - this will take some time.</span>")
|
||||
user.visible_message("<span class='warning'>[user] pauses, then dips [user.p_their()] head in concentration!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>Your mindshield implant becomes hot as it comes under attack!</span>")
|
||||
sleep(100) //10 seconds - not spawn() so the enthralling takes longer
|
||||
to_chat(user, "<span class='notice'>The nanobots composing the mindshield implant have been rendered inert. Now to continue.</span>")
|
||||
user.visible_message("<span class='warning'>[user] relaxes again.</span>")
|
||||
for(var/obj/item/implant/mindshield/L in target)
|
||||
if(L && L.implanted)
|
||||
qdel(L)
|
||||
to_chat(target, "<span class='boldannounce'>Your mental protection implant unexpectedly falters, dims, dies.</span>")
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin planting the tumor that will control the new thrall...</span>")
|
||||
user.visible_message("<span class='warning'>A strange energy passes from [user]'s hands into [target]'s head!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>You feel your memories twisting, morphing. A sense of horror dominates your mind.</span>")
|
||||
if(!do_mob(user, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='warning'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>")
|
||||
to_chat(target, "<span class='userdanger'>You wrest yourself away from [user]'s hands and compose yourself</span>")
|
||||
enthralling = 0
|
||||
return
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You place your hands to [target]'s head...</span>")
|
||||
user.visible_message("<span class='warning'>[user] places [user.p_their()] hands onto the sides of [target]'s head!</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin preparing [target]'s mind as a blank slate...</span>")
|
||||
user.visible_message("<span class='warning'>[user]'s palms flare a bright red against [target]'s temples!</span>")
|
||||
to_chat(target, "<span class='danger'>A terrible red light floods your mind. You collapse as conscious thought is wiped away.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>They have a mindshield implant. You begin to deactivate it - this will take some time.</span>")
|
||||
user.visible_message("<span class='warning'>[user] pauses, then dips [user.p_their()] head in concentration!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>Your mindshield implant becomes hot as it comes under attack!</span>")
|
||||
sleep(100) //10 seconds - not spawn() so the enthralling takes longer
|
||||
to_chat(user, "<span class='notice'>The nanobots composing the mindshield implant have been rendered inert. Now to continue.</span>")
|
||||
user.visible_message("<span class='warning'>[user] relaxes again.</span>")
|
||||
for(var/obj/item/implant/mindshield/L in target)
|
||||
if(L && L.implanted)
|
||||
qdel(L)
|
||||
to_chat(target, "<span class='boldannounce'>Your mental protection implant unexpectedly falters, dims, dies.</span>")
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin planting the tumor that will control the new thrall...</span>")
|
||||
user.visible_message("<span class='warning'>A strange energy passes from [user]'s hands into [target]'s head!</span>")
|
||||
to_chat(target, "<span class='boldannounce'>You feel your memories twisting, morphing. A sense of horror dominates your mind.</span>")
|
||||
if(!do_mob(user, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='warning'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>")
|
||||
to_chat(target, "<span class='userdanger'>You wrest yourself away from [user]'s hands and compose yourself</span>")
|
||||
enthralling = FALSE
|
||||
return
|
||||
|
||||
enthralling = 0
|
||||
to_chat(user, "<span class='shadowling'>You have enthralled <b>[target]</b>!</span>")
|
||||
target.visible_message("<span class='big'>[target] looks to have experienced a revelation!</span>", \
|
||||
"<span class='warning'>False faces all d<b>ark not real not real not--</b></span>")
|
||||
target.setOxyLoss(0) //In case the shadowling was choking them out
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
enthralling = FALSE
|
||||
to_chat(user, "<span class='shadowling'>You have enthralled <b>[target]</b>!</span>")
|
||||
target.visible_message("<span class='big'>[target] looks to have experienced a revelation!</span>", \
|
||||
"<span class='warning'>False faces all d<b>ark not real not real not--</b></span>")
|
||||
target.setOxyLoss(0) //In case the shadowling was choking them out
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_regenarmor //Resets a shadowling's species to normal, removes genetic defects, and re-equips their armor
|
||||
name = "Rapid Re-Hatch"
|
||||
@@ -405,7 +365,7 @@
|
||||
reviveThrallAcquired = 1
|
||||
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Black Recuperation</b> ability. \
|
||||
This will, after a short time, bring a dead thrall completely back to life with no bodily defects.</i></span>")
|
||||
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/reviveThrall(null))
|
||||
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/reviveThrall(null))
|
||||
|
||||
if(thralls < victory_threshold)
|
||||
to_chat(target, "<span class='shadowling'>You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present.</span>")
|
||||
@@ -571,169 +531,170 @@
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/reviveThrall
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall
|
||||
name = "Black Recuperation"
|
||||
desc = "Revives or empowers a thrall."
|
||||
panel = "Shadowling Abilities"
|
||||
range = 1
|
||||
charge_max = 600
|
||||
clothes_req = 0
|
||||
include_user = 0
|
||||
clothes_req = FALSE
|
||||
include_user = FALSE
|
||||
action_icon_state = "revive_thrall"
|
||||
humans_only = 1
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>You start focusing your powers on mending wounds of allies. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/reviveThrall/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/can_cast(mob/user = usr)
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/thrallToRevive in targets)
|
||||
var/choice = alert(user,"Empower a living thrall or revive a dead one?",,"Empower","Revive","Cancel")
|
||||
switch(choice)
|
||||
if("Empower")
|
||||
if(!is_thrall(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not a thrall.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(thrallToRevive.stat != CONSCIOUS)
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] must be conscious to become empowered.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(isshadowlinglesser(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is already empowered.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/empowered_thralls = 0
|
||||
for(var/datum/mind/M in SSticker.mode.shadowling_thralls)
|
||||
if(!ishuman(M.current))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(isshadowlinglesser(H))
|
||||
empowered_thralls++
|
||||
if(empowered_thralls >= EMPOWERED_THRALL_LIMIT)
|
||||
to_chat(user, "<span class='warning'>You cannot spare this much energy. There are too many empowered thralls.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] places [user.p_their()] hands over [thrallToRevive]'s face, red light shining from beneath.</span>", \
|
||||
"<span class='shadowling'>You place your hands on [thrallToRevive]'s face and begin gathering energy...</span>")
|
||||
to_chat(thrallToRevive, "<span class='userdanger'>[user] places [user.p_their()] hands over your face. You feel energy gathering. Stand still...</span>")
|
||||
if(!do_mob(user, thrallToRevive, 80))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges into [thrallToRevive]'s face!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
thrallToRevive.Weaken(5)
|
||||
thrallToRevive.visible_message("<span class='warning'><b>[thrallToRevive] collapses, [thrallToRevive.p_their()] skin and face distorting!</span>", \
|
||||
"<span class='userdanger'><i>AAAAAAAAAAAAAAAAAAAGH-</i></span>")
|
||||
sleep(20)
|
||||
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
|
||||
"<span class='shadowling'><b>You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
|
||||
darkness but wither slowly in light. In addition, you now have glare and true shadow walk.</b></span>")
|
||||
thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
|
||||
thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
if("Revive")
|
||||
if(!is_thrall(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not a thrall.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(thrallToRevive.stat != DEAD)
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is not dead.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] kneels over [thrallToRevive], placing [user.p_their()] hands on [thrallToRevive.p_their()] chest.</span>", \
|
||||
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
|
||||
thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive)
|
||||
if(!do_mob(user, thrallToRevive, 30))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
sleep(10)
|
||||
if(thrallToRevive.revive())
|
||||
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] heaves in breath, dim red light shining in [thrallToRevive.p_their()] eyes.</span>", \
|
||||
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
|
||||
thrallToRevive.Weaken(4)
|
||||
thrallToRevive.emote("gasp")
|
||||
playsound(thrallToRevive, "bodyfall", 50, 1)
|
||||
else
|
||||
charge_counter = charge_max
|
||||
return
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
return is_thrall(target)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/reviveThrall/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/thrallToRevive = targets[1]
|
||||
if(thrallToRevive.stat == CONSCIOUS)
|
||||
if(isshadowlinglesser(thrallToRevive))
|
||||
to_chat(user, "<span class='warning'>[thrallToRevive] is already empowered.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
var/empowered_thralls = 0
|
||||
for(var/datum/mind/M in SSticker.mode.shadowling_thralls)
|
||||
if(!ishuman(M.current))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(isshadowlinglesser(H))
|
||||
empowered_thralls++
|
||||
if(empowered_thralls >= EMPOWERED_THRALL_LIMIT)
|
||||
to_chat(user, "<span class='warning'>You cannot spare this much energy. There are too many empowered thralls.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] places [user.p_their()] hands over [thrallToRevive]'s face, red light shining from beneath.</span>", \
|
||||
"<span class='shadowling'>You place your hands on [thrallToRevive]'s face and begin gathering energy...</span>")
|
||||
to_chat(thrallToRevive, "<span class='userdanger'>[user] places [user.p_their()] hands over your face. You feel energy gathering. Stand still...</span>")
|
||||
if(!do_mob(user, thrallToRevive, 80))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges into [thrallToRevive]'s face!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
thrallToRevive.Weaken(5)
|
||||
thrallToRevive.visible_message("<span class='warning'><b>[thrallToRevive] collapses, [thrallToRevive.p_their()] skin and face distorting!</span>", \
|
||||
"<span class='userdanger'><i>AAAAAAAAAAAAAAAAAAAGH-</i></span>")
|
||||
sleep(20)
|
||||
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
|
||||
"<span class='shadowling'><b>You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \
|
||||
darkness but wither slowly in light. In addition, you now have glare and true shadow walk.</b></span>")
|
||||
thrallToRevive.set_species(/datum/species/shadow/ling/lesser)
|
||||
thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/glare(null))
|
||||
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
else if(thrallToRevive.stat == DEAD)
|
||||
user.visible_message("<span class='danger'>[user] kneels over [thrallToRevive], placing [user.p_their()] hands on [thrallToRevive.p_their()] chest.</span>", \
|
||||
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
|
||||
thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive)
|
||||
if(!do_mob(user, thrallToRevive, 30))
|
||||
to_chat(user, "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
to_chat(user, "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>")
|
||||
user.visible_message("<span class='boldannounce'><i>Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!</i></span>")
|
||||
playsound(thrallToRevive, 'sound/weapons/egloves.ogg', 50, 1)
|
||||
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
|
||||
user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
|
||||
sleep(10)
|
||||
if(thrallToRevive.revive())
|
||||
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] heaves in breath, dim red light shining in [thrallToRevive.p_their()] eyes.</span>", \
|
||||
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
|
||||
thrallToRevive.Weaken(4)
|
||||
thrallToRevive.emote("gasp")
|
||||
playsound(thrallToRevive, "bodyfall", 50, 1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The target must be awake to empower or dead to revive.</span>")
|
||||
revert_cast(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle
|
||||
name = "Destroy Engines"
|
||||
desc = "Extends the time of the emergency shuttle's arrival by ten minutes using a life force of our enemy. Shuttle will be unable to be recalled. This can only be used once."
|
||||
panel = "Shadowling Abilities"
|
||||
range = 1
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
charge_max = 600
|
||||
click_radius = -1 // Precision baby
|
||||
selection_activated_message = "<span class='notice'>You start gathering destructive powers to delay the shuttle. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
action_icon_state = "extend_shuttle"
|
||||
var/global/extendlimit = 0
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!shadowling_check(user))
|
||||
charge_counter = charge_max
|
||||
return
|
||||
return FALSE
|
||||
if(extendlimit == 1)
|
||||
to_chat(user, "<span class='warning'>Shuttle was already delayed.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(target.stat)
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>[target] must not be an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>Shuttle was already delayed.</span>")
|
||||
return FALSE
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>The shuttle must be inbound only to the station.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
var/mob/living/carbon/human/M = target
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flash a bright red!</span>", \
|
||||
"<span class='notice'>You begin to draw [M]'s life force.</span>")
|
||||
M.visible_message("<span class='warning'>[M]'s face falls slack, [M.p_their()] jaw slightly distending.</span>", \
|
||||
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
|
||||
extendlimit = 1
|
||||
if(!do_after(user, 150, target = M))
|
||||
extendlimit = 0
|
||||
to_chat(M, "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>")
|
||||
to_chat(user, "<span class='warning'>You have been interrupted. The draw has failed.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You project [M]'s life force toward the approaching shuttle, extending its arrival duration!</span>")
|
||||
M.visible_message("<span class='warning'>[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
|
||||
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
|
||||
M.death()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/more_minutes = 6000
|
||||
var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
|
||||
GLOB.event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
|
||||
SSshuttle.emergency.setTimer(timer)
|
||||
SSshuttle.emergency.canRecall = FALSE
|
||||
user.mind.spell_list.Remove(src) //Can only be used once!
|
||||
qdel(src)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !target.stat && !is_shadow_or_thrall(target)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flash a bright red!</span>", \
|
||||
"<span class='notice'>You begin to draw [target]'s life force.</span>")
|
||||
target.visible_message("<span class='warning'>[target]'s face falls slack, [target.p_their()] jaw slightly distending.</span>", \
|
||||
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
|
||||
extendlimit = 1
|
||||
if(!do_after(user, 150, target = target))
|
||||
extendlimit = 0
|
||||
to_chat(target, "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>")
|
||||
to_chat(user, "<span class='warning'>You have been interrupted. The draw has failed.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You project [target]'s life force toward the approaching shuttle, extending its arrival duration!</span>")
|
||||
target.visible_message("<span class='warning'>[target]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
|
||||
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
|
||||
target.death()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/more_minutes = 6000
|
||||
var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
|
||||
GLOB.event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
|
||||
SSshuttle.emergency.setTimer(timer)
|
||||
SSshuttle.emergency.canRecall = FALSE
|
||||
user.mind.spell_list.Remove(src) //Can only be used once!
|
||||
qdel(src)
|
||||
|
||||
// ASCENDANT ABILITIES BEYOND THIS POINT //
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/annihilate
|
||||
/obj/effect/proc_holder/spell/targeted/click/annihilate
|
||||
name = "Annihilate"
|
||||
desc = "Gibs someone instantly."
|
||||
panel = "Ascendant"
|
||||
range = 7
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
charge_max = FALSE
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "annihilate"
|
||||
selection_activated_message = "<span class='notice'>You start thinking about gibs. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/annihilate/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/click/annihilate/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/simple_animal/ascendant_shadowling/SHA = user
|
||||
if(SHA.phasing)
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
@@ -756,45 +717,42 @@
|
||||
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnosis
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis
|
||||
name = "Hypnosis"
|
||||
desc = "Instantly enthralls a human."
|
||||
panel = "Ascendant"
|
||||
range = 7
|
||||
charge_max = 0
|
||||
clothes_req = 0
|
||||
charge_max = FALSE
|
||||
clothes_req = FALSE
|
||||
action_icon_state = "enthrall"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/hypnosis/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/simple_animal/ascendant_shadowling/SHA = user
|
||||
if(SHA.phasing)
|
||||
charge_counter = charge_max
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
return
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='notice'>You start preparing to mindwash over a mortal mind. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>Your mind relaxes.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
if(is_shadow_or_thrall(target))
|
||||
to_chat(user, "<span class='warning'>You cannot enthrall an ally.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.ckey || !target.mind)
|
||||
to_chat(user, "<span class='warning'>The target has no mind.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>The target must be conscious.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You can only enthrall humans.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/can_cast(mob/living/simple_animal/ascendant_shadowling/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.phasing)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>You are not in the same plane of existence. Unphase first.</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
to_chat(user, "<span class='shadowling'>You instantly rearrange <b>[target]</b>'s memories, hyptonitizing [target.p_them()] into a thrall.</span>")
|
||||
to_chat(target, "<span class='userdanger'><font size=3>An agonizing spike of pain drives into your mind, and--</font></span>")
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
target.add_language("Shadowling Hivemind")
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return !is_shadow_or_thrall(target) && target.ckey && target.mind && !target.stat
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/hypnosis/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
|
||||
to_chat(user, "<span class='shadowling'>You instantly rearrange <b>[target]</b>'s memories, hyptonitizing [target.p_them()] into a thrall.</span>")
|
||||
to_chat(target, "<span class='userdanger'><font size=3>An agonizing spike of pain drives into your mind, and--</font></span>")
|
||||
SSticker.mode.add_thrall(target.mind)
|
||||
target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL
|
||||
target.add_language("Shadowling Hivemind")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -99,14 +99,14 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
|
||||
to_chat(H, "<span class='shadowling'><b><i>Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.</b></i></span>")
|
||||
H.ExtinguishMob()
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/enthrall(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/glare(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle(null))
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/shadowling_extend_shuttle(null))
|
||||
|
||||
QDEL_NULL(H.hud_used)
|
||||
H.hud_used = new /datum/hud/human(H, ui_style2icon(H.client.prefs.UI_style), H.client.prefs.UI_style_color, H.client.prefs.UI_style_alpha)
|
||||
@@ -172,8 +172,8 @@ GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-u
|
||||
H.mind.transfer_to(A)
|
||||
A.name = H.real_name
|
||||
A.languages = H.languages
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/annihilate(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/hypnosis(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm(null))
|
||||
A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit(null))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
if(!gain_desc)
|
||||
gain_desc = "You have gained \the [src] ability."
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/cast_check(skipcharge = 0, mob/living/user = usr)
|
||||
/obj/effect/proc_holder/spell/vampire/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/living/user = usr)
|
||||
if(!user.mind)
|
||||
return 0
|
||||
if(!ishuman(user))
|
||||
@@ -45,7 +45,7 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/vampire/can_cast(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/vampire/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(!user.mind)
|
||||
return 0
|
||||
if(!ishuman(user))
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
switch(href_list["school"])
|
||||
if("destruction")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball(null))
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball.")
|
||||
if("bluespace")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
|
||||
@@ -74,7 +74,7 @@
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
|
||||
if("robeless")
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/mind_transfer(null))
|
||||
to_chat(M, "<B>Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/radio/headset(M), slot_l_ear)
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
/datum/spellbook_entry/horseman
|
||||
name = "Curse of the Horseman"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/horsemask
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
log_name = "HH"
|
||||
category = "Offensive"
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
/datum/spellbook_entry/fireball
|
||||
name = "Fireball"
|
||||
spell_type = /obj/effect/proc_holder/spell/fireball
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
log_name = "FB"
|
||||
category = "Offensive"
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
/datum/spellbook_entry/mindswap
|
||||
name = "Mindswap"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
log_name = "MT"
|
||||
category = "Mobility"
|
||||
|
||||
@@ -877,7 +877,7 @@
|
||||
return
|
||||
|
||||
/obj/item/spellbook/oneuse/fireball
|
||||
spell = /obj/effect/proc_holder/spell/fireball
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/fireball
|
||||
spellname = "fireball"
|
||||
icon_state = "bookfireball"
|
||||
desc = "This book feels warm to the touch."
|
||||
@@ -910,7 +910,7 @@
|
||||
user.EyeBlind(10)
|
||||
|
||||
/obj/item/spellbook/oneuse/mindswap
|
||||
spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/mind_transfer
|
||||
spellname = "mindswap"
|
||||
icon_state = "bookmindswap"
|
||||
desc = "This book's cover is pristine, though its pages look ragged and torn."
|
||||
@@ -934,8 +934,8 @@
|
||||
to_chat(user, "<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
|
||||
return
|
||||
|
||||
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
|
||||
swapper.cast(user, stored_swap, 1)
|
||||
var/obj/effect/proc_holder/spell/targeted/click/mind_transfer/swapper = new
|
||||
swapper.cast(user, stored_swap)
|
||||
|
||||
to_chat(stored_swap, "<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
|
||||
to_chat(user, "<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
|
||||
@@ -966,7 +966,7 @@
|
||||
user.Weaken(20)
|
||||
|
||||
/obj/item/spellbook/oneuse/horsemask
|
||||
spell = /obj/effect/proc_holder/spell/targeted/horsemask
|
||||
spell = /obj/effect/proc_holder/spell/targeted/click/horsemask
|
||||
spellname = "horses"
|
||||
icon_state = "bookhorses"
|
||||
desc = "This book is more horse than your mind has room for."
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
Care should be taken in hiding the item you choose as your phylactery after using Bind Soul, as you cannot revive if it destroyed or too far from your body! <br><br> \
|
||||
</i>Provides Bind Soul, Ethereal Jaunt, Fireball, Rod Form, Disable Tech, and Greater Forcewall.<i>"
|
||||
log_name = "DL"
|
||||
spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/fireball, \
|
||||
spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/click/fireball, \
|
||||
/obj/effect/proc_holder/spell/targeted/rod_form, /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech, /obj/effect/proc_holder/spell/targeted/forcewall/greater)
|
||||
is_ragin_restricted = TRUE
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/obj/item/camera/spooky = 1,
|
||||
/obj/item/nullrod = 1
|
||||
)
|
||||
|
||||
|
||||
/datum/outfit/job/chaplain/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
. = ..()
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
new_deity = deity_name
|
||||
B.deity_name = new_deity
|
||||
|
||||
H.AddSpell(new /obj/effect/proc_holder/spell/targeted/chaplain_bless(null))
|
||||
H.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/chaplain_bless(null))
|
||||
|
||||
var/accepted = 0
|
||||
var/outoftime = 0
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/list/default_genes = list(REGEN, BREATHLESS, COLDRES)
|
||||
var/list/default_spells = list()
|
||||
var/activated = FALSE //for wishgranters to not give an option if someone already has it.
|
||||
|
||||
|
||||
/datum/superheroes/proc/create(var/mob/living/carbon/human/H)
|
||||
assign_genes(H)
|
||||
assign_spells(H)
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
/datum/superheroes/griffin
|
||||
name = "The Griffin"
|
||||
default_spells = list(/obj/effect/proc_holder/spell/targeted/recruit)
|
||||
default_spells = list(/obj/effect/proc_holder/spell/targeted/click/recruit)
|
||||
class = "Supervillain"
|
||||
desc = "You are The Griffin, the ultimate supervillain. You thrive on chaos and have no respect for the supposed authority \
|
||||
of the command staff of this station. Along with your gang of dim-witted yet trusty henchmen, you will be able to execute \
|
||||
@@ -145,100 +145,102 @@
|
||||
|
||||
|
||||
//The Griffin's special recruit abilitiy
|
||||
/obj/effect/proc_holder/spell/targeted/recruit
|
||||
/obj/effect/proc_holder/spell/targeted/click/recruit
|
||||
name = "Recruit Greyshirt"
|
||||
desc = "Allows you to recruit a conscious, non-braindead, non-catatonic human to be part of the Greyshirts, your personal henchmen. This works on Civilians only and you can recruit a maximum of 3!."
|
||||
charge_max = 450
|
||||
clothes_req = 0
|
||||
clothes_req = FALSE
|
||||
range = 1 //Adjacent to user
|
||||
action_icon_state = "spell_greytide"
|
||||
var/recruiting = 0
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/recruit/cast(list/targets,mob/living/user = usr)
|
||||
for(var/mob/living/carbon/human/target in targets)
|
||||
var/obj/item/organ/external/head/head_organ = target.get_organ("head")
|
||||
if(SSticker.mode.greyshirts.len >= 3)
|
||||
click_radius = -1
|
||||
selection_activated_message = "<span class='notice'>You start preparing a mindblowing monologue. <B>Left-click to cast at a target!</B></span>"
|
||||
selection_deactivated_message = "<span class='notice'>You decide to save your brilliance for another day.</span>"
|
||||
allowed_type = /mob/living/carbon/human
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/recruit/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
|
||||
if(SSticker.mode.greyshirts.len >= 3)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='warning'>You have already recruited the maximum number of henchmen.</span>")
|
||||
if(!in_range(user, target))
|
||||
to_chat(user, "<span class='warning'>You need to be closer to enthrall [target].</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!target.ckey)
|
||||
to_chat(user, "<span class='warning'>The target has no mind.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.stat)
|
||||
to_chat(user, "<span class='warning'>The target must be conscious.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(!ishuman(target))
|
||||
to_chat(user, "<span class='warning'>You can only recruit humans.</span>")
|
||||
charge_counter = charge_max
|
||||
return
|
||||
if(target.mind.assigned_role != "Civilian")
|
||||
to_chat(user, "<span class='warning'>You can only recruit Civilians.</span>")
|
||||
return
|
||||
if(recruiting)
|
||||
return FALSE
|
||||
if(recruiting)
|
||||
if(show_message)
|
||||
to_chat(user, "<span class='danger'>You are already recruiting!</span>")
|
||||
charge_counter = charge_max
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/recruit/valid_target(mob/living/carbon/human/target, user)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
return target.ckey && !target.stat
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/click/recruit/cast(list/targets,mob/living/user = usr)
|
||||
var/mob/living/carbon/human/target = targets[1]
|
||||
if(target.mind.assigned_role != "Civilian")
|
||||
to_chat(user, "<span class='warning'>You can only recruit Civilians.</span>")
|
||||
revert_cast(user)
|
||||
return
|
||||
recruiting = TRUE
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the recruiting process.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] focuses in concentration. Your head begins to ache.</span>")
|
||||
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You begin by introducing yourself and explaining what you're about.</span>")
|
||||
user.visible_message("<span class='danger'>[user] introduces [user.p_them()]self and explains [user.p_their()] plans.</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin the recruitment of [target].</span>")
|
||||
user.visible_message("<span class='danger'>[user] leans over towards [target], whispering excitedly as [user.p_they()] give[user.p_s()] a speech.</span>")
|
||||
to_chat(target, "<span class='danger'>You feel yourself agreeing with [user], and a surge of loyalty begins building.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>[target.p_they(TRUE)] are enslaved by Nanotrasen. You feel [target.p_their()] interest in your cause wane and disappear.</span>")
|
||||
user.visible_message("<span class='danger'>[user] stops talking for a moment, then moves back away from [target].</span>")
|
||||
to_chat(target, "<span class='danger'>Your mindshield implant activates, protecting you from conversion.</span>")
|
||||
return
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin filling out the application form with [target].</span>")
|
||||
user.visible_message("<span class='danger'>[user] pulls out a pen and paper and begins filling an application form with [target].</span>")
|
||||
to_chat(target, "<span class='danger'>You are being convinced by [user] to fill out an application form to become a henchman.</span>")//Ow the edge
|
||||
|
||||
if(!do_mob(user, target, 100)) //around 30 seconds total for enthralling, 45 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='danger'>The enrollment process has been interrupted - you have lost the attention of [target].</span>")
|
||||
to_chat(target, "<span class='warning'>You move away and are no longer under the charm of [user]. The application form is null and void.</span>")
|
||||
recruiting = FALSE
|
||||
return
|
||||
recruiting = 1
|
||||
to_chat(user, "<span class='danger'>This target is valid. You begin the recruiting process.</span>")
|
||||
to_chat(target, "<span class='userdanger'>[user] focuses in concentration. Your head begins to ache.</span>")
|
||||
|
||||
for(var/progress = 0, progress <= 3, progress++)
|
||||
switch(progress)
|
||||
if(1)
|
||||
to_chat(user, "<span class='notice'>You begin by introducing yourself and explaining what you're about.</span>")
|
||||
user.visible_message("<span class='danger'>[user] introduces [user.p_them()]self and explains [user.p_their()] plans.</span>")
|
||||
if(2)
|
||||
to_chat(user, "<span class='notice'>You begin the recruitment of [target].</span>")
|
||||
user.visible_message("<span class='danger'>[user] leans over towards [target], whispering excitedly as [user.p_they()] give[user.p_s()] a speech.</span>")
|
||||
to_chat(target, "<span class='danger'>You feel yourself agreeing with [user], and a surge of loyalty begins building.</span>")
|
||||
target.Weaken(12)
|
||||
sleep(20)
|
||||
if(ismindshielded(target))
|
||||
to_chat(user, "<span class='notice'>[target.p_they(TRUE)] are enslaved by Nanotrasen. You feel [target.p_their()] interest in your cause wane and disappear.</span>")
|
||||
user.visible_message("<span class='danger'>[user] stops talking for a moment, then moves back away from [target].</span>")
|
||||
to_chat(target, "<span class='danger'>Your mindshield implant activates, protecting you from conversion.</span>")
|
||||
return
|
||||
if(3)
|
||||
to_chat(user, "<span class='notice'>You begin filling out the application form with [target].</span>")
|
||||
user.visible_message("<span class='danger'>[user] pulls out a pen and paper and begins filling an application form with [target].</span>")
|
||||
to_chat(target, "<span class='danger'>You are being convinced by [user] to fill out an application form to become a henchman.</span>")//Ow the edge
|
||||
|
||||
if(!do_mob(user, target, 100)) //around 30 seconds total for enthralling, 45 for someone with a mindshield implant
|
||||
to_chat(user, "<span class='danger'>The enrollment process has been interrupted - you have lost the attention of [target].</span>")
|
||||
to_chat(target, "<span class='warning'>You move away and are no longer under the charm of [user]. The application form is null and void.</span>")
|
||||
recruiting = 0
|
||||
return
|
||||
|
||||
recruiting = 0
|
||||
to_chat(user, "<span class='notice'>You have recruited <b>[target]</b> as your henchman!</span>")
|
||||
to_chat(target, "<span class='deadsay'><b>You have decided to enroll as a henchman for [user]. You are now part of the feared 'Greyshirts'.</b></span>")
|
||||
to_chat(target, "<span class='deadsay'><b>You must follow the orders of [user], and help [user.p_them()] succeed in [user.p_their()] dastardly schemes.</span>")
|
||||
to_chat(target, "<span class='deadsay'>You may not harm other Greyshirt or [user]. However, you do not need to obey other Greyshirts.</span>")
|
||||
SSticker.mode.greyshirts += target.mind
|
||||
target.set_species(/datum/species/human)
|
||||
recruiting = FALSE
|
||||
to_chat(user, "<span class='notice'>You have recruited <b>[target]</b> as your henchman!</span>")
|
||||
to_chat(target, "<span class='deadsay'><b>You have decided to enroll as a henchman for [user]. You are now part of the feared 'Greyshirts'.</b></span>")
|
||||
to_chat(target, "<span class='deadsay'><b>You must follow the orders of [user], and help [user.p_them()] succeed in [user.p_their()] dastardly schemes.</span>")
|
||||
to_chat(target, "<span class='deadsay'>You may not harm other Greyshirt or [user]. However, you do not need to obey other Greyshirts.</span>")
|
||||
SSticker.mode.greyshirts += target.mind
|
||||
target.set_species(/datum/species/human)
|
||||
var/obj/item/organ/external/head/head_organ = target.get_organ("head")
|
||||
if(head_organ)
|
||||
head_organ.h_style = "Bald"
|
||||
head_organ.f_style = "Shaved"
|
||||
target.s_tone = 35
|
||||
// No `update_dna=0` here because the character is being over-written
|
||||
target.change_eye_color(1,1,1)
|
||||
for(var/obj/item/W in target.get_all_slots())
|
||||
target.unEquip(W)
|
||||
target.rename_character(target.real_name, "Generic Henchman ([rand(1, 1000)])")
|
||||
target.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey/greytide(target), slot_w_uniform)
|
||||
target.equip_to_slot_or_del(new /obj/item/clothing/shoes/black/greytide(target), slot_shoes)
|
||||
target.equip_to_slot_or_del(new /obj/item/storage/toolbox/mechanical/greytide(target), slot_l_hand)
|
||||
target.equip_to_slot_or_del(new /obj/item/radio/headset(target), slot_l_ear)
|
||||
var/obj/item/card/id/syndicate/W = new(target)
|
||||
W.icon_state = "lifetimeid"
|
||||
W.access = list(ACCESS_MAINT_TUNNELS)
|
||||
W.assignment = "Greyshirt"
|
||||
W.rank = "Greyshirt"
|
||||
W.flags |= NODROP
|
||||
W.SetOwnerInfo(target)
|
||||
W.UpdateName()
|
||||
target.equip_to_slot_or_del(W, slot_wear_id)
|
||||
target.regenerate_icons()
|
||||
target.s_tone = 35
|
||||
// No `update_dna=0` here because the character is being over-written
|
||||
target.change_eye_color(1,1,1)
|
||||
for(var/obj/item/W in target.get_all_slots())
|
||||
target.unEquip(W)
|
||||
target.rename_character(target.real_name, "Generic Henchman ([rand(1, 1000)])")
|
||||
target.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey/greytide(target), slot_w_uniform)
|
||||
target.equip_to_slot_or_del(new /obj/item/clothing/shoes/black/greytide(target), slot_shoes)
|
||||
target.equip_to_slot_or_del(new /obj/item/storage/toolbox/mechanical/greytide(target), slot_l_hand)
|
||||
target.equip_to_slot_or_del(new /obj/item/radio/headset(target), slot_l_ear)
|
||||
var/obj/item/card/id/syndicate/W = new(target)
|
||||
W.icon_state = "lifetimeid"
|
||||
W.access = list(ACCESS_MAINT_TUNNELS)
|
||||
W.assignment = "Greyshirt"
|
||||
W.rank = "Greyshirt"
|
||||
W.flags |= NODROP
|
||||
W.SetOwnerInfo(target)
|
||||
W.UpdateName()
|
||||
target.equip_to_slot_or_del(W, slot_wear_id)
|
||||
target.regenerate_icons()
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
/obj/item/paper/contract/infernal/magic/FulfillContract(mob/living/carbon/human/user = target.current, blood = 0)
|
||||
if(!istype(user) || !user.mind)
|
||||
return -1
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/hellish(null))
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/click/fireball/hellish(null))
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
return ..()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user