mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-02 13:32:32 +00:00
Wizardry Inc. (#8899)
Wizard spellbooks can now be stored in the belt slot.
Necromancers now get 10 spell points, up from 8.
Smoke now properly layers over mobs, obscuring them.
Wizard Apprentices and Skeletons are now in the Ghost Spawner menu. The former can be enabled by buying an Apprentice Pebble artifact, a new wizard item which acts as a portable spawnpoint. The latter by casting Raise Dead on a corpse.
Apprentices are now given additional spells at the bottom of their spellbook, depending on which type of wizard their master is."
Bought artifacts now appear in your hands, if you have any free.
The Return to Master spell has received numerous bugfixes and should now work as expected, most of the time.
This commit is contained in:
24
code/modules/ghostroles/spawner/human/antagonist/skeleton.dm
Normal file
24
code/modules/ghostroles/spawner/human/antagonist/skeleton.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/datum/ghostspawner/human/skeleton
|
||||
short_name = "skeleton"
|
||||
name = "Risen Skeleton"
|
||||
desc = "Serve your Master. Fight things."
|
||||
tags = list("Antagonist")
|
||||
|
||||
enabled = FALSE
|
||||
|
||||
spawn_mob = /mob/living/carbon/human/skeleton
|
||||
|
||||
/datum/ghostspawner/human/skeleton/select_spawnpoint(var/use)
|
||||
return TRUE //We just fake it here, since the spawnpoint is selected if someone is spawned in.
|
||||
|
||||
//The proc to actually spawn in the user
|
||||
/datum/ghostspawner/human/skeleton/spawn_mob(mob/user)
|
||||
if(!length(spawn_atoms))
|
||||
to_chat(user, SPAN_DANGER("There are no available skeletons to spawn at!"))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/skeleton/skeleton = pick(spawn_atoms)
|
||||
|
||||
if(user && skeleton)
|
||||
return skeleton.spawn_skeleton(user)
|
||||
return FALSE
|
||||
24
code/modules/ghostroles/spawner/human/antagonist/wizard.dm
Normal file
24
code/modules/ghostroles/spawner/human/antagonist/wizard.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/datum/ghostspawner/human/apprentice
|
||||
short_name = "apprentice"
|
||||
name = "Wizard Apprentice"
|
||||
desc = "Serve your Master. Cast Spells."
|
||||
tags = list("Antagonist")
|
||||
|
||||
enabled = FALSE
|
||||
|
||||
spawn_mob = /mob/living/carbon/human
|
||||
|
||||
/datum/ghostspawner/human/apprentice/select_spawnpoint(var/use)
|
||||
return TRUE //We just fake it here, since the spawnpoint is selected if someone is spawned in.
|
||||
|
||||
//The proc to actually spawn in the user
|
||||
/datum/ghostspawner/human/apprentice/spawn_mob(mob/user)
|
||||
if(!length(spawn_atoms))
|
||||
to_chat(user, SPAN_DANGER("There are no available apprentice pebbles to spawn at!"))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/apprentice_pebble/pebble = pick(spawn_atoms)
|
||||
|
||||
if(user && pebble)
|
||||
return pebble.spawn_apprentice(user)
|
||||
return FALSE
|
||||
@@ -1,6 +1,17 @@
|
||||
/mob/living/carbon/human/skeleton/Initialize(mapload)
|
||||
. = ..(mapload, "Skeleton")
|
||||
|
||||
/mob/living/carbon/human/skeleton
|
||||
var/master
|
||||
|
||||
/mob/living/carbon/human/skeleton/proc/spawn_skeleton(var/mob/user)
|
||||
src.ckey = user.ckey
|
||||
src.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
|
||||
src.name = src.real_name
|
||||
if(master)
|
||||
to_chat(src, "<B>You are a skeleton minion to [master], they are your master. Obey and protect your master at all costs, you have no free will.</B>")
|
||||
SSghostroles.remove_spawn_atom("skeleton", src)
|
||||
|
||||
/datum/species/skeleton //SPOOKY
|
||||
name = "Skeleton"
|
||||
name_plural = "skeletons"
|
||||
@@ -11,22 +22,22 @@
|
||||
|
||||
total_health = 70 //gotta get headshots to kill them, so they're frail
|
||||
|
||||
default_language = "Ceti Basic"
|
||||
language = "Cult"
|
||||
name_language = "Cult"
|
||||
default_language = LANGUAGE_TCB
|
||||
language = LANGUAGE_CULT
|
||||
name_language = LANGUAGE_CULT
|
||||
unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/sharp)
|
||||
darksight = 8
|
||||
has_organ = list() //skeletons are empty shells for now, maybe we can add something in the future
|
||||
siemens_coefficient = 0
|
||||
ethanol_resistance = -1 //no drunk skeletons
|
||||
taste_sensitivity = TASTE_NUMB
|
||||
breakcuffs = list(MALE,FEMALE,NEUTER)
|
||||
breakcuffs = list(MALE, FEMALE, NEUTER)
|
||||
|
||||
meat_type = /obj/item/reagent_containers/food/snacks/meat/undead
|
||||
|
||||
reagent_tag = IS_UNDEAD
|
||||
|
||||
virus_immune = 1
|
||||
virus_immune = TRUE
|
||||
|
||||
rarity_value = 10
|
||||
blurb = "Skeletons are undead brought back to life through dark wizardry, \
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/obj/item/apprentice_pebble
|
||||
name = "apprentice pebble"
|
||||
desc = "A pebble, it feels warm to the touch."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "pebble"
|
||||
origin_tech = list(TECH_BLUESPACE = 6, TECH_MATERIAL = 6, TECH_BIO = 6)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/obj/item/contract/apprentice/contract
|
||||
|
||||
/obj/item/apprentice_pebble/Initialize()
|
||||
. = ..()
|
||||
contract = new /obj/item/contract/apprentice(src)
|
||||
SSghostroles.add_spawn_atom("apprentice", src)
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
say_dead_direct("An artificer pebble has been created in [A.name]! Spawn at it by using the ghost spawner menu in the ghost tab.")
|
||||
|
||||
/obj/item/apprentice_pebble/Destroy()
|
||||
if(contract)
|
||||
QDEL_NULL(contract)
|
||||
SSghostroles.remove_spawn_atom("apprentice", src)
|
||||
return ..()
|
||||
|
||||
/obj/item/apprentice_pebble/proc/spawn_apprentice(var/mob/user)
|
||||
var/mob/living/carbon/human/G = new /mob/living/carbon/human(get_turf(src))
|
||||
G.ckey = user.ckey
|
||||
G.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
|
||||
G.name = G.real_name
|
||||
|
||||
G.preEquipOutfit(/datum/outfit/admin/wizard/apprentice, FALSE)
|
||||
G.equipOutfit(/datum/outfit/admin/wizard/apprentice, FALSE)
|
||||
|
||||
G.put_in_hands(contract)
|
||||
contract = null
|
||||
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(5, 0, get_turf(src))
|
||||
smoke.start()
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/apprentice_pebble/pickup(mob/living/user)
|
||||
..()
|
||||
if(!user.is_wizard())
|
||||
to_chat(user, SPAN_WARNING("As you pick up \the [src], you feel a wave of power wash over you."))
|
||||
for(var/obj/machinery/light/P in view(7, user))
|
||||
P.flicker(1)
|
||||
@@ -1,7 +1,8 @@
|
||||
/obj/item/contract/apprentice
|
||||
name = "apprentice wizarding contract"
|
||||
desc = "a wizarding school contract for those who want to sign their soul for a piece of the magic pie."
|
||||
desc = "A wizarding school contract for those who want to sign their soul for a piece of the magic pie."
|
||||
color = "#993300"
|
||||
var/list/additional_spells = list()
|
||||
|
||||
/obj/item/contract/apprentice/contract_effect(mob/user)
|
||||
if(user.mind.assigned_role == "Apprentice")
|
||||
@@ -12,8 +13,10 @@
|
||||
to_chat(user, SPAN_NOTICE("With the signing of this paper you agree to become \the [contract_master]'s apprentice in the art of wizardry."))
|
||||
user.faction = "Space Wizard"
|
||||
wizards.add_antagonist_mind(user.mind, TRUE)
|
||||
var/obj/item/I = new /obj/item/spellbook/student(get_turf(user))
|
||||
user.put_in_hands(I)
|
||||
var/obj/item/spellbook/student/S = new /obj/item/spellbook/student(get_turf(user))
|
||||
for(var/additional_spell in additional_spells)
|
||||
S.spellbook.spells[additional_spell] = additional_spells[additional_spell]
|
||||
user.put_in_hands(S)
|
||||
user.add_spell(new /spell/noclothes)
|
||||
if(contract_master)
|
||||
user.add_spell(new /spell/contract/return_master(contract_master), "const_spell_ready")
|
||||
|
||||
@@ -5,6 +5,7 @@ var/list/artefact_feedback = list(/obj/structure/closet/wizard/armor = "HS",
|
||||
/obj/item/gun/energy/staff/focus = "MF",
|
||||
/obj/item/monster_manual = "MA",
|
||||
/obj/item/contract/apprentice = "CP",
|
||||
/obj/item/apprentice_pebble = "AP",
|
||||
/obj/structure/closet/wizard/souls = "SS",
|
||||
/obj/structure/closet/wizard/scrying = "SO",
|
||||
/obj/item/teleportation_scroll = "TS",
|
||||
@@ -21,14 +22,15 @@ var/list/artefact_feedback = list(/obj/structure/closet/wizard/armor = "HS",
|
||||
icon_state = "spellbook"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = 2
|
||||
w_class = ITEMSIZE_SMALL
|
||||
slot_flags = SLOT_BELT
|
||||
var/uses = 1
|
||||
var/temp = null
|
||||
var/datum/spellbook/spellbook
|
||||
var/spellbook_type = /datum/spellbook/ //for spawning specific spellbooks.
|
||||
var/spellbook_type = /datum/spellbook //for spawning specific spellbooks.
|
||||
|
||||
/obj/item/spellbook/New()
|
||||
..()
|
||||
/obj/item/spellbook/Initialize()
|
||||
. = ..()
|
||||
set_spellbook(spellbook_type)
|
||||
|
||||
/obj/item/spellbook/proc/set_spellbook(var/type)
|
||||
@@ -159,8 +161,25 @@ var/list/artefact_feedback = list(/obj/structure/closet/wizard/armor = "HS",
|
||||
else
|
||||
if(ispath(path,/spell))
|
||||
temp = src.add_spell(usr,path)
|
||||
else if(ispath(path, /obj/item/contract/apprentice))
|
||||
var/obj/item/contract/apprentice/A = new path(get_turf(usr))
|
||||
A.contract_master = usr
|
||||
A.additional_spells = spellbook.apprentice_spells
|
||||
temp = "You have purchased \a [A]."
|
||||
spellbook.max_uses -= spellbook.spells[path]
|
||||
playsound(get_turf(usr),'sound/effects/phasein.ogg',50,1)
|
||||
usr.put_in_hands(A)
|
||||
else if(ispath(path, /obj/item/apprentice_pebble))
|
||||
var/obj/item/apprentice_pebble/A = new path(get_turf(usr))
|
||||
A.contract.additional_spells = spellbook.apprentice_spells
|
||||
A.contract.contract_master = usr
|
||||
temp = "You have purchased \a [A]."
|
||||
spellbook.max_uses -= spellbook.spells[path]
|
||||
playsound(get_turf(usr),'sound/effects/phasein.ogg',50,1)
|
||||
usr.put_in_hands(A)
|
||||
else
|
||||
var/obj/O = new path(get_turf(usr))
|
||||
usr.put_in_hands(O)
|
||||
temp = "You have purchased \a [O]."
|
||||
spellbook.max_uses -= spellbook.spells[path]
|
||||
//finally give it a bit of an oomf
|
||||
@@ -227,4 +246,5 @@ var/list/artefact_feedback = list(/obj/structure/closet/wizard/armor = "HS",
|
||||
/datum/spellbook/battlemage = 1,
|
||||
/datum/spellbook/druid = 1,
|
||||
/datum/spellbook/necromancer = 1
|
||||
) //spell's path = cost of spell
|
||||
) //spell's path = cost of spell
|
||||
var/list/apprentice_spells = list() // extra spells that apprentices get, based on their master's book
|
||||
@@ -30,5 +30,14 @@
|
||||
/obj/item/storage/belt/wands/full = 2,
|
||||
/obj/item/melee/energy/wizard = 2,
|
||||
/obj/item/monster_manual = 2,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
apprentice_spells = list(
|
||||
/spell/targeted/equip_item/shield = 1,
|
||||
/spell/targeted/torment = 1,
|
||||
/spell/targeted/heal_target = 2,
|
||||
/spell/targeted/shapeshift/corrupt_form = 1,
|
||||
/obj/item/melee/energy/wizard = 2
|
||||
)
|
||||
@@ -32,5 +32,14 @@
|
||||
/obj/item/gun/energy/staff/focus = 2,
|
||||
/obj/item/storage/belt/wands/full = 2,
|
||||
/obj/item/poppet = 1,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
apprentice_spells = list(
|
||||
/spell/targeted/heal_target = 1,
|
||||
/spell/targeted/heal_target/area = 1,
|
||||
/spell/targeted/resurrection = 2,
|
||||
/spell/targeted/genetic/blind = 1,
|
||||
/spell/radiant_aura = 1
|
||||
)
|
||||
@@ -30,5 +30,13 @@
|
||||
/obj/structure/closet/wizard/souls = 1,
|
||||
/obj/item/monster_manual = 1,
|
||||
/obj/item/poppet = 1,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
apprentice_spells = list(
|
||||
/spell/targeted/heal_target = 1,
|
||||
/spell/targeted/heal_target/sacrifice = 1,
|
||||
/spell/aoe_turf/conjure/grove/sanctuary = 1,
|
||||
/obj/item/poppet = 1
|
||||
)
|
||||
@@ -10,7 +10,7 @@
|
||||
title = "The Art of Necromancy"
|
||||
title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent."
|
||||
book_flags = CAN_MAKE_CONTRACTS
|
||||
max_uses = 8
|
||||
max_uses = 10
|
||||
|
||||
spells = list(/spell/targeted/projectile/dumbfire/fireball = 1,
|
||||
/spell/targeted/torment = 1,
|
||||
@@ -26,5 +26,13 @@
|
||||
/obj/structure/closet/wizard/armor = 1,
|
||||
/obj/structure/closet/wizard/scrying = 2,
|
||||
/obj/structure/closet/wizard/souls = 1,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
apprentice_spells = list(
|
||||
/spell/aoe_turf/conjure/summon/bats = 1,
|
||||
/spell/targeted/shapeshift/corrupt_form = 1,
|
||||
/spell/targeted/raise_dead = 2,
|
||||
/obj/structure/closet/wizard/souls = 1
|
||||
)
|
||||
@@ -25,5 +25,6 @@
|
||||
/obj/structure/closet/wizard/scrying = 2,
|
||||
/obj/item/storage/belt/wands/full = 4,
|
||||
/obj/item/teleportation_scroll = 1,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
@@ -28,5 +28,13 @@
|
||||
/obj/item/gun/energy/staff/animate = 1,
|
||||
/obj/structure/closet/wizard/scrying = 1,
|
||||
/obj/item/monster_manual = 2,
|
||||
/obj/item/contract/apprentice = 1
|
||||
/obj/item/contract/apprentice = 1,
|
||||
/obj/item/apprentice_pebble = 2
|
||||
)
|
||||
|
||||
apprentice_spells = list(
|
||||
/spell/targeted/projectile/dumbfire/fireball = 1,
|
||||
/spell/aoe_turf/smoke = 1,
|
||||
/spell/targeted/mindcontrol = 2,
|
||||
/obj/structure/closet/wizard/scrying = 1
|
||||
)
|
||||
|
||||
@@ -18,42 +18,34 @@
|
||||
..()
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
if(!(target.stat == DEAD))
|
||||
to_chat(user, "This spell can't affect the living.")
|
||||
return 0
|
||||
if(target.stat != DEAD)
|
||||
to_chat(user, SPAN_WARNING("This spell can't affect the living."))
|
||||
return FALSE
|
||||
|
||||
if(isundead(target))
|
||||
to_chat(user, "This spell can't affect the undead.")
|
||||
return 0
|
||||
to_chat(user, SPAN_WARNING("This spell can't affect the undead."))
|
||||
return FALSE
|
||||
|
||||
if(islesserform(target))
|
||||
to_chat(user, "This spell can't affect this lesser creature.")
|
||||
return 0
|
||||
to_chat(user, SPAN_WARNING("This spell can't affect this lesser creature."))
|
||||
return FALSE
|
||||
|
||||
if(isipc(target))
|
||||
to_chat(user, "This spell can't affect non-organics.")
|
||||
return 0
|
||||
to_chat(user, SPAN_WARNING("This spell can't affect non-organics."))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/skeleton/F = new(get_turf(target))
|
||||
var/mob/living/carbon/human/skeleton/F = new /mob/living/carbon/human/skeleton(get_turf(target))
|
||||
SSghostroles.add_spawn_atom("skeleton", F)
|
||||
var/area/A = get_area(F)
|
||||
if(A)
|
||||
say_dead_direct("A skeleton has been created in [A.name]! Spawn in as it by using the ghost spawner menu in the ghost tab.")
|
||||
target.visible_message("<span class='cult'>\The [target] explodes in a shower of gore, a skeleton emerges from the remains!</span>")
|
||||
target.gib()
|
||||
var/datum/ghosttrap/ghost = get_ghost_trap("skeleton minion")
|
||||
ghost.request_player(F,"A wizard is requesting a skeleton minion.", 60 SECONDS)
|
||||
spawn(600)
|
||||
if(F)
|
||||
if(!F.ckey || !F.client)
|
||||
F.visible_message("With no soul to keep \the [F] linked to this plane, it turns into dust.")
|
||||
F.dust()
|
||||
|
||||
F.master = user
|
||||
F.faction = user.faction
|
||||
|
||||
else
|
||||
to_chat(F, "<B>You are a skeleton minion to [usr], they are your master. Obey and protect your master at all costs, you have no free will.</B>")
|
||||
F.faction = usr.faction
|
||||
F.preEquipOutfit(/datum/outfit/admin/wizard/skeleton, FALSE)
|
||||
F.equipOutfit(/datum/outfit/admin/wizard/skeleton, FALSE)
|
||||
|
||||
//equips the skeleton war gear
|
||||
F.equip_to_slot_or_del(new /obj/item/clothing/under/gladiator(F), slot_w_uniform)
|
||||
F.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(F), slot_shoes)
|
||||
F.equip_to_slot_or_del(new /obj/item/material/twohanded/spear/bone(F), slot_back)
|
||||
F.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/bone(F), slot_head)
|
||||
F.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/bone(F), slot_wear_suit)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
@@ -20,9 +20,9 @@
|
||||
if(!target)
|
||||
return
|
||||
|
||||
to_chat(user, SPAN_WARNING("\The [user] teleported to you!"))
|
||||
to_chat(target, FONT_LARGE(SPAN_WARNING("\The [user] teleported to you!")))
|
||||
user.forceMove(get_turf(target))
|
||||
user.visible_message(SPAN_WARNING("\The [user] appears out of thin air!"))
|
||||
user.visible_message(SPAN_WARNING("\The [user] appears out of thin air!"), SPAN_NOTICE("You successfully teleport to \the [target]."))
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread
|
||||
smoke.set_up(5, 0, get_turf(user))
|
||||
smoke.attach(user)
|
||||
|
||||
Reference in New Issue
Block a user