From d08c1dfcad2f98aeda48569b45a8d39c3d812bea Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 20 Aug 2024 15:25:12 +1000 Subject: [PATCH] Moving wizard spells into a modpack as part of ability rewrite. --- code/__defines/gamemode.dm | 40 -- code/_onclick/hud/screen/screen_abilities.dm | 292 ------------- code/datums/extensions/abilities/abilities.dm | 4 + .../extensions/abilities/abilities_mob.dm | 59 +++ .../extensions/abilities/ability_admin.dm | 5 + .../extensions/abilities/ability_button.dm | 37 ++ .../extensions/abilities/ability_decl.dm | 299 +++++++++++++ .../extensions/abilities/ability_handler.dm | 137 +++++- .../abilities/ability_projectile.dm | 31 ++ .../extensions/storage/subtypes_misc.dm | 4 + code/datums/mind/mind.dm | 6 +- code/datums/trading/traders/ai.dm | 6 +- code/datums/trading/traders/goods.dm | 1 - code/datums/trading/traders/unique.dm | 3 - code/game/objects/effects/overlays.dm | 10 + code/game/objects/items/books/_book.dm | 95 ++--- .../objects/items/weapons/storage/bags.dm | 7 + code/game/objects/items/weapons/weaponry.dm | 3 +- code/modules/admin/admin_verbs.dm | 10 - code/modules/admin/view_variables/helpers.dm | 1 - code/modules/admin/view_variables/topic.dm | 12 - .../codex/categories/category_phenomena.dm | 18 +- code/modules/hydroponics/grown.dm | 2 +- code/modules/mob/login.dm | 5 - code/modules/mob/mob.dm | 6 - code/modules/mob/mob_defines.dm | 1 - code/modules/paperwork/paper.dm | 10 + code/modules/projectiles/projectile.dm | 25 +- code/modules/projectiles/projectile/change.dm | 10 +- .../reagents/reagent_containers/spray.dm | 3 - code/modules/spells/aoe_turf/aoe_turf.dm | 25 -- code/modules/spells/artifacts.dm | 42 -- code/modules/spells/construct_spells.dm | 10 - code/modules/spells/no_clothes.dm | 5 - code/modules/spells/racial_wizard.dm | 82 ---- code/modules/spells/spell_code.dm | 395 ------------------ code/modules/spells/spell_projectile.dm | 56 --- code/modules/spells/spellbook.dm | 320 -------------- code/modules/spells/spellbook/battlemage.dm | 44 -- code/modules/spells/spellbook/cleric.dm | 50 --- code/modules/spells/spellbook/druid.dm | 43 -- code/modules/spells/spellbook/spatial.dm | 48 --- code/modules/spells/spellbook/standard.dm | 54 --- code/modules/spells/spells.dm | 60 --- .../spells/targeted/projectile/projectile.dm | 45 -- icons/mob/screen/abilities.dmi | Bin 0 -> 464 bytes maps/modpack_testing/modpack_testing.dm | 1 + maps/tradeship/tradeship.dm | 1 + mods/content/psionics/_psionics.dme | 1 - mods/content/psionics/datum/chems.dm | 6 +- mods/content/psionics/datum/spells.dm | 7 - .../system/psionics/complexus/complexus.dm | 2 + .../psionics/system/psionics/mob/mob.dm | 1 + mods/gamemodes/cult/_cult.dme | 6 +- mods/gamemodes/cult/abilities/_handler.dm | 1 + mods/gamemodes/cult/abilities/construct.dm | 78 ++++ mods/gamemodes/cult/abilities/harvest.dm | 27 ++ mods/gamemodes/cult/abilities/shade.dm | 1 + .../cult/mobs/constructs/constructs.dm | 32 +- mods/gamemodes/cult/ritual.dm | 18 +- mods/gamemodes/cult/spells/construct.dm | 122 ------ mods/gamemodes/cult/spells/harvest.dm | 37 -- mods/gamemodes/cult/wizard.dm | 14 +- .../deity/forms/narsie/spells/tear_veil.dm | 1 - .../forms/starlight/spells/disable_tech.dm | 2 +- .../forms/starlight/spells/starlight_aura.dm | 2 +- .../forms/starlight/spells/veil_of_shadows.dm | 2 +- .../deity/forms/starlight/structures.dm | 3 +- mods/gamemodes/deity/forms/tower/spells.dm | 7 +- mods/gamemodes/deity/mobs/deity_boons.dm | 4 +- mods/gamemodes/deity/mobs/deity_sources.dm | 8 +- .../deity/mobs/phenomena/starlight.dm | 6 +- mods/gamemodes/deity/spells/boon.dm | 12 +- mods/gamemodes/deity/spells/construction.dm | 1 - mods/gamemodes/deity/spells/open_gateway.dm | 2 - mods/gamemodes/deity/spells/vision.dm | 3 +- mods/gamemodes/wizard/_wizard.dm | 15 + mods/gamemodes/wizard/_wizard.dme | 28 ++ mods/gamemodes/wizard/artifacts.dm | 90 ++++ .../gamemodes/wizard}/contracts.dm | 82 ++-- .../gamemodes/wizard/familiar.dm | 12 +- mods/gamemodes/wizard/icons/spell_icons.dmi | Bin 0 -> 296 bytes .../gamemodes/wizard/mode.dm | 0 .../gamemodes/wizard/outfits.dm | 4 +- mods/gamemodes/wizard/overrides.dm | 3 + .../gamemodes/wizard/role.dm | 57 +-- .../gamemodes/wizard}/scrolls.dm | 17 +- .../wizard/servant_items/caretaker.dm | 0 .../wizard/servant_items/champion.dm | 0 .../wizard/servant_items/familiar.dm | 0 .../gamemodes/wizard/servant_items/fiend.dm | 0 .../wizard/servant_items/infiltrator.dm | 0 .../wizard/servant_items/overseer.dm | 0 mods/gamemodes/wizard/spellbook/spellbook.dm | 309 ++++++++++++++ .../wizard/spellbook/spellbook_subtypes.dm | 17 + .../spellbook_types/_spellbook_type.dm | 19 + .../spellbook_types/spellbook_battlemage.dm | 46 ++ .../spellbook_types/spellbook_cleric.dm | 48 +++ .../spellbook_types/spellbook_druid.dm | 41 ++ .../spellbook_types/spellbook_spatial.dm | 45 ++ .../spellbook_types/spellbook_standard.dm | 52 +++ .../spellbook_types/spellbook_student.dm | 34 +- mods/gamemodes/wizard/spells/_spell.dm | 149 +++++++ .../gamemodes/wizard/spells/_spell_handler.dm | 97 +++++ .../wizard/spells_archive}/aoe_turf/blink.dm | 6 +- .../wizard/spells_archive}/aoe_turf/charge.dm | 4 +- .../aoe_turf/conjure/conjure.dm | 4 +- .../aoe_turf/conjure/druidic_spells.dm | 2 - .../aoe_turf/conjure/faithful_hound.dm | 1 - .../aoe_turf/conjure/force_portal.dm | 1 - .../aoe_turf/conjure/forcewall.dm | 2 +- .../spells_archive}/aoe_turf/conjure/grove.dm | 4 +- .../spells_archive}/aoe_turf/disable_tech.dm | 3 +- .../spells_archive}/aoe_turf/drain_blood.dm | 2 +- .../aoe_turf/exchange_wounds.dm | 4 +- .../wizard/spells_archive}/aoe_turf/knock.dm | 2 +- .../wizard/spells_archive}/aoe_turf/smoke.dm | 4 +- .../spells_archive}/aoe_turf/summons.dm | 4 +- .../spells_archive}/general/acid_spray.dm | 2 +- .../spells_archive}/general/area_teleport.dm | 1 - .../spells_archive}/general/camera_vision.dm | 7 - .../general/contract_spells.dm | 2 +- .../spells_archive}/general/create_air.dm | 3 - .../spells_archive}/general/invisibility.dm | 2 +- .../spells_archive}/general/mark_recall.dm | 7 +- .../general/portal_teleport.dm | 1 - .../spells_archive}/general/radiant_aura.dm | 1 - .../spells_archive}/general/return_master.dm | 2 +- .../spells_archive}/general/toggle_armor.dm | 2 +- .../spells_archive}/hand/blood_shards.dm | 2 +- .../spells_archive}/hand/burning_grip.dm | 2 +- .../wizard/spells_archive}/hand/entangle.dm | 2 +- .../wizard/spells_archive}/hand/hand.dm | 0 .../wizard/spells_archive}/hand/hand_item.dm | 0 .../spells_archive}/hand/slippery_surface.dm | 2 +- .../wizard/spells_archive}/hand/sunwrath.dm | 2 +- .../spells_archive}/spellbound_servants.dm | 41 +- .../spells_archive}/targeted/analyze.dm | 2 +- .../spells_archive}/targeted/blood_boil.dm | 2 +- .../spells_archive}/targeted/cleric_spells.dm | 19 +- .../targeted/equip/burning_touch.dm | 2 +- .../spells_archive}/targeted/equip/dyrnwyn.dm | 2 +- .../spells_archive}/targeted/equip/equip.dm | 0 .../targeted/equip/holy_relic.dm | 1 - .../targeted/equip/horsemask.dm | 8 +- .../targeted/equip/party_hardy.dm | 2 +- .../spells_archive}/targeted/equip/seed.dm | 1 - .../spells_archive}/targeted/equip/shield.dm | 1 - .../targeted/ethereal_jaunt.dm | 1 - .../targeted/exude_pleasantness.dm | 2 +- .../spells_archive}/targeted/genetic.dm | 8 +- .../targeted/glimpse_of_eternity.dm | 2 +- .../targeted/projectile/dumbfire.dm | 0 .../targeted/projectile/fireball.dm | 4 +- .../targeted/projectile/magic_missile.dm | 9 +- .../targeted/projectile/passage.dm | 3 +- .../targeted/projectile/stuncuff.dm | 4 +- .../spells_archive}/targeted/shapeshift.dm | 8 +- .../spells_archive}/targeted/shatter_mind.dm | 2 +- .../wizard/spells_archive}/targeted/shift.dm | 1 - .../spells_archive}/targeted/subjugate.dm | 2 +- .../wizard/spells_archive}/targeted/swap.dm | 7 - .../spells_archive}/targeted/targeted.dm | 21 +- .../spells_archive}/targeted/torment.dm | 2 +- .../gamemodes/wizard}/storage.dm | 2 +- .../gamemodes/wizard/wizard_clothes.dm | 3 +- .../gamemodes/wizard/wizard_props.dm | 0 mods/species/drakes/drake_abilities.dm | 1 + mods/species/vox/_vox.dme | 2 +- mods/species/vox/datum/antagonism.dm | 4 - mods/species/vox/gear/gun.dm | 24 -- mods/species/vox/wizard.dm | 26 ++ nebula.dme | 96 +---- 173 files changed, 2053 insertions(+), 2339 deletions(-) delete mode 100644 code/_onclick/hud/screen/screen_abilities.dm create mode 100644 code/datums/extensions/abilities/ability_admin.dm create mode 100644 code/datums/extensions/abilities/ability_button.dm create mode 100644 code/datums/extensions/abilities/ability_decl.dm create mode 100644 code/datums/extensions/abilities/ability_projectile.dm delete mode 100644 code/modules/spells/aoe_turf/aoe_turf.dm delete mode 100644 code/modules/spells/artifacts.dm delete mode 100644 code/modules/spells/construct_spells.dm delete mode 100644 code/modules/spells/no_clothes.dm delete mode 100644 code/modules/spells/racial_wizard.dm delete mode 100644 code/modules/spells/spell_code.dm delete mode 100644 code/modules/spells/spell_projectile.dm delete mode 100644 code/modules/spells/spellbook.dm delete mode 100644 code/modules/spells/spellbook/battlemage.dm delete mode 100644 code/modules/spells/spellbook/cleric.dm delete mode 100644 code/modules/spells/spellbook/druid.dm delete mode 100644 code/modules/spells/spellbook/spatial.dm delete mode 100644 code/modules/spells/spellbook/standard.dm delete mode 100644 code/modules/spells/spells.dm delete mode 100644 code/modules/spells/targeted/projectile/projectile.dm create mode 100644 icons/mob/screen/abilities.dmi delete mode 100644 mods/content/psionics/datum/spells.dm create mode 100644 mods/gamemodes/cult/abilities/_handler.dm create mode 100644 mods/gamemodes/cult/abilities/construct.dm create mode 100644 mods/gamemodes/cult/abilities/harvest.dm create mode 100644 mods/gamemodes/cult/abilities/shade.dm delete mode 100644 mods/gamemodes/cult/spells/construct.dm delete mode 100644 mods/gamemodes/cult/spells/harvest.dm create mode 100644 mods/gamemodes/wizard/_wizard.dm create mode 100644 mods/gamemodes/wizard/_wizard.dme create mode 100644 mods/gamemodes/wizard/artifacts.dm rename {code/modules/spells => mods/gamemodes/wizard}/contracts.dm (70%) rename code/modules/mob/living/simple_animal/familiars/familiars.dm => mods/gamemodes/wizard/familiar.dm (93%) create mode 100644 mods/gamemodes/wizard/icons/spell_icons.dmi rename code/game/gamemodes/wizard/wizard.dm => mods/gamemodes/wizard/mode.dm (100%) rename code/datums/outfits/wizardry.dm => mods/gamemodes/wizard/outfits.dm (91%) create mode 100644 mods/gamemodes/wizard/overrides.dm rename code/game/antagonist/outsider/wizard.dm => mods/gamemodes/wizard/role.dm (66%) rename {code/game/objects/items/weapons => mods/gamemodes/wizard}/scrolls.dm (81%) rename {code/game => mods}/gamemodes/wizard/servant_items/caretaker.dm (100%) rename {code/game => mods}/gamemodes/wizard/servant_items/champion.dm (100%) rename {code/game => mods}/gamemodes/wizard/servant_items/familiar.dm (100%) rename {code/game => mods}/gamemodes/wizard/servant_items/fiend.dm (100%) rename {code/game => mods}/gamemodes/wizard/servant_items/infiltrator.dm (100%) rename {code/game => mods}/gamemodes/wizard/servant_items/overseer.dm (100%) create mode 100644 mods/gamemodes/wizard/spellbook/spellbook.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_subtypes.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/_spellbook_type.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_battlemage.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_cleric.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_druid.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_spatial.dm create mode 100644 mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_standard.dm rename code/modules/spells/spellbook/student.dm => mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_student.dm (72%) create mode 100644 mods/gamemodes/wizard/spells/_spell.dm create mode 100644 mods/gamemodes/wizard/spells/_spell_handler.dm rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/blink.dm (91%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/charge.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/conjure.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/druidic_spells.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/faithful_hound.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/force_portal.dm (92%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/forcewall.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/conjure/grove.dm (93%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/disable_tech.dm (94%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/drain_blood.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/exchange_wounds.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/knock.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/smoke.dm (91%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/aoe_turf/summons.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/acid_spray.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/area_teleport.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/camera_vision.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/contract_spells.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/create_air.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/invisibility.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/mark_recall.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/portal_teleport.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/radiant_aura.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/return_master.dm (93%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/general/toggle_armor.dm (99%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/blood_shards.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/burning_grip.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/entangle.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/hand.dm (100%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/hand_item.dm (100%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/slippery_surface.dm (94%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/hand/sunwrath.dm (96%) rename {code/modules/spells/artifacts => mods/gamemodes/wizard/spells_archive}/spellbound_servants.dm (92%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/analyze.dm (93%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/blood_boil.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/cleric_spells.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/burning_touch.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/dyrnwyn.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/equip.dm (100%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/holy_relic.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/horsemask.dm (94%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/party_hardy.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/seed.dm (92%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/equip/shield.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/ethereal_jaunt.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/exude_pleasantness.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/genetic.dm (94%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/glimpse_of_eternity.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/projectile/dumbfire.dm (100%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/projectile/fireball.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/projectile/magic_missile.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/projectile/passage.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/projectile/stuncuff.dm (95%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/shapeshift.dm (98%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/shatter_mind.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/shift.dm (92%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/subjugate.dm (97%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/swap.dm (96%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/targeted.dm (88%) rename {code/modules/spells => mods/gamemodes/wizard/spells_archive}/targeted/torment.dm (97%) rename {code/modules/spells/artifacts => mods/gamemodes/wizard}/storage.dm (96%) rename code/modules/clothing/suits/wiz_robe.dm => mods/gamemodes/wizard/wizard_clothes.dm (98%) rename {code/game => mods}/gamemodes/wizard/wizard_props.dm (100%) delete mode 100644 mods/species/vox/datum/antagonism.dm create mode 100644 mods/species/vox/wizard.dm diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index 9493ae7aa125..680717a8e9ad 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -33,46 +33,6 @@ #define DEFAULT_TELECRYSTAL_AMOUNT 130 #define IMPLANT_TELECRYSTAL_AMOUNT(x) (round(x * 0.49)) // If this cost is ever greater than half of DEFAULT_TELECRYSTAL_AMOUNT then it is possible to buy more TC than you spend -///////////////// -////WIZARD ////// -///////////////// - -/* WIZARD SPELL FLAGS */ -#define GHOSTCAST BITFLAG(0) //can a ghost cast it? -#define NEEDSCLOTHES BITFLAG(1) //does it need the wizard garb to cast? Nonwizard spells should not have this -#define NEEDSHUMAN BITFLAG(2) //does it require the caster to be human? -#define Z2NOCAST BITFLAG(3) //if this is added, the spell can't be cast at centcomm -#define NO_SOMATIC BITFLAG(4) //spell will go off if the person is incapacitated or stunned -#define IGNOREPREV BITFLAG(5) //if set, each new target does not overlap with the previous one -//The following flags only affect different types of spell, and therefore overlap -//Targeted spells -#define INCLUDEUSER BITFLAG(6) //does the spell include the caster in its target selection? -#define SELECTABLE BITFLAG(7) //can you select each target for the spell? -#define NOFACTION BITFLAG(8) //Don't do the same as our faction -#define NONONFACTION BITFLAG(9) //Don't do people other than our faction -//AOE spells -#define IGNOREDENSE BITFLAG(10) //are dense turfs ignored in selection? -#define IGNORESPACE BITFLAG(11) //are space turfs ignored in selection? -//End split flags -#define CONSTRUCT_CHECK BITFLAG(12) //used by construct spells - checks for nullrods -#define NO_BUTTON BITFLAG(13) //spell won't show up in the HUD with this - -//invocation -#define SpI_SHOUT "shout" -#define SpI_WHISPER "whisper" -#define SpI_EMOTE "emote" -#define SpI_NONE "none" - -//upgrading -#define Sp_SPEED "speed" -#define Sp_POWER "power" -#define Sp_TOTAL "total" - -//casting costs -#define Sp_RECHARGE "recharge" -#define Sp_CHARGES "charges" -#define Sp_HOLDVAR "holdervar" - //Voting-related #define VOTE_PROCESS_ABORT 1 #define VOTE_PROCESS_COMPLETE 2 diff --git a/code/_onclick/hud/screen/screen_abilities.dm b/code/_onclick/hud/screen/screen_abilities.dm deleted file mode 100644 index 03961a964233..000000000000 --- a/code/_onclick/hud/screen/screen_abilities.dm +++ /dev/null @@ -1,292 +0,0 @@ -/obj/screen/ability_master - name = "Abilities" - icon = 'icons/mob/screen/spells.dmi' - icon_state = "grey_spell_ready" - screen_loc = ui_ability_master - requires_ui_style = FALSE - var/list/obj/screen/ability/ability_objects = list() - var/list/obj/screen/ability/spell_objects = list() - var/showing = FALSE // If we're 'open' or not. - var/const/abilities_per_row = 7 - var/open_state = "master_open" // What the button looks like when it's 'open', showing the other buttons. - var/closed_state = "master_closed" // Button when it's 'closed', hiding everything else. - -/obj/screen/ability_master/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat) - . = ..() - if(. != INITIALIZE_HINT_QDEL) - update_abilities(0, _owner) - -/obj/screen/ability_master/Destroy() - // Get rid of the ability objects. - remove_all_abilities() - ability_objects.Cut() - // After that, remove ourselves from the mob seeing us, so we can qdel cleanly. - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && owner.ability_master == src) - owner.ability_master = null - return ..() - -/obj/screen/ability_master/handle_mouse_drop(atom/over, mob/user, params) - if(showing) - return FALSE - . = ..() - -/obj/screen/ability_master/handle_click(mob/user, params) - if(length(ability_objects)) // If we're empty for some reason. - toggle_open() - -/obj/screen/ability_master/proc/toggle_open(var/forced_state = 0) - var/mob/owner = owner_ref?.resolve() - if(!istype(owner) || QDELETED(owner)) - return - if(showing && (forced_state != 2)) // We are closing the ability master, hide the abilities. - if(owner?.client) - for(var/obj/screen/ability/O in ability_objects) - owner.client.screen -= O -// O.handle_icon_updates = 0 - showing = 0 - overlays.len = 0 - overlays.Add(closed_state) - else if(forced_state != 1) // We're opening it, show the icons. - open_ability_master() - update_abilities(1) - showing = 1 - overlays.len = 0 - overlays.Add(open_state) - update_icon() - -/obj/screen/ability_master/proc/open_ability_master() - - var/client/owner_client - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner)) - owner_client = owner.client - - for(var/i = 1 to length(ability_objects)) - var/obj/screen/ability/A = ability_objects[i] - var/row = round(i/abilities_per_row) - A.screen_loc = "RIGHT-[(i-(row*abilities_per_row))+2]:16,TOP-[row+1]:16" - if(owner_client) - owner_client.screen += A - -/obj/screen/ability_master/proc/update_abilities(forced = 0, mob/user) - update_icon() - if(user && user.client) - if(!(src in user.client.screen)) - user.client.screen += src - var/i = 1 - for(var/obj/screen/ability/ability in ability_objects) - ability.update_icon(forced) - ability.maptext = "[i]" // Slot number - i++ - -/obj/screen/ability_master/on_update_icon() - if(ability_objects.len) - set_invisibility(INVISIBILITY_NONE) - else - set_invisibility(INVISIBILITY_ABSTRACT) - -/obj/screen/ability_master/proc/add_ability(var/name_given) - if(!name_given) - return - var/obj/screen/ability/new_button = new /obj/screen/ability - new_button.ability_master = src - new_button.SetName(name_given) - new_button.ability_icon_state = name_given - new_button.update_icon(1) - ability_objects.Add(new_button) - var/mob/living/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner) && owner.client) - toggle_open(2) //forces the icons to refresh on screen - -/obj/screen/ability_master/proc/remove_ability(var/obj/screen/ability/ability) - if(!ability) - return - ability_objects.Remove(ability) - if(istype(ability,/obj/screen/ability/spell)) - spell_objects.Remove(ability) - qdel(ability) - - - if(ability_objects.len) - toggle_open(showing + 1) - update_icon() -// else -// qdel(src) - -/obj/screen/ability_master/proc/remove_all_abilities() - for(var/obj/screen/ability/A in ability_objects) - remove_ability(A) - -/obj/screen/ability_master/proc/get_ability_by_name(name_to_search) - for(var/obj/screen/ability/A in ability_objects) - if(A.name == name_to_search) - return A - return null - -/obj/screen/ability_master/proc/get_ability_by_instance(var/obj/instance/) - for(var/obj/screen/ability/obj_based/O in ability_objects) - if(O.object == instance) - return O - return null - -/obj/screen/ability_master/proc/get_ability_by_spell(var/spell/s) - for(var/screen in spell_objects) - var/obj/screen/ability/spell/S = screen - if(S.spell == s) - return S - return null - -/obj/screen/ability_master/proc/synch_spells_to_mind(var/datum/mind/M) - if(!M) - return - LAZYINITLIST(M.learned_spells) - for(var/obj/screen/ability/spell/screen in spell_objects) - var/spell/S = screen.spell - M.learned_spells |= S - -///////////ACTUAL ABILITIES//////////// -//This is what you click to do things// -/////////////////////////////////////// -/obj/screen/ability - icon = 'icons/mob/screen/spells.dmi' - icon_state = "grey_spell_base" - maptext_x = 3 - requires_owner = FALSE - requires_ui_style = FALSE - var/background_base_state = "grey" - var/ability_icon_state = null - var/obj/screen/ability_master/ability_master - -/obj/screen/ability/Destroy() - if(ability_master) - ability_master.ability_objects -= src - var/mob/owner = ability_master.owner_ref?.resolve() - if(istype(owner) && owner.client) - owner.client.screen -= src - if(ability_master && !ability_master.ability_objects.len) - ability_master.update_icon() -// qdel(ability_master) - ability_master = null - return ..() - -/obj/screen/ability/on_update_icon() - overlays.Cut() - icon_state = "[background_base_state]_spell_base" - - overlays += ability_icon_state - -/obj/screen/ability/handle_click(mob/user, params) - activate() - -// Makes the ability be triggered. The subclasses of this are responsible for carrying it out in whatever way it needs to. -/obj/screen/ability/proc/activate() - to_world("[src] had activate() called.") - return - -/////////Obj Abilities//////// -//Buttons to trigger objects// -////////////////////////////// - -/obj/screen/ability/obj_based - var/obj/object = null - -/obj/screen/ability/obj_based/activate() - if(object) - object.Click() - -// Wizard -/obj/screen/ability/spell - var/spell/spell - var/spell_base - var/last_charge = 0 - var/icon/last_charged_icon - -/obj/screen/ability/spell/Destroy() - if(spell) - spell.connected_button = null - spell = null - return ..() - -/obj/screen/ability_master/proc/add_spell(var/spell/spell) - if(!spell) return - - if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one - return - - if(get_ability_by_spell(spell)) - return - - var/obj/screen/ability/spell/A = new(null) - A.ability_master = src - A.spell = spell - A.SetName(spell.name) - - if(!spell.override_base) //if it's not set, we do basic checks - if(spell.spell_flags & CONSTRUCT_CHECK) - A.spell_base = "const" //construct spells - else - A.spell_base = "wiz" //wizard spells - else - A.spell_base = spell.override_base - A.update_charge(1) - spell_objects.Add(A) - ability_objects.Add(A) - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner) && owner.client) - toggle_open(2) //forces the icons to refresh on screen - -/obj/screen/ability_master/proc/update_spells(var/forced = 0) - for(var/obj/screen/ability/spell/spell in spell_objects) - spell.update_charge(forced) - -/obj/screen/ability/spell/proc/update_charge(var/forced_update = 0) - if(!spell) - qdel(src) - return - - if(last_charge == spell.charge_counter && !forced_update) - return //nothing to see here - - overlays -= spell.hud_state - - if(spell.charge_type == Sp_RECHARGE || spell.charge_type == Sp_CHARGES) - if(spell.charge_counter < spell.charge_max) - icon_state = "[spell_base]_spell_base" - if(spell.charge_counter > 0) - var/icon/partial_charge = icon(src.icon, "[spell_base]_spell_ready") - partial_charge.Crop(1, 1, partial_charge.Width(), round(partial_charge.Height() * spell.charge_counter / spell.charge_max)) - overlays += partial_charge - if(last_charged_icon) - overlays -= last_charged_icon - last_charged_icon = partial_charge - else if(last_charged_icon) - overlays -= last_charged_icon - last_charged_icon = null - else - icon_state = "[spell_base]_spell_ready" - if(last_charged_icon) - overlays -= last_charged_icon - else - icon_state = "[spell_base]_spell_ready" - - overlays += spell.hud_state - - last_charge = spell.charge_counter - - overlays -= "silence" - if(spell.silenced) - overlays += "silence" - -/obj/screen/ability/spell/on_update_icon(var/forced = 0) - update_charge(forced) - return - -/obj/screen/ability/spell/activate() - spell.perform(usr) - -/obj/screen/ability_master/proc/silence_spells(var/amount) - for(var/obj/screen/ability/spell/spell in spell_objects) - spell.spell.silenced = amount - spell.spell.process() - spell.update_charge(1) diff --git a/code/datums/extensions/abilities/abilities.dm b/code/datums/extensions/abilities/abilities.dm index 7d7ff63a6f76..5043fe7595c6 100644 --- a/code/datums/extensions/abilities/abilities.dm +++ b/code/datums/extensions/abilities/abilities.dm @@ -54,3 +54,7 @@ for(var/datum/ability_handler/handler in ability_handlers) handler.refresh_login() +/datum/extension/abilities/proc/refresh_element_positioning() + var/row = 0 + for(var/datum/ability_handler/handler in ability_handlers) + row += handler.refresh_element_positioning(row) diff --git a/code/datums/extensions/abilities/abilities_mob.dm b/code/datums/extensions/abilities/abilities_mob.dm index b72d0ac2c5f0..74cdaa732466 100644 --- a/code/datums/extensions/abilities/abilities_mob.dm +++ b/code/datums/extensions/abilities/abilities_mob.dm @@ -18,6 +18,7 @@ return FALSE handler = new handler_type(abilities, src) LAZYADD(abilities.ability_handlers, handler) + handler.finalize_ability_handler() return handler /mob/proc/remove_ability_handler(handler_type) @@ -31,3 +32,61 @@ if(!LAZYLEN(abilities.ability_handlers)) remove_extension(src, /datum/extension/abilities) return TRUE + +/mob/living/proc/copy_abilities_from(mob/living/donor) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + if(!abilities) + return FALSE + . = FALSE + for(var/datum/ability_handler/handler in abilities.ability_handlers) + if(handler.copy_abilities_to(donor)) + . = TRUE + +/mob/living/proc/disable_abilities(var/amount = 0) + if(amount < 0) + return + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.disable_abilities(amount) + +/mob/living/proc/copy_abilities_to(mob/living/donor) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.copy_abilities_to(donor) + +/mob/proc/add_ability(ability_type, list/metadata) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return FALSE + var/datum/ability_handler/handler = add_ability_handler(ability.associated_handler_type) + return handler.add_ability(ability, metadata) + +/mob/proc/remove_ability(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return FALSE + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.remove_ability(ability_type) + +/mob/proc/get_ability_metadata(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return null + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.get_metadata(ability_type, create_if_missing = TRUE) + +/mob/proc/has_ability(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return null + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.provides_ability(ability_type) + +/mob/Stat() + if((. = ..()) && client) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.show_stat_string(src) diff --git a/code/datums/extensions/abilities/ability_admin.dm b/code/datums/extensions/abilities/ability_admin.dm new file mode 100644 index 000000000000..78e13eaf6b34 --- /dev/null +++ b/code/datums/extensions/abilities/ability_admin.dm @@ -0,0 +1,5 @@ +/* TODO - admin tools + give_ability in topic + remove_ability in topic + ability details in VV/player panel +*/ \ No newline at end of file diff --git a/code/datums/extensions/abilities/ability_button.dm b/code/datums/extensions/abilities/ability_button.dm new file mode 100644 index 000000000000..ebdc9450d406 --- /dev/null +++ b/code/datums/extensions/abilities/ability_button.dm @@ -0,0 +1,37 @@ +/obj/screen/ability_button + requires_ui_style = FALSE + requires_owner = FALSE + icon = 'icons/mob/screen/abilities.dmi' + icon_state = "ability" + + var/ability_category_tag + var/datum/ability_handler/owning_handler + +/obj/screen/ability_button/Destroy() + if(owning_handler) + owning_handler.remove_screen_element(src) + owning_handler = null + return ..() + +/obj/screen/ability_button/on_update_icon() + if(!isnull(ability_category_tag) && owning_handler?.ability_category_tag == ability_category_tag) + invisibility = owning_handler.showing_abilities ? 0 : INVISIBILITY_ABSTRACT + else + invisibility = 0 + +/obj/screen/ability_button/handle_click(mob/user, params) + to_chat(user, "Click!") + +/obj/screen/ability_button/toggle_category + name = "toggle ability cateogry" + icon_state = "category" + +/obj/screen/ability_button/toggle_category/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) + . = ..() + update_icon() + +/obj/screen/ability_button/toggle_category/handle_click(mob/user, params) + owning_handler?.toggle_category_visibility() + +/obj/screen/ability_button/toggle_category/on_update_icon() + icon_state = owning_handler?.showing_abilities ? initial(icon_state) : "[initial(icon_state)]-off" diff --git a/code/datums/extensions/abilities/ability_decl.dm b/code/datums/extensions/abilities/ability_decl.dm new file mode 100644 index 000000000000..397a4dd46e6d --- /dev/null +++ b/code/datums/extensions/abilities/ability_decl.dm @@ -0,0 +1,299 @@ +/decl/ability + abstract_type = /decl/ability + /// A descriptive identifier string. + var/name + /// A descriptive string about the ability. + var/desc + /// An associated handler type, used in add_ability(). + var/associated_handler_type + /// If set, will play a sound when used. + var/use_sound + /// Volume for above. + var/use_sound_volume = 50 + /// If set, this ability will create a projectile rather than applying the effect directly. + var/projectile_type + /// Sets the projectile step_delay. + var/projectile_step_delay = 1 + /// Determines the lifetime of the projectile. + var/projectile_duration = 1 SECOND + /// If not set, the ability will have documentation generated for the codex. + var/hidden_from_codex = FALSE + /// If set, this ability will be silenced by null rod and similar mechanics. + var/is_supernatural = FALSE + /// If set, this ability is applied to a square of this radius. + var/effect_radius = 0 + /// Set to except the inner space of the spell from target checks. + var/effect_inner_radius = -1 + /// If set, user will be excepted from targets. + var/user_is_immune = FALSE + /// What flags to check before an ability can be used, if any. + var/check_incapacitated = (INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT) + /// What type of mob is required to use this ability. + var/mob/expected_mob_type = /mob/living + /// If set, this ability will never target our faction. + var/faction_immune = FALSE + /// If set, this ability will only target our faction. + var/faction_only = FALSE + /// If set along with target turf type, will include dense turfs. + var/ignore_dense_turfs = TRUE + /// If set along target turf type, will include space turfs. + var/ignore_space_turfs = FALSE + /// If set, will attempt to draw from this icon on the turf where the ability is used. + var/overlay_icon + /// If set, will attempt to draw this icon_state on the turf where the ability is used. + var/overlay_icon_state + /// Will delete the overlay after this time. + var/overlay_lifespan = 1 SECOND + /// If set, this ability can only be used while standing on a turf (not in an atom's contents or null loc). + var/requires_turf = TRUE + /// If set, this ability cannot be used on the admin z-level. + var/admin_blocked = TRUE + /// If set to a numeric value, the ability cannot be used before the cooldown has expired. + var/cooldown_time + /// If set, a do_after() will be applied to this spell. + var/ability_use_channel + /// Maximum charges that can be held of this item at a time. If unset, item does not accumulate charges. + var/max_charge + /// How long it takes between charges. + var/charge_delay = 1 SECOND + + // Various failure messages. + /// Failed due to purged/null rod. + var/cast_failed_purged_str = "Another power interferes with your own!" + /// Failed due to non-turf loc. + var/cast_failed_no_turf = "You must be standing on solid ground to use this ability." + /// Failed due to being on admin level + var/cast_failed_no_admin_level = "This ability cannot be used on the admin z-level." + /// Failed due to being invalid mob type + var/cast_failed_wrong_mob_type = "This ability may only be used by living creature." + /// Failed due to being downed/buckled + var/cast_failed_incapacitated = "You are in no state to use that ability." + /// Failed due to still being on cooldown from last use + var/cast_failed_on_cooldown = "You cannot use that ability again just yet." + /// Failed to to still recharging + var/cast_failed_no_charges = "You are out of charges for that ability." + +// This is the main entrypoint for the ability use chain. +/decl/ability/proc/use_ability(mob/user, atom/target, list/metadata) + + LAZYINITLIST(metadata) // so that we don't have to pass it back up through the chain + . = metadata + + if(!can_use_ability(user, metadata)) + return + + if(!prepare_to_cast(user, target, metadata)) + return + + // Fire a projectile if that is how this ability works. + if(projectile_type) + var/obj/item/projectile/projectile = new projectile_type(get_turf(user)) + if(istype(projectile, /obj/item/projectile/ability)) + var/obj/item/projectile/ability/ability_projectile = projectile + ability_projectile.owner = user + ability_projectile.ability_metadata = metadata + ability_projectile.carried_ability = src + projectile.original = target + projectile.starting = get_turf(user) + projectile.shot_from = user + projectile.current = projectile.original + projectile.yo = target.y - user.y + projectile.xo = target.x - user.x + projectile.life_span = projectile_duration + projectile.hitscan = !projectile_step_delay + projectile.step_delay = projectile_step_delay + projectile.launch(target) + return + + // Otherwise, just apply to the target directly. + apply_effect(user, target, metadata) + +/decl/ability/proc/show_cast_channel_msg(mob/user, atom/target, list/metadata) + user.visible_message( + SPAN_NOTICE("\The [user] begins preparing to use an ability!"), + SPAN_NOTICE("You begin preparing to use an ability.") + ) + +/decl/ability/proc/show_ability_cast_msg(mob/user, list/targets, list/metadata) + user.visible_message( + SPAN_NOTICE("\The [user] casts an ability!"), + SPAN_NOTICE("You cast an ability!") + ) + +/decl/ability/proc/prepare_to_cast(mob/user, atom/target, list/metadata) + if(ability_use_channel) + show_cast_channel_msg(user, target, metadata) + if(!do_after(user, ability_use_channel, target) || !can_use_ability(user, metadata)) + return FALSE + if(cooldown_time) + metadata["next_cast"] = world.time + cooldown_time + return TRUE + +/decl/ability/proc/can_use_ability(mob/user, list/metadata, silent = FALSE) + + if(!user.has_ability(type)) + error("\The [user] utilized the ability '[type]' without having access to it.") + if(!silent) + to_chat(user, SPAN_WARNING("You shouldn't have this ability! Please notify a developer or raise an issue ticket.")) + return FALSE + + var/turf/my_turf = get_turf(user) + if(requires_turf) + if(!istype(my_turf)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_turf)) + return FALSE + if(admin_blocked && isAdminLevel(my_turf.z)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_admin_level)) + return FALSE + + if(!istype(user, expected_mob_type)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_wrong_mob_type)) + return FALSE + + if(!isnull(check_incapacitated) && user.incapacitated(check_incapacitated)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_incapacitated)) + return FALSE + + if(cooldown_time && world.time < metadata["next_cast"]) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_on_cooldown)) + return FALSE + + if(max_charge && metadata["charges"] <= 0) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_charges)) + return FALSE + + if(is_supernatural) + var/is_purged = FALSE + if(isanimal(user)) + var/mob/living/simple_animal/critter = user + is_purged = !!critter.purge + if(!is_purged) + for(var/turf/turf in range(user, 1)) + if(turf.get_null_rod()) + is_purged = TRUE + break + if(is_purged) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_purged_str)) + return FALSE + + return TRUE + +/decl/ability/proc/can_target(mob/user, atom/target, list/metadata) + if(target == user && !user_is_immune) + return FALSE + if(user.faction) + if(faction_immune && ismob(target)) + var/mob/target_mob = target + if(target_mob.faction == user.faction) + return FALSE + if(faction_only) + if(!ismob(target)) + return FALSE + var/mob/target_mob = target + if(target_mob.faction != user.faction) + return FALSE + else if(faction_only) + return FALSE + if(isturf(target)) + if(ignore_dense_turfs && target.density) + return FALSE + if(ignore_space_turfs && istype(target, /turf/space)) + return FALSE + return TRUE + +/decl/ability/proc/get_effected(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + if(effect_radius <= 0) + return can_target(user, hit_target, metadata) ? list(hit_target) : null + var/list/except_atoms = effect_inner_radius >= 0 ? range(effect_inner_radius, projectile) : null + for(var/mob/living/target in range(projectile, effect_radius)) + if(target in except_atoms) + continue + if(can_target(user, target, metadata)) + LAZYADD(., target) + +/decl/ability/proc/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + SHOULD_CALL_PARENT(TRUE) + if(use_sound) + playsound(get_turf(user), use_sound, use_sound_volume, 1) + if(istype(projectile)) + projectile.expended = TRUE + + admin_attacker_log(user, "attempted to use ability [src] on [hit_target]") + + var/list/targets = get_effected(user, hit_target, metadata, projectile) + show_ability_cast_msg(user, targets, metadata) + while(length(targets)) + var/target = targets[1] + apply_effect_to(user, target, metadata) + targets = prune_targets(user, target, targets, metadata) + finish_casting(user, hit_target, metadata) + +/decl/ability/proc/finish_casting(mob/user, atom/hit_target, list/metadata) + return + +/decl/ability/proc/prune_targets(user, previous_target, list/targets, list/metadata) + if(!length(targets)) + return null + if(previous_target) + LAZYREMOVE(targets, previous_target) + return targets + +/decl/ability/proc/apply_visuals(mob/user, atom/target, list/metadata) + if(!overlay_icon || !overlay_lifespan) + return + var/turf/overlay_loc = get_turf(target) + if(!isturf(overlay_loc) || locate(/obj/effect/overlay) in overlay_loc) + return + var/obj/effect/overlay/ability_overlay = new(overlay_loc) + ability_overlay.icon = overlay_icon + ability_overlay.icon_state = overlay_icon_state + ability_overlay.anchored = TRUE + ability_overlay.set_density(FALSE) + QDEL_IN(ability_overlay, overlay_lifespan) + +/decl/ability/proc/apply_effect_to(mob/user, atom/target, list/metadata) + SHOULD_CALL_PARENT(TRUE) + apply_visuals(user, target, metadata) + +/decl/ability/proc/get_default_metadata() + . = list() + if(cooldown_time) + .["next_cast"] = 0 + if(max_charge) + .["charges"] = max_charge + .["next_charge"] = 0 + +/decl/ability/proc/recharge(mob/owner, list/metadata) + if(max_charge <= 0 || metadata["charges"] >= max_charge) + return FALSE + if(world.time < metadata["next_charge"]) + return TRUE + metadata["next_charge"] = world.time + charge_delay + metadata["charges"]++ + return TRUE + +/decl/ability/proc/get_stat_strings(list/metadata) + var/use_name = metadata["ability_name"] || name + if(cooldown_time) + var/on_cooldown = metadata["next_cast"] - world.time + if(on_cooldown > 0) + return list( + use_name, + "[ceil(on_cooldown/10)]s" + ) + if(max_charge) + return list( + use_name, + "[metadata["charges"]]/[max_charge]" + ) + +/decl/ability/ranged + abstract_type = /decl/ability/ranged + projectile_type = /obj/item/projectile/ability diff --git a/code/datums/extensions/abilities/ability_handler.dm b/code/datums/extensions/abilities/ability_handler.dm index 05ad274748d0..b707a5ba446b 100644 --- a/code/datums/extensions/abilities/ability_handler.dm +++ b/code/datums/extensions/abilities/ability_handler.dm @@ -1,8 +1,14 @@ /datum/ability_handler abstract_type = /datum/ability_handler + var/showing_abilities = FALSE + var/ability_category_tag var/mob/owner - var/list/ability_items var/datum/extension/abilities/master + var/list/ability_items + var/list/screen_elements + var/list/known_abilities + var/list/recharging_abilities + var/stat_panel_type = "Abilities" /datum/ability_handler/New(_master) master = _master @@ -12,16 +18,132 @@ if(!istype(owner)) CRASH("Ability handler received invalid owner!") ..() + refresh_login() + +/datum/ability_handler/Process() + + if(!length(recharging_abilities)) + return PROCESS_KILL + + for(var/decl/ability/ability as anything in recharging_abilities) + if(!ability.recharge(owner, get_metadata(ability))) + LAZYREMOVE(recharging_abilities, ability) + +/datum/ability_handler/proc/get_metadata(decl/ability/ability, create_if_missing = TRUE) + if(istype(ability)) + . = known_abilities[ability.type] + if(!islist(.) && create_if_missing) + . = ability.get_default_metadata() + known_abilities[ability.type] = . + else if(ispath(ability, /decl/ability)) + . = known_abilities[ability.type] + if(!islist(. && create_if_missing)) + ability = GET_DECL(ability) + if(!istype(ability)) + return list() + . = ability.get_default_metadata() + known_abilities[ability.type] = . + else if(create_if_missing) + PRINT_STACK_TRACE("ability metadata retrieval passed invalid ability type: '[ability]'") + . = list() /datum/ability_handler/Destroy() + recharging_abilities = null + known_abilities = null QDEL_NULL_LIST(ability_items) + if(length(screen_elements)) + QDEL_NULL(screen_elements) if(master) LAZYREMOVE(master.ability_handlers, src) master.update() master = null owner = null + if(is_processing) + STOP_PROCESSING(SSprocessing, src) return ..() +/datum/ability_handler/proc/add_ability(ability_type, list/metadata) + if(provides_ability(ability_type)) + return FALSE + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability)) + return FALSE + if(!islist(metadata)) + metadata = ability.get_default_metadata() + LAZYSET(known_abilities, ability_type, metadata) + if(ability.max_charge) + LAZYDISTINCTADD(recharging_abilities, ability_type) + if(!is_processing) + START_PROCESSING(SSprocessing, src) + return TRUE + +/datum/ability_handler/proc/remove_ability(ability_type) + if(!provides_ability(ability_type)) + return FALSE + LAZYREMOVE(known_abilities, ability_type) + LAZYREMOVE(recharging_abilities, ability_type) + if(!LAZYLEN(recharging_abilities) && is_processing) + STOP_PROCESSING(SSprocessing, src) + return TRUE + +/datum/ability_handler/proc/provides_ability(ability_type) + return (ability_type in known_abilities) + +/datum/ability_handler/proc/finalize_ability_handler() + return + +/datum/ability_handler/proc/refresh_element_positioning(row = 1, col = 1) + if(!LAZYLEN(screen_elements)) + return 0 + var/button_pos = col + var/button_row = row + . = 1 + for(var/obj/screen/element in screen_elements) + if(istype(element, /obj/screen/ability_button/toggle_category)) + element.screen_loc = "RIGHT-[col],TOP-[row]" + else if(!element.invisibility) + button_pos++ + if((button_pos-col) > 5) + button_row++ + .++ + button_pos = col+1 + element.screen_loc = "RIGHT-[button_pos],TOP-[button_row]" + +/datum/ability_handler/proc/toggle_category_visibility(force_state) + showing_abilities = isnull(force_state) ? !showing_abilities : force_state + update_screen_elements() + if(master) + master.refresh_element_positioning() + +/datum/ability_handler/proc/update_screen_elements() + for(var/obj/screen/ability_button/ability_button in screen_elements) + ability_button.update_icon() + +/datum/ability_handler/proc/copy_abilities_to(mob/living/donor) + return + +/datum/ability_handler/proc/disable_abilities(amount) + return FALSE + +/datum/ability_handler/proc/add_screen_element(atom/element, update_positions = TRUE) + LAZYDISTINCTADD(screen_elements, element) + owner?.client?.screen |= element + if(istype(element, /obj/screen/ability_button)) + var/obj/screen/ability_button/ability_button = element + ability_button.owning_handler = src + if(update_positions && master && length(screen_elements)) + master.refresh_element_positioning() + +/datum/ability_handler/proc/remove_screen_element(atom/element, update_positions = TRUE) + LAZYREMOVE(screen_elements, element) + owner?.client?.screen -= element + if(istype(element, /obj/screen/ability_button)) + var/obj/screen/ability_button/ability_button = element + if(ability_button.owning_handler == src) + ability_button.owning_handler = null + if(update_positions && master && LAZYLEN(screen_elements)) + master.refresh_element_positioning() + /datum/ability_handler/proc/cancel() if(LAZYLEN(ability_items)) for(var/thing in ability_items) @@ -29,9 +151,20 @@ qdel(thing) ability_items = null +/datum/ability_handler/proc/show_stat_string(mob/user) + if(!stat_panel_type || !statpanel(stat_panel_type)) + return + for(var/ability_type in known_abilities) + var/decl/ability/ability = GET_DECL(ability_type) + var/list/stat_strings = ability.get_stat_strings(get_metadata(ability)) + if(length(stat_strings) >= 2) + stat(stat_strings[1], stat_strings[2]) + /// Individual ability methods/disciplines (psioncs, etc.) so that mobs can have multiple. /datum/ability_handler/proc/refresh_login() - return + SHOULD_CALL_PARENT(TRUE) + if(LAZYLEN(screen_elements)) + owner?.client?.screen |= screen_elements /datum/ability_handler/proc/do_self_invocation(mob/user) return FALSE diff --git a/code/datums/extensions/abilities/ability_projectile.dm b/code/datums/extensions/abilities/ability_projectile.dm new file mode 100644 index 000000000000..896acba2e95a --- /dev/null +++ b/code/datums/extensions/abilities/ability_projectile.dm @@ -0,0 +1,31 @@ +/obj/item/projectile/ability + name = "ability" + // The projectile is functionally a tracer, the ability deals the damage. + nodamage = TRUE + penetrating = FALSE + + /// Default; can be set by the ability. + life_span = 1 SECOND + + var/expended = FALSE + var/mob/owner + var/list/ability_metadata + var/decl/ability/carried_ability + +/obj/item/projectile/ability/Destroy() + owner = null + carried_ability = null + return ..() + +/obj/item/projectile/ability/explosion_act() + SHOULD_CALL_PARENT(FALSE) + +/obj/item/projectile/ability/Bump(var/atom/A, forced=0) + if(loc && carried_ability && !expended) + carried_ability.apply_effect(owner, A, ability_metadata, src) + return TRUE + +/obj/item/projectile/ability/on_impact(var/atom/A) + if(loc && carried_ability && !expended) + carried_ability.apply_effect(owner, A, ability_metadata, src) + return TRUE diff --git a/code/datums/extensions/storage/subtypes_misc.dm b/code/datums/extensions/storage/subtypes_misc.dm index 03cbf0d2e0f3..faa5805f24c5 100644 --- a/code/datums/extensions/storage/subtypes_misc.dm +++ b/code/datums/extensions/storage/subtypes_misc.dm @@ -1,3 +1,7 @@ +/datum/storage/book + max_w_class = ITEM_SIZE_SMALL + storage_slots = 1 + /datum/storage/bible max_w_class = ITEM_SIZE_SMALL max_storage_space = 4 diff --git a/code/datums/mind/mind.dm b/code/datums/mind/mind.dm index 6102b20d1876..681f9671c317 100644 --- a/code/datums/mind/mind.dm +++ b/code/datums/mind/mind.dm @@ -78,9 +78,7 @@ /datum/mind/proc/handle_mob_deletion(mob/living/deleted_mob) if (current == deleted_mob) - current.spellremove() current = null - if (original == deleted_mob) original = null @@ -96,12 +94,10 @@ new_character.skillset.obtain_from_mob(current) //handles moving skills over. + current.copy_abilities_to(new_character) current = new_character //link ourself to our new body new_character.mind = src //and link our new body to ourself - if(learned_spells && learned_spells.len) - restore_spells(new_character) - if(active) new_character.key = key //now transfer the key to link the client to our new body diff --git a/code/datums/trading/traders/ai.dm b/code/datums/trading/traders/ai.dm index 2166a7ba1cfd..4b366fbb108b 100644 --- a/code/datums/trading/traders/ai.dm +++ b/code/datums/trading/traders/ai.dm @@ -35,9 +35,9 @@ They sell generic supplies and ask for generic supplies. /obj/item/modular_computer/pda = TRADER_BLACKLIST_SUB, /obj/item/uplink = TRADER_BLACKLIST ) + possible_trading_items = list( /obj/item/bag = TRADER_SUBTYPES_ONLY, - /obj/item/bag/cash/infinite = TRADER_BLACKLIST, /obj/item/backpack = TRADER_ALL, /obj/item/backpack/cultpack = TRADER_BLACKLIST, /obj/item/backpack/holding = TRADER_BLACKLIST, @@ -59,9 +59,9 @@ They sell generic supplies and ask for generic supplies. /obj/item/clothing/glasses = TRADER_SUBTYPES_ONLY, /obj/item/clothing/glasses/hud = TRADER_BLACKLIST_ALL, /obj/item/clothing/glasses/blindfold/tape = TRADER_BLACKLIST, - /obj/item/clothing/glasses/chameleon = TRADER_BLACKLIST + /obj/item/clothing/glasses/chameleon = TRADER_BLACKLIST, + /obj/item/bag/cash/infinite = TRADER_BLACKLIST ) - insult_drop = 0 compliment_increase = 0 diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index 5935889e6323..ab72e6725887 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -47,7 +47,6 @@ /obj/item/deck = TRADER_SUBTYPES_ONLY, /obj/item/pack = TRADER_SUBTYPES_ONLY, /obj/item/dice = TRADER_ALL, - /obj/item/dice/d20/cursed = TRADER_BLACKLIST, /obj/item/gun/launcher/money = TRADER_THIS_TYPE ) diff --git a/code/datums/trading/traders/unique.dm b/code/datums/trading/traders/unique.dm index 666e20bad592..6cb80284c6ff 100644 --- a/code/datums/trading/traders/unique.dm +++ b/code/datums/trading/traders/unique.dm @@ -103,10 +103,7 @@ "Beyond the Veil", "Deadverse" ) - possible_wanted_items = list( - /mob/living/simple_animal/familiar = TRADER_SUBTYPES_ONLY, - /mob/living/simple_animal/familiar/pet = TRADER_BLACKLIST, /mob/living/simple_animal/hostile/mimic = TRADER_ALL ) possible_trading_items = list( diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 4a78d796efd2..6ac93e8fee24 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -54,3 +54,13 @@ . = ..() pixel_x += rand(-10, 10) pixel_y += rand(-10, 10) + +/// Set and cleaned up by moving projectiles for the most part. +/obj/effect/overlay/projectile_trail + var/obj/item/projectile/master + +/obj/effect/overlay/projectile_trail/Destroy() + if(master) + LAZYREMOVE(master.proj_trails, src) + master = null + return ..() diff --git a/code/game/objects/items/books/_book.dm b/code/game/objects/items/books/_book.dm index 6ccc01a0d781..ecfad12daca6 100644 --- a/code/game/objects/items/books/_book.dm +++ b/code/game/objects/items/books/_book.dm @@ -9,13 +9,17 @@ material = /decl/material/solid/organic/plastic matter = list(/decl/material/solid/organic/paper = MATTER_AMOUNT_REINFORCEMENT) - var/dat // Actual page content - var/pencode_dat // Cache pencode if input, so it can be edited later. - var/author // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned - var/unique = 0 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified - var/title // The real name of the book. - var/carved = 0 // Has the book been hollowed out for use as a secret storage item? - var/obj/item/store //What's in the book? + /// Actual page content + var/dat + /// Cache pencode if input, so it can be edited later. + var/pencode_dat + /// Who wrote the thing, can be changed by pen or PC. It is not automatically assigned + var/author + /// 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified + var/unique = FALSE + /// The real name of the book. + var/title + /// Who modified the book last? var/last_modified_ckey /// If TRUE, mild solvents can dissolve ink off the page. /// If FALSE, the user instead receives a message about how the text doesn't seem to be normal ink. @@ -54,62 +58,49 @@ return try_to_read(user) || ..() /obj/item/book/proc/try_to_read(var/mob/user) - if(carved) - if(store) - to_chat(user, "\A [store] falls out of [title]!") - store.dropInto(loc) - store = null - return + if(storage) + var/list/stored = get_stored_inventory() + if(length(stored)) + for(var/atom/movable/thing in stored) + to_chat(user, SPAN_NOTICE("\A [thing] falls out of [title]!")) + thing.dropInto(loc) else - to_chat(user, "The pages of [title] have been cut out!") - return + to_chat(user, SPAN_NOTICE("The pages of [title] have been cut out!")) + return + if(dat) - user.visible_message("[user] opens a book titled \"[src.title]\" and begins reading intently.") + user.visible_message("\The [user] opens a book titled \"[title]\" and begins reading intently.") var/processed_dat = user.handle_reading_literacy(user, dat) if(processed_dat) show_browser(user, processed_dat, "window=book;size=1000x550") onclose(user, "book") else - to_chat(user, "This book is completely blank!") + to_chat(user, SPAN_WARNING("This book is completely blank!")) /obj/item/book/attackby(obj/item/W, mob/user) - if(carved == 1) - if(!store) - if(W.w_class < ITEM_SIZE_NORMAL) - if(!user.try_unequip(W, src)) - return - store = W - to_chat(user, "You put [W] in [title].") - return - else - to_chat(user, "[W] won't fit in [title].") - return - else - to_chat(user, "There's already something in [title]!") - return + if(IS_PEN(W)) if(unique) - to_chat(user, "These pages don't seem to take the ink well. Looks like you can't modify it.") - return + to_chat(user, SPAN_WARNING("These pages don't seem to take the ink well. Looks like you can't modify it.")) + return TRUE + var/choice = input("What would you like to change?") in list("Title", "Contents", "Author", "Cancel") switch(choice) if("Title") var/newtitle = reject_bad_text(sanitize_safe(input("Write a new title:"))) if(!newtitle) - to_chat(usr, "The title is invalid.") - return + to_chat(usr, SPAN_WARNING("The title is invalid.")) else newtitle = usr.handle_writing_literacy(usr, newtitle) if(newtitle) last_modified_ckey = user.ckey title = newtitle SetName(title) - if("Contents") + if("Contents") var/content = sanitize(input(usr, "What would you like your book to say?", "Editing Book", pencode_dat) as message|null, MAX_BOOK_MESSAGE_LEN) if(!content) - to_chat(usr, "The content is invalid.") - return + to_chat(usr, SPAN_WARNING("The content is invalid.")) else content = usr.handle_writing_literacy(usr, content) if(content) @@ -120,24 +111,28 @@ if("Author") var/newauthor = sanitize(input(usr, "Write the author's name:")) if(!newauthor) - to_chat(usr, "The name is invalid.") - return + to_chat(usr, SPAN_WARNING("The name is invalid.")) else newauthor = usr.handle_writing_literacy(usr, newauthor) if(newauthor) last_modified_ckey = user.ckey author = newauthor - else - return - else if(istype(W, /obj/item/knife) || IS_WIRECUTTER(W)) - if(carved) return - to_chat(user, "You begin to carve out [title].") - if(do_after(user, 30, src)) - to_chat(user, "You carve out the pages from [title]! You didn't want to read it anyway.") - carved = 1 - return + return TRUE + + if((istype(W, /obj/item/knife) || IS_WIRECUTTER(W)) && user.a_intent == I_HURT && try_carve(user, W)) + return TRUE + + return ..() + +/obj/item/book/proc/try_carve(mob/user, obj/item/tool) + if(storage) + to_chat(user, SPAN_WARNING("\The [src] has already been carved out.")) else - ..() + to_chat(user, SPAN_NOTICE("You begin to carve out [title] with \the [tool].")) + if(do_after(user, 3 SECONDS, src) && !storage) + to_chat(user, SPAN_NOTICE("You carve out the pages from [title] with \the [tool]! You didn't want to read it anyway.")) + storage = new /datum/storage/book(src) + return TRUE /obj/item/book/use_on_mob(mob/living/target, mob/living/user, animate = TRUE) if(user.get_target_zone() == BP_EYES) diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 821efe92ddb1..002fbe039ba7 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -113,6 +113,13 @@ if(length(contents) && storage) storage.make_exact_fit() +// Magic cash bag, used for adminspawn and wizards. +/obj/item/bag/cash/infinite + storage = /datum/storage/bag/cash/infinite + +/obj/item/bag/cash/infinite/WillContain() + return list(/obj/item/cash/c1000) + /obj/item/bag/sack name = "sack" desc = "A simple sack for carrying goods." diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 572af911651e..2329270cd77d 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -35,8 +35,7 @@ return ..() /obj/item/nullrod/proc/holy_act(mob/living/target, mob/living/user) - if(target.mind && LAZYLEN(target.mind.learned_spells)) - target.silence_spells(30 SECONDS) + if(target.disable_abilities(30 SECONDS)) to_chat(target, SPAN_DANGER("You've been silenced!")) return TRUE return FALSE diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 067a4e742412..a4fea26f3db3 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -881,16 +881,6 @@ var/global/list/admin_verbs_mod = list( log_and_message_admins("told everyone to man up and deal with it.") -/client/proc/give_spell(mob/T as mob in SSmobs.mob_list) // -- Urist - set category = "Fun" - set name = "Give Spell" - set desc = "Gives a spell to a mob." - var/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells - if(!S) return - T.add_spell(new S) - SSstatistics.add_field_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_and_message_admins("gave [key_name(T)] the spell [S].") - /client/proc/change_lobby_screen() set name = "Lobby Screen: Change" set category = "Fun" diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm index 8e30b30b4d7e..65fcfb977be0 100644 --- a/code/modules/admin/view_variables/helpers.dm +++ b/code/modules/admin/view_variables/helpers.dm @@ -37,7 +37,6 @@ return ..() + {" - diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index 450d0540ca72..49463405d7e3 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -1,4 +1,3 @@ - /client/proc/view_var_Topic(href, href_list, hsrc) //This should all be moved over to datum/admins/Topic() or something ~Carn if( (usr.client != src) || !src.holder ) @@ -97,17 +96,6 @@ src.holder.show_player_panel(victim) href_list["datumrefresh"] = href_list["mob_player_panel"] - else if(href_list["give_spell"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/victim = locate(href_list["give_spell"]) - if(!istype(victim)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_spell(victim) - href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["godmode"]) if(!check_rights(R_REJUVENATE)) return diff --git a/code/modules/codex/categories/category_phenomena.dm b/code/modules/codex/categories/category_phenomena.dm index f9777ed43fa8..e2637bf9e73d 100644 --- a/code/modules/codex/categories/category_phenomena.dm +++ b/code/modules/codex/categories/category_phenomena.dm @@ -4,16 +4,16 @@ /decl/codex_category/phenomena/Populate() - // This needs duplicate checking but I resent even having to spend time on spellcode. - var/list/spells = list() - for(var/thing in subtypesof(/spell)) - var/spell/spell = thing - if(!initial(spell.hidden_from_codex) && initial(spell.desc) && initial(spell.name)) - spells["[initial(spell.name)] (phenomena)"] = initial(spell.desc) - for(var/spell in spells) + var/list/abilities = list() + for(var/decl/ability/ability in decls_repository.get_decls_of_subtype_unassociated(/decl/ability)) + if(ability.hidden_from_codex || !ability.is_supernatural || !ability.desc) + continue + abilities["[ability.name] (phenomena)"] = ability.desc + + for(var/ability in abilities) var/datum/codex_entry/entry = new( - _display_name = spell, - _antag_text = spells[spell] + _display_name = ability, + _antag_text = abilities[ability] ) items |= entry.name . = ..() diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 6a8d499a97bc..106dbd793466 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -252,7 +252,7 @@ var/global/list/_wood_materials = list( var/static/list/rollable_types = list( /obj/item/paper/cig, /obj/item/paper, - /obj/item/teleportation_scroll + /obj/item/paper/scroll ) if(is_type_in_list(W, rollable_types)) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index a2d7f65ab163..69d4989287c5 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -112,11 +112,6 @@ update_action_buttons() update_mouse_pointer() - if(ability_master) - ability_master.update_abilities(TRUE, src) - ability_master.toggle_open(1) - ability_master.synch_spells_to_mind(mind) - if(get_preference_value(/datum/client_preference/show_status_markers) == PREF_SHOW) if(status_markers?.mob_image_personal) client.images |= status_markers.mob_image_personal diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e1fb929142b7..298566597d1d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -17,8 +17,6 @@ QDEL_NULL(hud_used) if(active_storage) active_storage.close(src) - if(istype(ability_master)) - QDEL_NULL(ability_master) if(istype(skillset)) QDEL_NULL(skillset) QDEL_NULL_LIST(grabbed_by) @@ -57,7 +55,6 @@ QDEL_NULL_SCREEN(radio_use_icon) QDEL_NULL_SCREEN(gun_move_icon) QDEL_NULL_SCREEN(gun_setting_icon) - QDEL_NULL_SCREEN(ability_master) QDEL_NULL_SCREEN(zone_sel) /mob/Initialize() @@ -68,7 +65,6 @@ if(!istype(move_intent)) move_intent = GET_DECL(move_intent) . = ..() - ability_master = new(null, src) refresh_ai_handler() START_PROCESSING(SSmobs, src) @@ -242,8 +238,6 @@ SHOULD_NOT_SLEEP(TRUE) if(QDELETED(src)) return PROCESS_KILL - if(ability_master) - ability_master.update_spells(0) #define UNBUCKLED 0 #define PARTIALLY_BUCKLED 1 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 57bd60dde48c..8df551c2bc09 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -60,7 +60,6 @@ var/obj/screen/gun/radio/radio_use_icon var/obj/screen/gun/move/gun_move_icon var/obj/screen/gun/mode/gun_setting_icon - var/obj/screen/ability_master/ability_master /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0d32e6b7005a..8eac08cf0198 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -578,3 +578,13 @@ var/global/datum/topic_state/default/paper_state/paper_topic_state = new /obj/item/paper/crumpled/bloody icon_state = "scrap_bloodied" + +// Stub type for moving teleportation scrolls into a modpack. +/obj/item/paper/scroll + name = "A scroll of paper." + icon = 'icons/obj/wizard.dmi' + icon_state = "scroll" + item_state = "paper" + w_class = ITEM_SIZE_TINY + throw_speed = 4 + throw_range = 20 diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 27db3cb6a61e..986b8ba05dd4 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -14,6 +14,18 @@ is_spawnable_type = FALSE atom_damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, ELECTROCUTE are the only things that should be in here, Try not to use PAIN as it doesn't go through stun_effect_act + // Code for handling tails, if any. + /// If the projectile leaves a trail. + var/proj_trail = FALSE + /// How long the trail lasts. + var/proj_trail_lifespan = 0 + /// What icon to use for the projectile trail. + var/proj_trail_icon = 'icons/obj/wizard.dmi' + /// What icon_state to use for the projectile trail. + var/proj_trail_icon_state = "trail" + /// Any extant trail effects. + var/list/proj_trails + var/bumped = 0 //Prevents it from hitting more than one guy at once var/def_zone = "" //Aiming at var/atom/movable/firer = null//Who shot it @@ -319,7 +331,15 @@ return 1 /obj/item/projectile/proc/before_move() - return + if(!proj_trail || !isturf(loc)) + return + var/obj/effect/overlay/projectile_trail/trail = new(loc) + trail.master = src + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.set_density(FALSE) + LAZYADD(proj_trails, trail) + QDEL_IN(trail, proj_trail_lifespan) /obj/item/projectile/proc/after_move() if(hitscan && tracer_type && !(locate(/obj/effect/projectile) in loc)) @@ -612,6 +632,7 @@ trajectory.initialize_location(target.x, target.y, target.z, 0, 0) /obj/item/projectile/Destroy() + QDEL_NULL_LIST(proj_trails) if(hitscan) if(loc && trajectory) var/datum/point/pcache = trajectory.copy_to() @@ -653,4 +674,4 @@ QDEL_NULL(beam_index) /obj/item/projectile/proc/update_effect(var/obj/effect/projectile/effect) - return \ No newline at end of file + return diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index e66053ebe84d..1f7e403aeae1 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -55,12 +55,9 @@ var/mob/living/new_mob = apply_transformation(M, choice) if(new_mob) new_mob.a_intent = "hurt" - if(M.mind) - for (var/spell/S in M.mind.learned_spells) - new_mob.add_spell(new S.type) - new_mob.a_intent = "hurt" - transfer_key_from_mob_to_mob(M, new_mob) - to_chat(new_mob, "Your form morphs into that of \a [choice].") + new_mob.copy_abilities_from(M) + transfer_key_from_mob_to_mob(M, new_mob) + to_chat(new_mob, "Your form morphs into that of \a [choice].") else new_mob = M if(new_mob) @@ -68,4 +65,3 @@ if(new_mob != M && !QDELETED(M)) qdel(M) - diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 69cea54c49e2..6bc6961aaa5f 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -37,9 +37,6 @@ if(A?.storage || istype(A, /obj/structure/table) || istype(A, /obj/structure/closet) || istype(A, /obj/item/chems) || istype(A, /obj/structure/hygiene/sink) || istype(A, /obj/structure/janitorialcart)) return - if(istype(A, /spell)) - return - if(proximity) if(standard_dispenser_refill(user, A)) return diff --git a/code/modules/spells/aoe_turf/aoe_turf.dm b/code/modules/spells/aoe_turf/aoe_turf.dm deleted file mode 100644 index 46febbfbe5fd..000000000000 --- a/code/modules/spells/aoe_turf/aoe_turf.dm +++ /dev/null @@ -1,25 +0,0 @@ -/* -Aoe turf spells target a ring of tiles around the user -This ring has an outer radius (range) and an inner radius (inner_radius) -Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm -*/ - -/spell/aoe_turf //affects all turfs in view or range (depends) - spell_flags = IGNOREDENSE - var/inner_radius = -1 //for all your ring spell needs - -/spell/aoe_turf/choose_targets(mob/user = usr) - var/list/targets = list() - - for(var/turf/target in view_or_range(range, holder, selection_type)) - if(!(target in view_or_range(inner_radius, holder, selection_type))) - if(target.density && (spell_flags & IGNOREDENSE)) - continue - if(isspaceturf(target) && (spell_flags & IGNORESPACE)) - continue - targets += target - - if(!targets.len) //doesn't waste the spell - return - - return targets \ No newline at end of file diff --git a/code/modules/spells/artifacts.dm b/code/modules/spells/artifacts.dm deleted file mode 100644 index cdc27d60afc3..000000000000 --- a/code/modules/spells/artifacts.dm +++ /dev/null @@ -1,42 +0,0 @@ -//////////////////////Scrying orb////////////////////// - -/obj/item/scrying - name = "scrying orb" - desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means." - icon = 'icons/obj/projectiles.dmi' - icon_state = "bluespace" - throw_speed = 3 - throw_range = 7 - throwforce = 10 - atom_damage_type = BURN - force = 10 - hitsound = 'sound/magic/forcewall.ogg' - max_health = ITEM_HEALTH_NO_DAMAGE - -/obj/item/scrying/attack_self(mob/user) - var/decl/special_role/wizard/wizards = GET_DECL(/decl/special_role/wizard) - if((user.mind && !wizards.is_antagonist(user.mind))) - to_chat(user, "You stare into the orb and see nothing but your own reflection.") - return - - to_chat(user, "You can see... everything!") // This never actually happens. - visible_message("[user] stares into [src], their eyes glazing over.") - - user.teleop = user.ghostize(1) - announce_ghost_joinleave(user.teleop, 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.") - return - - - -/////////////////////////Cursed Dice/////////////////////////// -/obj/item/dice/d20/cursed - desc = "A dice with twenty sides said to have an ill effect on those that are unlucky..." - -/obj/item/dice/d20/cursed/attack_self(mob/user) - ..() - if(isliving(user)) - var/mob/living/M = user - if(icon_state == "[name][sides]") - M.heal_damage(BRUTE, 30) - else if(icon_state == "[name]1") - M.take_damage(30) diff --git a/code/modules/spells/construct_spells.dm b/code/modules/spells/construct_spells.dm deleted file mode 100644 index 0c705aff4fc0..000000000000 --- a/code/modules/spells/construct_spells.dm +++ /dev/null @@ -1,10 +0,0 @@ -//////////////////////////////Construct Spells///////////////////////// - -/proc/findNullRod(var/atom/target) - if(istype(target,/obj/item/nullrod)) - return 1 - else if(target.contents) - for(var/atom/A in target.contents) - if(findNullRod(A)) - return 1 - return 0 diff --git a/code/modules/spells/no_clothes.dm b/code/modules/spells/no_clothes.dm deleted file mode 100644 index 3b8502923519..000000000000 --- a/code/modules/spells/no_clothes.dm +++ /dev/null @@ -1,5 +0,0 @@ -/spell/noclothes - name = "No Clothes" - desc = "Learn the ancient art of not wearing fancy robes while casting spells." - feedback = "NC" - spell_flags = NO_BUTTON \ No newline at end of file diff --git a/code/modules/spells/racial_wizard.dm b/code/modules/spells/racial_wizard.dm deleted file mode 100644 index c06b8671aae4..000000000000 --- a/code/modules/spells/racial_wizard.dm +++ /dev/null @@ -1,82 +0,0 @@ -//this file is full of all the racial spells/artifacts/etc that each species has. - -/obj/item/magic_rock - name = "magical rock" - desc = "Legends say that this rock will unlock the true potential of anyone who touches it." - icon = 'icons/obj/wizard.dmi' - icon_state = "magic rock" - w_class = ITEM_SIZE_SMALL - throw_speed = 1 - throw_range = 3 - force = 15 - material = /decl/material/solid/stone/basalt - var/list/potentials = list( - SPECIES_HUMAN = /obj/item/bag/cash/infinite - ) - -/obj/item/magic_rock/attack_self(mob/user) - if(!ishuman(user)) - to_chat(user, "\The [src] can do nothing for such a simple being.") - return - var/mob/living/human/H = user - var/reward = potentials[H.species.get_root_species_name(H)] //we get body type because that lets us ignore subspecies. - if(!reward) - to_chat(user, "\The [src] does not know what to make of you.") - return - for(var/spell/S in user.mind.learned_spells) - if(istype(S,reward)) - to_chat(user, "\The [src] can do no more for you.") - return - var/a = new reward() - if(ispath(reward,/spell)) - H.add_spell(a) - else if(ispath(reward,/obj)) - H.put_in_hands(a) - to_chat(user, "\The [src] crumbles in your hands.") - qdel(src) - -/obj/item/bag/cash/infinite - storage = /datum/storage/bag/cash/infinite - -/obj/item/bag/cash/infinite/WillContain() - return list(/obj/item/cash/c1000) - -/spell/messa_shroud/choose_targets() - return list(get_turf(holder)) - -/spell/messa_shroud/cast(var/list/targets, mob/user) - var/turf/T = targets[1] - - if(!istype(T)) - return - - var/obj/O = new /obj(T) - O.set_light(range, -10, "#ffffff") - - spawn(duration) - qdel(O) - -/mob/observer/eye/freelook/wizard_eye - name_sufix = "Wizard Eye" - -/mob/observer/eye/freelook/wizard_eye/Initialize() - . = ..() //we dont use the Ai one because it has AI specific procs imbedded in it. - visualnet = cameranet - -/mob/living/proc/release_eye() - set name = "Release Vision" - set desc = "Return your sight to your body." - set category = "Abilities" - - verbs -= /mob/living/proc/release_eye //regardless of if we have an eye or not we want to get rid of this verb. - - if(!eyeobj) - return - eyeobj.release(src) - -/mob/observer/eye/freelook/wizard_eye/Destroy() - if(isliving(eyeobj.owner)) - var/mob/living/L = eyeobj.owner - L.release_eye() - qdel(eyeobj) - return ..() \ No newline at end of file diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm deleted file mode 100644 index 653d2b8cae2f..000000000000 --- a/code/modules/spells/spell_code.dm +++ /dev/null @@ -1,395 +0,0 @@ -var/global/list/spells = typesof(/spell) //needed for the badmin verb for now - -/spell - var/name - var/desc - var/feedback = "" //what gets sent if this spell gets chosen by the spellbook. - parent_type = /datum - var/panel = "Spells"//What panel the proc holder needs to go on. - - var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? - /*Spell schools as follows: - Racial - Only tagged to spells gained for being a certain race - Conjuration - Creating an object or transporting it. - Transmutation - Modifying an object or transforming it. - Illusion - Altering perception or thought. - */ - var/charge_type = Sp_RECHARGE //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that - - var/charge_max = 100 //recharge time in deciseconds if charge_type = Sp_RECHARGE or starting charges if charge_type = Sp_CHARGES - var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = Sp_RECHARGE or -- each cast if charge_type = Sp_CHARGES - var/still_recharging_msg = "The spell is still recharging." - - var/silenced = 0 //not a binary - the length of time we can't cast this for - var/processing = 0 //are we processing already? Mainly used so that silencing a spell doesn't call process() again. (and inadvertedly making it run twice as fast) - - var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" - var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used - - var/spell_flags = NEEDSCLOTHES - var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell - var/invocation_type = SpI_NONE //can be none, whisper, shout, and emote - var/range = 7 //the range of the spell; outer radius for aoe spells - var/message = "" //whatever it says to the guy affected by it - var/selection_type = "view" //can be "range" or "view" - var/atom/movable/holder //where the spell is. Normally the user, can be an item - var/duration = 0 //how long the spell lasts - - var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values - var/list/level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 0) //maximum possible levels in each category. Total does cover both. - var/cooldown_reduc = 0 //If set, defines how much charge_max drops by every speed upgrade - var/delay_reduc = 0 - var/cooldown_min = 0 //minimum possible cooldown for a charging spell - - var/overlay = 0 - var/overlay_icon = 'icons/obj/wizard.dmi' - var/overlay_icon_state = "spell" - var/overlay_lifespan = 0 - - var/sparks_spread = 0 - var/sparks_amt = 0 //cropped at 10 - var/smoke_spread = 0 //1 - harmless, 2 - harmful - var/smoke_amt = 0 //cropped at 10 - - var/critfailchance = 0 - var/time_between_channels = 0 //Delay between casts - var/number_of_channels = 1 //How many times can we channel? - - var/cast_delay = 1 - var/cast_sound = "" - - var/hud_state = "" //name of the icon used in generating the spell hud object - var/override_base = "" - - - var/obj/screen/connected_button - - var/hidden_from_codex = FALSE - -/////////////////////// -///SETUP AND PROCESS/// -/////////////////////// - -/spell/New() - ..() - - //still_recharging_msg = "[name] is still recharging." - charge_counter = charge_max - -/spell/proc/process() - if(processing) - return - processing = 1 - spawn(0) - while(charge_counter < charge_max || silenced > 0) - charge_counter = min(charge_max,charge_counter+1) - silenced = max(0,silenced-1) - sleep(1) - if(connected_button) - var/obj/screen/ability/spell/S = connected_button - if(!istype(S)) - return - S.update_charge(1) - processing = 0 - return - -///////////////// -/////CASTING///// -///////////////// - -/spell/proc/choose_targets(mob/user = usr) //depends on subtype - see targeted.dm, aoe_turf.dm, dumbfire.dm, or code in general folder - return - -/spell/proc/perform(mob/user = usr, skipcharge = 0) //if recharge is started is important for the trigger spells - if(!holder) - holder = user //just in case - if(!cast_check(skipcharge, user)) - return - to_chat(user, SPAN_NOTICE("You start casting \the [name]...")) - if(cast_delay && !spell_do_after(user, cast_delay)) - return - var/list/targets = choose_targets(user) - if(!check_valid_targets(targets)) - to_chat(user, SPAN_WARNING("\The [name] fizzles. There are no valid targets nearby.")) - return - var/time = 0 - admin_attacker_log(user, "attempted to cast the spell [name]") - do - time++ - if(!check_valid_targets(targets)) //make sure we HAVE something - break - if(cast_check(1,user, targets)) //we check again, otherwise you can choose a target and then wait for when you are no longer able to cast (I.E. Incapacitated) to use it. - invocation(user, targets) - take_charge(user, skipcharge) - before_cast(targets) //applies any overlays and effects - if(prob(critfailchance)) - critfail(targets, user) - else - cast(targets, user, time) - after_cast(targets) //generates the sparks, smoke, target messages etc. - else - break - while(time != number_of_channels && do_after(user, time_between_channels, incapacitation_flags = INCAPACITATION_KNOCKOUT|INCAPACITATION_FORCELYING|INCAPACITATION_STUNNED, same_direction=1)) - after_spell(targets, user, time) //When we are done with the spell completely. - - - -/spell/proc/cast(list/targets, mob/user, var/channel_duration) //the actual meat of the spell - return - -/spell/proc/critfail(list/targets, mob/user) //the wizman has fucked up somehow - return - -/spell/proc/after_spell(var/list/targets, var/mob/user, var/channel_duration) //After everything else is done. - return - -/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types - switch(type) - if("bruteloss") - target.take_damage(amount) - if("fireloss") - target.take_damage(amount, BURN) - if("toxloss") - target.take_damage(amount, TOX) - if("oxyloss") - target.take_damage(amount, OXY) - if("brainloss") - target.take_damage(amount, BRAIN) - if("stunned") - ADJ_STATUS(target, STAT_STUN, amount) - if("weakened") - ADJ_STATUS(target, STAT_WEAK, amount) - if("paralysis") - ADJ_STATUS(target, STAT_PARA, amount) - else - target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars - return - -/////////////////////////// -/////CASTING WRAPPERS////// -/////////////////////////// - -/spell/proc/before_cast(list/targets) - for(var/atom/target in targets) - if(overlay) - var/location - if(isliving(target)) - location = target.loc - else if(isturf(target)) - location = target - var/obj/effect/overlay/spell = new /obj/effect/overlay(location) - spell.icon = overlay_icon - spell.icon_state = overlay_icon_state - spell.anchored = TRUE - spell.set_density(0) - spawn(overlay_lifespan) - qdel(spell) - -/spell/proc/after_cast(list/targets) - if(cast_sound) - playsound(get_turf(holder),cast_sound,50,1) - for(var/atom/target in targets) - var/location = get_turf(target) - if(isliving(target) && message) - to_chat(target, text("[message]")) - if(sparks_spread) - spark_at(location, amount = sparks_amt) - if(smoke_spread) - if(smoke_spread == 1) - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - else if(smoke_spread == 2) - var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - -///////////////////// -////CASTING TOOLS//// -///////////////////// -/*Checkers, cost takers, message makers, etc*/ - -/spell/proc/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //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(silenced > 0) - return 0 - - if(!(src in user.mind.learned_spells) && holder == user && !(isanimal(user))) - error("[user] utilized the spell '[src]' without having it.") - to_chat(user, "You shouldn't have this spell! Something's wrong.") - return 0 - - var/turf/user_turf = get_turf(user) - if(!user_turf) - to_chat(user, "You cannot cast spells in null space!") - - if((spell_flags & Z2NOCAST) && isAdminLevel(user_turf.z)) //Certain spells are not allowed on the centcomm zlevel - return 0 - - if(spell_flags & CONSTRUCT_CHECK) - for(var/turf/T in range(holder, 1)) - if(findNullRod(T)) - return 0 - - if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone - return 0 - - if(holder == user) - if(isanimal(user)) - var/mob/living/simple_animal/SA = user - if(SA.purge) - to_chat(SA, "The null sceptre's power interferes with your own!") - return 0 - - if(!(spell_flags & GHOSTCAST)) - if(!(spell_flags & NO_SOMATIC)) - var/mob/living/L = user - if(L.incapacitated(INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT)) - to_chat(user, "You can't cast spells while incapacitated!") - return 0 - - if(ishuman(user) && !(invocation_type in list(SpI_EMOTE, SpI_NONE)) && user.get_item_blocking_speech()) - to_chat(user, "Mmmf mrrfff!") - return 0 - - var/spell/noclothes/spell = locate() in user.mind.learned_spells - if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)))//clothes check - if(!user.wearing_wiz_garb()) - return 0 - - return 1 - -/spell/proc/check_charge(var/skipcharge, mob/user) - if(!skipcharge) - switch(charge_type) - if(Sp_RECHARGE) - if(charge_counter < charge_max) - to_chat(user, still_recharging_msg) - return 0 - if(Sp_CHARGES) - if(!charge_counter) - to_chat(user, "[name] has no charges left.") - return 0 - return 1 - -/spell/proc/take_charge(mob/user = user, var/skipcharge) - if(!skipcharge) - switch(charge_type) - if(Sp_RECHARGE) - charge_counter = 0 //doesn't start recharging until the targets selecting ends - src.process() - return 1 - if(Sp_CHARGES) - charge_counter-- //returns the charge if the targets selecting fails - return 1 - if(Sp_HOLDVAR) - adjust_var(user, holder_var_type, holder_var_amount) - return 1 - return 0 - return 1 - -/spell/proc/check_valid_targets(var/list/targets) - if(!targets) - return 0 - if(!islist(targets)) - targets = list(targets) - else if(!targets.len) - return 0 - - var/list/valid_targets = view_or_range(range, holder, selection_type) - for(var/target in targets) - if(!(target in valid_targets)) - return 0 - return 1 - -/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount - - switch(invocation_type) - if(SpI_SHOUT) - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation) - else - user.say(replacetext(invocation," ","`")) - if(SpI_WHISPER) - if(prob(50)) - user.whisper(invocation) - else - user.whisper(replacetext(invocation," ","`")) - if(SpI_EMOTE) - user.custom_emote(VISIBLE_MESSAGE, invocation) - -///////////////////// -///UPGRADING PROCS/// -///////////////////// - -/spell/proc/can_improve(var/upgrade_type) - if(level_max[Sp_TOTAL] <= ( spell_levels[Sp_SPEED] + spell_levels[Sp_POWER] )) //too many levels, can't do it - return 0 - - //if(upgrade_type && spell_levels[upgrade_type] && level_max[upgrade_type]) - if(upgrade_type && spell_levels[upgrade_type] >= level_max[upgrade_type]) - return 0 - - return 1 - -/spell/proc/empower_spell() - if(!can_improve(Sp_POWER)) - return 0 - - spell_levels[Sp_POWER]++ - - return 1 - -/spell/proc/quicken_spell() - if(!can_improve(Sp_SPEED)) - return 0 - - spell_levels[Sp_SPEED]++ - - if(delay_reduc && cast_delay) - cast_delay = max(0, cast_delay - delay_reduc) - else if(cast_delay) - cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) - - if(charge_type == Sp_RECHARGE) - if(cooldown_reduc) - charge_max = max(cooldown_min, charge_max - cooldown_reduc) - else - charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose - if(charge_max < charge_counter) - charge_counter = charge_max - - var/temp = "" - name = initial(name) - switch(level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) - if(3) - temp = "You have improved [name] into Efficient [name]." - name = "Efficient [name]" - if(2) - temp = "You have improved [name] into Quickened [name]." - name = "Quickened [name]" - if(1) - temp = "You have improved [name] into Free [name]." - name = "Free [name]" - if(0) - temp = "You have improved [name] into Instant [name]." - name = "Instant [name]" - - return temp - -/spell/proc/spell_do_after(var/mob/user, delay, var/numticks = 5) - if(!user || isnull(user)) - return 0 - - var/incap_flags = INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING - if(!(spell_flags & (GHOSTCAST))) - incap_flags |= INCAPACITATION_KNOCKOUT - - return do_after(user,delay, incapacitation_flags = incap_flags) - -/proc/view_or_range(distance = world.view , center = usr , type) - switch(type) - if("view") - . = view(distance,center) - if("range") - . = range(distance,center) \ No newline at end of file diff --git a/code/modules/spells/spell_projectile.dm b/code/modules/spells/spell_projectile.dm deleted file mode 100644 index 1599a59d3a78..000000000000 --- a/code/modules/spells/spell_projectile.dm +++ /dev/null @@ -1,56 +0,0 @@ -/obj/item/projectile/spell_projectile - name = "spell" - icon = 'icons/obj/projectiles.dmi' - - nodamage = 1 //Most of the time, anyways - - var/spell/targeted/projectile/carried - - penetrating = 0 - life_span = 10 //set by the duration of the spell - - var/proj_trail = 0 //if it leaves a trail - var/proj_trail_lifespan = 0 //deciseconds - var/proj_trail_icon = 'icons/obj/wizard.dmi' - var/proj_trail_icon_state = "trail" - var/list/trails = new() - -/obj/item/projectile/spell_projectile/Destroy() - for(var/trail in trails) - qdel(trail) - carried = null - return ..() - -/obj/item/projectile/spell_projectile/explosion_act() - SHOULD_CALL_PARENT(FALSE) - return - -/obj/item/projectile/spell_projectile/before_move() - if(proj_trail && src && src.loc) //pretty trails - var/obj/effect/overlay/trail = new /obj/effect/overlay(loc) - trails += trail - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.set_density(0) - spawn(proj_trail_lifespan) - trails -= trail - qdel(trail) - -/obj/item/projectile/spell_projectile/proc/prox_cast(var/list/targets) - if(loc) - carried.prox_cast(targets, src) - qdel(src) - return - -/obj/item/projectile/spell_projectile/Bump(var/atom/A, forced=0) - if(loc && carried) - prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src)) - return 1 - -/obj/item/projectile/spell_projectile/on_impact() - if(loc && carried) - prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src)) - return 1 - -/obj/item/projectile/spell_projectile/seeking - name = "seeking spell" diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm deleted file mode 100644 index b9ab445eeae6..000000000000 --- a/code/modules/spells/spellbook.dm +++ /dev/null @@ -1,320 +0,0 @@ -#define NOREVERT 1 -#define LOCKED 2 -#define CAN_MAKE_CONTRACTS 4 -#define INVESTABLE 8 -#define NO_LOCKING 16 - -//spells/spellbooks have a variable for this but as artefacts are literal items they do not. -//so we do this instead. -var/global/list/artefact_feedback = list( - /obj/structure/closet/wizard/armor = "HS", - /obj/item/gun/energy/staff/focus = "MF", - /obj/item/gun/energy/staff/fire = "FS", - /obj/item/summoning_stone = "ST", - /obj/item/magic_rock = "RA", - /obj/item/contract/apprentice = "CP", - /obj/structure/closet/wizard/scrying = "SO", - /obj/item/teleportation_scroll = "TS", - /obj/item/gun/energy/staff = "ST", - /obj/item/gun/energy/staff/animate = "SA", - /obj/item/dice/d20/cursed = "DW" -) - -/obj/item/spellbook - name = "master spell book" - desc = "The legendary book of spells of the wizard." - icon = 'icons/obj/library.dmi' - icon_state = "book" - throw_speed = 1 - throw_range = 5 - w_class = ITEM_SIZE_NORMAL - material = /decl/material/solid/organic/paper - matter = list(/decl/material/solid/organic/leather = MATTER_AMOUNT_REINFORCEMENT) - var/uses = 1 - var/temp = null - var/datum/spellbook/spellbook - var/spellbook_type = /datum/spellbook/ //for spawning specific spellbooks. - var/investing_time = 0 //what time we target forr a return on our spell investment. - var/has_sacrificed = 0 //whether we have already got our sacrifice bonus for the current investment. - -/obj/item/spellbook/Initialize() - . = ..() - set_spellbook(spellbook_type) - -/obj/item/spellbook/proc/set_spellbook(var/type) - if(spellbook) - qdel(spellbook) - spellbook = new type() - uses = spellbook.max_uses - name = spellbook.name - desc = spellbook.desc - -/obj/item/spellbook/attack_self(mob/user) - if(!user.mind) - return - if (user.mind.assigned_special_role != /decl/special_role/wizard) - if (user.mind.assigned_special_role != "Wizard's Apprentice") - to_chat(user, "You can't make heads or tails of this book.") - return - if (spellbook.book_flags & LOCKED) - to_chat(user, "Drat! This spellbook's apprentice-proof lock is on!") - return - else if (spellbook.book_flags & LOCKED) - to_chat(user, "You notice the apprentice-proof lock is on. Luckily you are beyond such things.") - interact(user) - -/obj/item/spellbook/proc/make_sacrifice(obj/item/I, mob/user, var/reagent) - if(has_sacrificed) - to_chat(user, SPAN_WARNING("\The [src] is already sated! Wait for a return on your investment before you sacrifice more to it.")) - return - if(reagent) - if(I.reagents?.has_reagent(reagent, 5)) - I.remove_from_reagents(reagent, 5) - else if(LAZYACCESS(I.matter, reagent) >= (SHEET_MATERIAL_AMOUNT * 5)) - qdel(I) - else - if(istype(I,/obj/item/stack)) - var/obj/item/stack/S = I - if(S.amount < S.max_amount) - to_chat(usr, "You must sacrifice [S.max_amount] stacks of [S]!") - return - qdel(I) - to_chat(user, "Your sacrifice was accepted!") - has_sacrificed = 1 - investing_time = max(investing_time - 6000,1) //subtract 10 minutes. Make sure it doesn't act funky at the beginning of the game. - - -/obj/item/spellbook/attackby(obj/item/I, mob/user) - if(investing_time) - for(var/type in spellbook.sacrifice_objects) - if(istype(I,type)) - make_sacrifice(I, user) - return TRUE - - for(var/mat in spellbook.sacrifice_materials) - if(LAZYACCESS(I.matter, mat) > (SHEET_MATERIAL_AMOUNT * 10)) - make_sacrifice(I, user, mat) - return TRUE - - if(I.reagents) - for(var/id in spellbook.sacrifice_reagents) - if(I.reagents.has_reagent(id, 5)) - make_sacrifice(I, user, id) - return TRUE - ..() - -/obj/item/spellbook/interact(mob/user) - var/dat = null - if(temp) - dat = "[temp]
Return" - else - dat = "

[spellbook.title]

[spellbook.title_desc]
You have [uses] spell slot\s left.

" - dat += "
Requires Wizard Garb
Selectable Target
Spell Charge Type: Recharge, Sacrifice, Charges

" - dat += "
To use a contract, first bind it to your soul, then give it to someone to sign. This will bind their soul to you.

" - for(var/i in 1 to spellbook.spells.len) - var/name = "" //name of target - var/desc = "" //description of target - var/info = "" //additional information - if(ispath(spellbook.spells[i],/datum/spellbook)) - var/datum/spellbook/S = spellbook.spells[i] - name = initial(S.name) - desc = initial(S.book_desc) - info = "[initial(S.max_uses)] Spell Slots" - else if(ispath(spellbook.spells[i],/obj)) - var/obj/O = spellbook.spells[i] - name = "Artefact: [capitalize(initial(O.name))]" //because 99.99% of objects dont have capitals in them and it makes it look weird. - desc = initial(O.desc) - else if(ispath(spellbook.spells[i],/spell)) - var/spell/S = spellbook.spells[i] - name = initial(S.name) - desc = initial(S.desc) - var/testing = initial(S.spell_flags) - if(testing & NEEDSCLOTHES) - info = "W" - var/type = "" - switch(initial(S.charge_type)) - if(Sp_RECHARGE) - type = "R" - if(Sp_HOLDVAR) - type = "S" - if(Sp_CHARGES) - type = "C" - info += "[type]" - dat += "[name]" - if(length(info)) - dat += " ([info])" - dat += " ([spellbook.spells[spellbook.spells[i]]] spell slot[spellbook.spells[spellbook.spells[i]] > 1 ? "s" : "" ])" - if(spellbook.book_flags & CAN_MAKE_CONTRACTS) - dat += " Make Contract" - dat += "
[desc]

" - dat += "
" - dat += "
Re-memorise your spellbook.
" - if(spellbook.book_flags & INVESTABLE) - if(investing_time) - dat += "
Currently investing in a slot...
" - else - dat += "
Invest a Spell Slot
Investing a spellpoint will return two spellpoints back in 15 minutes.
Some say a sacrifice could even shorten the time...
" - if(!(spellbook.book_flags & NOREVERT)) - dat += "
Choose different spellbook.
" - if(!(spellbook.book_flags & NO_LOCKING)) - dat += "
[spellbook.book_flags & LOCKED ? "Unlock" : "Lock"] the spellbook.
" - show_browser(user, dat, "window=spellbook") - -/obj/item/spellbook/CanUseTopic(var/mob/living/human/H) - if(!istype(H)) - return STATUS_CLOSE - - if(H.mind && (spellbook.book_flags & LOCKED) && H.mind.assigned_special_role == "Wizard's Apprentice") //make sure no scrubs get behind the lock - return STATUS_CLOSE - - return ..() - -/obj/item/spellbook/OnTopic(var/mob/living/human/user, href_list) - if(href_list["lock"] && !(spellbook.book_flags & NO_LOCKING)) - if(spellbook.book_flags & LOCKED) - spellbook.book_flags &= ~LOCKED - else - spellbook.book_flags |= LOCKED - . = TOPIC_REFRESH - - else if(href_list["temp"]) - temp = null - . = TOPIC_REFRESH - - else if(href_list["book"]) - if(initial(spellbook.max_uses) != spellbook.max_uses || uses != spellbook.max_uses) - temp = "You've already purchased things using this spellbook!" - else - src.set_spellbook(/datum/spellbook) - temp = "You have reverted back to the Book of Tomes." - . = TOPIC_REFRESH - - else if(href_list["invest"]) - temp = invest() - . = TOPIC_REFRESH - - else if(href_list["path"]) - var/path = locate(href_list["path"]) in spellbook.spells - if(!path) - return TOPIC_HANDLED - if(uses < spellbook.spells[path]) - to_chat(user, "You do not have enough spell slots to purchase this.") - return TOPIC_HANDLED - send_feedback(path) //feedback stuff - if(ispath(path,/datum/spellbook)) - src.set_spellbook(path) - temp = "You have chosen a new spellbook." - else - if(href_list["contract"]) - if(!(spellbook.book_flags & CAN_MAKE_CONTRACTS)) - return //no - uses -= spellbook.spells[path] - spellbook.max_uses -= spellbook.spells[path] //no basksies - var/obj/O = new /obj/item/contract/boon(get_turf(user),path) - temp = "You have purchased \the [O]." - else - if(ispath(path,/spell)) - temp = src.add_spell(user,path) - if(temp) - uses -= spellbook.spells[path] - else - var/obj/O = new path(get_turf(user)) - temp = "You have purchased \a [O]." - uses -= spellbook.spells[path] - spellbook.max_uses -= spellbook.spells[path] - //finally give it a bit of an oomf - playsound(get_turf(user),'sound/effects/phasein.ogg',50,1) - . = TOPIC_REFRESH - - else if(href_list["reset"] && !(spellbook.book_flags & NOREVERT)) - var/area/map_template/wizard_station/A = get_area(user) - if(istype(A)) - uses = spellbook.max_uses - investing_time = 0 - has_sacrificed = 0 - user.spellremove() - temp = "All spells and investments have been removed. You may now memorise a new set of spells." - SSstatistics.add_field_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - else - to_chat(user, "You must be in the wizard academy to re-memorise your spells.") - . = TOPIC_REFRESH - - src.interact(user) - -/obj/item/spellbook/proc/invest() - if(uses < 1) - return "You don't have enough slots to invest!" - if(investing_time) - return "You can only invest one spell slot at a time." - uses-- - START_PROCESSING(SSobj, src) - investing_time = world.time + (15 MINUTES) - return "You invest a spellslot and will recieve two in return in 15 minutes." - -/obj/item/spellbook/Process() - if(investing_time && investing_time <= world.time) - src.visible_message("\The [src] emits a soft chime.") - uses += 2 - if(uses > spellbook.max_uses) - spellbook.max_uses = uses - investing_time = 0 - has_sacrificed = 0 - STOP_PROCESSING(SSobj, src) - return 1 - -/obj/item/spellbook/Destroy() - STOP_PROCESSING(SSobj, src) - . = ..() - -/obj/item/spellbook/proc/send_feedback(var/path) - if(ispath(path,/datum/spellbook)) - var/datum/spellbook/S = path - SSstatistics.add_field_details("wizard_spell_learned","[initial(S.feedback)]") - else if(ispath(path,/spell)) - var/spell/S = path - SSstatistics.add_field_details("wizard_spell_learned","[initial(S.feedback)]") - else if(ispath(path,/obj)) - SSstatistics.add_field_details("wizard_spell_learned","[artefact_feedback[path]]") - - -/obj/item/spellbook/proc/add_spell(var/mob/user, var/spell_path) - for(var/spell/S in user.mind.learned_spells) - if(istype(S,spell_path)) - if(!S.can_improve()) - return - if(S.can_improve(Sp_SPEED) && S.can_improve(Sp_POWER)) - switch(alert(user, "Do you want to upgrade this spell's speed or power?", "Spell upgrade", "Speed", "Power", "Cancel")) - if("Speed") - return S.quicken_spell() - if("Power") - return S.empower_spell() - else - return - else if(S.can_improve(Sp_POWER)) - return S.empower_spell() - else if(S.can_improve(Sp_SPEED)) - return S.quicken_spell() - - var/spell/S = new spell_path() - user.add_spell(S) - return "You learn the spell [S]" - -/datum/spellbook - var/name = "\improper Book of Tomes" - var/desc = "The legendary book of spells of the wizard." - var/book_desc = "Holds information on the various tomes available to a wizard" - var/feedback = "" //doesn't need one. - var/book_flags = NOREVERT - var/max_uses = 1 - var/title = "Book of Tomes" - var/title_desc = "This tome marks down all the available tomes for use. Choose wisely, there are no refunds." - var/list/spells = list(/datum/spellbook/standard = 1, - /datum/spellbook/cleric = 1, - /datum/spellbook/battlemage = 1, - /datum/spellbook/spatial = 1, - /datum/spellbook/druid = 1 - ) //spell's path = cost of spell - - var/list/sacrifice_reagents - var/list/sacrifice_objects - var/list/sacrifice_materials diff --git a/code/modules/spells/spellbook/battlemage.dm b/code/modules/spells/spellbook/battlemage.dm deleted file mode 100644 index 70a95e643ea4..000000000000 --- a/code/modules/spells/spellbook/battlemage.dm +++ /dev/null @@ -1,44 +0,0 @@ -//Battlemage is all about mixing physical with the mystical in head to head combat. -//Things like utility and mobility come second. -/datum/spellbook/battlemage - name = "\improper Battlemage's Bible" - feedback = "BM" - desc = "Smells like blood." - book_desc = "Mix physical with the mystical in head to head combat." - title = "The Art of Magical Combat" - title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." - book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 6 - - spells = list( - /spell/targeted/projectile/dumbfire/passage = 1, - /spell/targeted/equip_item/dyrnwyn = 1, - /spell/targeted/equip_item/shield = 1, - /spell/targeted/projectile/dumbfire/fireball = 1, - /spell/targeted/torment = 1, - /spell/targeted/heal_target = 2, - /spell/aoe_turf/conjure/mirage = 1, - /spell/targeted/shapeshift/corrupt_form = 1, - /spell/radiant_aura = 1, - /spell/noclothes = 1, - /obj/structure/closet/wizard/armor = 1, - /obj/item/gun/energy/staff/focus = 1, - /obj/item/gun/energy/staff/fire = 1, - /obj/item/dice/d20/cursed = 1, - /obj/item/summoning_stone = 2, - /obj/item/magic_rock = 1, - /obj/item/contract/wizard/xray = 1, - /obj/item/contract/wizard/telepathy = 1, - /obj/item/contract/apprentice = 1 - ) - - sacrifice_objects = list( - /obj/item/sword, - /obj/item/twohanded/fireaxe, - /obj/item/baton, - /obj/item/knife/ritual, - /obj/item/knife/kitchen/cleaver, - /obj/item/knife/folding/combat/balisong, - /obj/item/knife/folding/tacticool, - /obj/item/star - ) diff --git a/code/modules/spells/spellbook/cleric.dm b/code/modules/spells/spellbook/cleric.dm deleted file mode 100644 index ad447b2d2cec..000000000000 --- a/code/modules/spells/spellbook/cleric.dm +++ /dev/null @@ -1,50 +0,0 @@ -//Cleric is all about healing. Mobility and offense comes at a higher price but not impossible. -/obj/item/spellbook/cleric - spellbook_type = /datum/spellbook/cleric - -/datum/spellbook/cleric - name = "\improper Cleric's Tome" - feedback = "CR" - desc = "For those who do not harm, or at least feel sorry about it." - book_desc = "All about healing. Mobility and offense comes at a higher price but not impossible." - title = "Cleric's Tome of Healing" - title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." - book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 7 - - spells = list( - /spell/targeted/heal_target/major = 1, - /spell/targeted/heal_target/area = 1, - /spell/targeted/heal_target/sacrifice = 1, - /spell/targeted/genetic/blind = 1, - /spell/targeted/shapeshift/baleful_polymorph = 1, - /spell/targeted/projectile/dumbfire/stuncuff = 1, - /spell/targeted/ethereal_jaunt = 2, - /spell/aoe_turf/knock = 1, - /spell/radiant_aura = 1, - /spell/targeted/equip_item/holy_relic = 1, - /spell/aoe_turf/conjure/grove/sanctuary = 1, - /spell/targeted/projectile/dumbfire/fireball = 2, - /spell/area_teleport = 2, - /spell/portal_teleport = 2, - /spell/aoe_turf/conjure/forcewall = 1, - /spell/noclothes = 1, - /obj/item/magic_rock = 1, - /obj/structure/closet/wizard/scrying = 2, - /obj/item/summoning_stone = 2, - /obj/item/contract/wizard/telepathy = 1, - /obj/item/contract/apprentice = 1 - ) - - sacrifice_reagents = list( - /decl/material/liquid/adminordrazine - ) - sacrifice_objects = list( - /obj/item/stack/nanopaste, - /obj/item/scanner/health, - /obj/item/scanner/breath, - /obj/item/stack/medical/bandage/advanced, - /obj/item/stack/medical/ointment/advanced, - /obj/item/bodybag/rescue, - /obj/item/defibrillator - ) diff --git a/code/modules/spells/spellbook/druid.dm b/code/modules/spells/spellbook/druid.dm deleted file mode 100644 index ec86e1ac93b6..000000000000 --- a/code/modules/spells/spellbook/druid.dm +++ /dev/null @@ -1,43 +0,0 @@ -//all about the summons, nature, and a bit o' healin. - -/obj/item/spellbook/druid - spellbook_type = /datum/spellbook/druid - -/datum/spellbook/druid - name = "\improper Druid's Leaflet" - feedback = "DL" - desc = "It smells like an air freshener." - book_desc = "Summons, nature, and a bit o' healin." - title = "Druidic Guide on how to be smug about nature" - title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." - book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 6 - - spells = list( - /spell/targeted/heal_target = 1, - /spell/targeted/heal_target/sacrifice = 1, - /spell/aoe_turf/conjure/mirage = 1, - /spell/aoe_turf/conjure/summon/bats = 1, - /spell/aoe_turf/conjure/summon/bear = 1, - /spell/targeted/equip_item/party_hardy = 1, - /spell/targeted/equip_item/seed = 1, - /spell/targeted/shapeshift/avian = 1, - /spell/aoe_turf/disable_tech = 1, - /spell/hand/charges/entangle = 1, - /spell/aoe_turf/conjure/grove/sanctuary = 1, - /spell/aoe_turf/knock = 1, - /spell/area_teleport = 2, - /spell/portal_teleport = 2, - /spell/noclothes = 1, - /obj/item/magic_rock = 1, - /obj/item/summoning_stone = 2, - /obj/item/contract/wizard/telepathy = 1, - /obj/item/contract/apprentice = 1 - ) - sacrifice_objects = list( - /obj/item/seeds, - /obj/item/wirecutters/clippers, - /obj/item/scanner/plant, - /obj/item/tool/axe/hatchet, - /obj/item/tool/hoe/mini - ) diff --git a/code/modules/spells/spellbook/spatial.dm b/code/modules/spells/spellbook/spatial.dm deleted file mode 100644 index 7006ea577e78..000000000000 --- a/code/modules/spells/spellbook/spatial.dm +++ /dev/null @@ -1,48 +0,0 @@ -//all about moving around and mobility and being an annoying shit. - -/obj/item/spellbook/spatial - spellbook_type = /datum/spellbook/spatial - -/datum/spellbook/spatial - name = "\improper Spatial Manual" - feedback = "SP" - desc = "You feel like this might disappear from out of under you." - book_desc = "Movement and teleportation. Run from your problems!" - title = "Manual of Spatial Transportation" - title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." - book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 11 - - spells = list( - /spell/targeted/ethereal_jaunt = 1, - /spell/aoe_turf/blink = 1, - /spell/area_teleport = 1, - /spell/portal_teleport = 1, - /spell/targeted/projectile/dumbfire/passage = 1, - /spell/mark_recall = 1, - /spell/targeted/swap = 1, - /spell/targeted/shapeshift/avian = 1, - /spell/targeted/projectile/magic_missile = 1, - /spell/targeted/heal_target = 1, - /spell/aoe_turf/conjure/forcewall = 1, - /spell/aoe_turf/smoke = 1, - /spell/aoe_turf/conjure/summon/bats = 3, - /spell/noclothes = 1, - /obj/item/dice/d20/cursed = 1, - /obj/structure/closet/wizard/scrying = 2, - /obj/item/teleportation_scroll = 1, - /obj/item/magic_rock = 1, - /obj/item/summoning_stone = 3, - /obj/item/contract/wizard/telepathy = 1, - /obj/item/contract/apprentice = 1 - ) - - sacrifice_reagents = list( - /decl/material/liquid/amphetamines - ) - sacrifice_objects = list( - /obj/item/stack/telecrystal - ) - sacrifice_materials = list( - /decl/material/solid/gemstone/diamond - ) \ No newline at end of file diff --git a/code/modules/spells/spellbook/standard.dm b/code/modules/spells/spellbook/standard.dm deleted file mode 100644 index 5b30a7c9918b..000000000000 --- a/code/modules/spells/spellbook/standard.dm +++ /dev/null @@ -1,54 +0,0 @@ -//the spellbook we know and love. Well, the one we know, at least. - -/obj/item/spellbook/standard - spellbook_type = /datum/spellbook/standard - -/datum/spellbook/standard - name = "\improper Standard Spellbook" - feedback = "SB" - title = "Book of Spells and Artefacts" - title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." - book_desc = "A general wizard's spellbook. All its spells are easy to use but hard to master." - book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 6 - - spells = list( - /spell/targeted/projectile/magic_missile = 1, - /spell/targeted/projectile/dumbfire/fireball = 1, - /spell/aoe_turf/disable_tech = 1, - /spell/aoe_turf/smoke = 1, - /spell/targeted/genetic/blind = 1, - /spell/targeted/subjugation = 1, - /spell/aoe_turf/conjure/forcewall = 1, - /spell/aoe_turf/blink = 1, - /spell/area_teleport = 1, - /spell/targeted/ethereal_jaunt = 1, - /spell/targeted/heal_target = 1, - /spell/aoe_turf/knock = 1, - /spell/noclothes = 2, - /obj/item/gun/energy/staff/focus = 1, - /obj/item/gun/energy/staff/fire = 1, - /obj/item/gun/energy/staff/animate = 1, - /obj/structure/closet/wizard/scrying = 1, - /obj/item/summoning_stone = 2, - /obj/item/magic_rock = 1, - /obj/item/contract/wizard/telepathy = 1, - /obj/item/contract/apprentice = 1 - ) - - sacrifice_objects = list( - /obj/item/toolbox, - /obj/item/cane, - /obj/item/flamethrower, - /obj/item/plastique, - /obj/item/dice, - /obj/item/soap, - /obj/item/flame/candle, - /obj/item/flame/candle/scented/incense, - /obj/item/caution, - /obj/item/towel, - /obj/item/tank/jetpack, - /obj/item/plunger, - /obj/item/megaphone, - /obj/item/deck/cards - ) \ No newline at end of file diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm deleted file mode 100644 index ad550747a7ff..000000000000 --- a/code/modules/spells/spells.dm +++ /dev/null @@ -1,60 +0,0 @@ -/datum/mind - var/list/learned_spells - -/mob/Stat() - . = ..() - if(. && ability_master && ability_master.spell_objects) - for(var/obj/screen/ability/spell/screen in ability_master.spell_objects) - var/spell/S = screen.spell - if((!S.connected_button) || !statpanel(S.panel)) - continue //Not showing the noclothes spell - switch(S.charge_type) - if(Sp_RECHARGE) - statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button) - if(Sp_CHARGES) - statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button) - if(Sp_HOLDVAR) - statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button) - -/proc/restore_spells(var/mob/H) - if(H.mind && H.mind.learned_spells) - var/list/spells = list() - for(var/spell/spell_to_remove in H.mind.learned_spells) //remove all the spells from other people. - if(ismob(spell_to_remove.holder)) - var/mob/M = spell_to_remove.holder - spells += spell_to_remove - M.remove_spell(spell_to_remove) - - for(var/spell/spell_to_add in spells) - H.add_spell(spell_to_add) - H.ability_master.update_abilities(0,H) - -/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready") - if(!ability_master) - ability_master = new(null, src) - spell_to_add.holder = src - if(mind) - if(!mind.learned_spells) - mind.learned_spells = list() - mind.learned_spells |= spell_to_add - ability_master.add_spell(spell_to_add, spell_base) - return 1 - -/mob/proc/remove_spell(var/spell/spell_to_remove) - if(!spell_to_remove || !istype(spell_to_remove)) - return - - if(mind) - mind.learned_spells -= spell_to_remove - if (ability_master) - ability_master.remove_ability(ability_master.get_ability_by_spell(spell_to_remove)) - return 1 - -/mob/proc/silence_spells(var/amount = 0) - if(amount < 0) - return - - if(!ability_master) - return - - ability_master.silence_spells(amount) \ No newline at end of file diff --git a/code/modules/spells/targeted/projectile/projectile.dm b/code/modules/spells/targeted/projectile/projectile.dm deleted file mode 100644 index 6df791094be2..000000000000 --- a/code/modules/spells/targeted/projectile/projectile.dm +++ /dev/null @@ -1,45 +0,0 @@ -/* -Projectile spells make special projectiles (obj/item/spell_projectile) and fire them at targets -Dumbfire projectile spells fire directly ahead of the user -spell_projectiles call their spell's (carried) prox_cast when they get in range of a target -If the spell_projectile is seeking, it will update its target every process and follow them -*/ - -/spell/targeted/projectile - range = 7 - var/proj_type = /obj/item/projectile/spell_projectile //use these. They are very nice - var/proj_step_delay = 1 //lower = faster - var/cast_prox_range = 1 - -/spell/targeted/projectile/cast(list/targets, mob/user = usr) - for(var/atom/target in targets) - var/obj/item/projectile/projectile = new proj_type(user.loc, user.dir) - - if(!projectile) - return - - if(istype(projectile, /obj/item/projectile/spell_projectile)) - var/obj/item/projectile/spell_projectile/SP = projectile - SP.carried = src //casting is magical - projectile.original = target - projectile.starting = get_turf(user) - projectile.shot_from = user //fired from the user - projectile.current = projectile.original - projectile.yo = target.y - user.y - projectile.xo = target.x - user.x - projectile.life_span = src.duration - projectile.hitscan = !proj_step_delay - projectile.step_delay = proj_step_delay - projectile.launch(target) - return - -/spell/targeted/projectile/proc/choose_prox_targets(mob/user = usr, var/atom/movable/spell_holder) - var/list/targets = list() - for(var/mob/living/M in range(spell_holder, cast_prox_range)) - if(M == user && !(spell_flags & INCLUDEUSER)) - continue - targets += M - return targets - -/spell/targeted/projectile/proc/prox_cast(var/list/targets, var/atom/movable/spell_holder) - return targets \ No newline at end of file diff --git a/icons/mob/screen/abilities.dmi b/icons/mob/screen/abilities.dmi new file mode 100644 index 0000000000000000000000000000000000000000..ca7d904bd71dbc6d68106bb685a6af3174168aa5 GIT binary patch literal 464 zcmV;>0WbcEP)?(f5P}yNyn%R-uJi_a z{Z5=boaW)8l!nlsxDdYlj0rYPEv;k`-N4c}E%&11djzaPh>lhCcLD|g#x(You warp back to Nar-Sie[prey ? " along with your prey":""].") - else - to_chat(user, "...something's wrong!")//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world. - diff --git a/mods/gamemodes/cult/wizard.dm b/mods/gamemodes/cult/wizard.dm index b29fa023f65c..79ddc58471af 100644 --- a/mods/gamemodes/cult/wizard.dm +++ b/mods/gamemodes/cult/wizard.dm @@ -1,14 +1,13 @@ -// #ifdef GAMEMODE_PACK_WIZARD -// todo: add wizard gamemode define check once it's modularized +#ifdef GAMEMODE_PACK_WIZARD /decl/modpack/cult/post_initialize() . = ..() global.artefact_feedback[/obj/structure/closet/wizard/souls] = "SS" -/datum/spellbook/standard/New() +/decl/spellbook/standard/New() spells[/obj/structure/closet/wizard/souls] = 1 ..() -/datum/spellbook/druid/New() +/decl/spellbook/druid/New() spells[/obj/structure/closet/wizard/souls] = 1 ..() @@ -18,7 +17,7 @@ /obj/structure/closet/wizard/souls/WillContain() return list( - /obj/item/contract/boon/wizard/artificer, + /obj/item/paper/contract/boon/wizard/artificer, /obj/item/belt/soulstone/full, ) @@ -36,7 +35,7 @@ /obj/item/belt/soulstone/full/WillContain() return list(/obj/item/soulstone = max(1, storage?.storage_slots)) -/obj/item/contract/boon/wizard/artificer +/obj/item/paper/contract/boon/wizard/artificer path = /spell/aoe_turf/conjure/construct desc = "This contract has a passage dedicated to an entity known as 'Nar-Sie'." @@ -44,4 +43,5 @@ material = /decl/material/solid/stone/cult /obj/item/summoning_stone - material = /decl/material/solid/stone/cult \ No newline at end of file + material = /decl/material/solid/stone/cult +#endif \ No newline at end of file diff --git a/mods/gamemodes/deity/forms/narsie/spells/tear_veil.dm b/mods/gamemodes/deity/forms/narsie/spells/tear_veil.dm index daf6b5d59d9d..ea4ce10f7d65 100644 --- a/mods/gamemodes/deity/forms/narsie/spells/tear_veil.dm +++ b/mods/gamemodes/deity/forms/narsie/spells/tear_veil.dm @@ -3,7 +3,6 @@ desc = "Use your mental strength to literally tear a hole from this dimension to the next, letting things through..." charge_max = 300 - spell_flags = Z2NOCAST invocation = "none" invocation_type = SpI_NONE diff --git a/mods/gamemodes/deity/forms/starlight/spells/disable_tech.dm b/mods/gamemodes/deity/forms/starlight/spells/disable_tech.dm index f6462ae33fed..d63da364ccbb 100644 --- a/mods/gamemodes/deity/forms/starlight/spells/disable_tech.dm +++ b/mods/gamemodes/deity/forms/starlight/spells/disable_tech.dm @@ -1,4 +1,4 @@ /spell/aoe_turf/disable_tech/starlight hidden_from_codex = TRUE charge_max = 600 - spell_flags = 0 \ No newline at end of file + requires_wizard_garb = FALSE diff --git a/mods/gamemodes/deity/forms/starlight/spells/starlight_aura.dm b/mods/gamemodes/deity/forms/starlight/spells/starlight_aura.dm index 8ad867e41b3e..07059aea0381 100644 --- a/mods/gamemodes/deity/forms/starlight/spells/starlight_aura.dm +++ b/mods/gamemodes/deity/forms/starlight/spells/starlight_aura.dm @@ -1,5 +1,5 @@ /spell/radiant_aura/starlight name = "Starlight Aura" desc = "This spell makes you immune to laser fire, for a short while at least." - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 400 diff --git a/mods/gamemodes/deity/forms/starlight/spells/veil_of_shadows.dm b/mods/gamemodes/deity/forms/starlight/spells/veil_of_shadows.dm index e47edecd0822..3abc00e50c63 100644 --- a/mods/gamemodes/deity/forms/starlight/spells/veil_of_shadows.dm +++ b/mods/gamemodes/deity/forms/starlight/spells/veil_of_shadows.dm @@ -5,7 +5,7 @@ invocation_type = SpI_EMOTE invocation = "flickers out of existance" school = "Divine" - spell_flags = 0 + requires_wizard_garb = FALSE duration = 100 var/timer_id var/light_steps = 4 diff --git a/mods/gamemodes/deity/forms/starlight/structures.dm b/mods/gamemodes/deity/forms/starlight/structures.dm index 7fa1c3d358b3..40b7fc5debe4 100644 --- a/mods/gamemodes/deity/forms/starlight/structures.dm +++ b/mods/gamemodes/deity/forms/starlight/structures.dm @@ -127,8 +127,7 @@ user.mind.transfer_to(H) H.set_species(possible_forms[looking_for]["species"]) for(var/s in possible_forms[looking_for]["spells"]) - var/spell/S = new s - H.add_spell(S) + H.add_ability(S) var/decl/special_role/godcultist/godcult = GET_DECL(/decl/special_role/godcultist) godcult.add_antagonist_mind(H.mind, 1, "[looking_for] of [linked_god]", "You are a powerful entity in the service to \the [linked_god]. [possible_forms[looking_for]["species"]]", specific_god = linked_god) stop_looking_for(TRUE) diff --git a/mods/gamemodes/deity/forms/tower/spells.dm b/mods/gamemodes/deity/forms/tower/spells.dm index 18b88647edfe..cc69a59fbaec 100644 --- a/mods/gamemodes/deity/forms/tower/spells.dm +++ b/mods/gamemodes/deity/forms/tower/spells.dm @@ -21,12 +21,12 @@ /spell/aoe_turf/conjure/faithful_hound/tower desc = "This spell allows you to summon a singular spectral dog that guards the nearby area. Anyone without the password is barked at or bitten." charge_max = 1 - spell_flags = 0 + requires_wizard_garb = FALSE /spell/aoe_turf/conjure/force_portal/tower desc = "This spell allows you to summon a force portal. Anything that hits the portal gets sucked inside and is then thrown out when the portal explodes." charge_max = 2 - spell_flags = 0 + requires_wizard_garb = FALSE /spell/acid_spray/tower desc = "The simplest form of aggressive conjuration: acid spray is quite effective in melting both man and object." @@ -38,7 +38,7 @@ /spell/targeted/heal_target/major/tower charge_max = 1 - spell_flags = INCLUDEUSER | SELECTABLE + can_select_target = TRUE desc = "Allows you to heal others for a great amount." /spell/targeted/heal_target/area/tower @@ -48,7 +48,6 @@ /spell/targeted/ethereal_jaunt/tower desc = "Allows you to liquefy for a short duration, letting you pass through all dense objects." charge_max = 2 - spell_flags = Z2NOCAST | INCLUDEUSER /spell/aoe_turf/conjure/forcewall/tower desc = "A temporary invincible wall for you to summon." diff --git a/mods/gamemodes/deity/mobs/deity_boons.dm b/mods/gamemodes/deity/mobs/deity_boons.dm index da05d9a5ff2b..21eda36a6bce 100644 --- a/mods/gamemodes/deity/mobs/deity_boons.dm +++ b/mods/gamemodes/deity/mobs/deity_boons.dm @@ -42,8 +42,8 @@ if(istype(S, spell.type)) to_chat(src, SPAN_WARNING("They already know that spell!")) return 0 - target.add_spell(spell) - spell.set_connected_god(src) + target.add_ability(spell) + spell.set_connected_god(target, src) to_chat(target, SPAN_NOTICE("You feel a surge of power as you learn the art of [current_boon].")) return 1 diff --git a/mods/gamemodes/deity/mobs/deity_sources.dm b/mods/gamemodes/deity/mobs/deity_sources.dm index a1ec947983d8..241e50bc5f05 100644 --- a/mods/gamemodes/deity/mobs/deity_sources.dm +++ b/mods/gamemodes/deity/mobs/deity_sources.dm @@ -4,9 +4,11 @@ adjust_source(3, L) minions += L.mind +/* var/spell/construction/C = new() - L.add_spell(C) - C.set_connected_god(src) + L.add_ability(C) + C.set_connected_god(L, src) +*/ if(form) L.faction = form.faction update_followers() @@ -22,7 +24,7 @@ for(var/s in M.learned_spells) var/spell/S = s if(S.connected_god == src) - M.current.remove_spell(S) + M.current.remove_ability(S) qdel(S) /mob/living/deity/proc/remove_follower(var/mob/living/L) diff --git a/mods/gamemodes/deity/mobs/phenomena/starlight.dm b/mods/gamemodes/deity/mobs/phenomena/starlight.dm index 72a6f0dbf07f..644596c457ef 100644 --- a/mods/gamemodes/deity/mobs/phenomena/starlight.dm +++ b/mods/gamemodes/deity/mobs/phenomena/starlight.dm @@ -73,9 +73,9 @@ L.put_in_hands_or_store_or_drop(new w_type(T)) if(form["spells"]) for(var/s in form["spells"]) - var/spell/boon = new s - boon.set_connected_god(linked) - L.add_spell(boon) + var/decl/ability/boon = GET_DECL(s) + boon.set_connected_god(L, linked) + L.add_ability(boon) to_chat(L, "You have been chosen by your master to lead your fellow followers into the next age of rebirth.
You have been granted powerful armor and a powerful spell. Don't lose them, as they are your key to your divinity and leadership.
You also have particular sway over your deity's structures.
") to_chat(linked, SPAN_NOTICE("\The [L] is now your herald!")) linked.remove_phenomena(name) diff --git a/mods/gamemodes/deity/spells/boon.dm b/mods/gamemodes/deity/spells/boon.dm index 269a0b4bc4cf..0048334cbf91 100644 --- a/mods/gamemodes/deity/spells/boon.dm +++ b/mods/gamemodes/deity/spells/boon.dm @@ -1,11 +1,11 @@ -/spell - var/mob/living/deity/connected_god //Do we have this spell based off a boon from a god? - -/spell/proc/set_connected_god(var/mob/living/deity/god) - connected_god = god +/decl/ability/proc/set_connected_god(mob/living/subject, mob/living/deity/god) + var/list/metadata = subject.get_ability_metadata(type) + metadata["connected_god"] = god // todo: godform check_charge to parallel take_charge. currently a boon always succeeds +/* /spell/take_charge(mob/user, skipcharge) if(connected_god) return connected_god.take_charge(user, max(1, charge_max/10)) - return ..() \ No newline at end of file + return ..() +*/ \ No newline at end of file diff --git a/mods/gamemodes/deity/spells/construction.dm b/mods/gamemodes/deity/spells/construction.dm index 0005154ad6ea..621fb4a3d720 100644 --- a/mods/gamemodes/deity/spells/construction.dm +++ b/mods/gamemodes/deity/spells/construction.dm @@ -7,7 +7,6 @@ cast_delay = 10 charge_max = 100 - spell_flags = Z2NOCAST invocation = "none" invocation_type = SpI_NONE diff --git a/mods/gamemodes/deity/spells/open_gateway.dm b/mods/gamemodes/deity/spells/open_gateway.dm index db83a05c8917..c8658c4def21 100644 --- a/mods/gamemodes/deity/spells/open_gateway.dm +++ b/mods/gamemodes/deity/spells/open_gateway.dm @@ -3,7 +3,6 @@ desc = "Open a gateway for your master. Don't do it for too long, or you will die." charge_max = 600 - spell_flags = Z2NOCAST invocation = "none" invocation_type = SpI_NONE @@ -29,6 +28,5 @@ to_chat(holder, SPAN_DANGER("The gateway consumes you... leaving nothing but dust.")) holder.dust() - /spell/open_gateway/after_spell(var/list/targets) QDEL_NULL_LIST(targets) \ No newline at end of file diff --git a/mods/gamemodes/deity/spells/vision.dm b/mods/gamemodes/deity/spells/vision.dm index dabe6cf4fcaf..1bf585112ca8 100644 --- a/mods/gamemodes/deity/spells/vision.dm +++ b/mods/gamemodes/deity/spells/vision.dm @@ -3,7 +3,6 @@ desc = "See what your master sees." charge_max = 10 - spell_flags = Z2NOCAST invocation = "none" invocation_type = SpI_NONE @@ -18,4 +17,4 @@ if(!fl) return fl.set_visualnet(god.eyenet) - + diff --git a/mods/gamemodes/wizard/_wizard.dm b/mods/gamemodes/wizard/_wizard.dm new file mode 100644 index 000000000000..9e2a4ea24d7b --- /dev/null +++ b/mods/gamemodes/wizard/_wizard.dm @@ -0,0 +1,15 @@ +//invocation +#define SpI_SHOUT "shout" +#define SpI_WHISPER "whisper" +#define SpI_EMOTE "emote" +#define SpI_NONE "none" + +//upgrading +#define Sp_SPEED "speed" +#define Sp_POWER "power" +#define Sp_TOTAL "total" + +//casting costs +#define Sp_RECHARGE "recharge" +#define Sp_CHARGES "charges" +#define Sp_HOLDVAR "holdervar" diff --git a/mods/gamemodes/wizard/_wizard.dme b/mods/gamemodes/wizard/_wizard.dme new file mode 100644 index 000000000000..66206a5d338b --- /dev/null +++ b/mods/gamemodes/wizard/_wizard.dme @@ -0,0 +1,28 @@ +#ifndef GAMEMODE_PACK_WIZARD +#define GAMEMODE_PACK_WIZARD +// BEGIN_INCLUDE +#include "_wizard.dm" +#include "artifacts.dm" +#include "contracts.dm" +#include "familiar.dm" +#include "mode.dm" +#include "outfits.dm" +#include "overrides.dm" +#include "role.dm" +#include "scrolls.dm" +#include "storage.dm" +#include "wizard_clothes.dm" +#include "wizard_props.dm" +#include "spellbook\spellbook_subtypes.dm" +#include "spellbook\spellbook.dm" +#include "spellbook\spellbook_types\_spellbook_type.dm" +#include "spellbook\spellbook_types\spellbook_battlemage.dm" +#include "spellbook\spellbook_types\spellbook_cleric.dm" +#include "spellbook\spellbook_types\spellbook_druid.dm" +#include "spellbook\spellbook_types\spellbook_spatial.dm" +#include "spellbook\spellbook_types\spellbook_standard.dm" +#include "spellbook\spellbook_types\spellbook_student.dm" +#include "spells\_spell_handler.dm" +#include "spells\_spell.dm" +// END_INCLUDE +#endif diff --git a/mods/gamemodes/wizard/artifacts.dm b/mods/gamemodes/wizard/artifacts.dm new file mode 100644 index 000000000000..2b02b4a7d75c --- /dev/null +++ b/mods/gamemodes/wizard/artifacts.dm @@ -0,0 +1,90 @@ +/atom/proc/get_null_rod() + for(var/atom/movable/thing as anything in get_contained_external_atoms()) + var/result = thing.get_null_rod() + if(result) + return result + +/obj/item/nullrod/get_null_rod() + return src + +//////////////////////Scrying orb////////////////////// +/obj/item/scrying + name = "scrying orb" + desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means." + icon = 'icons/obj/projectiles.dmi' + icon_state = "bluespace" + throw_speed = 3 + throw_range = 7 + throwforce = 10 + atom_damage_type = BURN + force = 10 + hitsound = 'sound/magic/forcewall.ogg' + max_health = ITEM_HEALTH_NO_DAMAGE + +/obj/item/scrying/attack_self(mob/user) + var/decl/special_role/wizard/wizards = GET_DECL(/decl/special_role/wizard) + if((user.mind && !wizards.is_antagonist(user.mind))) + to_chat(user, SPAN_NOTICE("You stare into the orb and see nothing but your own reflection.")) + return TRUE + to_chat(user, "You can see... everything!") // This never actually happens. + visible_message("[user] stares into [src], their eyes glazing over.") + user.teleop = user.ghostize(1) + announce_ghost_joinleave(user.teleop, 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.") + return TRUE + +/////////////////////////Cursed Dice/////////////////////////// +/obj/item/dice/d20/cursed + desc = "A dice with twenty sides said to have an ill effect on those that are unlucky..." + +/datum/trader/ship/toyshop/New() + LAZYSET(possible_trading_items, /obj/item/dice/d20/cursed, TRADER_BLACKLIST) + ..() + +/obj/item/dice/d20/cursed/attack_self(mob/user) + ..() + if(isliving(user)) + var/mob/living/M = user + if(icon_state == "[name][sides]") + M.heal_damage(BRUTE, 30) + else if(icon_state == "[name]1") + M.take_damage(30) + +/////////////////////////Magic rock/////////////////////////// +/obj/item/magic_rock + name = "magical rock" + desc = "Legends say that this rock will unlock the true potential of anyone who touches it." + icon = 'icons/obj/wizard.dmi' + icon_state = "magic rock" + w_class = ITEM_SIZE_SMALL + throw_speed = 1 + throw_range = 3 + force = 15 + material = /decl/material/solid/stone/basalt + var/list/potentials = list( + SPECIES_HUMAN = /obj/item/bag/cash/infinite + ) + +/obj/item/magic_rock/attack_self(mob/user) + + var/species_name = user.get_species_name() + if(!species_name) + to_chat(user, SPAN_WARNING("\The [src] can do nothing for such a simple being.")) + return TRUE + + var/reward = potentials[species_name] + if(ispath(reward, /decl/ability)) + if(user.has_ability(reward)) + to_chat(user, SPAN_WARNING("\The [src] can do nothing more for you.")) + return TRUE + user.add_ability(reward) + + else if(ispath(reward, /obj/item)) + user.put_in_hands(new reward(get_turf(user))) + + else + to_chat(user, SPAN_WARNING("\The [src] does not know what to make of you.")) + return TRUE + + to_chat(user, SPAN_NOTICE("\The [src] crumbles in your hands.")) + qdel(src) + return TRUE diff --git a/code/modules/spells/contracts.dm b/mods/gamemodes/wizard/contracts.dm similarity index 70% rename from code/modules/spells/contracts.dm rename to mods/gamemodes/wizard/contracts.dm index 1b6ebf527f7e..7161118f7711 100644 --- a/code/modules/spells/contracts.dm +++ b/mods/gamemodes/wizard/contracts.dm @@ -1,13 +1,18 @@ -/obj/item/contract +/obj/item/paper/contract name = "contract" desc = "written in the blood of some unfortunate fellow." icon = 'icons/mob/screen/spells.dmi' icon_state = "master_open" - material = /decl/material/solid/organic/paper var/contract_master = null - var/list/contract_spells = list(/spell/contract/reward,/spell/contract/punish,/spell/contract/return_master) - -/obj/item/contract/attack_self(mob/user) + var/list/contract_spells = list( + /* + /spell/contract/reward, + /spell/contract/punish, + /spell/contract/return_master + */ + ) + +/obj/item/paper/contract/attack_self(mob/user) if(contract_master == null) to_chat(user, "You bind the contract to your soul, making you the recipient of whatever poor fool's soul that decides to contract with you.") contract_master = user @@ -25,23 +30,23 @@ user.visible_message("\The [src] visibly rejects \the [user], erasing their signature from the line.") return user.visible_message("\The [src] disappears with a flash of light.") - if(contract_spells.len && isliving(contract_master)) //if it aint text its probably a mob or another user + if(length(contract_spells) && isliving(contract_master)) //if it aint text its probably a mob or another user var/mob/living/M = contract_master for(var/spell_type in contract_spells) - M.add_spell(new spell_type(user), "const_spell_ready") + M.add_ability(spell_type) log_and_message_admins("signed their soul over to \the [contract_master] using \the [src].", user) qdel(src) -/obj/item/contract/proc/contract_effect(mob/user) +/obj/item/paper/contract/proc/contract_effect(mob/user) to_chat(user, "You've signed your soul over to \the [contract_master] and with that your unbreakable vow of servitude begins.") return 1 -/obj/item/contract/apprentice +/obj/item/paper/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." color = "#993300" -/obj/item/contract/apprentice/contract_effect(mob/user) +/obj/item/paper/contract/apprentice/contract_effect(mob/user) if(user.mind.assigned_special_role == "Wizard's Apprentice") to_chat(user, "You are already a wizarding apprentice!") return 0 @@ -54,15 +59,15 @@ return 1 return 0 -/obj/item/contract/wizard //contracts that involve making a deal with the Wizard Acadamy (or NON PLAYERS) +/obj/item/paper/contract/wizard //contracts that involve making a deal with the Wizard Acadamy (or NON PLAYERS) contract_master = "\improper Wizard Academy" -/obj/item/contract/wizard/xray +/obj/item/paper/contract/wizard/xray name = "xray vision contract" desc = "This contract is almost see-through..." color = "#339900" -/obj/item/contract/wizard/xray/contract_effect(mob/user) +/obj/item/paper/contract/wizard/xray/contract_effect(mob/user) ..() if (user.add_genetic_condition(GENE_COND_XRAY)) user.set_sight(user.sight|SEE_MOBS|SEE_OBJS|SEE_TURFS) @@ -72,21 +77,21 @@ return 1 return 0 -/obj/item/contract/wizard/telepathy +/obj/item/paper/contract/wizard/telepathy name = "telepathy contract" desc = "The edges of the contract grow blurry when you look away from them. To be fair, actually reading it gives you a headache." color = "#fcc605" -/obj/item/contract/wizard/telepathy/contract_effect(mob/user) +/obj/item/paper/contract/wizard/telepathy/contract_effect(mob/user) ..() return user.add_genetic_condition(GENE_COND_REMOTE_TALK) -/obj/item/contract/boon +/obj/item/paper/contract/boon name = "boon contract" desc = "this contract grants you a boon for signing it." var/path -/obj/item/contract/boon/Initialize(mapload, var/new_path) +/obj/item/paper/contract/boon/Initialize(mapload, var/new_path) . = ..(mapload) if(new_path) path = new_path @@ -94,49 +99,48 @@ if(ispath(path,/obj)) var/obj/O = path item_name = initial(O.name) - else if(ispath(path,/spell)) - var/spell/S = path - item_name = initial(S.name) + else if(ispath(path,/decl/ability)) + var/decl/ability/S = GET_DECL(path) + item_name = S.name name = "[item_name] contract" -/obj/item/contract/boon/contract_effect(mob/user) +/obj/item/paper/contract/boon/contract_effect(mob/user) ..() if(user.mind.assigned_special_role == "Spellbound Servant") to_chat(user, "As a servant you find yourself unable to use this contract.") return 0 - if(ispath(path,/spell)) - user.add_spell(new path) - return 1 - else if(ispath(path,/obj)) + if(ispath(path,/obj)) new path(get_turf(user.loc)) playsound(get_turf(usr),'sound/magic/charge.ogg',50,1) return 1 + if(ispath(path, /decl/ability)) + user.add_ability(path) + return 1 -/obj/item/contract/boon/wizard +/obj/item/paper/contract/boon/wizard contract_master = "\improper Wizard Academy" -/obj/item/contract/boon/wizard/fireball - path = /spell/targeted/projectile/dumbfire/fireball +/obj/item/paper/contract/boon/wizard/fireball + //path = /spell/targeted/projectile/dumbfire/fireball desc = "This contract feels warm to the touch." -/obj/item/contract/boon/wizard/smoke - path = /spell/aoe_turf/smoke +/obj/item/paper/contract/boon/wizard/smoke + //path = /spell/aoe_turf/smoke desc = "This contract smells as dank as they come." -/obj/item/contract/boon/wizard/forcewall - path = /spell/aoe_turf/conjure/forcewall +/obj/item/paper/contract/boon/wizard/forcewall + //path = /spell/aoe_turf/conjure/forcewall contract_master = "\improper Mime Federation" desc = "This contract has a dedication to mimes everywhere at the top." -/obj/item/contract/boon/wizard/knock - path = /spell/aoe_turf/knock +/obj/item/paper/contract/boon/wizard/knock + //path = /spell/aoe_turf/knock desc = "This contract is hard to hold still." -/obj/item/contract/boon/wizard/horsemask - path = /spell/targeted/equip_item/horsemask +/obj/item/paper/contract/boon/wizard/horsemask + //path = /spell/targeted/equip_item/horsemask desc = "This contract is more horse than your mind has room for." -/obj/item/contract/boon/wizard/charge - path = /spell/aoe_turf/charge +/obj/item/paper/contract/boon/wizard/charge + //path = /spell/aoe_turf/charge desc = "This contract is made of 100% post-consumer wizard." - diff --git a/code/modules/mob/living/simple_animal/familiars/familiars.dm b/mods/gamemodes/wizard/familiar.dm similarity index 93% rename from code/modules/mob/living/simple_animal/familiars/familiars.dm rename to mods/gamemodes/wizard/familiar.dm index 309a8521d7e2..4bc8e84ec294 100644 --- a/code/modules/mob/living/simple_animal/familiars/familiars.dm +++ b/mods/gamemodes/wizard/familiar.dm @@ -17,7 +17,7 @@ . = ..() add_language(/decl/language/human/common) for(var/spell in wizardy_spells) - src.add_spell(new spell, "const_spell_ready") + src.add_ability(spell) /mob/living/simple_animal/familiar/carcinus name = "carcinus" @@ -49,7 +49,7 @@ max_health = 100 natural_weapon = /obj/item/natural_weapon/bite min_gas = null - wizardy_spells = list(/spell/aoe_turf/conjure/forcewall) + //wizardy_spells = list(/spell/aoe_turf/conjure/forcewall) ai = /datum/mob_controller/familiar_pike /datum/mob_controller/familiar_pike @@ -67,7 +67,7 @@ response_help_3p = "$USER$ thinks better of touching $TARGET$." max_health = 150 natural_weapon = /obj/item/natural_weapon/horror - wizardy_spells = list(/spell/targeted/torment) + //wizardy_spells = list(/spell/targeted/torment) /obj/item/natural_weapon/horror name = "foul touch" @@ -93,10 +93,12 @@ speak_emote = list("entones") mob_size = MOB_SIZE_SMALL max_health = 25 + /* wizardy_spells = list( /spell/targeted/heal_target, /spell/targeted/heal_target/area ) + */ /mob/living/simple_animal/familiar/pet/mouse name = "elderly mouse" @@ -109,7 +111,7 @@ response_harm = "stamps on" max_health = 15 natural_weapon = /obj/item/natural_weapon/bite/mouse - wizardy_spells = list(/spell/aoe_turf/smoke) + //wizardy_spells = list(/spell/aoe_turf/smoke) ai = /datum/mob_controller/familiar_mouse /datum/mob_controller/familiar_mouse @@ -130,4 +132,4 @@ mob_size = MOB_SIZE_SMALL max_health = 25 natural_weapon = /obj/item/natural_weapon/claws/weak - wizardy_spells = list(/spell/targeted/subjugation) + //wizardy_spells = list(/spell/targeted/subjugation) diff --git a/mods/gamemodes/wizard/icons/spell_icons.dmi b/mods/gamemodes/wizard/icons/spell_icons.dmi new file mode 100644 index 0000000000000000000000000000000000000000..c04ac8fbbea88c5494e2f41ccff834b98897b2b3 GIT binary patch literal 296 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnH3?%tPCZz)@&H$ef*8>L*7@sjV{%?Fb_!2)* zkg+7lFPOpM*^M+HC#5PRqQoV&IJqdZpd>RtkAb0LPHTm(5;xg1>5+|JH26^*=pYNmGhI+o5eb7s!6Dpj4ZQRGB~rLY=P q(wZ1f(S;XU4cP9S{@~ES$PjJoz5Vvow|{{aF?hQAxvXI don't feel strong enough without my robe.") - return 0 - if(!is_wiz_garb(get_equipped_item(slot_shoes_str)) && (!istype(species.species_hud) || (slot_shoes_str in species.species_hud.equip_slots))) - to_chat(src, "I don't feel strong enough without my sandals.") - return 0 - if(!is_wiz_garb(get_equipped_item(slot_head_str)) && (!istype(species.species_hud) || (slot_head_str in species.species_hud.equip_slots))) - to_chat(src, "I don't feel strong enough without my hat.") - return 0 - return 1 +/mob/proc/wearing_wizard_garb() + return "Silly creature, you can't wear clothes. Only clothed wizards can cast this spell." + +/mob/living/wearing_wizard_garb() + + var/decl/species/species = get_species() + if(!species || !istype(species.species_hud)) + return ..() + + var/list/static/slot_check = list( + slot_wear_suit_str = "robe", + slot_shoes_str = "sandals", + slot_head_str = "hat" + ) + for(var/slot in slot_check) + var/obj/item/thing = get_equipped_item(slot) + if(!istype(thing) || !thing.is_wizard_garb()) + return "You don't feel strong enough without your [slot_check[slot]]..." diff --git a/code/game/objects/items/weapons/scrolls.dm b/mods/gamemodes/wizard/scrolls.dm similarity index 81% rename from code/game/objects/items/weapons/scrolls.dm rename to mods/gamemodes/wizard/scrolls.dm index 506dd56d7a10..c012993f99f3 100644 --- a/code/game/objects/items/weapons/scrolls.dm +++ b/mods/gamemodes/wizard/scrolls.dm @@ -1,17 +1,10 @@ -/obj/item/teleportation_scroll +/obj/item/paper/scroll/teleportation name = "scroll of teleportation" desc = "A scroll for moving around." - icon = 'icons/obj/wizard.dmi' - icon_state = "scroll" - var/uses = 4.0 - w_class = ITEM_SIZE_TINY - item_state = "paper" - throw_speed = 4 - throw_range = 20 origin_tech = @'{"wormholes":4}' - material = /decl/material/solid/organic/paper + var/uses = 4.0 -/obj/item/teleportation_scroll/attack_self(mob/user) +/obj/item/paper/scroll/teleportation/attack_self(mob/user) var/decl/special_role/wizard/wizards = GET_DECL(/decl/special_role/wizard) if((user.mind && !wizards.is_antagonist(user.mind))) to_chat(usr, "You stare at the scroll but cannot make sense of the markings!") @@ -28,7 +21,7 @@ onclose(user, "scroll") return -/obj/item/teleportation_scroll/Topic(href, href_list) +/obj/item/paper/scroll/teleportation/Topic(href, href_list) if(..()) return 1 if (!ishuman(usr)) @@ -42,7 +35,7 @@ attack_self(H) return -/obj/item/teleportation_scroll/proc/teleportscroll(var/mob/user) +/obj/item/paper/scroll/teleportation/proc/teleportscroll(var/mob/user) var/area/thearea = input(user, "Area to jump to", "BOOYEA") as null|anything in wizteleportlocs thearea = thearea ? wizteleportlocs[thearea] : thearea diff --git a/code/game/gamemodes/wizard/servant_items/caretaker.dm b/mods/gamemodes/wizard/servant_items/caretaker.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/caretaker.dm rename to mods/gamemodes/wizard/servant_items/caretaker.dm diff --git a/code/game/gamemodes/wizard/servant_items/champion.dm b/mods/gamemodes/wizard/servant_items/champion.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/champion.dm rename to mods/gamemodes/wizard/servant_items/champion.dm diff --git a/code/game/gamemodes/wizard/servant_items/familiar.dm b/mods/gamemodes/wizard/servant_items/familiar.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/familiar.dm rename to mods/gamemodes/wizard/servant_items/familiar.dm diff --git a/code/game/gamemodes/wizard/servant_items/fiend.dm b/mods/gamemodes/wizard/servant_items/fiend.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/fiend.dm rename to mods/gamemodes/wizard/servant_items/fiend.dm diff --git a/code/game/gamemodes/wizard/servant_items/infiltrator.dm b/mods/gamemodes/wizard/servant_items/infiltrator.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/infiltrator.dm rename to mods/gamemodes/wizard/servant_items/infiltrator.dm diff --git a/code/game/gamemodes/wizard/servant_items/overseer.dm b/mods/gamemodes/wizard/servant_items/overseer.dm similarity index 100% rename from code/game/gamemodes/wizard/servant_items/overseer.dm rename to mods/gamemodes/wizard/servant_items/overseer.dm diff --git a/mods/gamemodes/wizard/spellbook/spellbook.dm b/mods/gamemodes/wizard/spellbook/spellbook.dm new file mode 100644 index 000000000000..bb5f197c0ee5 --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook.dm @@ -0,0 +1,309 @@ +#define NOREVERT 1 +#define LOCKED 2 +#define CAN_MAKE_CONTRACTS 4 +#define INVESTABLE 8 +#define NO_LOCKING 16 + +//spells/spellbooks have a variable for this but as artefacts are literal items they do not. +//so we do this instead. +var/global/list/artefact_feedback = list( + /obj/structure/closet/wizard/armor = "HS", + /obj/item/gun/energy/staff/focus = "MF", + /obj/item/gun/energy/staff/fire = "FS", +// /obj/item/summoning_stone = "ST", + /obj/item/magic_rock = "RA", + /obj/item/paper/contract/apprentice = "CP", + /obj/structure/closet/wizard/scrying = "SO", + /obj/item/paper/scroll/teleportation = "TS", + /obj/item/gun/energy/staff = "ST", + /obj/item/gun/energy/staff/animate = "SA", + /obj/item/dice/d20/cursed = "DW" +) + +/obj/item/book/spell + name = "master spell book" + desc = "The legendary book of spells of the wizard." + material = /decl/material/solid/organic/paper + matter = list(/decl/material/solid/organic/leather = MATTER_AMOUNT_REINFORCEMENT) + unique = TRUE + /// What message is the book currently displaying? + var/shown_message + /// How many uses remain? + var/uses = 1 + /// for spawning specific spellbooks. + var/decl/spellbook/spellbook = /decl/spellbook + /// what time we target for a return on our spell investment. + var/investing_time = 0 + /// whether we have already got our sacrifice bonus for the current investment. + var/has_sacrificed = 0 + +/obj/item/book/spell/Initialize() + . = ..() + set_spellbook(spellbook) + +/obj/item/book/spell/proc/set_spellbook(new_type) + spellbook = istype(new_type, /decl/spellbook) ? new_type : GET_DECL(new_type) + uses = spellbook.max_uses + name = spellbook.name + desc = spellbook.desc + +/obj/item/book/spell/attack_self(mob/user) + + if(!user.mind) + return + + if (user.mind.assigned_special_role != /decl/special_role/wizard) + if (user.mind.assigned_special_role != "Wizard's Apprentice") + to_chat(user, SPAN_WARNING("You can't make heads or tails of this book.")) + return + if (spellbook.book_flags & LOCKED) + to_chat(user, SPAN_WARNING("Drat! This spellbook's apprentice-proof lock is on!")) + return + else if (spellbook.book_flags & LOCKED) + to_chat(user, SPAN_NOTICE("You notice the apprentice-proof lock is on. Luckily you are beyond such things.")) + interact(user) + +/obj/item/book/spell/proc/make_sacrifice(obj/item/I, mob/user, var/reagent) + if(has_sacrificed) + to_chat(user, SPAN_WARNING("\The [src] is already sated! Wait for a return on your investment before you sacrifice more to it.")) + return + if(reagent) + if(I.reagents?.has_reagent(reagent, 5)) + I.remove_from_reagents(reagent, 5) + else if(LAZYACCESS(I.matter, reagent) >= (SHEET_MATERIAL_AMOUNT * 5)) + qdel(I) + else + if(istype(I,/obj/item/stack)) + var/obj/item/stack/S = I + if(S.amount < S.max_amount) + to_chat(usr, SPAN_WARNING("You must sacrifice [S.max_amount] stacks of [S]!")) + return + qdel(I) + to_chat(user, SPAN_NOTICE("Your sacrifice was accepted!")) + has_sacrificed = 1 + investing_time = max(investing_time - (10 MINUTES),1) //subtract 10 minutes. Make sure it doesn't act funky at the beginning of the game. + + +/obj/item/book/spell/attackby(obj/item/I, mob/user) + if(investing_time) + for(var/type in spellbook.sacrifice_objects) + if(istype(I,type)) + make_sacrifice(I, user) + return TRUE + + for(var/mat in spellbook.sacrifice_materials) + if(LAZYACCESS(I.matter, mat) > (SHEET_MATERIAL_AMOUNT * 10)) + make_sacrifice(I, user, mat) + return TRUE + + if(I.reagents) + for(var/id in spellbook.sacrifice_reagents) + if(I.reagents.has_reagent(id, 5)) + make_sacrifice(I, user, id) + return TRUE + ..() + +/obj/item/book/spell/interact(mob/user) + var/dat = null + if(shown_message) + dat = "[shown_message]
Return" + else + dat = "

[spellbook.title]

[spellbook.title_desc]
You have [uses] spell slot\s left.

" + dat += "
Requires Wizard Garb
Selectable Target
Spell Charge Type: Recharge, Sacrifice, Charges

" + dat += "
To use a contract, first bind it to your soul, then give it to someone to sign. This will bind their soul to you.

" + + for(var/spell in spellbook.spells) + var/spell_cost = spellbook.spells[spell] + + var/spell_name + var/spell_desc + var/spell_info = list() + + if(ispath(spell, /decl/spellbook)) + var/decl/spellbook/spellbook_data = GET_DECL(spell) + spell_name = spellbook_data.name + spell_desc = spellbook_data.book_desc + spell_info = "[spellbook_data.max_uses] spell slots" + else if(ispath(spell, /obj)) + var/obj/O = spell + spell_name = "Artefact: [capitalize(initial(O.name))]" //because 99.99% of objects dont have capitals in them and it makes it look weird. + spell_desc = initial(O.desc) + else if(ispath(spell, /decl/ability/spell)) + var/decl/ability/spell/spell_decl = GET_DECL(spell) + spell_name = spell_decl.name + spell_desc = spell_decl.desc + if(spell_decl.requires_wizard_garb) + spell_info = "W" + /* + var/type = "" + switch(initial(S.charge_type)) + if(Sp_RECHARGE) + spell_type = "R" + if(Sp_HOLDVAR) + spell_type = "S" + if(Sp_CHARGES) + spell_type = "C" + spell_info += "[spell_type] + */ + + dat += "[spell_name]" + if(length(spell_info)) + dat += " ([spell_info])" + dat += " ([spell_cost] spell slot[spell_cost > 1 ? "s" : "" ])" + if(spellbook.book_flags & CAN_MAKE_CONTRACTS) + dat += " Make Contract" + dat += "
[spell_desc]

" + dat += "
" + dat += "
Re-memorise your spellbook.
" + if(spellbook.book_flags & INVESTABLE) + if(investing_time) + dat += "
Currently investing in a slot...
" + else + dat += "
Invest a Spell Slot
Investing a spellpoint will return two spellpoints back in 15 minutes.
Some say a sacrifice could even shorten the time...
" + if(!(spellbook.book_flags & NOREVERT)) + dat += "
Choose different spellbook.
" + if(!(spellbook.book_flags & NO_LOCKING)) + dat += "
[spellbook.book_flags & LOCKED ? "Unlock" : "Lock"] the spellbook.
" + show_browser(user, dat, "window=spellbook") + +/obj/item/book/spell/CanUseTopic(var/mob/living/human/H) + if(!istype(H)) + return STATUS_CLOSE + + if(H.mind && (spellbook.book_flags & LOCKED) && H.mind.assigned_special_role == "Wizard's Apprentice") //make sure no scrubs get behind the lock + return STATUS_CLOSE + + return ..() + +/obj/item/book/spell/OnTopic(var/mob/living/human/user, href_list) + if(href_list["lock"] && !(spellbook.book_flags & NO_LOCKING)) + if(spellbook.book_flags & LOCKED) + spellbook.book_flags &= ~LOCKED + else + spellbook.book_flags |= LOCKED + . = TOPIC_REFRESH + + else if(href_list["shown_message"]) + shown_message = null + . = TOPIC_REFRESH + + else if(href_list["book"]) + if(initial(spellbook.max_uses) != spellbook.max_uses || uses != spellbook.max_uses) + shown_message = "You've already purchased things using this spellbook!" + else + src.set_spellbook(/decl/spellbook) + shown_message = "You have reverted back to the Book of Tomes." + . = TOPIC_REFRESH + + else if(href_list["invest"]) + shown_message = invest() + . = TOPIC_REFRESH + + else if(href_list["path"]) + var/path = locate(href_list["path"]) in spellbook.spells + if(!path) + return TOPIC_HANDLED + if(uses < spellbook.spells[path]) + to_chat(user, SPAN_WARNING("You do not have enough spell slots to purchase this.")) + return TOPIC_HANDLED + send_feedback(path) //feedback stuff + if(ispath(path,/decl/spellbook)) + src.set_spellbook(path) + shown_message = "You have chosen a new spellbook." + else + if(href_list["contract"]) + if(!(spellbook.book_flags & CAN_MAKE_CONTRACTS)) + return //no + uses -= spellbook.spells[path] + spellbook.max_uses -= spellbook.spells[path] //no basksies + shown_message = "You have purchased \the [new /obj/item/paper/contract/boon(get_turf(user),path)]." + else + if(ispath(path, /decl/ability)) + shown_message = user.add_ability(path) + if(shown_message) + uses -= spellbook.spells[path] + else + var/obj/O = new path(get_turf(user)) + shown_message = "You have purchased \a [O]." + uses -= spellbook.spells[path] + spellbook.max_uses -= spellbook.spells[path] + //finally give it a bit of an oomf + playsound(get_turf(user),'sound/effects/phasein.ogg',50,1) + . = TOPIC_REFRESH + + else if(href_list["reset"] && !(spellbook.book_flags & NOREVERT)) + var/area/map_template/wizard_station/A = get_area(user) + if(istype(A)) + uses = spellbook.max_uses + investing_time = 0 + has_sacrificed = 0 + user.remove_ability_handler(/datum/ability_handler/spells) + shown_message = "All spells and investments have been removed. You may now memorise a new set of spells." + SSstatistics.add_field_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + else + to_chat(user, SPAN_WARNING("You must be in the wizard academy to re-memorise your spells.")) + . = TOPIC_REFRESH + + src.interact(user) + +/obj/item/book/spell/proc/invest() + if(uses < 1) + return "You don't have enough slots to invest!" + if(investing_time) + return "You can only invest one spell slot at a time." + uses-- + START_PROCESSING(SSobj, src) + investing_time = world.time + (15 MINUTES) + return "You invest a spellslot and will recieve two in return in 15 minutes." + +/obj/item/book/spell/Process() + if(investing_time && investing_time <= world.time) + src.visible_message("\The [src] emits a soft chime.") + uses += 2 + if(uses > spellbook.max_uses) + spellbook.max_uses = uses + investing_time = 0 + has_sacrificed = 0 + STOP_PROCESSING(SSobj, src) + return 1 + +/obj/item/book/spell/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/book/spell/proc/send_feedback(var/path) + if(ispath(path,/decl/spellbook)) + var/decl/spellbook/S = GET_DECL(path) + SSstatistics.add_field_details("wizard_spell_learned","[S.feedback]") + else if(ispath(path,/decl/ability/spell)) + var/decl/ability/spell/S = GET_DECL(path) + SSstatistics.add_field_details("wizard_spell_learned","[S.feedback]") + else if(ispath(path,/obj)) + SSstatistics.add_field_details("wizard_spell_learned","[artefact_feedback[path]]") + +/obj/item/book/spell/proc/memorize_spell(var/mob/user, var/spell_path) + + var/decl/ability/spell/spell = GET_DECL(spell_path) + if(!istype(spell)) + return + + if(!user.has_ability(spell_path)) + user.add_ability(spell) + return "You learn the spell [spell]" + + var/list/metadata = user.get_ability_metadata(spell_path) + var/improve_speed = spell.can_improve(Sp_SPEED, metadata) + var/improve_power = spell.can_improve(Sp_POWER, metadata) + if(improve_speed && improve_power) + switch(alert(user, "Do you want to upgrade this spell's speed or power?", "Spell upgrade", "Speed", "Power", "Cancel")) + if("Speed") + return spell.quicken_spell(user, metadata) + if("Power") + return spell.empower_spell(user, metadata) + else + return + if(improve_power) + return spell.empower_spell(user, metadata) + if(improve_speed) + return spell.quicken_spell(user, metadata) + diff --git a/mods/gamemodes/wizard/spellbook/spellbook_subtypes.dm b/mods/gamemodes/wizard/spellbook/spellbook_subtypes.dm new file mode 100644 index 000000000000..ac104aa5de9a --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_subtypes.dm @@ -0,0 +1,17 @@ +/obj/item/book/spell/cleric + spellbook = /decl/spellbook/cleric + +/obj/item/book/spell/druid + spellbook = /decl/spellbook/druid + +/obj/item/book/spell/spatial + spellbook = /decl/spellbook/spatial + +/obj/item/book/spell/standard + spellbook = /decl/spellbook/standard + +/obj/item/book/spell/student + spellbook = /decl/spellbook/student + +/obj/item/book/spell/apprentice + spellbook = /decl/spellbook/student/apprentice diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/_spellbook_type.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/_spellbook_type.dm new file mode 100644 index 000000000000..f83cb6f5608d --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/_spellbook_type.dm @@ -0,0 +1,19 @@ +/decl/spellbook + var/name = "\improper Book of Tomes" + var/desc = "The legendary book of spells of the wizard." + var/book_desc = "Holds information on the various tomes available to a wizard" + var/feedback = "" //doesn't need one. + var/book_flags = NOREVERT + var/max_uses = 1 + var/title = "Book of Tomes" + var/title_desc = "This tome marks down all the available tomes for use. Choose wisely, there are no refunds." + var/list/spells = list( + /decl/spellbook/standard = 1, + /decl/spellbook/cleric = 1, + /decl/spellbook/battlemage = 1, + /decl/spellbook/spatial = 1, + /decl/spellbook/druid = 1 + ) + var/list/sacrifice_reagents + var/list/sacrifice_objects + var/list/sacrifice_materials diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_battlemage.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_battlemage.dm new file mode 100644 index 000000000000..8236f94b0474 --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_battlemage.dm @@ -0,0 +1,46 @@ +//Battlemage is all about mixing physical with the mystical in head to head combat. +//Things like utility and mobility come second. +/decl/spellbook/battlemage + name = "\improper Battlemage's Bible" + feedback = "BM" + desc = "Smells like blood." + book_desc = "Mix physical with the mystical in head to head combat." + title = "The Art of Magical Combat" + title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." + book_flags = CAN_MAKE_CONTRACTS|INVESTABLE + max_uses = 6 + + spells = list( + /* + /spell/targeted/projectile/dumbfire/passage = 1, + /spell/targeted/equip_item/dyrnwyn = 1, + /spell/targeted/equip_item/shield = 1, + /spell/targeted/projectile/dumbfire/fireball = 1, + /spell/targeted/torment = 1, + /spell/targeted/heal_target = 2, + /spell/aoe_turf/conjure/mirage = 1, + /spell/targeted/shapeshift/corrupt_form = 1, + /spell/radiant_aura = 1, + /spell/noclothes = 1, + */ + /obj/structure/closet/wizard/armor = 1, + /obj/item/gun/energy/staff/focus = 1, + /obj/item/gun/energy/staff/fire = 1, + /obj/item/dice/d20/cursed = 1, +// /obj/item/summoning_stone = 2, + /obj/item/magic_rock = 1, + /obj/item/paper/contract/wizard/xray = 1, + /obj/item/paper/contract/wizard/telepathy = 1, + /obj/item/paper/contract/apprentice = 1 + ) + + sacrifice_objects = list( + /obj/item/sword, + /obj/item/twohanded/fireaxe, + /obj/item/baton, + /obj/item/knife/ritual, + /obj/item/knife/kitchen/cleaver, + /obj/item/knife/folding/combat/balisong, + /obj/item/knife/folding/tacticool, + /obj/item/star + ) diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_cleric.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_cleric.dm new file mode 100644 index 000000000000..0ce0debe67df --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_cleric.dm @@ -0,0 +1,48 @@ +//Cleric is all about healing. Mobility and offense comes at a higher price but not impossible. +/decl/spellbook/cleric + name = "\improper Cleric's Tome" + feedback = "CR" + desc = "For those who do not harm, or at least feel sorry about it." + book_desc = "All about healing. Mobility and offense comes at a higher price but not impossible." + title = "Cleric's Tome of Healing" + title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." + book_flags = CAN_MAKE_CONTRACTS|INVESTABLE + max_uses = 7 + + spells = list( +/* + /spell/targeted/heal_target/major = 1, + /spell/targeted/heal_target/area = 1, + /spell/targeted/heal_target/sacrifice = 1, + /spell/targeted/genetic/blind = 1, + /spell/targeted/shapeshift/baleful_polymorph = 1, + /spell/targeted/projectile/dumbfire/stuncuff = 1, + /spell/targeted/ethereal_jaunt = 2, + /spell/aoe_turf/knock = 1, + /spell/radiant_aura = 1, + /spell/targeted/equip_item/holy_relic = 1, + /spell/aoe_turf/conjure/grove/sanctuary = 1, + /spell/targeted/projectile/dumbfire/fireball = 2, + /spell/area_teleport = 2, + /spell/portal_teleport = 2, + /spell/aoe_turf/conjure/forcewall = 1, + /spell/noclothes = 1, +*/ + /obj/item/magic_rock = 1, + /obj/structure/closet/wizard/scrying = 2, +// /obj/item/summoning_stone = 2, + /obj/item/paper/contract/wizard/telepathy = 1, + /obj/item/paper/contract/apprentice = 1 + ) + sacrifice_reagents = list( + /decl/material/liquid/adminordrazine + ) + sacrifice_objects = list( + /obj/item/stack/nanopaste, + /obj/item/scanner/health, + /obj/item/scanner/breath, + /obj/item/stack/medical/bandage/advanced, + /obj/item/stack/medical/ointment/advanced, + /obj/item/bodybag/rescue, + /obj/item/defibrillator + ) diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_druid.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_druid.dm new file mode 100644 index 000000000000..a1e155777c36 --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_druid.dm @@ -0,0 +1,41 @@ +//all about the summons, nature, and a bit o' healin. +/decl/spellbook/druid + name = "\improper Druid's Leaflet" + feedback = "DL" + desc = "It smells like an air freshener." + book_desc = "Summons, nature, and a bit o' healin." + title = "Druidic Guide on how to be smug about nature" + title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." + book_flags = CAN_MAKE_CONTRACTS|INVESTABLE + max_uses = 6 + + spells = list( +/* + /spell/targeted/heal_target = 1, + /spell/targeted/heal_target/sacrifice = 1, + /spell/aoe_turf/conjure/mirage = 1, + /spell/aoe_turf/conjure/summon/bats = 1, + /spell/aoe_turf/conjure/summon/bear = 1, + /spell/targeted/equip_item/party_hardy = 1, + /spell/targeted/equip_item/seed = 1, + /spell/targeted/shapeshift/avian = 1, + /spell/aoe_turf/disable_tech = 1, + /spell/hand/charges/entangle = 1, + /spell/aoe_turf/conjure/grove/sanctuary = 1, + /spell/aoe_turf/knock = 1, + /spell/area_teleport = 2, + /spell/portal_teleport = 2, + /spell/noclothes = 1, +*/ + /obj/item/magic_rock = 1, +// /obj/item/summoning_stone = 2, + /obj/item/paper/contract/wizard/telepathy = 1, + /obj/item/paper/contract/apprentice = 1 + ) + sacrifice_objects = list( + /obj/item/seeds, + /obj/item/wirecutters/clippers, + /obj/item/scanner/plant, + /obj/item/tool/axe/hatchet, + /obj/item/tool/hoe/mini + ) diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_spatial.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_spatial.dm new file mode 100644 index 000000000000..585dc4465014 --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_spatial.dm @@ -0,0 +1,45 @@ +//all about moving around and mobility and being an annoying shit. +/decl/spellbook/spatial + name = "\improper Spatial Manual" + feedback = "SP" + desc = "You feel like this might disappear from out of under you." + book_desc = "Movement and teleportation. Run from your problems!" + title = "Manual of Spatial Transportation" + title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." + book_flags = CAN_MAKE_CONTRACTS|INVESTABLE + max_uses = 11 + + spells = list( +/* + /spell/targeted/ethereal_jaunt = 1, + /spell/aoe_turf/blink = 1, + /spell/area_teleport = 1, + /spell/portal_teleport = 1, + /spell/targeted/projectile/dumbfire/passage = 1, + /spell/mark_recall = 1, + /spell/targeted/swap = 1, + /spell/targeted/shapeshift/avian = 1, + /spell/targeted/projectile/magic_missile = 1, + /spell/targeted/heal_target = 1, + /spell/aoe_turf/conjure/forcewall = 1, + /spell/aoe_turf/smoke = 1, + /spell/aoe_turf/conjure/summon/bats = 3, + /spell/noclothes = 1, +*/ + /obj/item/dice/d20/cursed = 1, + /obj/structure/closet/wizard/scrying = 2, + /obj/item/paper/scroll/teleportation = 1, + /obj/item/magic_rock = 1, +// /obj/item/summoning_stone = 3, + /obj/item/paper/contract/wizard/telepathy = 1, + /obj/item/paper/contract/apprentice = 1 + ) + sacrifice_reagents = list( + /decl/material/liquid/amphetamines + ) + sacrifice_objects = list( + /obj/item/stack/telecrystal + ) + sacrifice_materials = list( + /decl/material/solid/gemstone/diamond + ) \ No newline at end of file diff --git a/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_standard.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_standard.dm new file mode 100644 index 000000000000..20ed460059f7 --- /dev/null +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_standard.dm @@ -0,0 +1,52 @@ +//the spellbook we know and love. Well, the one we know, at least. +/decl/spellbook/standard + name = "\improper Standard Spellbook" + feedback = "SB" + title = "Book of Spells and Artefacts" + title_desc = "Buy spells using your available spell slots. Artefacts may also be bought however their cost is permanent." + book_desc = "A general wizard's spellbook. All its spells are easy to use but hard to master." + book_flags = CAN_MAKE_CONTRACTS|INVESTABLE + max_uses = 6 + + spells = list( +/* + /spell/targeted/projectile/magic_missile = 1, + /spell/targeted/projectile/dumbfire/fireball = 1, + /spell/aoe_turf/disable_tech = 1, + /spell/aoe_turf/smoke = 1, + /spell/targeted/genetic/blind = 1, + /spell/targeted/subjugation = 1, + /spell/aoe_turf/conjure/forcewall = 1, + /spell/aoe_turf/blink = 1, + /spell/area_teleport = 1, + /spell/targeted/ethereal_jaunt = 1, + /spell/targeted/heal_target = 1, + /spell/aoe_turf/knock = 1, + /spell/noclothes = 2, +*/ + /obj/item/gun/energy/staff/focus = 1, + /obj/item/gun/energy/staff/fire = 1, + /obj/item/gun/energy/staff/animate = 1, + /obj/structure/closet/wizard/scrying = 1, +// /obj/item/summoning_stone = 2, + /obj/item/magic_rock = 1, + /obj/item/paper/contract/wizard/telepathy = 1, + /obj/item/paper/contract/apprentice = 1 + ) + + sacrifice_objects = list( + /obj/item/toolbox, + /obj/item/cane, + /obj/item/flamethrower, + /obj/item/plastique, + /obj/item/dice, + /obj/item/soap, + /obj/item/flame/candle, + /obj/item/flame/candle/scented/incense, + /obj/item/caution, + /obj/item/towel, + /obj/item/tank/jetpack, + /obj/item/plunger, + /obj/item/megaphone, + /obj/item/deck/cards + ) \ No newline at end of file diff --git a/code/modules/spells/spellbook/student.dm b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_student.dm similarity index 72% rename from code/modules/spells/spellbook/student.dm rename to mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_student.dm index 1a4b2c4c2ebf..07499329e19a 100644 --- a/code/modules/spells/spellbook/student.dm +++ b/mods/gamemodes/wizard/spellbook/spellbook_types/spellbook_student.dm @@ -1,28 +1,22 @@ //wizard's training wheels. Basically. Same shit as in the general one. - -/obj/item/spellbook/student - spellbook_type = /datum/spellbook/student - -/datum/spellbook/student - name = "\improper Student's Spellbook" - feedback = "ST" - desc = "This spell book has a sticker on it that says, 'certified for children 5 and older'." - book_desc = "This spellbook is dedicated to teaching neophytes in the ways of magic." - title = "Book of Spells and Education" +/decl/spellbook/student + name = "\improper Student's Spellbook" + feedback = "ST" + desc = "This spell book has a sticker on it that says, 'certified for children 5 and older'." + book_desc = "This spellbook is dedicated to teaching neophytes in the ways of magic." + title = "Book of Spells and Education" title_desc = "Hello. Congratulations on becoming a wizard. You may be asking yourself: What? A wizard? Already? Of course! Anybody can become a wizard! Learning to be a good one is the hard part.
Without further adue, let us begin by learning the three concepts of wizardry, 'Spell slots', 'Spells', and 'Artifacts'.
Firstly lets try to understand the 'spell slot'. A spell slot is the measurable amount of spells and artifacts one tome can give. Most spells will only take up a singular spell slot, however more powerful spells/artifacts can take up more.
Spells are spells. They can have requirements, such as wizard garb, and most can be upgraded by purchasing additional spell slots for them. Most upgrades fall into two categories, 'Speed' and 'Power'. Speed upgrades decrease the time you have to spend recharging your spell. Power increases the potency of your spells. Spells are also special in that they can be refunded while inside the Wizard Acadamy, so if you want to test a spell out before moving out into the field, feel free to do that in the comfort of our home.
Artifacts, or 'Artefacts' as we call them, are powerful wizard tools or items made specially for wizards everywhere. Extremely potent, they cannot be refunded like spells, and some of them can be used by non-wizards, so be careful!
Knowing these three concepts puts you in a league above most wizards, however knowledge of spells is just as important so we've included a list of spells below made specifically for the beginning wizard. Take all of them, or mix and match, remember being creative is half of being a wizard!" book_flags = CAN_MAKE_CONTRACTS|INVESTABLE - max_uses = 5 - + max_uses = 5 spells = list( - /spell/aoe_turf/knock = 1, - /spell/targeted/ethereal_jaunt = 1, +/* + /spell/aoe_turf/knock = 1, + /spell/targeted/ethereal_jaunt = 1, /spell/targeted/projectile/magic_missile = 1, - /obj/item/gun/energy/staff/focus = 1, - /obj/item/contract/wizard/xray = 1 +*/ + /obj/item/gun/energy/staff/focus = 1, + /obj/item/paper/contract/wizard/xray = 1 ) -/datum/spellbook/student/apprentice +/decl/spellbook/student/apprentice book_flags = CAN_MAKE_CONTRACTS|INVESTABLE|NOREVERT|NO_LOCKING - -/obj/item/spellbook/apprentice - spellbook_type = /datum/spellbook/student/apprentice diff --git a/mods/gamemodes/wizard/spells/_spell.dm b/mods/gamemodes/wizard/spells/_spell.dm new file mode 100644 index 000000000000..e8924c64a22f --- /dev/null +++ b/mods/gamemodes/wizard/spells/_spell.dm @@ -0,0 +1,149 @@ +/decl/ability/spell + associated_handler_type = /datum/ability_handler/spells + abstract_type = /decl/ability/spell + is_supernatural = TRUE + effect_radius = 1 + overlay_icon = 'icons/obj/wizard.dmi' + overlay_icon_state = "spell" + max_charge = 0 + + var/silenced = 0 + var/requires_wizard_garb = TRUE + var/vocal_component = TRUE + var/invocation_type = SpI_NONE + var/invocation_string + var/sparks_spread + var/sparks_amt + var/smoke_spread + var/smoke_amt + var/feedback + +/decl/ability/spell/can_use_ability(mob/user, list/metadata, silent = FALSE) + + if(!(. = ..())) + return + + if(requires_wizard_garb) + var/failure = user.wearing_wizard_garb() + if(failure) + if(!silent) + to_chat(user, SPAN_WARNING(failure)) + return FALSE + + if(vocal_component && user.get_item_blocking_speech()) + if(!silent) + to_chat(user, SPAN_WARNING("This spell requires a vocal incantation, and your mouth is blocked!")) + return FALSE + + if(LAZYACCESS(metadata, silenced) > 0) + if(!silent) + to_chat(user, SPAN_WARNING("Your magic has been silenced!")) + return FALSE + + return TRUE + +/decl/ability/spell/show_ability_cast_msg(mob/user, list/targets, list/metadata) + if(!invocation_string || invocation_type == SpI_NONE) + return + switch(invocation_type) + if(SpI_SHOUT) + if(prob(50)) + user.say(invocation_string) + else + user.say(replacetext(invocation_string," ","`")) + if(SpI_WHISPER) + if(prob(50)) + user.whisper(invocation_string) + else + user.whisper(replacetext(invocation_string," ","`")) + if(SpI_EMOTE) + user.custom_emote(VISIBLE_MESSAGE, invocation_string) + +/decl/ability/spell/finish_casting(mob/user, atom/hit_target, list/metadata) + ..() + var/turf/location = get_turf(user) + if(!istype(location)) + return + + if(sparks_spread && sparks_amt) + spark_at(location, amount = sparks_amt) + + if(smoke_spread && smoke_amt) + var/datum/effect/effect/system/smoke_spread/smoke + switch(smoke_spread) + if(1) + smoke = new /datum/effect/effect/system/smoke_spread() + if(2) + smoke = new /datum/effect/effect/system/smoke_spread/bad() + if(smoke) + smoke.set_up(smoke_amt, 0, location) + smoke.start() + +#ifdef MODPACK_PSIONICS +/decl/ability/spell/can_use_ability(mob/user, list/metadata, silent) + . = ..() + if(.) + var/spell_leech = user.disrupts_psionics() + if(spell_leech) + if(!silent) + to_chat(user, SPAN_WARNING("You try to marshal your energy, but find it leeched away by \the [spell_leech]!")) + return FALSE +#endif + +/decl/ability/spell/proc/can_improve(upgrade_type, list/metadata) + + // We got a null or false value, why? + if(!upgrade_type) + return FALSE + + //too many levels, can't do it + var/list/current_levels = metadata["current_upgrade_levels"] + if(metadata["max_upgrades"] <= current_levels[Sp_POWER] + current_levels[Sp_SPEED]) + return FALSE + + // Can we continue upgrading this field? + var/list/max_levels = metadata["max_upgrade_levels"] + return current_levels[upgrade_type] <= max_levels[upgrade_type] + +/decl/ability/spell/proc/empower_spell(mob/user, list/metadata) + if(can_improve(Sp_POWER, metadata)) + var/list/current_levels = metadata["current_upgrade_levels"] + current_levels[Sp_POWER]++ + return TRUE + return FALSE + +/decl/ability/spell/proc/quicken_spell(mob/user, list/metadata) + if(!can_improve(Sp_SPEED, metadata)) + return FALSE + var/list/current_levels = metadata["current_upgrade_levels"] + current_levels[Sp_SPEED]++ + +/* + if(delay_reduc && cast_delay) + cast_delay = max(0, cast_delay - delay_reduc) + else if(cast_delay) + cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) + + if(charge_type == Sp_RECHARGE) + if(cooldown_reduc) + charge_max = max(cooldown_min, charge_max - cooldown_reduc) + else + charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose + if(charge_max < charge_counter) + charge_counter = charge_max + +*/ + var/list/max_levels = metadata["max_upgrade_levels"] + switch(max_levels[Sp_SPEED]-current_levels[Sp_SPEED]) + if(3) + to_chat(user, SPAN_NOTICE("You have improved [name] into Efficient [name].")) + metadata["ability_name"] = "Efficient [name]" + if(2) + to_chat(user, SPAN_NOTICE("You have improved [name] into Quickened [name].")) + metadata["ability_name"] = "Quickened [name]" + if(1) + to_chat(user, SPAN_NOTICE("You have improved [name] into Free [name].")) + metadata["ability_name"] = "Free [name]" + if(0) + to_chat(user, SPAN_NOTICE("You have improved [name] into Instant [name].")) + metadata["ability_name"] = "Instant [name]" diff --git a/mods/gamemodes/wizard/spells/_spell_handler.dm b/mods/gamemodes/wizard/spells/_spell_handler.dm new file mode 100644 index 000000000000..eea21ccf9ac1 --- /dev/null +++ b/mods/gamemodes/wizard/spells/_spell_handler.dm @@ -0,0 +1,97 @@ +/datum/ability_handler/spells + ability_category_tag = "wizard_spells" + +/datum/ability_handler/spells/refresh_login() + . = ..() + +/* +mob life: +/spell/proc/process() + if(processing) + return + processing = 1 + spawn(0) + while(charge_counter < charge_max || silenced > 0) + charge_counter = min(charge_max,charge_counter+1) + silenced = max(0,silenced-1) + sleep(1) + if(connected_button) + var/obj/screen/ability/spell/S = connected_button + if(!istype(S)) + return + S.update_charge(1) + processing = 0 + return +*/ + +/datum/ability_handler/spells/copy_abilities_to(mob/living/donor) +// var/datum/ability_handler/spells/spells = donor.get_ability_handler(/datum/ability_handler/spells, create_if_missing = TRUE) +/* + for (var/spell/S in M.mind.learned_spells) + new_mob.add_ability(S.type, donor.get_ability_metadata(S.type, create_if_missing = FALSE)) +*/ + +/datum/ability_handler/spells/disable_abilities(amount) + return +/* + ability_master.silence_spells(amount) + for(var/obj/screen/ability/spell/spell in spell_objects) + spell.spell.silenced = amount + spell.spell.process() + spell.update_charge(1) + . = TRUE +*/ + +/datum/ability_handler/spells/finalize_ability_handler() + . = ..() + add_screen_element(new /obj/screen/ability_button/toggle_category/spells(null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/one( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/two( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/three( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/four( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/five( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/six( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/seven( null, null, null, null, null, null, null), FALSE) + add_screen_element(new /obj/screen/ability_button/spell_debugger/eight( null, null, null, null, null, null, null)) + toggle_category_visibility(TRUE) + +/obj/screen/ability_button/toggle_category/spells + ability_category_tag = "wizard_spells" + +/obj/screen/ability_button/spell_debugger + name = "debug spell" + icon = 'mods/gamemodes/wizard/icons/spell_icons.dmi' + ability_category_tag = "wizard_spells" + +/obj/screen/ability_button/spell_debugger/handle_click(mob/user, params) + to_chat(user, "[name] click!") + +/obj/screen/ability_button/spell_debugger/one + name = "debug spell one" + +/obj/screen/ability_button/spell_debugger/two + name = "debug spell two" + +/obj/screen/ability_button/spell_debugger/three + name = "debug spell three" + +/obj/screen/ability_button/spell_debugger/four + name = "debug spell four" + +/obj/screen/ability_button/spell_debugger/five + name = "debug spell five" + +/obj/screen/ability_button/spell_debugger/six + name = "debug spell six" + +/obj/screen/ability_button/spell_debugger/seven + name = "debug spell seven" + +/obj/screen/ability_button/spell_debugger/eight + name = "debug spell eight" + +/client/verb/debug_wizard_handler() + set name = "Debug Wizard Handler" + set category = "Debug" + set src = usr + usr.add_ability_handler(/datum/ability_handler/spells) diff --git a/code/modules/spells/aoe_turf/blink.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/blink.dm similarity index 91% rename from code/modules/spells/aoe_turf/blink.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/blink.dm index 3fd742aec243..a426eaa8be0e 100644 --- a/code/modules/spells/aoe_turf/blink.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/blink.dm @@ -4,11 +4,11 @@ feedback = "BL" school = "conjuration" charge_max = 20 - spell_flags = Z2NOCAST | IGNOREDENSE | IGNORESPACE + ignore_space_turfs = TRUE invocation = "none" invocation_type = SpI_NONE range = 7 - inner_radius = 1 + effect_inner_radius = 1 level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 4) cooldown_min = 5 //4 deciseconds reduction per rank @@ -39,6 +39,6 @@ /spell/aoe_turf/blink/empower_spell() if(!..()) return 0 - inner_radius += 1 + effect_inner_radius += 1 return "You've increased the inner range of [src]." \ No newline at end of file diff --git a/code/modules/spells/aoe_turf/charge.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/charge.dm similarity index 97% rename from code/modules/spells/aoe_turf/charge.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/charge.dm index d1e47760c9a0..286a23bbaf5a 100644 --- a/code/modules/spells/aoe_turf/charge.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/charge.dm @@ -4,7 +4,7 @@ school = "transmutation" charge_max = 600 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "DIRI CEL" invocation_type = SpI_WHISPER range = 0 @@ -69,4 +69,4 @@ desc = "This spell charges things around it using the lifeforce gained by sacrificed blood." charge_type = Sp_HOLDVAR holder_var_type = "bruteloss" - holder_var_amount = 30 \ No newline at end of file + holder_var_amount = 30 diff --git a/code/modules/spells/aoe_turf/conjure/conjure.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/conjure.dm similarity index 97% rename from code/modules/spells/aoe_turf/conjure/conjure.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/conjure.dm index 9291456f41a6..2a271519a46c 100644 --- a/code/modules/spells/aoe_turf/conjure/conjure.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/conjure.dm @@ -37,10 +37,8 @@ How they spawn stuff is decided by behaviour vars, which are explained below summon_type -= summoned_object_type else summoned_object_type = pick(summon_type) - var/turf/spawn_place = pick(targets) - if(spell_flags & IGNOREPREV) - targets -= spawn_place + var/turf/spawn_place = pick(targets) var/atom/summoned_object if(ispath(summoned_object_type,/turf)) spawn_place.ChangeTurf(summoned_object_type) diff --git a/code/modules/spells/aoe_turf/conjure/druidic_spells.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/druidic_spells.dm similarity index 98% rename from code/modules/spells/aoe_turf/conjure/druidic_spells.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/druidic_spells.dm index e6f0b8ea2607..5986bf19abbe 100644 --- a/code/modules/spells/aoe_turf/conjure/druidic_spells.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/druidic_spells.dm @@ -22,7 +22,6 @@ feedback = "SB" charge_max = 1200 //2 minutes - spell_flags = NEEDSCLOTHES invocation = "Bla'yo daya!" invocation_type = SpI_SHOUT level_max = list(Sp_TOTAL = 3, Sp_SPEED = 3, Sp_POWER = 3) @@ -48,7 +47,6 @@ desc = "This spell summons a permanent bear companion that will follow your orders." feedback = "BR" charge_max = 3000 //5 minutes because this is a REALLY powerful spell. May tone it down/up. - spell_flags = NEEDSCLOTHES invocation = "REA'YO GOR DAYA!" invocation_type = SpI_SHOUT level_max = list(Sp_TOTAL = 4, Sp_SPEED = 0, Sp_POWER = 4) diff --git a/code/modules/spells/aoe_turf/conjure/faithful_hound.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/faithful_hound.dm similarity index 96% rename from code/modules/spells/aoe_turf/conjure/faithful_hound.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/faithful_hound.dm index 4511e6a07f46..0cba61770d10 100644 --- a/code/modules/spells/aoe_turf/conjure/faithful_hound.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/faithful_hound.dm @@ -4,7 +4,6 @@ feedback = "FH" charge_max = 600 - spell_flags = NEEDSCLOTHES invocation = "Du korilath tangus" invocation_type = SpI_WHISPER range = 0 diff --git a/code/modules/spells/aoe_turf/conjure/force_portal.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/force_portal.dm similarity index 92% rename from code/modules/spells/aoe_turf/conjure/force_portal.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/force_portal.dm index 293e176051f1..d264f768f8a1 100644 --- a/code/modules/spells/aoe_turf/conjure/force_portal.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/force_portal.dm @@ -5,7 +5,6 @@ feedback = "FP" summon_type = list(/obj/effect/force_portal) charge_max = 200 - spell_flags = NEEDSCLOTHES range = 0 cast_sound = null diff --git a/code/modules/spells/aoe_turf/conjure/forcewall.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/forcewall.dm similarity index 97% rename from code/modules/spells/aoe_turf/conjure/forcewall.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/forcewall.dm index 1c937f3f6d8c..61b44c3e2aa6 100644 --- a/code/modules/spells/aoe_turf/conjure/forcewall.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/forcewall.dm @@ -6,7 +6,7 @@ summon_type = list(/obj/effect/forcefield) duration = 300 charge_max = 100 - spell_flags = 0 + requires_wizard_garb = FALSE range = 0 cast_sound = 'sound/magic/forcewall.ogg' diff --git a/code/modules/spells/aoe_turf/conjure/grove.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/grove.dm similarity index 93% rename from code/modules/spells/aoe_turf/conjure/grove.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/grove.dm index 77f68981e9db..ecf23d4a982e 100644 --- a/code/modules/spells/aoe_turf/conjure/grove.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/conjure/grove.dm @@ -2,7 +2,7 @@ name = "Grove" desc = "Creates a sanctuary of nature around the wizard as well as creating a healing plant." - spell_flags = IGNOREDENSE | IGNORESPACE | NEEDSCLOTHES | Z2NOCAST | IGNOREPREV + ignore_space_turfs = TRUE charge_max = 1200 school = "transmutation" @@ -37,7 +37,7 @@ feedback = "SY" invocation = "Bo K'Iitan!" invocation_type = SpI_SHOUT - spell_flags = IGNOREDENSE | IGNORESPACE | NEEDSCLOTHES | Z2NOCAST | IGNOREPREV + ignore_space_turfs = TRUE cooldown_min = 600 level_max = list(Sp_TOTAL = 3, Sp_SPEED = 3, Sp_POWER = 1) diff --git a/code/modules/spells/aoe_turf/disable_tech.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/disable_tech.dm similarity index 94% rename from code/modules/spells/aoe_turf/disable_tech.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/disable_tech.dm index d9912e1c3907..0781dbff3cc8 100644 --- a/code/modules/spells/aoe_turf/disable_tech.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/disable_tech.dm @@ -3,12 +3,11 @@ desc = "This spell disables all weapons, cameras and most other technology in range." feedback = "DT" charge_max = 400 - spell_flags = NEEDSCLOTHES invocation = "NEC CANTIO" invocation_type = SpI_SHOUT selection_type = "range" range = 0 - inner_radius = -1 + effect_inner_radius = -1 level_max = list(Sp_TOTAL = 2, Sp_SPEED = 2, Sp_POWER = 2) cooldown_min = 200 //50 deciseconds reduction per rank diff --git a/code/modules/spells/aoe_turf/drain_blood.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/drain_blood.dm similarity index 98% rename from code/modules/spells/aoe_turf/drain_blood.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/drain_blood.dm index 8ad4ea6b8a29..45992f0fb773 100644 --- a/code/modules/spells/aoe_turf/drain_blood.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/drain_blood.dm @@ -7,7 +7,7 @@ invocation = "whispers something darkly" invocation_type = SpI_EMOTE range = 3 - inner_radius = 0 + effect_inner_radius = 0 time_between_channels = 100 number_of_channels = 3 diff --git a/code/modules/spells/aoe_turf/exchange_wounds.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/exchange_wounds.dm similarity index 95% rename from code/modules/spells/aoe_turf/exchange_wounds.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/exchange_wounds.dm index 7293e960d292..8416443fce1a 100644 --- a/code/modules/spells/aoe_turf/exchange_wounds.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/exchange_wounds.dm @@ -6,12 +6,12 @@ invocation = "Esh Yek Vai!" invocation_type = SpI_SHOUT charge_max = 400 - spell_flags = 0 + requires_wizard_garb = FALSE var/amt_healed = 0 var/heal_max = 100 range = 4 - inner_radius = 0 + effect_inner_radius = 0 number_of_channels = 0 time_between_channels = 20 diff --git a/code/modules/spells/aoe_turf/knock.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/knock.dm similarity index 96% rename from code/modules/spells/aoe_turf/knock.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/knock.dm index 3cf8614eeaa7..0123fe279782 100644 --- a/code/modules/spells/aoe_turf/knock.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/knock.dm @@ -4,7 +4,7 @@ feedback = "KN" school = "transmutation" charge_max = 100 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Aulie Oxin Fiera." invocation_type = SpI_WHISPER range = 3 diff --git a/code/modules/spells/aoe_turf/smoke.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/smoke.dm similarity index 91% rename from code/modules/spells/aoe_turf/smoke.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/smoke.dm index f9f0138908fb..1cd2f0de83a1 100644 --- a/code/modules/spells/aoe_turf/smoke.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/smoke.dm @@ -4,11 +4,11 @@ feedback = "SM" school = "transmutation" charge_max = 120 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "none" invocation_type = SpI_NONE range = 1 - inner_radius = -1 + effect_inner_radius = -1 level_max = list(Sp_TOTAL = 3, Sp_SPEED = 3, Sp_POWER = 2) cooldown_min = 20 //25 deciseconds reduction per rank diff --git a/code/modules/spells/aoe_turf/summons.dm b/mods/gamemodes/wizard/spells_archive/aoe_turf/summons.dm similarity index 96% rename from code/modules/spells/aoe_turf/summons.dm rename to mods/gamemodes/wizard/spells_archive/aoe_turf/summons.dm index be61819d9eab..d88c0a49fcae 100644 --- a/code/modules/spells/aoe_turf/summons.dm +++ b/mods/gamemodes/wizard/spells_archive/aoe_turf/summons.dm @@ -15,7 +15,6 @@ school = "conjuration" charge_max = 1200 - spell_flags = NEEDSCLOTHES invocation = "Nouk Fhumm Sacp Risska!" invocation_type = SpI_SHOUT range = 1 @@ -31,7 +30,7 @@ school = "conjuration" charge_max = 1200 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Ia-Ia! Naomesnalia!" invocation_type = SpI_SHOUT summon_amt = 10 @@ -47,7 +46,6 @@ feedback = "MR" school = "illusion" charge_max = 1200 - spell_flags = NEEDSCLOTHES invocation = "Nouk Fhunhm Sacp Risska!" invocation_type = SpI_SHOUT range = 1 diff --git a/code/modules/spells/general/acid_spray.dm b/mods/gamemodes/wizard/spells_archive/general/acid_spray.dm similarity index 96% rename from code/modules/spells/general/acid_spray.dm rename to mods/gamemodes/wizard/spells_archive/general/acid_spray.dm index 752a17eecb72..59c0b52de231 100644 --- a/code/modules/spells/general/acid_spray.dm +++ b/mods/gamemodes/wizard/spells_archive/general/acid_spray.dm @@ -3,7 +3,7 @@ desc = "A common spell used to destroy basically anything in front of the wizard." school = "conjuration" feedback = "as" - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 600 invocation = "Tagopar lethodar!" diff --git a/code/modules/spells/general/area_teleport.dm b/mods/gamemodes/wizard/spells_archive/general/area_teleport.dm similarity index 98% rename from code/modules/spells/general/area_teleport.dm rename to mods/gamemodes/wizard/spells_archive/general/area_teleport.dm index 68e20f3d6f9a..edcaf890f180 100644 --- a/code/modules/spells/general/area_teleport.dm +++ b/mods/gamemodes/wizard/spells_archive/general/area_teleport.dm @@ -4,7 +4,6 @@ feedback = "TP" school = "conjuration" charge_max = 60 SECONDS - spell_flags = NEEDSCLOTHES invocation = "Scyar Nila!" invocation_type = SpI_SHOUT cooldown_min = 200 //100 deciseconds reduction per rank diff --git a/code/modules/spells/general/camera_vision.dm b/mods/gamemodes/wizard/spells_archive/general/camera_vision.dm similarity index 96% rename from code/modules/spells/general/camera_vision.dm rename to mods/gamemodes/wizard/spells_archive/general/camera_vision.dm index cfd0cfb030e2..bda4f1a0594c 100644 --- a/code/modules/spells/general/camera_vision.dm +++ b/mods/gamemodes/wizard/spells_archive/general/camera_vision.dm @@ -1,19 +1,12 @@ /spell/camera_connection name = "Camera Connection" desc = "This spell allows the wizard to connect to the local camera network and see what it sees." - school = "racial" - invocation_type = SpI_EMOTE invocation = "emits a beeping sound before standing very, very still." - charge_max = 600 //1 minute charge_type = Sp_RECHARGE - - - spell_flags = Z2NOCAST hud_state = "wiz_IPC" - var/extension_type = /datum/extension/eye/cameranet /spell/camera_connection/New() diff --git a/code/modules/spells/general/contract_spells.dm b/mods/gamemodes/wizard/spells_archive/general/contract_spells.dm similarity index 98% rename from code/modules/spells/general/contract_spells.dm rename to mods/gamemodes/wizard/spells_archive/general/contract_spells.dm index fa95cd16e23c..a509e196e687 100644 --- a/code/modules/spells/general/contract_spells.dm +++ b/mods/gamemodes/wizard/spells_archive/general/contract_spells.dm @@ -6,7 +6,7 @@ desc = "A spell perfecting the techniques of keeping a servant happy and obedient." school = "transmutation" - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "none" invocation_type = SpI_NONE diff --git a/code/modules/spells/general/create_air.dm b/mods/gamemodes/wizard/spells_archive/general/create_air.dm similarity index 96% rename from code/modules/spells/general/create_air.dm rename to mods/gamemodes/wizard/spells_archive/general/create_air.dm index 405e161a54a9..512afb1e12e7 100644 --- a/code/modules/spells/general/create_air.dm +++ b/mods/gamemodes/wizard/spells_archive/general/create_air.dm @@ -1,12 +1,9 @@ /spell/create_air name = "Create Air" desc = "A much used spell used in the vasteness of space to make it not so killey." - charge_max = 200 - spell_flags = Z2NOCAST invocation = "none" invocation_type = SpI_NONE - number_of_channels = 0 time_between_channels = 200 hud_state = "wiz_air" diff --git a/code/modules/spells/general/invisibility.dm b/mods/gamemodes/wizard/spells_archive/general/invisibility.dm similarity index 95% rename from code/modules/spells/general/invisibility.dm rename to mods/gamemodes/wizard/spells_archive/general/invisibility.dm index 3fbab715efd1..7abfe818b757 100644 --- a/code/modules/spells/general/invisibility.dm +++ b/mods/gamemodes/wizard/spells_archive/general/invisibility.dm @@ -2,7 +2,7 @@ name = "invisibility" desc = "A simple spell of invisibility, for when you really just can't afford a paper bag." feedback = "IV" - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 100 invocation = "Ror Rim Or!" invocation_type = SpI_SHOUT diff --git a/code/modules/spells/general/mark_recall.dm b/mods/gamemodes/wizard/spells_archive/general/mark_recall.dm similarity index 96% rename from code/modules/spells/general/mark_recall.dm rename to mods/gamemodes/wizard/spells_archive/general/mark_recall.dm index a8e987c8d540..a102fec1e0f1 100644 --- a/code/modules/spells/general/mark_recall.dm +++ b/mods/gamemodes/wizard/spells_archive/general/mark_recall.dm @@ -4,7 +4,6 @@ feedback = "MK" school = "conjuration" charge_max = 600 //1 minutes for how OP this shit is (apparently not as op as I thought) - spell_flags = Z2NOCAST invocation = "Re-Alki R'natha." invocation_type = SpI_WHISPER cooldown_min = 300 @@ -42,9 +41,7 @@ /spell/mark_recall/empower_spell() if(!..()) return 0 - - spell_flags = NO_SOMATIC - + check_incapacitated = 0 return "You will always be able to cast this spell, even while unconscious or handcuffed." /obj/effect/cleanable/wizard_mark @@ -80,7 +77,7 @@ return TRUE /obj/effect/cleanable/wizard_mark/attackby(var/obj/item/I, var/mob/user) - if(istype(I, /obj/item/spellbook)) + if(istype(I, /obj/item/book/spell)) user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) visible_message("\The [src] fades away!") qdel(src) diff --git a/code/modules/spells/general/portal_teleport.dm b/mods/gamemodes/wizard/spells_archive/general/portal_teleport.dm similarity index 98% rename from code/modules/spells/general/portal_teleport.dm rename to mods/gamemodes/wizard/spells_archive/general/portal_teleport.dm index 1f1ed0ad603b..dc42380f3f50 100644 --- a/code/modules/spells/general/portal_teleport.dm +++ b/mods/gamemodes/wizard/spells_archive/general/portal_teleport.dm @@ -3,7 +3,6 @@ desc = "This spell creates a long lasting portal to an area of your selection." feedback = "TP" school = "conjuration" - spell_flags = NEEDSCLOTHES invocation = "Scyar Peranda!" invocation_type = SpI_SHOUT charge_max = 30 MINUTES diff --git a/code/modules/spells/general/radiant_aura.dm b/mods/gamemodes/wizard/spells_archive/general/radiant_aura.dm similarity index 95% rename from code/modules/spells/general/radiant_aura.dm rename to mods/gamemodes/wizard/spells_archive/general/radiant_aura.dm index 27e85404027e..4219cc1dc3a0 100644 --- a/code/modules/spells/general/radiant_aura.dm +++ b/mods/gamemodes/wizard/spells_archive/general/radiant_aura.dm @@ -5,7 +5,6 @@ invocation_type = SpI_EMOTE invocation = "conjures a sphere of fire around themselves." school = "conjuration" - spell_flags = NEEDSCLOTHES charge_max = 300 cooldown_min = 100 level_max = list(Sp_TOTAL = 2, Sp_SPEED = 2, Sp_POWER = 0) diff --git a/code/modules/spells/general/return_master.dm b/mods/gamemodes/wizard/spells_archive/general/return_master.dm similarity index 93% rename from code/modules/spells/general/return_master.dm rename to mods/gamemodes/wizard/spells_archive/general/return_master.dm index 119cc93804de..481822a02355 100644 --- a/code/modules/spells/general/return_master.dm +++ b/mods/gamemodes/wizard/spells_archive/general/return_master.dm @@ -4,7 +4,7 @@ school = "conjuration" charge_max = 600 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "none" invocation_type = SpI_NONE cooldown_min = 200 diff --git a/code/modules/spells/general/toggle_armor.dm b/mods/gamemodes/wizard/spells_archive/general/toggle_armor.dm similarity index 99% rename from code/modules/spells/general/toggle_armor.dm rename to mods/gamemodes/wizard/spells_archive/general/toggle_armor.dm index 5da3bf537f83..bb9e1d1918fd 100644 --- a/code/modules/spells/general/toggle_armor.dm +++ b/mods/gamemodes/wizard/spells_archive/general/toggle_armor.dm @@ -1,6 +1,6 @@ /spell/toggle_armor name = "Toggle Armor" - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 10 school = "Conjuration" var/list/armor_pieces diff --git a/code/modules/spells/hand/blood_shards.dm b/mods/gamemodes/wizard/spells_archive/hand/blood_shards.dm similarity index 97% rename from code/modules/spells/hand/blood_shards.dm rename to mods/gamemodes/wizard/spells_archive/hand/blood_shards.dm index 0908ee285201..203bb3ecd82d 100644 --- a/code/modules/spells/hand/blood_shards.dm +++ b/mods/gamemodes/wizard/spells_archive/hand/blood_shards.dm @@ -1,7 +1,7 @@ /spell/hand/charges/blood_shard name = "Blood Shards" desc = "Invoke a corrupted projectile forward that causes an enemy's blood to fly out in painful shards. Anyone hit by this will have their blood explode out of them in a spray of smaller shards. Stores two charges." - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 600 invocation = "opens their hand, which bursts into vicious red light." invocation_type = SpI_EMOTE diff --git a/code/modules/spells/hand/burning_grip.dm b/mods/gamemodes/wizard/spells_archive/hand/burning_grip.dm similarity index 97% rename from code/modules/spells/hand/burning_grip.dm rename to mods/gamemodes/wizard/spells_archive/hand/burning_grip.dm index 772b4e6aa9c4..f973dfa3fc1e 100644 --- a/code/modules/spells/hand/burning_grip.dm +++ b/mods/gamemodes/wizard/spells_archive/hand/burning_grip.dm @@ -4,7 +4,7 @@ school = "transmutation" feedback = "bg" range = 5 - spell_flags = 0 + requires_wizard_garb = FALSE invocation_type = SpI_NONE show_message = " throws sparks from their hands" spell_delay = 120 diff --git a/code/modules/spells/hand/entangle.dm b/mods/gamemodes/wizard/spells_archive/hand/entangle.dm similarity index 96% rename from code/modules/spells/hand/entangle.dm rename to mods/gamemodes/wizard/spells_archive/hand/entangle.dm index 37a4776fe28e..5d6445f9b666 100644 --- a/code/modules/spells/hand/entangle.dm +++ b/mods/gamemodes/wizard/spells_archive/hand/entangle.dm @@ -4,7 +4,7 @@ feedback = "ET" school = "transmutation" charge_max = 600 - spell_flags = NEEDSCLOTHES | SELECTABLE | IGNOREPREV + can_select_target = TRUE invocation = "Bu-Ekel'Inas!" invocation_type = SpI_SHOUT range = 3 diff --git a/code/modules/spells/hand/hand.dm b/mods/gamemodes/wizard/spells_archive/hand/hand.dm similarity index 100% rename from code/modules/spells/hand/hand.dm rename to mods/gamemodes/wizard/spells_archive/hand/hand.dm diff --git a/code/modules/spells/hand/hand_item.dm b/mods/gamemodes/wizard/spells_archive/hand/hand_item.dm similarity index 100% rename from code/modules/spells/hand/hand_item.dm rename to mods/gamemodes/wizard/spells_archive/hand/hand_item.dm diff --git a/code/modules/spells/hand/slippery_surface.dm b/mods/gamemodes/wizard/spells_archive/hand/slippery_surface.dm similarity index 94% rename from code/modules/spells/hand/slippery_surface.dm rename to mods/gamemodes/wizard/spells_archive/hand/slippery_surface.dm index 3b5fc448d034..3e958f1dce61 100644 --- a/code/modules/spells/hand/slippery_surface.dm +++ b/mods/gamemodes/wizard/spells_archive/hand/slippery_surface.dm @@ -4,7 +4,7 @@ school = "transmutation" feedback = "su" range = 5 - spell_flags = 0 + requires_wizard_garb = FALSE invocation_type = SpI_NONE show_message = " snaps their fingers." spell_delay = 50 diff --git a/code/modules/spells/hand/sunwrath.dm b/mods/gamemodes/wizard/spells_archive/hand/sunwrath.dm similarity index 96% rename from code/modules/spells/hand/sunwrath.dm rename to mods/gamemodes/wizard/spells_archive/hand/sunwrath.dm index 63da9a54c611..79bc75d8c66c 100644 --- a/code/modules/spells/hand/sunwrath.dm +++ b/mods/gamemodes/wizard/spells_archive/hand/sunwrath.dm @@ -1,7 +1,7 @@ /spell/hand/duration/sunwrath name = "Sun God's Wrath" desc = "Your hands become a gateway of fire, shooting hot plasma from your fingertips." - spell_flags = 0 + requires_wizard_garb = FALSE charge_max = 600 invocation_type = SpI_SHOUT invocation = "Herald! Bless me with your anger!" diff --git a/code/modules/spells/artifacts/spellbound_servants.dm b/mods/gamemodes/wizard/spells_archive/spellbound_servants.dm similarity index 92% rename from code/modules/spells/artifacts/spellbound_servants.dm rename to mods/gamemodes/wizard/spells_archive/spellbound_servants.dm index 0f6bb21c84ed..72911794c563 100644 --- a/code/modules/spells/artifacts/spellbound_servants.dm +++ b/mods/gamemodes/wizard/spells_archive/spellbound_servants.dm @@ -27,10 +27,7 @@ /datum/spellbound_type/proc/equip_servant(var/mob/living/human/H) for(var/stype in spells) - var/spell/S = new stype() - if(S.spell_flags & NEEDSCLOTHES) - S.spell_flags &= ~NEEDSCLOTHES - H.add_spell(S) + H.add_ability(stype) . = list() for(var/etype in equipment) var/obj/item/I = new etype(get_turf(H)) @@ -52,7 +49,7 @@ /obj/item/clothing/jumpsuit/lightpurple = slot_w_uniform_str, /obj/item/clothing/shoes/sandal = slot_shoes_str, /obj/item/staff = BP_R_HAND, - /obj/item/spellbook/apprentice = BP_L_HAND, + /obj/item/book/spell/apprentice = BP_L_HAND, /obj/item/clothing/suit/wizrobe = slot_wear_suit_str) spells = list(/spell/noclothes) @@ -109,29 +106,29 @@ if("Space Pike") H.add_genetic_condition(GENE_COND_NO_BREATH) H.add_genetic_condition(GENE_COND_SPACE_RESISTANCE) - familiar_type = /mob/living/simple_animal/hostile/carp/pike + //familiar_type = /mob/living/simple_animal/hostile/carp/pike if("Mouse") H.verbs |= /mob/living/proc/ventcrawl - familiar_type = /mob/living/simple_animal/passive/mouse + //familiar_type = /mob/living/simple_animal/passive/mouse if("Cat") H.add_genetic_condition(GENE_COND_RUNNING) - familiar_type = /mob/living/simple_animal/passive/cat + //familiar_type = /mob/living/simple_animal/passive/cat if("Bear") - familiar_type = /mob/living/simple_animal/hostile/bear - var/spell/targeted/shapeshift/familiar/F = new() - F.possible_transformations = list(familiar_type) - H.add_spell(F) + //familiar_type = /mob/living/simple_animal/hostile/bear + if(familiar_type) + H.add_ability(familiar_type) /datum/spellbound_type/servant/fiend name = "Fiend" desc = "A practitioner of dark and evil magics, almost certainly a demon, and possibly a lawyer." spiel = "The Summoning Ritual has bound you to this world with limited access to your infernal powers; you'll have to be strategic in how you use them. Follow your Master's orders as well as you can!" - spells = list(/spell/targeted/projectile/dumbfire/fireball/firebolt, - /spell/targeted/ethereal_jaunt, - /spell/targeted/torment, - /spell/area_teleport, - /spell/hand/charges/blood_shard - ) + spells = list( + /spell/targeted/projectile/dumbfire/fireball/firebolt, + /spell/targeted/ethereal_jaunt, + /spell/targeted/torment, + /spell/area_teleport, + /spell/hand/charges/blood_shard + ) /datum/spellbound_type/servant/fiend/equip_servant(var/mob/living/human/H) if(H.gender == MALE) @@ -173,8 +170,8 @@ /obj/item/clothing/pants/casual/blackjeans/outfit = slot_w_uniform_str, /obj/item/clothing/suit/jacket/hoodie/grim = slot_wear_suit_str, /obj/item/clothing/shoes/sandal/grimboots = slot_shoes_str, - /obj/item/contract/wizard/xray = BP_L_HAND, - /obj/item/contract/wizard/telepathy = BP_R_HAND + /obj/item/paper/contract/wizard/xray = BP_L_HAND, + /obj/item/paper/contract/wizard/telepathy = BP_R_HAND ) spells = list( /spell/toggle_armor/overseer, @@ -273,7 +270,7 @@ if(T.density) turfs -= T if(turfs.len) - src.visible_message("\The [src] vanishes!") + src.visible_message(SPAN_NOTICE("\The [src] vanishes!")) src.forceMove(pick(turfs)) show_browser(user, null, "window=summoning") qdel(src) @@ -281,4 +278,4 @@ /obj/item/summoning_stone/OnTopic(user, href_list, state) if(href_list["type"]) use_type(href_list["type"],user) - return TOPIC_HANDLED \ No newline at end of file + return TOPIC_HANDLED diff --git a/code/modules/spells/targeted/analyze.dm b/mods/gamemodes/wizard/spells_archive/targeted/analyze.dm similarity index 93% rename from code/modules/spells/targeted/analyze.dm rename to mods/gamemodes/wizard/spells_archive/targeted/analyze.dm index 705d97399c70..dbf151f4435e 100644 --- a/code/modules/spells/targeted/analyze.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/analyze.dm @@ -5,7 +5,7 @@ feedback = "AZ" school = "illusion" charge_max = 100 - spell_flags = INCLUDEUSER|SELECTABLE + can_select_target = TRUE range = 2 invocation_type = SpI_WHISPER invocation = "Fu Yi Fim" diff --git a/code/modules/spells/targeted/blood_boil.dm b/mods/gamemodes/wizard/spells_archive/targeted/blood_boil.dm similarity index 96% rename from code/modules/spells/targeted/blood_boil.dm rename to mods/gamemodes/wizard/spells_archive/targeted/blood_boil.dm index 4c39b3b4620b..569edc10f976 100644 --- a/code/modules/spells/targeted/blood_boil.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/blood_boil.dm @@ -4,7 +4,7 @@ feedback = "BO" school = "transmutation" charge_max = 300 - spell_flags = 0 + requires_wizard_garb = FALSE invocation_type = SpI_NONE range = 5 max_targets = 1 diff --git a/code/modules/spells/targeted/cleric_spells.dm b/mods/gamemodes/wizard/spells_archive/targeted/cleric_spells.dm similarity index 96% rename from code/modules/spells/targeted/cleric_spells.dm rename to mods/gamemodes/wizard/spells_archive/targeted/cleric_spells.dm index 74061d776dd6..03e74724789e 100644 --- a/code/modules/spells/targeted/cleric_spells.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/cleric_spells.dm @@ -4,7 +4,8 @@ feedback = "CL" school = "transmutation" charge_max = 20 SECONDS - spell_flags = INCLUDEUSER | SELECTABLE + can_select_target = TRUE + invocation = "Di'Nath!" invocation_type = SpI_SHOUT range = 2 @@ -40,7 +41,7 @@ amt_dam_brute = -7 amt_dam_robo = -5 charge_max = 10 SECONDS - spell_flags = SELECTABLE + can_select_target = TRUE invocation = "Di'Na!" hud_state = "heal_touch" @@ -50,7 +51,7 @@ desc = "A spell used to fix others that cannot be fixed with regular medicine." feedback = "CM" charge_max = 30 SECONDS - spell_flags = INCLUDEUSER | SELECTABLE | NEEDSCLOTHES + can_select_target = TRUE invocation = "Borv Di'Nath!" range = 1 level_max = list(Sp_TOTAL = 2, Sp_SPEED = 1, Sp_POWER = 1) @@ -84,7 +85,7 @@ desc = "This spell heals everyone in an area." feedback = "HA" charge_max = 1 MINUTE - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE invocation = "Nal Di'Nath!" range = 2 max_targets = 0 @@ -112,7 +113,7 @@ name = "Sacrifice" desc = "This spell heals immensily. For a price. Does not require wizard garb." feedback = "SF" - spell_flags = SELECTABLE + can_select_target = TRUE invocation = "Ei'Nath Borv Di'Nath!" charge_type = Sp_HOLDVAR holder_var_type = "fireloss" @@ -146,7 +147,7 @@ name = "Trance" desc = "A mighty spell of restoration that briefly forces its target into a deep, dreamless sleep, rapidly repairing their body and soul as their senses are dulled. The users of this mighty art are known for being short lived, slowly devolving into raving madness as the power they once relied on fails them with excessive use." feedback = "TC" - spell_flags = SELECTABLE + can_select_target = TRUE invocation = "Di' Dae Nath!" charge_max = 2 MINUTES @@ -201,9 +202,7 @@ name = "Revoke Death" desc = "Revoke that of death itself. Comes at a cost that may be hard to manage for some." feedback = "RK" - - spell_flags = SELECTABLE - + can_select_target = TRUE charge_type = Sp_CHARGES charge_max = 1 invocation = "Di Le Nal Yen Nath!" @@ -243,6 +242,6 @@ for(var/s in M.mind.learned_spells) if(istype(s, /spell/toggle_armor)) //Can keep the armor n junk. continue - M.remove_spell(s) + M.remove_ability(s) for(var/a in M.auras) M.remove_aura(a) \ No newline at end of file diff --git a/code/modules/spells/targeted/equip/burning_touch.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/burning_touch.dm similarity index 98% rename from code/modules/spells/targeted/equip/burning_touch.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/burning_touch.dm index 7f876ed2ae6e..1186210e7311 100644 --- a/code/modules/spells/targeted/equip/burning_touch.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/burning_touch.dm @@ -5,7 +5,7 @@ school = "conjuration" invocation = "Horila Kiha!" invocation_type = SpI_SHOUT - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE range = -1 duration = 0 max_targets = 1 diff --git a/code/modules/spells/targeted/equip/dyrnwyn.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/dyrnwyn.dm similarity index 97% rename from code/modules/spells/targeted/equip/dyrnwyn.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/dyrnwyn.dm index 71d7ace1e4f0..2ccb294dbd68 100644 --- a/code/modules/spells/targeted/equip/dyrnwyn.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/dyrnwyn.dm @@ -8,7 +8,7 @@ school = "conjuration" invocation = "Anrhydeddu Fi!" invocation_type = SpI_SHOUT - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE range = -1 level_max = list(Sp_TOTAL = 1, Sp_SPEED = 0, Sp_POWER = 1) duration = 300 //30 seconds diff --git a/code/modules/spells/targeted/equip/equip.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/equip.dm similarity index 100% rename from code/modules/spells/targeted/equip/equip.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/equip.dm diff --git a/code/modules/spells/targeted/equip/holy_relic.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/holy_relic.dm similarity index 96% rename from code/modules/spells/targeted/equip/holy_relic.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/holy_relic.dm index 7c6dadf5da26..252c7b504848 100644 --- a/code/modules/spells/targeted/equip/holy_relic.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/holy_relic.dm @@ -4,7 +4,6 @@ feedback = "SR" school = "conjuration" charge_type = Sp_RECHARGE - spell_flags = NEEDSCLOTHES | INCLUDEUSER invocation = "Yee'Ro Su!" invocation_type = SpI_SHOUT range = 0 diff --git a/code/modules/spells/targeted/equip/horsemask.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/horsemask.dm similarity index 94% rename from code/modules/spells/targeted/equip/horsemask.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/horsemask.dm index 31995ba86bd0..c95b26873cc0 100644 --- a/code/modules/spells/targeted/equip/horsemask.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/horsemask.dm @@ -5,7 +5,7 @@ charge_type = Sp_RECHARGE charge_max = 150 charge_counter = 0 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Kn'a Ftaghu, Puck'Bthnk!" invocation_type = SpI_SHOUT range = 7 @@ -42,7 +42,5 @@ /spell/targeted/equip_item/horsemask/empower_spell() if(!..()) return 0 - - spell_flags = SELECTABLE - - return "You can now select your target with [src]" \ No newline at end of file + can_select_target = TRUE + return "You can now select your target with [src]" diff --git a/code/modules/spells/targeted/equip/party_hardy.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/party_hardy.dm similarity index 97% rename from code/modules/spells/targeted/equip/party_hardy.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/party_hardy.dm index f6f7ba54d071..e3513abee0d9 100644 --- a/code/modules/spells/targeted/equip/party_hardy.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/party_hardy.dm @@ -6,7 +6,7 @@ charge_type = Sp_RECHARGE charge_max = 900 cooldown_min = 600 - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE invocation = "Llet'Su G'iit Rrkned!" //Let's get wrecked. invocation_type = SpI_SHOUT range = 6 diff --git a/code/modules/spells/targeted/equip/seed.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/seed.dm similarity index 92% rename from code/modules/spells/targeted/equip/seed.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/seed.dm index 2252ec75c8c0..5b1135eb9a04 100644 --- a/code/modules/spells/targeted/equip/seed.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/seed.dm @@ -4,7 +4,6 @@ feedback = "SE" delete_old = 0 - spell_flags = INCLUDEUSER | NEEDSCLOTHES invocation_type = SpI_WHISPER invocation = "Ria'li akta." diff --git a/code/modules/spells/targeted/equip/shield.dm b/mods/gamemodes/wizard/spells_archive/targeted/equip/shield.dm similarity index 96% rename from code/modules/spells/targeted/equip/shield.dm rename to mods/gamemodes/wizard/spells_archive/targeted/equip/shield.dm index b725196ad3a6..6592163c8b6e 100644 --- a/code/modules/spells/targeted/equip/shield.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/equip/shield.dm @@ -5,7 +5,6 @@ school = "conjuration" invocation = "Sia helda!" invocation_type = SpI_SHOUT - spell_flags = INCLUDEUSER | NEEDSCLOTHES range = -1 max_targets = 1 diff --git a/code/modules/spells/targeted/ethereal_jaunt.dm b/mods/gamemodes/wizard/spells_archive/targeted/ethereal_jaunt.dm similarity index 98% rename from code/modules/spells/targeted/ethereal_jaunt.dm rename to mods/gamemodes/wizard/spells_archive/targeted/ethereal_jaunt.dm index e686e7712dc5..45d2b3297d2a 100644 --- a/code/modules/spells/targeted/ethereal_jaunt.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/ethereal_jaunt.dm @@ -4,7 +4,6 @@ feedback = "EJ" school = "transmutation" charge_max = 30 SECONDS - spell_flags = Z2NOCAST | NEEDSCLOTHES | INCLUDEUSER invocation = "none" invocation_type = SpI_NONE range = 0 diff --git a/code/modules/spells/targeted/exude_pleasantness.dm b/mods/gamemodes/wizard/spells_archive/targeted/exude_pleasantness.dm similarity index 96% rename from code/modules/spells/targeted/exude_pleasantness.dm rename to mods/gamemodes/wizard/spells_archive/targeted/exude_pleasantness.dm index 74ae51237ab7..7911fe6a712c 100644 --- a/code/modules/spells/targeted/exude_pleasantness.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/exude_pleasantness.dm @@ -3,7 +3,7 @@ desc = "A simple spell used to make friends with people. Be warned, this spell only has a subtle effect" feedback = "AP" school = "Illusion" - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE range = 5 max_targets = 0 charge_max = 100 diff --git a/code/modules/spells/targeted/genetic.dm b/mods/gamemodes/wizard/spells_archive/targeted/genetic.dm similarity index 94% rename from code/modules/spells/targeted/genetic.dm rename to mods/gamemodes/wizard/spells_archive/targeted/genetic.dm index bcc5233b9b65..ec25ac886db1 100644 --- a/code/modules/spells/targeted/genetic.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/genetic.dm @@ -23,7 +23,7 @@ code\game\dna\genes\goon_powers.dm school = "illusion" duration = 300 charge_max = 300 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Sty Kaly." invocation_type = SpI_WHISPER message = "Your eyes cry out in pain!" @@ -48,7 +48,7 @@ code\game\dna\genes\goon_powers.dm desc = "A spell used to make someone look like a blind fool, and also makes them a blind fool." feedback = "HY" school = "illusion" - spell_flags = SELECTABLE + can_select_target = TRUE charge_max = 600 invocation_type = SpI_SHOUT invocation = "Sty Di Kaly!" @@ -61,10 +61,10 @@ code\game\dna\genes\goon_powers.dm feedback = "SB" school = "transmutation" invocation = "Tid Caeh Yor!" - spell_flags = NOFACTION + faction_immune = TRUE invocation_type = SpI_SHOUT charge_max = 60 SECONDS - spell_flags = 0 + requires_wizard_garb = FALSE amt_dizziness = 0 amt_eye_blurry = 5 amt_stunned = 1 diff --git a/code/modules/spells/targeted/glimpse_of_eternity.dm b/mods/gamemodes/wizard/spells_archive/targeted/glimpse_of_eternity.dm similarity index 96% rename from code/modules/spells/targeted/glimpse_of_eternity.dm rename to mods/gamemodes/wizard/spells_archive/targeted/glimpse_of_eternity.dm index a4d783245ab9..fb747b57bbb4 100644 --- a/code/modules/spells/targeted/glimpse_of_eternity.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/glimpse_of_eternity.dm @@ -5,7 +5,7 @@ school = "illusion" invocation = "Ghe Tar Yet!" invocation_type = SpI_SHOUT - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE max_targets = 0 charge_max = 400 range = 3 diff --git a/code/modules/spells/targeted/projectile/dumbfire.dm b/mods/gamemodes/wizard/spells_archive/targeted/projectile/dumbfire.dm similarity index 100% rename from code/modules/spells/targeted/projectile/dumbfire.dm rename to mods/gamemodes/wizard/spells_archive/targeted/projectile/dumbfire.dm diff --git a/code/modules/spells/targeted/projectile/fireball.dm b/mods/gamemodes/wizard/spells_archive/targeted/projectile/fireball.dm similarity index 96% rename from code/modules/spells/targeted/projectile/fireball.dm rename to mods/gamemodes/wizard/spells_archive/targeted/projectile/fireball.dm index ef65dc885f73..9a60ba1ff773 100644 --- a/code/modules/spells/targeted/projectile/fireball.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/projectile/fireball.dm @@ -6,7 +6,7 @@ school = "conjuration" charge_max = 10 SECONDS - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Oni-Soma!" invocation_type = SpI_SHOUT range = 20 @@ -14,7 +14,7 @@ level_max = list(Sp_TOTAL = 5, Sp_SPEED = 0, Sp_POWER = 5) duration = 20 - proj_step_delay = 1 + projectile_step_delay = 1 amt_dam_brute = 20 amt_dam_fire = 25 diff --git a/code/modules/spells/targeted/projectile/magic_missile.dm b/mods/gamemodes/wizard/spells_archive/targeted/projectile/magic_missile.dm similarity index 95% rename from code/modules/spells/targeted/projectile/magic_missile.dm rename to mods/gamemodes/wizard/spells_archive/targeted/projectile/magic_missile.dm index 1d72399718a9..77d87141d7ff 100644 --- a/code/modules/spells/targeted/projectile/magic_missile.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/projectile/magic_missile.dm @@ -4,7 +4,6 @@ feedback = "MM" school = "conjuration" charge_max = 150 - spell_flags = NEEDSCLOTHES invocation = "Forti Gy-Ama!" invocation_type = SpI_SHOUT range = 7 @@ -15,7 +14,7 @@ proj_type = /obj/item/projectile/spell_projectile/seeking/magic_missile duration = 10 - proj_step_delay = 5 + projectile_step_delay = 5 hud_state = "wiz_mm" cast_sound = 'sound/magic/magic_missile.ogg' @@ -43,14 +42,10 @@ return "[src] does more damage now." - - //PROJECTILE - /obj/item/projectile/spell_projectile/seeking/magic_missile name = "magic missile" icon_state = "magicm" - - proj_trail = 1 + proj_trail = TRUE proj_trail_lifespan = 5 proj_trail_icon_state = "magicmd" diff --git a/code/modules/spells/targeted/projectile/passage.dm b/mods/gamemodes/wizard/spells_archive/targeted/projectile/passage.dm similarity index 95% rename from code/modules/spells/targeted/projectile/passage.dm rename to mods/gamemodes/wizard/spells_archive/targeted/projectile/passage.dm index b99e147bee22..3b826a366b7a 100644 --- a/code/modules/spells/targeted/projectile/passage.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/projectile/passage.dm @@ -13,10 +13,9 @@ level_max = list(Sp_TOTAL = 1, Sp_SPEED = 0, Sp_POWER = 1) - spell_flags = NEEDSCLOTHES duration = 15 - proj_step_delay = 1 + projectile_step_delay = 1 hud_state = "gen_project" cast_sound = 'sound/magic/lightning_bolt.ogg' diff --git a/code/modules/spells/targeted/projectile/stuncuff.dm b/mods/gamemodes/wizard/spells_archive/targeted/projectile/stuncuff.dm similarity index 95% rename from code/modules/spells/targeted/projectile/stuncuff.dm rename to mods/gamemodes/wizard/spells_archive/targeted/projectile/stuncuff.dm index 520463815888..23cfc941fd05 100644 --- a/code/modules/spells/targeted/projectile/stuncuff.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/projectile/stuncuff.dm @@ -7,7 +7,7 @@ charge_type = Sp_CHARGES charge_max = 6 charge_counter = 6 - spell_flags = 0 + requires_wizard_garb = FALSE invocation = "Fu'Reai Diakan!" invocation_type = SpI_SHOUT range = 20 @@ -15,7 +15,7 @@ level_max = list(Sp_TOTAL = 0, Sp_SPEED = 0, Sp_POWER = 0) duration = 20 - proj_step_delay = 1 + projectile_step_delay = 1 amt_stunned = 6 diff --git a/code/modules/spells/targeted/shapeshift.dm b/mods/gamemodes/wizard/spells_archive/targeted/shapeshift.dm similarity index 98% rename from code/modules/spells/targeted/shapeshift.dm rename to mods/gamemodes/wizard/spells_archive/targeted/shapeshift.dm index 24e92093ea13..98c97ef3b887 100644 --- a/code/modules/spells/targeted/shapeshift.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/shapeshift.dm @@ -109,7 +109,7 @@ share_damage = 0 invocation = "Yo'balada!" invocation_type = SpI_SHOUT - spell_flags = NEEDSCLOTHES | SELECTABLE + can_select_target = TRUE range = 3 duration = 150 //15 seconds. cooldown_min = 200 //20 seconds @@ -139,7 +139,7 @@ share_damage = 0 invocation = "Poli'crakata!" invocation_type = SpI_SHOUT - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE range = -1 duration = 150 charge_max = 600 @@ -155,7 +155,7 @@ invocation = "mutters something dark and twisted as their form begins to twist..." invocation_type = SpI_EMOTE - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE range = -1 duration = 150 charge_max = 1200 @@ -196,7 +196,7 @@ invocation_type = SpI_EMOTE invocation = "'s body dissipates into a pale mass of light, then reshapes!" range = -1 - spell_flags = INCLUDEUSER + requires_wizard_garb = FALSE duration = 0 charge_max = 2 MINUTES toggle = 1 diff --git a/code/modules/spells/targeted/shatter_mind.dm b/mods/gamemodes/wizard/spells_archive/targeted/shatter_mind.dm similarity index 96% rename from code/modules/spells/targeted/shatter_mind.dm rename to mods/gamemodes/wizard/spells_archive/targeted/shatter_mind.dm index f84d6765035d..be2ca86bdbae 100644 --- a/code/modules/spells/targeted/shatter_mind.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/shatter_mind.dm @@ -4,7 +4,7 @@ feedback = "SM" school = "illusion" charge_max = 300 - spell_flags = 0 + requires_wizard_garb = FALSE invocation_type = SpI_NONE range = 5 max_targets = 1 diff --git a/code/modules/spells/targeted/shift.dm b/mods/gamemodes/wizard/spells_archive/targeted/shift.dm similarity index 92% rename from code/modules/spells/targeted/shift.dm rename to mods/gamemodes/wizard/spells_archive/targeted/shift.dm index 2b53b60d2441..638b48447222 100644 --- a/code/modules/spells/targeted/shift.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/shift.dm @@ -3,7 +3,6 @@ desc = "This spell allows you to pass through walls" charge_max = 200 - spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK invocation_type = SpI_NONE range = -1 duration = 50 //in deciseconds diff --git a/code/modules/spells/targeted/subjugate.dm b/mods/gamemodes/wizard/spells_archive/targeted/subjugate.dm similarity index 97% rename from code/modules/spells/targeted/subjugate.dm rename to mods/gamemodes/wizard/spells_archive/targeted/subjugate.dm index 700dac35b36d..d50647c5f135 100644 --- a/code/modules/spells/targeted/subjugate.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/subjugate.dm @@ -4,7 +4,7 @@ feedback = "SJ" school = "illusion" charge_max = 500 - spell_flags = NOFACTION + faction_immune = TRUE invocation = "Dii Oda Baji." invocation_type = SpI_WHISPER diff --git a/code/modules/spells/targeted/swap.dm b/mods/gamemodes/wizard/spells_archive/targeted/swap.dm similarity index 96% rename from code/modules/spells/targeted/swap.dm rename to mods/gamemodes/wizard/spells_archive/targeted/swap.dm index 150bd9030772..6b892cb84872 100644 --- a/code/modules/spells/targeted/swap.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/swap.dm @@ -3,23 +3,16 @@ desc = "This spell swaps the positions of the wizard and a target. Causes brain damage." feedback = "SW" school = "conjuration" - charge_type = Sp_HOLDVAR holder_var_type = "brainloss" holder_var_amount = 10 - invocation = "Joyo!" invocation_type = SpI_WHISPER - level_max = list(Sp_TOTAL = 2, Sp_SPEED = 0, Sp_POWER = 2) - - spell_flags = Z2NOCAST range = 6 max_targets = 1 compatible_mobs = list(/mob/living) - hud_state = "wiz_swap" - cast_sound = 'sound/magic/mandswap.ogg' /spell/targeted/swap/cast(var/list/targets, mob/user) diff --git a/code/modules/spells/targeted/targeted.dm b/mods/gamemodes/wizard/spells_archive/targeted/targeted.dm similarity index 88% rename from code/modules/spells/targeted/targeted.dm rename to mods/gamemodes/wizard/spells_archive/targeted/targeted.dm index 46e6e242b26b..3a8382f61c6e 100644 --- a/code/modules/spells/targeted/targeted.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/targeted.dm @@ -1,8 +1,3 @@ -/* -Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range -Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm -*/ - /spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range @@ -49,7 +44,7 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp targets += target else if(max_targets == 1) //single target can be picked - if((range == 0 || range == -1) && spell_flags & INCLUDEUSER) + if((range == 0 || range == -1) && !user_is_immune) targets += user else var/list/possible_targets = list() @@ -60,11 +55,11 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp starting_targets = view_or_range(range, holder, selection_type) for(var/mob/living/M in starting_targets) - if(!(spell_flags & INCLUDEUSER) && M == user) + if(user_is_immune && M == user) continue - if((spell_flags & NOFACTION) && user.faction == M.faction) + if(faction_immune && user.faction == M.faction) continue - if((spell_flags & NONONFACTION) && user.faction != M.faction) + if(faction_only && user.faction != M.faction) continue if(compatible_mobs && compatible_mobs.len) if(!is_type_in_list(M, compatible_mobs)) continue @@ -73,7 +68,7 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp possible_targets += M if(possible_targets.len) - if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details + if(can_select_target) //if we are allowed to choose. see setup.dm for details var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets if(temp_target) targets += temp_target @@ -92,13 +87,13 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp starting_targets = view_or_range(range, holder, selection_type) for(var/mob/living/target in starting_targets) - if(!(spell_flags & INCLUDEUSER) && target == user) + if(user_is_immune && target == user) continue if(compatible_mobs && !is_type_in_list(target, compatible_mobs)) continue possible_targets += target - if(spell_flags & SELECTABLE) + if(can_select_target) for(var/i = 1; i<=max_targets, i++) if(!possible_targets.len) break @@ -121,7 +116,7 @@ Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are exp else targets += pick(possible_targets) - if(!(spell_flags & INCLUDEUSER) && (user in targets)) + if(user_is_immune && (user in targets)) targets -= user if(compatible_mobs && compatible_mobs.len) diff --git a/code/modules/spells/targeted/torment.dm b/mods/gamemodes/wizard/spells_archive/targeted/torment.dm similarity index 97% rename from code/modules/spells/targeted/torment.dm rename to mods/gamemodes/wizard/spells_archive/targeted/torment.dm index e98836699f30..5f4c11f57681 100644 --- a/code/modules/spells/targeted/torment.dm +++ b/mods/gamemodes/wizard/spells_archive/targeted/torment.dm @@ -4,7 +4,7 @@ feedback = "TM" school = "illusion" charge_max = 150 - spell_flags = NOFACTION + faction_immune = TRUE invocation = "Rai Di-Kaal!" invocation_type = SpI_SHOUT range = 5 diff --git a/code/modules/spells/artifacts/storage.dm b/mods/gamemodes/wizard/storage.dm similarity index 96% rename from code/modules/spells/artifacts/storage.dm rename to mods/gamemodes/wizard/storage.dm index 4d84cab7d3d5..cca444a36cb5 100644 --- a/code/modules/spells/artifacts/storage.dm +++ b/mods/gamemodes/wizard/storage.dm @@ -26,5 +26,5 @@ /obj/structure/closet/wizard/scrying/WillContain() return list( /obj/item/scrying, - /obj/item/contract/wizard/xray, + /obj/item/paper/contract/wizard/xray, ) \ No newline at end of file diff --git a/code/modules/clothing/suits/wiz_robe.dm b/mods/gamemodes/wizard/wizard_clothes.dm similarity index 98% rename from code/modules/clothing/suits/wiz_robe.dm rename to mods/gamemodes/wizard/wizard_clothes.dm index 5cdec0aadc8b..bcf25ee7828a 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/mods/gamemodes/wizard/wizard_clothes.dm @@ -53,7 +53,7 @@ ARMOR_BIO = ARMOR_BIO_MINOR, ARMOR_RAD = ARMOR_RAD_MINOR ) - allowed = list(/obj/item/teleportation_scroll) + allowed = list(/obj/item/paper/scroll) siemens_coefficient = 0.8 wizard_garb = 1 @@ -110,4 +110,3 @@ body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_ARMS|SLOT_LEGS armor = null siemens_coefficient = 1.0 - diff --git a/code/game/gamemodes/wizard/wizard_props.dm b/mods/gamemodes/wizard/wizard_props.dm similarity index 100% rename from code/game/gamemodes/wizard/wizard_props.dm rename to mods/gamemodes/wizard/wizard_props.dm diff --git a/mods/species/drakes/drake_abilities.dm b/mods/species/drakes/drake_abilities.dm index 455a261d3b9e..cc8aa530edd6 100644 --- a/mods/species/drakes/drake_abilities.dm +++ b/mods/species/drakes/drake_abilities.dm @@ -1,4 +1,5 @@ /datum/ability_handler/grafadreka + ability_category_tag = "drake_abilities" var/spit_projectile_type = /obj/item/projectile/drake_spit var/next_spit = 0 diff --git a/mods/species/vox/_vox.dme b/mods/species/vox/_vox.dme index 0819c87c80af..de8ec23ba518 100644 --- a/mods/species/vox/_vox.dme +++ b/mods/species/vox/_vox.dme @@ -4,8 +4,8 @@ #include "_vox.dm" #include "mobs_vox.dm" #include "organs_vox.dm" +#include "wizard.dm" #include "datum\accessories.dm" -#include "datum\antagonism.dm" #include "datum\cultures_vox.dm" #include "datum\descriptors_vox.dm" #include "datum\factions_vox.dm" diff --git a/mods/species/vox/datum/antagonism.dm b/mods/species/vox/datum/antagonism.dm deleted file mode 100644 index 4b8c182ee3a0..000000000000 --- a/mods/species/vox/datum/antagonism.dm +++ /dev/null @@ -1,4 +0,0 @@ -// Wizard -/obj/item/magic_rock/Initialize(ml, material_key) - LAZYSET(potentials, SPECIES_VOX, /spell/targeted/shapeshift/true_form) - . = ..() diff --git a/mods/species/vox/gear/gun.dm b/mods/species/vox/gear/gun.dm index c4f62db86c9c..a2e5706de5d8 100644 --- a/mods/species/vox/gear/gun.dm +++ b/mods/species/vox/gear/gun.dm @@ -78,27 +78,3 @@ /decl/material/liquid/sedatives, /decl/material/liquid/paralytics ) - -/spell/targeted/shapeshift/true_form - name = "True Form" - desc = "Pay respect to your heritage. Become what you once were." - - school = "racial" - spell_flags = INCLUDEUSER - invocation_type = SpI_EMOTE - range = -1 - invocation = "begins to grow!" - charge_max = 1200 //2 minutes - duration = 300 //30 seconds - - smoke_amt = 5 - smoke_spread = 1 - - possible_transformations = list(/mob/living/simple_animal/hostile/parrot/space/lesser) - - hud_state = "wiz_vox" - - cast_sound = 'sound/voice/shriek1.ogg' - revert_sound = 'sound/voice/shriek1.ogg' - - drop_items = 0 diff --git a/mods/species/vox/wizard.dm b/mods/species/vox/wizard.dm new file mode 100644 index 000000000000..5722c42451b1 --- /dev/null +++ b/mods/species/vox/wizard.dm @@ -0,0 +1,26 @@ +// Wizard +#ifdef GAMEMODE_PACK_WIZARD +/* +/obj/item/magic_rock/Initialize(ml, material_key) + LAZYSET(potentials, SPECIES_VOX, /spell/targeted/shapeshift/true_form) + . = ..() + +/spell/targeted/shapeshift/true_form + name = "True Form" + desc = "Pay respect to your heritage. Become what you once were." + school = "racial" + requires_wizard_garb = FALSE + invocation_type = SpI_EMOTE + range = -1 + invocation = "begins to grow!" + charge_max = 1200 //2 minutes + duration = 300 //30 seconds + smoke_amt = 5 + smoke_spread = 1 + possible_transformations = list(/mob/living/simple_animal/hostile/parrot/space/lesser) + hud_state = "wiz_vox" + cast_sound = 'sound/voice/shriek1.ogg' + revert_sound = 'sound/voice/shriek1.ogg' + drop_items = 0 +*/ +#endif \ No newline at end of file diff --git a/nebula.dme b/nebula.dme index c434541c3908..15149496a4b7 100644 --- a/nebula.dme +++ b/nebula.dme @@ -188,7 +188,6 @@ #include "code\_onclick\hud\robot.dm" #include "code\_onclick\hud\skybox.dm" #include "code\_onclick\hud\screen\_screen.dm" -#include "code\_onclick\hud\screen\screen_abilities.dm" #include "code\_onclick\hud\screen\screen_action_button.dm" #include "code\_onclick\hud\screen\screen_ai_button.dm" #include "code\_onclick\hud\screen\screen_attack_selector.dm" @@ -417,8 +416,12 @@ #include "code\datums\extensions\state_machine.dm" #include "code\datums\extensions\abilities\abilities.dm" #include "code\datums\extensions\abilities\abilities_mob.dm" +#include "code\datums\extensions\abilities\ability_admin.dm" +#include "code\datums\extensions\abilities\ability_button.dm" +#include "code\datums\extensions\abilities\ability_decl.dm" #include "code\datums\extensions\abilities\ability_handler.dm" #include "code\datums\extensions\abilities\ability_item.dm" +#include "code\datums\extensions\abilities\ability_projectile.dm" #include "code\datums\extensions\appearance\appearance.dm" #include "code\datums\extensions\appearance\base_icon_state.dm" #include "code\datums\extensions\appearance\cardborg.dm" @@ -592,7 +595,6 @@ #include "code\datums\outfits\pirates.dm" #include "code\datums\outfits\spec_op.dm" #include "code\datums\outfits\tournament.dm" -#include "code\datums\outfits\wizardry.dm" #include "code\datums\outfits\equipment\backpacks.dm" #include "code\datums\outfits\equipment\survival_box.dm" #include "code\datums\outfits\jobs\_defines.dm" @@ -751,7 +753,6 @@ #include "code\game\antagonist\outsider\actors.dm" #include "code\game\antagonist\outsider\ert.dm" #include "code\game\antagonist\outsider\mercenary.dm" -#include "code\game\antagonist\outsider\wizard.dm" #include "code\game\antagonist\station\provocateur.dm" #include "code\game\antagonist\station\thrall.dm" #include "code\game\area\area_abstract.dm" @@ -788,14 +789,6 @@ #include "code\game\gamemodes\objectives\objective_protect.dm" #include "code\game\gamemodes\objectives\objective_rev.dm" #include "code\game\gamemodes\objectives\objective_steal.dm" -#include "code\game\gamemodes\wizard\wizard.dm" -#include "code\game\gamemodes\wizard\wizard_props.dm" -#include "code\game\gamemodes\wizard\servant_items\caretaker.dm" -#include "code\game\gamemodes\wizard\servant_items\champion.dm" -#include "code\game\gamemodes\wizard\servant_items\familiar.dm" -#include "code\game\gamemodes\wizard\servant_items\fiend.dm" -#include "code\game\gamemodes\wizard\servant_items\infiltrator.dm" -#include "code\game\gamemodes\wizard\servant_items\overseer.dm" #include "code\game\jobs\_access_defs.dm" #include "code\game\jobs\access.dm" #include "code\game\jobs\access_datum.dm" @@ -1224,7 +1217,6 @@ #include "code\game\objects\items\weapons\RCD.dm" #include "code\game\objects\items\weapons\RPD.dm" #include "code\game\objects\items\weapons\RSF.dm" -#include "code\game\objects\items\weapons\scrolls.dm" #include "code\game\objects\items\weapons\secrets_disk.dm" #include "code\game\objects\items\weapons\shields.dm" #include "code\game\objects\items\weapons\soap.dm" @@ -2042,7 +2034,6 @@ #include "code\modules\clothing\suits\shouldercapes.dm" #include "code\modules\clothing\suits\toggles.dm" #include "code\modules\clothing\suits\utility.dm" -#include "code\modules\clothing\suits\wiz_robe.dm" #include "code\modules\clothing\suits\armor\_armor.dm" #include "code\modules\clothing\suits\armor\adminbus_and_memes.dm" #include "code\modules\clothing\suits\armor\bulletproof.dm" @@ -2930,7 +2921,6 @@ #include "code\modules\mob\living\simple_animal\aquatic\aquatic_fish.dm" #include "code\modules\mob\living\simple_animal\aquatic\aquatic_sharks.dm" #include "code\modules\mob\living\simple_animal\crow\crow.dm" -#include "code\modules\mob\living\simple_animal\familiars\familiars.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi.dm" #include "code\modules\mob\living\simple_animal\friendly\crab.dm" @@ -3672,84 +3662,6 @@ #include "code\modules\species\station\human_bodytypes.dm" #include "code\modules\species\station\monkey.dm" #include "code\modules\species\station\monkey_bodytypes.dm" -#include "code\modules\spells\artifacts.dm" -#include "code\modules\spells\construct_spells.dm" -#include "code\modules\spells\contracts.dm" -#include "code\modules\spells\no_clothes.dm" -#include "code\modules\spells\racial_wizard.dm" -#include "code\modules\spells\spell_code.dm" -#include "code\modules\spells\spell_projectile.dm" -#include "code\modules\spells\spellbook.dm" -#include "code\modules\spells\spells.dm" -#include "code\modules\spells\aoe_turf\aoe_turf.dm" -#include "code\modules\spells\aoe_turf\blink.dm" -#include "code\modules\spells\aoe_turf\charge.dm" -#include "code\modules\spells\aoe_turf\disable_tech.dm" -#include "code\modules\spells\aoe_turf\drain_blood.dm" -#include "code\modules\spells\aoe_turf\exchange_wounds.dm" -#include "code\modules\spells\aoe_turf\knock.dm" -#include "code\modules\spells\aoe_turf\smoke.dm" -#include "code\modules\spells\aoe_turf\summons.dm" -#include "code\modules\spells\aoe_turf\conjure\conjure.dm" -#include "code\modules\spells\aoe_turf\conjure\druidic_spells.dm" -#include "code\modules\spells\aoe_turf\conjure\faithful_hound.dm" -#include "code\modules\spells\aoe_turf\conjure\force_portal.dm" -#include "code\modules\spells\aoe_turf\conjure\forcewall.dm" -#include "code\modules\spells\aoe_turf\conjure\grove.dm" -#include "code\modules\spells\artifacts\spellbound_servants.dm" -#include "code\modules\spells\artifacts\storage.dm" -#include "code\modules\spells\general\acid_spray.dm" -#include "code\modules\spells\general\area_teleport.dm" -#include "code\modules\spells\general\camera_vision.dm" -#include "code\modules\spells\general\contract_spells.dm" -#include "code\modules\spells\general\create_air.dm" -#include "code\modules\spells\general\invisibility.dm" -#include "code\modules\spells\general\mark_recall.dm" -#include "code\modules\spells\general\portal_teleport.dm" -#include "code\modules\spells\general\radiant_aura.dm" -#include "code\modules\spells\general\return_master.dm" -#include "code\modules\spells\general\toggle_armor.dm" -#include "code\modules\spells\hand\blood_shards.dm" -#include "code\modules\spells\hand\burning_grip.dm" -#include "code\modules\spells\hand\entangle.dm" -#include "code\modules\spells\hand\hand.dm" -#include "code\modules\spells\hand\hand_item.dm" -#include "code\modules\spells\hand\slippery_surface.dm" -#include "code\modules\spells\hand\sunwrath.dm" -#include "code\modules\spells\spellbook\battlemage.dm" -#include "code\modules\spells\spellbook\cleric.dm" -#include "code\modules\spells\spellbook\druid.dm" -#include "code\modules\spells\spellbook\spatial.dm" -#include "code\modules\spells\spellbook\standard.dm" -#include "code\modules\spells\spellbook\student.dm" -#include "code\modules\spells\targeted\analyze.dm" -#include "code\modules\spells\targeted\blood_boil.dm" -#include "code\modules\spells\targeted\cleric_spells.dm" -#include "code\modules\spells\targeted\ethereal_jaunt.dm" -#include "code\modules\spells\targeted\exude_pleasantness.dm" -#include "code\modules\spells\targeted\genetic.dm" -#include "code\modules\spells\targeted\glimpse_of_eternity.dm" -#include "code\modules\spells\targeted\shapeshift.dm" -#include "code\modules\spells\targeted\shatter_mind.dm" -#include "code\modules\spells\targeted\shift.dm" -#include "code\modules\spells\targeted\subjugate.dm" -#include "code\modules\spells\targeted\swap.dm" -#include "code\modules\spells\targeted\targeted.dm" -#include "code\modules\spells\targeted\torment.dm" -#include "code\modules\spells\targeted\equip\burning_touch.dm" -#include "code\modules\spells\targeted\equip\dyrnwyn.dm" -#include "code\modules\spells\targeted\equip\equip.dm" -#include "code\modules\spells\targeted\equip\holy_relic.dm" -#include "code\modules\spells\targeted\equip\horsemask.dm" -#include "code\modules\spells\targeted\equip\party_hardy.dm" -#include "code\modules\spells\targeted\equip\seed.dm" -#include "code\modules\spells\targeted\equip\shield.dm" -#include "code\modules\spells\targeted\projectile\dumbfire.dm" -#include "code\modules\spells\targeted\projectile\fireball.dm" -#include "code\modules\spells\targeted\projectile\magic_missile.dm" -#include "code\modules\spells\targeted\projectile\passage.dm" -#include "code\modules\spells\targeted\projectile\projectile.dm" -#include "code\modules\spells\targeted\projectile\stuncuff.dm" #include "code\modules\sprite_accessories\_accessory.dm" #include "code\modules\sprite_accessories\_accessory_category.dm" #include "code\modules\sprite_accessories\cosmetics\_accessory_cosmetics.dm"