diff --git a/code/datums/spell.dm b/code/datums/spell.dm index fe2e7431cf3..f5356474019 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -70,6 +70,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin var/ghost = 0 // Skip life check. var/clothes_req = 1 //see if it requires clothes + var/human_req = 0 //spell can only be cast by humans + var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell var/invocation_emote_self = null @@ -102,11 +104,11 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin 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, "You shouldn't have this spell! Something's wrong.") return 0 - if(istype(user, /mob/living/carbon/human)) + + if(ishuman(user)) var/mob/living/carbon/human/caster = user if(caster.remoteview_target) caster.remoteview_target = null @@ -129,26 +131,31 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if(!ghost) if(user.stat && !stat_allowed) - to_chat(user, "Not when you're incapacitated.") + to_chat(user, "You can't cast this spell while incapacitated.") 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/spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list())) - if(clothes_req && !(spell && istype(spell)))//clothes check - if(!istype(user, /mob/living/carbon/human)) - to_chat(user, "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans.") + + 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) && !(clothes_spell && istype(clothes_spell)))//clothes check + var/mob/living/carbon/human/H = user + if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard)) + to_chat(user, "I don't feel strong enough without my robe.") return 0 - if(!istype(user:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/rig/wizard)) - to_chat(user, "I don't feel strong enough without my robe.") + if(!istype(H.shoes, /obj/item/clothing/shoes/sandal)) + to_chat(user, "I don't feel strong enough without my sandals.") return 0 - if(!istype(user:shoes, /obj/item/clothing/shoes/sandal)) - to_chat(user, "I don't feel strong enough without my sandals.") - return 0 - if(!istype(user:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/rig/wizard)) + if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard)) to_chat(user, "I don't feel strong enough without my hat.") return 0 + else if(!ishuman(user)) + if(clothes_req || human_req) + to_chat(user, "This spell can only be cast by humans!") + return 0 + if(nonabstract_req && (isbrain(user) || ispAI(user))) + to_chat(user, "This spell can only be cast by physical beings!") + return 0 if(!skipcharge) switch(charge_type) @@ -426,7 +433,6 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin return 0 if(ishuman(user)) - var/mob/living/carbon/human/H = user if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled()) @@ -442,8 +448,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard)) return 0 else - if(clothes_req) + if(clothes_req || human_req) return 0 - if(isbrain(user) || ispAI(user)) + if(nonabstract_req && (isbrain(user) || ispAI(user))) return 0 return 1 diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index badf94d60d6..c213828cf29 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -1,7 +1,8 @@ /obj/effect/proc_holder/spell/targeted/area_teleport name = "Area teleport" desc = "This spell teleports you to a type of area of your selection." - + nonabstract_req = 1 + var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list var/invocation_area = 1 //if the invocation appends the selected area diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 9e8a6941f0b..b9ad3d22e70 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -10,6 +10,7 @@ range = -1 cooldown_min = 100 //50 deciseconds reduction per rank include_user = 1 + nonabstract_req = 1 centcom_cancast = 0 //Prevent people from getting to centcom var phaseshift = 0 diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm index b0b85f4b47c..296521405a0 100644 --- a/code/datums/spells/mime.dm +++ b/code/datums/spells/mime.dm @@ -11,6 +11,7 @@ clothes_req = 0 range = 0 cast_sound = null + human_req = 1 action_icon_state = "mime" action_background_icon_state = "bg_mime" @@ -35,6 +36,7 @@ charge_max = 3000 range = -1 include_user = 1 + human_req = 1 action_icon_state = "mime" action_background_icon_state = "bg_mime" diff --git a/code/datums/spells/shapeshift.dm b/code/datums/spells/shapeshift.dm new file mode 100644 index 00000000000..a5f1de1baec --- /dev/null +++ b/code/datums/spells/shapeshift.dm @@ -0,0 +1,82 @@ +/obj/effect/proc_holder/spell/targeted/shapeshift + name = "Shapechange" + desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed." + clothes_req = 0 + human_req = 0 + charge_max = 200 + cooldown_min = 50 + range = -1 + include_user = 1 + invocation = "RAC'WA NO!" + invocation_type = "shout" + action_icon_state = "shapeshift" + + var/shapeshift_type + var/list/current_shapes = list() + var/list/current_casters = list() + var/list/possible_shapes = list(/mob/living/simple_animal/mouse,\ + /mob/living/simple_animal/pet/corgi,\ + /mob/living/simple_animal/bot/ed209,\ + /mob/living/simple_animal/hostile/construct/armoured) + +/obj/effect/proc_holder/spell/targeted/shapeshift/cast(list/targets, mob/user = usr) + for(var/mob/living/M in targets) + if(!shapeshift_type) + var/list/animal_list = list() + for(var/path in possible_shapes) + var/mob/living/simple_animal/A = path + animal_list[initial(A.name)] = path + shapeshift_type = input(M, "Choose Your Animal Form!", "It's Morphing Time!", null) as anything in animal_list + if(!shapeshift_type) //If you aren't gonna decide I am! + shapeshift_type = pick(animal_list) + shapeshift_type = animal_list[shapeshift_type] + if(M in current_shapes) + Restore(M) + else + Shapeshift(M) + +/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Shapeshift(mob/living/caster) + for(var/mob/living/M in caster) + if(M.status_flags & GODMODE) + to_chat(caster, "You're already shapeshifted!") + return + + var/mob/living/shape = new shapeshift_type(caster.loc) + caster.loc = shape + caster.status_flags |= GODMODE + + current_shapes |= shape + current_casters |= caster + clothes_req = 0 + human_req = 0 + + caster.mind.transfer_to(shape) + +/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Restore(mob/living/shape) + var/mob/living/caster + for(var/mob/living/M in shape) + if(M in current_casters) + caster = M + break + if(!caster) + return + caster.loc = shape.loc + caster.status_flags &= ~GODMODE + + clothes_req = initial(clothes_req) + human_req = initial(human_req) + current_casters.Remove(caster) + current_shapes.Remove(shape) + + shape.mind.transfer_to(caster) + qdel(shape) //Gib it maybe ? + +/obj/effect/proc_holder/spell/targeted/shapeshift/dragon + name = "Dragon Form" + desc = "Take on the shape a lesser ash drake." + invocation = "RAAAAAAAAWR!" + + shapeshift_type = /mob/living/simple_animal/hostile/megafauna/dragon/lesser + list/current_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser) + list/current_casters = list() + list/possible_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser) \ No newline at end of file diff --git a/code/datums/spells/turf_teleport.dm b/code/datums/spells/turf_teleport.dm index ce3f5720cf0..bcde1d0c2e9 100644 --- a/code/datums/spells/turf_teleport.dm +++ b/code/datums/spells/turf_teleport.dm @@ -1,6 +1,7 @@ /obj/effect/proc_holder/spell/targeted/turf_teleport name = "Turf Teleport" desc = "This spell teleports the target to the turf in range." + nonabstract_req = 1 var/inner_tele_radius = 1 var/outer_tele_radius = 2 diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index a2b11c8a214..84636fdf4fd 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -192,9 +192,10 @@ to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.") H.set_species("Skeleton") if(2) - to_chat(user, "You don't feel so good...") - message_admins("[key_name_admin(user)] has started transforming into a dragon via dragon's blood.") - H.ForceContractDisease(new /datum/disease/transformation/dragon(0)) + to_chat(user, "Power courses through you! You can now shift your form at will.") + if(user.mind) + var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new + user.mind.AddSpell(D) if(3) to_chat(user, "You feel like you could walk straight through lava now.") H.weather_immunities |= "lava" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index 5832842b4ca..5ced32e8bfe 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -264,8 +264,8 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/dragon/lesser name = "lesser ash drake" - maxHealth = 300 - health = 300 + maxHealth = 200 + health = 200 faction = list("neutral") melee_damage_upper = 30 melee_damage_lower = 30 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index c29a6e8a4f8..f939dbdc91f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -73,7 +73,7 @@ if(isliving(target)) var/mob/living/L = target if(L.stat != DEAD) - if(ranged && ranged_cooldown <= world.time) + if(!client && ranged && ranged_cooldown <= world.time) OpenFire() else devour(L) diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 325d886af8a..9bf1a315131 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/paradise.dme b/paradise.dme index e7698d5eeed..d9b5b155bb0 100644 --- a/paradise.dme +++ b/paradise.dme @@ -304,6 +304,7 @@ #include "code\datums\spells\mind_transfer.dm" #include "code\datums\spells\projectile.dm" #include "code\datums\spells\rathens.dm" +#include "code\datums\spells\shapeshift.dm" #include "code\datums\spells\summonitem.dm" #include "code\datums\spells\touch_attacks.dm" #include "code\datums\spells\trigger.dm"