diff --git a/maplestation.dme b/maplestation.dme index dde1d478c94b..4ce291af1761 100644 --- a/maplestation.dme +++ b/maplestation.dme @@ -6298,6 +6298,7 @@ #include "maplestation_modules\code\__DEFINES\paperwork_defines.dm" #include "maplestation_modules\code\__DEFINES\signals.dm" #include "maplestation_modules\code\__DEFINES\spans.dm" +#include "maplestation_modules\code\__DEFINES\status_effects.dm" #include "maplestation_modules\code\__DEFINES\traits.dm" #include "maplestation_modules\code\__DEFINES\vv.dm" #include "maplestation_modules\code\__DEFINES\magic\attunements.dm" @@ -6309,9 +6310,11 @@ #include "maplestation_modules\code\__DEFINES\magic\spellbook\spellbook_categories.dm" #include "maplestation_modules\code\__DEFINES\magic\spellbook\spellbook_customization_interfaces.dm" #include "maplestation_modules\code\__DEFINES\magic\spellbook\spellbook_entry_types.dm" +#include "maplestation_modules\code\__DEFINES\research\techweb_nodes.dm" #include "maplestation_modules\code\__DEFINES\subsystems\_module_subsystem_defines.dm" #include "maplestation_modules\code\__DEFINES\subsystems\_module_subsystem_priorities.dm" #include "maplestation_modules\code\__HELPERS\magic_helpers.dm" +#include "maplestation_modules\code\__HELPERS\object_helpers.dm" #include "maplestation_modules\code\__HELPERS\text_helpers.dm" #include "maplestation_modules\code\controllers\configuration\entries\autotransfer.dm" #include "maplestation_modules\code\controllers\subsystem\autotransfer.dm" @@ -6356,6 +6359,7 @@ #include "maplestation_modules\code\datums\pain\pain_status_effects\pain_limp.dm" #include "maplestation_modules\code\datums\pain\pain_status_effects\sharp_pain.dm" #include "maplestation_modules\code\datums\pain\pain_status_effects\temp_pack.dm" +#include "maplestation_modules\code\datums\quirks\_quirk.dm" #include "maplestation_modules\code\datums\quirks\good.dm" #include "maplestation_modules\code\datums\quirks\negative.dm" #include "maplestation_modules\code\datums\quirks\neutral.dm" @@ -6401,6 +6405,7 @@ #include "maplestation_modules\code\game\objects\items\devices\scanners\autopsy_scanner.dm" #include "maplestation_modules\code\game\objects\items\devices\scanners\engineering.dm" #include "maplestation_modules\code\game\objects\items\devices\scanners\mana_lens.dm" +#include "maplestation_modules\code\game\objects\items\granters\meditation.dm" #include "maplestation_modules\code\game\objects\items\other_loadout_items\loadout_inhand_items.dm" #include "maplestation_modules\code\game\objects\items\storage\belt.dm" #include "maplestation_modules\code\game\objects\items\storage\boxes.dm" @@ -6515,18 +6520,10 @@ #include "maplestation_modules\code\modules\client\preferences\spellbook\spellbook_helpers.dm" #include "maplestation_modules\code\modules\client\preferences\spellbook\spellbook_item_customization_menu.dm" #include "maplestation_modules\code\modules\client\preferences\spellbook\spellbook_manager.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_entry.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_aeromancy.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_cryokinesis.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_electrokinesis.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_geomancy.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_healing.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_hydrokinesis.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_lumenomancy.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_misc.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_thaumaturgy.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_thermokinesis.dm" -#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_spell_entry.dm" +#include "maplestation_modules\code\modules\client\preferences\spellbook\items\_spellbook_entry.dm" +#include "maplestation_modules\code\modules\client\preferences\spellbook\items\_spellbook_spell_entry.dm" +#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_cantrips.dm" +#include "maplestation_modules\code\modules\client\preferences\spellbook\items\spellbook_item_manipulation.dm" #include "maplestation_modules\code\modules\client\verbs\looc.dm" #include "maplestation_modules\code\modules\clothing\digi_clothing.dm" #include "maplestation_modules\code\modules\clothing\accessories\accessories.dm" @@ -6628,15 +6625,19 @@ #include "maplestation_modules\code\modules\loadouts\loadout_ui\loadout_manager.dm" #include "maplestation_modules\code\modules\loadouts\loadout_ui\loadout_outfit_helpers.dm" #include "maplestation_modules\code\modules\magic\spell.dm" -#include "maplestation_modules\code\modules\magic\components\has_mana.dm" #include "maplestation_modules\code\modules\magic\components\uses_mana.dm" #include "maplestation_modules\code\modules\magic\mana\living_mana.dm" +#include "maplestation_modules\code\modules\magic\mana\magic_wands.dm" #include "maplestation_modules\code\modules\magic\mana\mana.dm" #include "maplestation_modules\code\modules\magic\mana\mana_chemicals.dm" #include "maplestation_modules\code\modules\magic\mana\mana_overload.dm" #include "maplestation_modules\code\modules\magic\mana\mana_pool.dm" #include "maplestation_modules\code\modules\magic\mana\attunements\attunement.dm" #include "maplestation_modules\code\modules\magic\mana\sources\mana_batteries.dm" +#include "maplestation_modules\code\modules\magic\mana\sources\altars\_magic_altars.dm" +#include "maplestation_modules\code\modules\magic\mana\sources\altars\meditation_mat.dm" +#include "maplestation_modules\code\modules\magic\mana\sources\altars\nature_shrine.dm" +#include "maplestation_modules\code\modules\magic\mana\sources\altars\stellar_oculory.dm" #include "maplestation_modules\code\modules\magic\mana\sources\leylines\leylines.dm" #include "maplestation_modules\code\modules\magic\mana\sources\leylines\leyline_intensities\leyline_attunements.dm" #include "maplestation_modules\code\modules\magic\mana\sources\leylines\leyline_intensities\leyline_intensities.dm" @@ -6644,6 +6645,7 @@ #include "maplestation_modules\code\modules\magic\story_spells\acid_touch.dm" #include "maplestation_modules\code\modules\magic\story_spells\airhike.dm" #include "maplestation_modules\code\modules\magic\story_spells\convect.dm" +#include "maplestation_modules\code\modules\magic\story_spells\eyes_of_night.dm" #include "maplestation_modules\code\modules\magic\story_spells\finger_flame.dm" #include "maplestation_modules\code\modules\magic\story_spells\flare.dm" #include "maplestation_modules\code\modules\magic\story_spells\freeze_person.dm" @@ -6651,9 +6653,11 @@ #include "maplestation_modules\code\modules\magic\story_spells\ice_blast.dm" #include "maplestation_modules\code\modules\magic\story_spells\ice_knife.dm" #include "maplestation_modules\code\modules\magic\story_spells\illusion.dm" +#include "maplestation_modules\code\modules\magic\story_spells\light_breaker.dm" #include "maplestation_modules\code\modules\magic\story_spells\mage_hand.dm" #include "maplestation_modules\code\modules\magic\story_spells\mana_charge.dm" #include "maplestation_modules\code\modules\magic\story_spells\mana_sense.dm" +#include "maplestation_modules\code\modules\magic\story_spells\mana_tap.dm" #include "maplestation_modules\code\modules\magic\story_spells\sense_equilibrium.dm" #include "maplestation_modules\code\modules\magic\story_spells\shock_touch.dm" #include "maplestation_modules\code\modules\magic\story_spells\soothe.dm" @@ -6750,12 +6754,14 @@ #include "maplestation_modules\code\modules\reagents\reagent_containers\cups\glassbottle.dm" #include "maplestation_modules\code\modules\recycling\holder.dm" #include "maplestation_modules\code\modules\research\designs\autolathe_designs.dm" +#include "maplestation_modules\code\modules\research\designs\magic_designs.dm" #include "maplestation_modules\code\modules\research\designs\mecha_designs.dm" #include "maplestation_modules\code\modules\research\designs\medical_designs.dm" #include "maplestation_modules\code\modules\research\designs\wiremod_designs.dm" #include "maplestation_modules\code\modules\research\machinery\experimentor.dm" #include "maplestation_modules\code\modules\research\techweb\_research.dm" #include "maplestation_modules\code\modules\research\techweb\all_nodes.dm" +#include "maplestation_modules\code\modules\research\techweb\magic_nodes.dm" #include "maplestation_modules\code\modules\research\xenobiology\cores.dm" #include "maplestation_modules\code\modules\research\xenobiology\potions.dm" #include "maplestation_modules\code\modules\robotic_limb_detach\robot_limb_detach_quirk.dm" diff --git a/maplestation_modules/code/__DEFINES/colors.dm b/maplestation_modules/code/__DEFINES/colors.dm index 0e9c2454dfbd..cf6656cfcdf8 100644 --- a/maplestation_modules/code/__DEFINES/colors.dm +++ b/maplestation_modules/code/__DEFINES/colors.dm @@ -9,3 +9,6 @@ // unused on the downstream so it was killed over a year ago, now back with a vengeance! #define RUNE_COLOR_EMP "#4D94FF" + +// colors used for volite and magic related stuff +#define CIRCUIT_COLOR_MAGIC "#a8ffe2" diff --git a/maplestation_modules/code/__DEFINES/magic/attunements.dm b/maplestation_modules/code/__DEFINES/magic/attunements.dm index 40fdb40cfbd3..bdec5c37894a 100644 --- a/maplestation_modules/code/__DEFINES/magic/attunements.dm +++ b/maplestation_modules/code/__DEFINES/magic/attunements.dm @@ -23,6 +23,8 @@ #define MAGIC_ELEMENT_LIFE /datum/attunement/life #define MAGIC_ELEMENT_EARTH /datum/attunement/earth #define MAGIC_ELEMENT_ELECTRIC /datum/attunement/electric +#define MAGIC_ELEMENT_DARK /datum/attunement/dark +#define MAGIC_ELEMENT_WATER /datum/attunement/water // When other elements are used, add them here // Alignments diff --git a/maplestation_modules/code/__DEFINES/magic/magic_bitflags.dm b/maplestation_modules/code/__DEFINES/magic/magic_bitflags.dm index 93c99c927756..65dd75831c51 100644 --- a/maplestation_modules/code/__DEFINES/magic/magic_bitflags.dm +++ b/maplestation_modules/code/__DEFINES/magic/magic_bitflags.dm @@ -9,3 +9,13 @@ #define MANA_POOL_CANNOT_TRANSFER (1<<5) #define MANA_POOL_TRANSFER_SKIP_ACTIVE (1<<6) + +/// used to dictate which of the default rules a mana transfer will abide by +// No rules, default. Doesn't do anything, actually. +#define MANA_TRANSFER_ANARCHY (1<<0) +// Stops or skips transfer when the transfer hits or passes the target pool's softcap +#define MANA_TRANSFER_SOFTCAP (1<<1) +// Same as the above, but with added behavior to prevent a transfer that would put someone above the softcap +#define MANA_TRANSFER_SOFTCAP_NO_PASS (1<<2) +// None of the above, just adds manual rules to transfer. +#define MANA_TRANSFER_MANUAL_RULES (1<<3) diff --git a/maplestation_modules/code/__DEFINES/magic/magic_defines.dm b/maplestation_modules/code/__DEFINES/magic/magic_defines.dm index 58869e1b1d22..184b74903897 100644 --- a/maplestation_modules/code/__DEFINES/magic/magic_defines.dm +++ b/maplestation_modules/code/__DEFINES/magic/magic_defines.dm @@ -7,7 +7,7 @@ #define MANA_CRYSTAL_BASE_RECHARGE 0.001 #define BASE_MANA_CAPACITY 1000 -#define MANA_CRYSTAL_BASE_MANA_CAPACITY (BASE_MANA_CAPACITY * 0.2) +#define MANA_CRYSTAL_BASE_MANA_CAPACITY (BASE_MANA_CAPACITY * 0.3) #define CARBON_BASE_MANA_CAPACITY (BASE_MANA_CAPACITY) #define LEYLINE_BASE_CAPACITY 600 //todo: standardize @@ -36,11 +36,12 @@ #define MANA_CRYSTAL_BASE_DECAY_DIVISOR (BASE_MANA_EXPONENTIAL_DIVISOR * 5) // in vols per second -#define BASE_MANA_DONATION_RATE (BASE_MANA_CAPACITY * 0.5) +#define BASE_MANA_DONATION_RATE (BASE_MANA_CAPACITY * 0.1) #define BASE_MANA_CRYSTAL_DONATION_RATE (BASE_MANA_DONATION_RATE * 0.1) #define BASE_LEYLINE_DONATION_RATE 30 #define MANA_BATTERY_MAX_TRANSFER_DISTANCE 3 +#define MAGIC_ALTAR_MAX_TRANSFER_DISTANCE 6 #define MAGIC_MATERIAL_NAME "Volite" #define MAGIC_UNIT_OF_MEASUREMENT "Vol" diff --git a/maplestation_modules/code/__DEFINES/magic/spellbook/spellbook_categories.dm b/maplestation_modules/code/__DEFINES/magic/spellbook/spellbook_categories.dm index 6fc1cc6d778f..27817d457a74 100644 --- a/maplestation_modules/code/__DEFINES/magic/spellbook/spellbook_categories.dm +++ b/maplestation_modules/code/__DEFINES/magic/spellbook/spellbook_categories.dm @@ -1,10 +1,2 @@ -#define SPELLBOOK_CATEGORY_THERMOKINESIS "Thermokinesis" -#define SPELLBOOK_CATEGORY_CRYOKINESIS "Cryokinesis" -#define SPELLBOOK_CATEGORY_HYDROKINESIS "Hydrokinesis" -#define SPELLBOOK_CATEGORY_THAUMATURGY "Thaumaturgy" -#define SPELLBOOK_CATEGORY_LUMENOMANCY "Lumenomancy" -#define SPELLBOOK_CATEGORY_AEROMANCY "Aeromancy" -#define SPELLBOOK_CATEGORY_GEOMANCY "Geomancy" -#define SPELLBOOK_CATEGORY_ELECTROKINESIS "Electrokinesis" -#define SPELLBOOK_CATEGORY_LIFE_MAGIC "Life Magic" -#define SPELLBOOK_CATEGORY_MISC "Misc. Spells" +#define SPELLBOOK_CATEGORY_CANTRIPS "Cantrips" +#define SPELLBOOK_CATEGORY_MANIPULATION "Manipulation" diff --git a/maplestation_modules/code/__DEFINES/research/techweb_nodes.dm b/maplestation_modules/code/__DEFINES/research/techweb_nodes.dm new file mode 100644 index 000000000000..2943ab85e600 --- /dev/null +++ b/maplestation_modules/code/__DEFINES/research/techweb_nodes.dm @@ -0,0 +1,3 @@ +#define TECHWEB_NODE_ARTIFICIAL_VOLITE "artificial_volite" +#define TECHWEB_NODE_MANA_BASE "mana_base_node" +#define TECHWEB_NODE_STELLAR_OCULORY "stellar_oculory_unlock" diff --git a/maplestation_modules/code/__DEFINES/status_effects.dm b/maplestation_modules/code/__DEFINES/status_effects.dm new file mode 100644 index 000000000000..0ee11c6d3305 --- /dev/null +++ b/maplestation_modules/code/__DEFINES/status_effects.dm @@ -0,0 +1,2 @@ +// place for IDs like its base code equivalent +#define MEDITATION_MAT_EFFECT "meditation_mat" diff --git a/maplestation_modules/code/__DEFINES/traits.dm b/maplestation_modules/code/__DEFINES/traits.dm index 32514177eae2..0f84670c0407 100644 --- a/maplestation_modules/code/__DEFINES/traits.dm +++ b/maplestation_modules/code/__DEFINES/traits.dm @@ -4,3 +4,7 @@ #define TRAIT_FEATHERED "feathers" /// Gives positive mood on drinking anything caffeinated, kinda generic so people can like coffee, tea, energy drinks, whatever. #define TRAIT_CAFFEINE_LOVER "caffeine_lover" +/// First of a potential series, this is the trait a mob with the psionic quirk will get. generally affects the costs/cooldowns of specific spells +#define TRAIT_FULL_PSIONIC "full_psionic" +/// Used to empower other mental effects, notably the meditate family +#define TRAIT_EMPOWERED_MEDITATION "empowered_meditation" diff --git a/maplestation_modules/code/__HELPERS/object_helpers.dm b/maplestation_modules/code/__HELPERS/object_helpers.dm new file mode 100644 index 000000000000..f23bab31d2c3 --- /dev/null +++ b/maplestation_modules/code/__HELPERS/object_helpers.dm @@ -0,0 +1,76 @@ +// code that checks for starlight on a movable atom. pillaged from starlight condensation, but not used there because we're a modular codebase, so lets pretend we did that +#define FULL_STARLIGHT 2 +#define PARTIAL_STARLIGHT 1 +#define NO_STARLIGHT 0 + +/atom/movable/proc/checktilestarlightdirectional(turf/turf_to_check, direction, starlight_max_range) + if(direction == UP) + turf_to_check = GET_TURF_ABOVE(turf_to_check) + if(!turf_to_check) + return NO_STARLIGHT + var/area/area_to_check = get_area(turf_to_check) + var/levels_of_glass = 0 // Since starlight condensation only works 2 tiles to the side anyways, it shouldn't work with like 100 z-levels of glass + while(levels_of_glass <= starlight_max_range) + // Outdoors covers lavaland and unroofed areas but with tiles under, + // while space covers normal space and those caused by explosions, + // if there is a floor tile when checking above, that means + // a roof exists so the outdoors should only work downwards + if(isspaceturf(turf_to_check) || (area_to_check.outdoors && direction == DOWN)) + if (levels_of_glass) + return PARTIAL_STARLIGHT // Glass gives a penalty. + return FULL_STARLIGHT // No glass = can activate fully. + + // Our turf is transparent, but it's NOT openspace - it's something like glass which reduces power + if(istransparentturf(turf_to_check) && !(istype(turf_to_check, /turf/open/openspace))) + levels_of_glass += 1 + + // Our turf is transparent OR openspace - we can check higher or lower z-levels + if(istransparentturf(turf_to_check) || istype(turf_to_check, /turf/open/openspace)) + // Check above or below us + if(direction == UP) + turf_to_check = GET_TURF_ABOVE(turf_to_check) + else + turf_to_check = GET_TURF_BELOW(turf_to_check) + + // If we found a turf above or below us, + // then we can rerun the loop on the newly found turf / area + // (Probably, with +1 to levels_of_glass) + if(turf_to_check) + area_to_check = get_area(turf_to_check) + continue + + // If we didn't find a turf above or below us - + // Checking below, we assume that space is below us (as we're standing on station) + // Checking above, we check that the area is "outdoors" before assuming if it is space or not. + else + if(direction == DOWN || (direction == UP && area_to_check.outdoors)) + if (levels_of_glass) + return PARTIAL_STARLIGHT + return FULL_STARLIGHT + + return NO_STARLIGHT // Hit a non-space, Non-transparent turf - no starlight for you + +/atom/movable/proc/checktilestarlight(turf/original_turf, satisfied_with_penalty, starlight_max_range) + var/current_starlight_level = checktilestarlightdirectional(original_turf, DOWN, starlight_max_range) + if(current_starlight_level == FULL_STARLIGHT) + return current_starlight_level + if(current_starlight_level && satisfied_with_penalty) // do not care if there is a +penalty or no + return current_starlight_level + var/starlight_level_from_above = checktilestarlightdirectional(original_turf, UP, starlight_max_range) + if(starlight_level_from_above > current_starlight_level) + return starlight_level_from_above + else + return current_starlight_level + +/atom/movable/proc/checkstarlight(check_range) + var/starlight_max_range = check_range + var/turf/turf_of_target = get_turf(src) + switch(checktilestarlight(turf_of_target, FALSE, starlight_max_range)) + if(PARTIAL_STARLIGHT) + return PARTIAL_STARLIGHT + if(FULL_STARLIGHT) + return FULL_STARLIGHT + for(var/turf/turf_to_check in view(src, starlight_max_range)) + if(checktilestarlight(turf_to_check, TRUE, starlight_max_range)) + return PARTIAL_STARLIGHT + return NO_STARLIGHT diff --git a/maplestation_modules/code/datums/components/crafting/recipes.dm b/maplestation_modules/code/datums/components/crafting/recipes.dm index bcb3c83df58d..aa1d38217a7e 100644 --- a/maplestation_modules/code/datums/components/crafting/recipes.dm +++ b/maplestation_modules/code/datums/components/crafting/recipes.dm @@ -34,7 +34,8 @@ result = /obj/item/clothing/neck/mana_star reqs = list( /obj/item/mana_battery/mana_crystal/cut = 1, - /obj/item/stack/sheet/mineral/gold = 1, // cheap for now + /obj/item/stack/sheet/cloth = 2, + /obj/item/stack/sheet/mineral/gold = 4, // not so cheap now ) tool_behaviors = list(TOOL_SCREWDRIVER) time = 5 SECONDS @@ -50,3 +51,30 @@ tool_behaviors = list(TOOL_CROWBAR) time = 5 SECONDS category = CAT_EQUIPMENT + +/datum/crafting_recipe/scrapwand + name = "Makeshift Wand" + result = /obj/item/magic_wand + reqs = list( + /obj/item/pen = 1, + /obj/item/stack/rods = 1, + /obj/item/stack/cable_coil = 3, + ) + +/datum/crafting_recipe/woodenwand + name = "Gold-Capped Wooden Wand" + result = /obj/item/magic_wand/wooden + reqs = list( + /obj/item/stack/sheet/mineral/wood = 2, + /obj/item/stack/sheet/mineral/gold = 1, + ) + +/datum/crafting_recipe/nature_shrine + name = "The Stump Which Watches" + time = 30 SECONDS + reqs = list( + /obj/item/stack/sheet/mineral/wood = 10, + /obj/item/mana_battery/mana_crystal/standard = 1, + ) + result = /obj/structure/magic_altar/nature + category = CAT_MISC diff --git a/maplestation_modules/code/datums/quirks/_quirk.dm b/maplestation_modules/code/datums/quirks/_quirk.dm new file mode 100644 index 000000000000..5d5ea579b489 --- /dev/null +++ b/maplestation_modules/code/datums/quirks/_quirk.dm @@ -0,0 +1,15 @@ +// somehow i stumbled accross the first case of needing to add a power via quirks. Funny +// also potentially overkill but honestly i fully anticipate this having more cases + +/datum/quirk/power_granting + var/datum/action/action_type + abstract_parent_type = /datum/quirk/power_granting + +/datum/quirk/power_granting/add_unique(client/client_source) + var/datum/action/new_action = new action_type(src) + // failsafe incase the power granted is somehow already owned by the quirk holder + var/datum/action/duplicate_check = locate(action_type) in quirk_holder.actions + if(duplicate_check) + return + new_action.Grant(quirk_holder) + diff --git a/maplestation_modules/code/datums/quirks/good.dm b/maplestation_modules/code/datums/quirks/good.dm index 1f21aac82ab8..3fb311384200 100644 --- a/maplestation_modules/code/datums/quirks/good.dm +++ b/maplestation_modules/code/datums/quirks/good.dm @@ -116,3 +116,17 @@ if(istype(human_holder)) human_holder.sprint_length_max /= 1.5 human_holder.sprint_length = human_holder.sprint_length_max + +/datum/quirk/power_granting/psionic + name = "Psionic" + desc = "You are able to manipulate and control the flow of mana with your mind." + icon = FA_ICON_HAND_SPOCK // because theres not really many better options, and this one is highly unlikely to be used elsewise + value = 2 + mob_trait = TRAIT_FULL_PSIONIC + gain_text = span_notice("You feel as if you can see a form of light you've never seen before.") + lose_text = span_danger("You feel as if a part of your being was ripped from you.") + medical_record_text = "Patient displays provable extrasensory perception." + action_type = /datum/action/cooldown/spell/touch/mana_tap + + + diff --git a/maplestation_modules/code/game/objects/items/devices/scanners/mana_lens.dm b/maplestation_modules/code/game/objects/items/devices/scanners/mana_lens.dm index 8c3b3d7a5ddc..b35126157b47 100644 --- a/maplestation_modules/code/game/objects/items/devices/scanners/mana_lens.dm +++ b/maplestation_modules/code/game/objects/items/devices/scanners/mana_lens.dm @@ -13,27 +13,9 @@ pickup_sound = 'maplestation_modules/sound/items/pickup/device.ogg' /obj/item/mana_lens/interact_with_atom(atom/movable/interacting_with, mob/living/user) - if (isturf(interacting_with)) - balloon_alert(user, "object has no mana pool!") // turfs should not ever have mana pools, doing this just so it doesn't error + if (isturf(interacting_with)) // turfs should not ever have mana pools, doing this so it doesn't runtime return if (!interacting_with.mana_pool) balloon_alert(user, "object has no mana pool!") return balloon_alert(user, "mana amount: [interacting_with.mana_pool.amount]") - -/datum/design/proto_mana_lens - name = "Prototype Mana Lens" - desc = "The first prototype of a device capable of reading the prescence of mana." - id = "mana_lens" - build_type = PROTOLATHE - materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT * 1.5, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2.5, /datum/material/gold = SMALL_MATERIAL_AMOUNT) - build_path = /obj/item/mana_lens - -/datum/techweb_node/mana_base - id = "mana_base" - starting_node = TRUE - display_name = "Early Magical Tech" - description = "The first bits of technology surronding magic." - design_ids = list( - "mana_lens", // more will be added to this - ) diff --git a/maplestation_modules/code/game/objects/items/granters/meditation.dm b/maplestation_modules/code/game/objects/items/granters/meditation.dm new file mode 100644 index 000000000000..8887a03065fc --- /dev/null +++ b/maplestation_modules/code/game/objects/items/granters/meditation.dm @@ -0,0 +1,47 @@ +/obj/item/book/granter/action/spell/meditation + name = "Nanotrasen Approved Meditation Guidebook" + granted_action = /datum/action/cooldown/spell/charged/meditate + action_name = "meditation" + icon = 'maplestation_modules/icons/obj/service/library.dmi' + pages_to_mastery = 5 + icon_state = "bookmeditation" + desc = "The backside is littered with phrases such as: 'Get all access to your mind!' '10 Quick Tips to make your willpower Robust!' and 'Copyright Nanotrasen Inspiration Machine 2565.'" + remarks = list( + "So I just hold still and just... do nothing?", + "There are several sections about the productive benefits about meditation, but very little about the actual quality of life benefits.", + "Theres an already out of date coupon for 'healing crystals' in the pages.", + "You know, despite the eight spoked wheel representing the Noble Eightfold Path of Buddhism printed on the front, there has been no actual reference to Buddhism or its principles.", + "At this rate I should probably find what works for me on my own.", + "Focus on my breathing, and clear my mind of thoughts. Oh wait, I need to keep reading.", + "It says that I should ideally find a comfortable or non-intrusive place to meditate in, and then recommends a list of various mats and seats to try. Or I could just make one with some cloth.", + ) + +/obj/item/book/granter/action/spell/meditation/recoil(mob/living/user) + . = ..() + to_chat(user, "That copy was dreadfully uninformative, unoriginal, and honestly boring.") + user.emote("yawn") + +/obj/item/book/granter/action/spell/lesser_splattercasting + name = "Nanotrasen Unapproved Meditation Guidebook" + granted_action = /datum/action/cooldown/spell/charged/meditate/lesser_splattercasting + action_name = "lesser splattercasting" + icon = 'maplestation_modules/icons/obj/service/library.dmi' + pages_to_mastery = 5 + icon_state = "booklessersplattercasting" + desc = "The backside is littered with phrases such as: 'How to make your mind valid!' 'Greytiding success in your future!' and 'Copyright Syndicate Inspiration Machine 2565.'" + remarks = list( + "Wait, isn't blood magic banned by the Syndicate too?", + "Can they stop with the joke of repeatedly appending the same information with 'evil?' I don't think the Syndicate personally thinks they're evil.", + "It says that a sharp object isn't entirely needed, just intent and mastery.", + "Ideally I should have some method of recovering the blood available, such as iron or a Bloody Mary.", + "A prepared site where I can focus more clearly without environmental disturbances is best, especially since people will be confused about what I'm doing.", + "Doing this after drinking a Nar'Sour would be pretty funny, actually.", + "Another section of dry motivational quotes. Great.", + "This is just a blank red page.", + "Wait, why was there a blank red page? Doesn't blood turn brownish when it dries on paper?", + ) + +/obj/item/book/granter/action/spell/lesser_splattercasting/recoil(mob/living/user) + . = ..() + to_chat(user, "That copy was also dreadfully uninformative, unoriginal, and honestly boring.") + user.emote("yawn") diff --git a/maplestation_modules/code/modules/cargo/goodies.dm b/maplestation_modules/code/modules/cargo/goodies.dm index d457245377c9..8448fae29617 100644 --- a/maplestation_modules/code/modules/cargo/goodies.dm +++ b/maplestation_modules/code/modules/cargo/goodies.dm @@ -24,7 +24,7 @@ /datum/supply_pack/goody/volite_single_pack name = "Volite Crystal Single Pack" - desc = "A singular volite crystal, ready for use." // planned to be cut with rework part 2, here for ease of access. + desc = "A singular volite crystal, ready for use." cost = PAYCHECK_CREW * 4 contains = list( /obj/item/mana_battery/mana_crystal/standard, @@ -32,7 +32,7 @@ /datum/supply_pack/goody/small_volite_pack name = "Small Volite Crystal Single Pack" - desc = "A miniaturized volite crystal." // planned to be cut with rework part 2 + desc = "A miniaturized volite crystal." cost = PAYCHECK_CREW * 2 contains = list( /obj/item/mana_battery/mana_crystal/small, @@ -45,3 +45,20 @@ contains = list( /obj/item/mana_battery/mana_crystal/lignite, ) + +/datum/supply_pack/goody/meditation_guide_single + name = "Meditation Guide Single Pack" + desc = "Provides a single copy of the Nanotrasen Approved Meditation Guidebook" + cost = PAYCHECK_CREW + contains = list( + /obj/item/book/granter/action/spell/meditation, + ) + +/datum/supply_pack/service/lesser_splattercasting_guide + name = "Lesser Splattercasting Guide Multi-Pack" + desc = "Provides a single copy of the Nanotrasen Unapproved Meditation Guidebook" + cost = PAYCHECK_CREW + contraband = TRUE + contains = list( + /obj/item/book/granter/action/spell/lesser_splattercasting, + ) diff --git a/maplestation_modules/code/modules/cargo/packs.dm b/maplestation_modules/code/modules/cargo/packs.dm index 536579fa10c1..8331d02c3d1c 100644 --- a/maplestation_modules/code/modules/cargo/packs.dm +++ b/maplestation_modules/code/modules/cargo/packs.dm @@ -348,15 +348,26 @@ icon_state = "opscrate" base_icon_state = "opscrate" -/datum/supply_pack/science/volitious_lignite_single_pack +/datum/supply_pack/science/volitious_lignite name = "Volitious Lignite Pack" desc = "A bundle containing 5 pieces of a natural source of volite, volitious lignite." cost = PAYCHECK_COMMAND * 2 contains = list( - /obj/item/mana_battery/mana_crystal/lignite, - /obj/item/mana_battery/mana_crystal/lignite, - /obj/item/mana_battery/mana_crystal/lignite, - /obj/item/mana_battery/mana_crystal/lignite, - /obj/item/mana_battery/mana_crystal/lignite, + /obj/item/mana_battery/mana_crystal/lignite = 5, + ) +/datum/supply_pack/service/meditation_guide + name = "Meditation Guide Multi-Pack" + desc = "Provides a multi-pack of the Nanotrasen Approved Meditation Guidebook" + cost = PAYCHECK_CREW * 4 // you get the fifth one for free! + contains = list( + /obj/item/book/granter/action/spell/meditation = 5, ) +/datum/supply_pack/service/lesser_splattercasting_guide + name = "Lesser Splattercasting Guide Multi-Pack" + desc = "Provides a multi-pack of the Nanotrasen Unapproved Meditation Guidebook" + cost = PAYCHECK_CREW * 4 // you also get the fifth one for free! + contraband = TRUE + contains = list( + /obj/item/book/granter/action/spell/lesser_splattercasting = 5, + ) diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_entry.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/_spellbook_entry.dm similarity index 100% rename from maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_entry.dm rename to maplestation_modules/code/modules/client/preferences/spellbook/items/_spellbook_entry.dm diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_spell_entry.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/_spellbook_spell_entry.dm similarity index 100% rename from maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_spell_entry.dm rename to maplestation_modules/code/modules/client/preferences/spellbook/items/_spellbook_spell_entry.dm diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_aeromancy.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_aeromancy.dm deleted file mode 100644 index 2f385cd68ee0..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_aeromancy.dm +++ /dev/null @@ -1,15 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_aeromancy_items, generate_spellbook_items(SPELLBOOK_CATEGORY_AEROMANCY)) - -/datum/spellbook_item/spell/airhike - name = "Air hike" - description = "Force wind beneath one's feet for a boost of movement where one is facing to jump over 2 tiles or to jump up a Zlevel and a tile ahead." - lore = "A somewhat intermediate spell not from its complexity, but applying proper force that won't have the user spin out of control. \ - A spell that is often grown out of due to its unwieldly application, at least for aeromancers, it is known as a party trick or crude application in the magic community, but it is useful in a pinch.\n\ - A common experiment for early aeromancers after wondering if applying force to oneself is possible. Those that learn through experimentation require training to consistantly control it, eventually moving onto finer control or dropping it after one too many crashes.\n\ - Most scholars might prefer students not to spend too much time blasting themselves wildly due to injuries slowing down or stopping proper study.\n\ - If given a proper clear area, some might argue its a safe way to explain distance, the idea of self as a target, and points of force which can be applied to spells that require finesse.\n\ - The name was given due to mages that appeared to walk on air itself, and like climbing a mountain side, if caution is not taken would be fatigued and fall from their height." - - category = SPELLBOOK_CATEGORY_AEROMANCY - - our_action_typepath = /datum/action/cooldown/spell/airhike diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cantrips.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cantrips.dm new file mode 100644 index 000000000000..56df1cd8495f --- /dev/null +++ b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cantrips.dm @@ -0,0 +1,232 @@ +GLOBAL_LIST_INIT(spellbook_cantrip_items, generate_spellbook_items(SPELLBOOK_CATEGORY_CANTRIPS)) + +/datum/spellbook_item/spell/acid_touch + name = "Acid Touch" + description = "Empowers your finger with a sticky acid, melting anything (or anyone) you touch." + lore = "A very volatile spell which has resulted in many a wizard accidentily melting off their own hands. \ + The acid generated is comparable to that of sulfuric acid.\nThis has led to the spell gaining wide use \ + in the criminal underworld, as it is a very effective way to make entrances or exits, dispose of evidence, \ + or create a distraction." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/touch/acid_touch + +/datum/spellbook_item/spell/airhike + name = "Air hike" + description = "Force wind beneath one's feet for a boost of movement where one is facing to jump over 2 tiles or to jump up a Zlevel and a tile ahead." + lore = "A somewhat intermediate spell not from its complexity, but applying proper force that won't have the user spin out of control. \ + A spell that is often grown out of due to its unwieldly application, at least for aeromancers, it is known as a party trick or crude application in the magic community, but it is useful in a pinch.\n\ + A common experiment for early aeromancers after wondering if applying force to oneself is possible. Those that learn through experimentation require training to consistantly control it, eventually moving onto finer control or dropping it after one too many crashes.\n\ + Most scholars might prefer students not to spend too much time blasting themselves wildly due to injuries slowing down or stopping proper study.\n\ + If given a proper clear area, some might argue its a safe way to explain distance, the idea of self as a target, and points of force which can be applied to spells that require finesse.\n\ + The name was given due to mages that appeared to walk on air itself, and like climbing a mountain side, if caution is not taken would be fatigued and fall from their height." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/airhike + +/datum/spellbook_item/spell/convect + name = "Convect" + description = "Manipulate the temperature of anything you can touch." + lore = "Often considered the precursor to all thermal magic, convect is one of the most important fundumentals of thermokinesis. \ + An extremely common spell, at least for thermomancers, it is well known among the wider magic community and rather typical.\n\ + Latently available to some, with that latency being why it's so common. Those that learn through the latency typically require training to consistantly control it.\n\ + This latency, linked with it's relative simplicity of casting, causes stories of previous thaumic blanks suddenly bursting into flames/\ + freezing themselves (often due to intense emotion, though triggers can be diverse) to be common among the magic community.\n\ + While exceptions exist, most users can only manipulate temperature in the direction of their thermokinetic school/predisposition (fire/ice or both)." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/convect + +/datum/spellbook_item/spell/finger_flame + name = "Finger Flame" + description = "With a snap, conjures a small flame at the tip of your fingers." + lore = "More of a party trick than a real spell, Finger Flame is known far and wide as the showiest trick in a thermomancer's book. \ + While not particularly useful, it's a fantastic way to get attention, intimidate someone, demonstrate your powers, or light a cigarette.\n\ + Its low potency makes Finger Flame hardly expensive or tiresome to cast and maintain, \ + making it a good way to practice your control over fire (or rather, to practice avoiding burning yourself)." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/touch/finger_flame/mana + +/datum/spellbook_item/spell/conjure_item/flare + name = "Flare" + description = "Conjure lumens into a glob to be held or thrown to light an area." + lore = "A simple application of lumenomancy, although quite complex enough for those new to magic to have the resulting globule sustain itself for so long. \n\ + An extremely common spell, used to gauge a child's power if they are able to even emit a moment of light, it is well known among the wider magic community.\n\ + Effort is taken to understand lumens and conjuring it out of mana. Those that study might prefer to focus on another school of magic, causing them to skip proper flare casting.\n\ + A relatively safe spell that dissipates by itself under normal circumstances, the nebulous construct leaves no residue so clean up isn't needed.\n\ + Considered to be a helpful spell, its short lived life is mostly used to help locate more permanent lighting options.\n\ + Those interested in the lumenomancy school/predisposition use this spell to further their understanding of luminosity and their ability to warp its directions." + + category = SPELLBOOK_CATEGORY_CANTRIPS + has_params = TRUE + + our_action_typepath = /datum/action/cooldown/spell/conjure_item/flare +// Customization to allow lesser flare +/datum/spellbook_item/spell/conjure_item/flare/generate_customization_params() + . = list() + .["lesser"] = new /datum/spellbook_customization_entry/boolean("lesser", "Lesser, weaker, somewhat cheaper version", "A cheap less lasting flare that fizzles out faster than normally, along with a considerable cooldown between casts, for those just learning magic or unable to grasp the full concept of luminosity.") + + +/datum/spellbook_item/spell/freeze_person + name = "Freeze Person" + description = "A well known and effective spell that encases your victim in a block of enchanted ice." + lore = "Iconic and infamous, Freeze Person has been used to great effect to solidify opponents, victims, and other targets of mages for centuries.\ + Though it is quite useful to stop someone in their tracks, the ice around them is resistant enough to protect them from incoming attacks.\ + Just be careful you know exactly what this spell is before casting it." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/freeze_person + +/datum/spellbook_item/spell/healing_touch + name = "Healing Touch" + description = "Lay your hands upon a target to heal their wounds." + lore = "Often called for the action taken while invoking, \"Lay on Hands\", this spell is a staple of any healer's arsenal. \ + Healing Touch is often used by chaplains and priests to aid the ailing and wounded they encounter in their duties. \ + However, that's not to say that its use is exclusively for the holy, as some medical practitioners \ + (especially those who find themselves on the frontier, where supplies are scarce) \ + have been known to utilize it occasionally to expedite their work - \ + though many still find physical tools or chemicals to be more reliable, and thus, it's use is not as common as one might think." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/touch/healing_touch + +/datum/spellbook_item/spell/ice_blast + name = "Ice Blast" + description = "An incantation to summon a condensed energy proejctile made out of ice. On contact with anything, it'll cover the nearby surfaces with a thin layer of ice." + lore = "The favored tool of Frost Mages, Clowns, and Frost Clowns, Ice Blasts are quick and easy ways of inconveniencing an area for slip and slides alike." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/projectile/ice_blast + +/datum/spellbook_item/spell/ice_knife + name = "Ice Knife" + description = "Conjures an ice knife at will in your hands." + lore = "A spell not commonly practiced by followers of Cryokinesis for the fact that the knife's durability is much less desirable than a real one, some still sought to learn it for the sake of self defense. \ + Even then, the knife does not hold well on it's own and will eventually dissapear as to preserve mana." + + category = SPELLBOOK_CATEGORY_CANTRIPS + has_params = TRUE + + our_action_typepath = /datum/action/cooldown/spell/conjure_item/ice_knife + +/datum/spellbook_item/spell/ice_knife/generate_customization_params() + . = list() + .["ice_blade"] = new /datum/spellbook_customization_entry/boolean("ice_blade", "Ice Armblade Variant", "Construct a blade around your arm, in exchange of harming you in the process.") + +/datum/spellbook_item/spell/illusion + name = "Illusion" + description = "Summon an illusionary clone of yourself at the target location. Looks identical to you, \ + but will not hold up to physical scrutiny. Has a long range, but lasts for only a short time, and is less effective in darker areas." + lore = "Sometimes known as \"Mirror Image\" by more advanced pracitioners, Illusion is a well practiced spell which bends the light \ + in such a way to create an almost perfect copy of the caster. Of course, being effectively an advanced trick of the light, \ + the illusion is not capable of much besides being used to confuse and distract or otherwise look pretty." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/illusion + +/datum/spellbook_item/spell/mage_hand + name = "Mage Hand" + description = "Magically manipulate an item from a distance. Gains a small refund for psychics." + lore = "The favorite of lazy magicians and tricksters alike, \ + Mage Hand is a simple spell that allows the caster to manipulate an item from a distance. \ + The spell is often used to retrieve items that are out of reach, play pranks on unsuspecting victims, \ + press some buttons on a distant keyboard, or to simply avoid having to get up from a comfortable chair.\n\ + Due to its simplicity, the spell is often taught to the young as a first spell - and due to this commonality, \ + it is very easily recognized by most." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/apply_mutations/mage_hand + +/datum/spellbook_item/spell/shock_touch + name = "Shocking Grasp" + description = "Empower your hand to deliver a shock to your target. \ + While the zap is not powerful enough to stun or kill, it will cause them to drop their held items - or restart a stopped heart." + lore = "A spell which has gained notoriety for its utility in the medical field. \ + Many wizards have found use in it, to jolt a patient out of a coma, or to restart a heart which has stopped beating. \ + However, it is also a favorite of clowns, who use it as a less-obvious joybuzzer.\n\n\ + Oddly, some Geneticists have found latent genes in their test subjects which allow them to use a similar ability, \ + without the need for learning any magic or using any mana. It has yet to be determined if humanoidkind has an innate, untapped ability \ + to manipulate electricity that this spell and the genetic ability are tapping into, or if it is simply a coincidence." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/touch/shock/magical + +/datum/spellbook_item/spell/soothe + name = "Soothe" + description = "Attempt to soothe a target, stopping them from feeling rage, fear, doubt, or similar emotions for a short time. \ + This effect can be resisted by sentient targets, but also works on more simple-minded creatures." + lore = "A spell that is often used by by clergical figures, psychologists, or nurses to calm down those who cannot be reasoned with \ + due to its ability to provide tranquility to those in a state of panic or fear. \n\ + Likewise, those who work with animals may use it to pacify a rampaging beast or settle a frightened pet.\n\ + However, its ability to be resisted by sentient creatures who are in extreme mental duress, especially anger, \ + means it is not always reliable - and thus - conventional methods are often preferred." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/soothe_target + +/datum/spellbook_item/spell/soft_and_wet + name = "Water Control" + description = "Wet a dry spot, or dry a wet spot, from a distance. \ + Wetting a requires a water source - you can draw upon condensation in your surroundings, or supply your own." + lore = "Quite a mundane spell, Water Control does just that - control water, in whatever form it may be in. Except ice. \ + It allows you to break apart water molecules into vapor or condense them into liquid. \ + Hydromancers are often seen using this spell to put out fires, much to the chagrin of thermomancers." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/soft_and_wet + +/datum/spellbook_item/spell/sending + name = "Sending" + description = "Its Telepathy, but with magic. Gets a full refund when used by a psychic." + lore = "Using your magical attunement (or other aptitudes) \ + you can send a message to another creature within a short radius. " + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/list_target/telepathy/mana + +/datum/spellbook_item/spell/sense_equilibrium + name = "Sense Equilibrium" + description = "Divert pathways in a person's brain from one area to another, enhancing one at the cost of the other." + lore = "Shape the power of the mind to your will." // I ain't writing all that. + + category = SPELLBOOK_CATEGORY_CANTRIPS + has_params = TRUE + + our_action_typepath = /datum/action/cooldown/spell/list_target/sense_equilibrium + +// Customization to allow greater sense equilibrium +/datum/spellbook_item/spell/sense_equilibrium/generate_customization_params() + . = list() + .["greater"] = new /datum/spellbook_customization_entry/boolean("greater", "Greater, stronger, shorter lasting version", "A more expensive and shorter lasting form of Sense Equilibrium which allows the user to pinpoint the exact effect they wish the spell to have.") + +/datum/spellbook_item/spell/eyes_of_night + name = "Eyes of Night" + description = "Attune your eyes to see better in the dark." + lore = "A staple of dark mages, and one of the most commonly used dark magic spells, this spell allows one to see within the dark without illuminating the surronding area." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/eyes_of_night + +/datum/spellbook_item/spell/light_breaker + name = "Light Breaker" + description = "Fire a fast projectile which shatters most lights." + lore = "Favorite of dark mages, nightmares, and wizards suffering from a migrane, this spell propels a near imperceptible lance which shatters a targeted light source." + + category = SPELLBOOK_CATEGORY_CANTRIPS + + our_action_typepath = /datum/action/cooldown/spell/pointed/projectile/light_breaker diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cryokinesis.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cryokinesis.dm deleted file mode 100644 index 65206ed42242..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_cryokinesis.dm +++ /dev/null @@ -1,37 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_cryokinesis_items, generate_spellbook_items(SPELLBOOK_CATEGORY_CRYOKINESIS)) - -/datum/spellbook_item/spell/ice_blast - name = "Ice Blast" - description = "An incantation to summon a condensed energy proejctile made out of ice. On contact with anything, it'll cover the nearby surfaces with a thin layer of ice." - lore = "The favored tool of Frost Mages, Clowns, and Frost Clowns, Ice Blasts are quick and easy ways of inconveniencing an area for slip and slides alike." - - category = SPELLBOOK_CATEGORY_CRYOKINESIS - - our_action_typepath = /datum/action/cooldown/spell/pointed/projectile/ice_blast - -/datum/spellbook_item/spell/ice_knife - name = "Ice Knife" - description = "Conjures an ice knife at will in your hands." - lore = "A spell not commonly practiced by followers of Cryokinesis for the fact that the knife's durability is much less desirable than a real one, some still sought to learn it for the sake of self defense. \ - Even then, the knife does not hold well on it's own and will eventually dissapear as to preserve mana." - - category = SPELLBOOK_CATEGORY_CRYOKINESIS - has_params = TRUE - - our_action_typepath = /datum/action/cooldown/spell/conjure_item/ice_knife - -/datum/spellbook_item/spell/ice_knife/generate_customization_params() - . = list() - .["ice_blade"] = new /datum/spellbook_customization_entry/boolean("ice_blade", "Ice Armblade Variant", "Construct a blade around your arm, in exchange of harming you in the process.") - - -/datum/spellbook_item/spell/freeze_person - name = "Freeze Person" - description = "A well known and effective spell that encases your victim in a block of enchanted ice." - lore = "Iconic and infamous, Freeze Person has been used to great effect to solidify opponents, victims, and other targets of mages for centuries.\ - Though it is quite useful to stop someone in their tracks, the ice around them is resistant enough to protect them from incoming attacks.\ - Just be careful you know exactly what this spell is before casting it." - - category = SPELLBOOK_CATEGORY_CRYOKINESIS - - our_action_typepath = /datum/action/cooldown/spell/pointed/freeze_person diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_electrokinesis.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_electrokinesis.dm deleted file mode 100644 index 0c1a4476d3da..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_electrokinesis.dm +++ /dev/null @@ -1,16 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_electrokinesis_items, generate_spellbook_items(SPELLBOOK_CATEGORY_ELECTROKINESIS)) - -/datum/spellbook_item/spell/shock_touch - name = "Shocking Grasp" - description = "Empower your hand to deliver a shock to your target. \ - While the zap is not powerful enough to stun or kill, it will cause them to drop their held items - or restart a stopped heart." - lore = "A spell which has gained notoriety for its utility in the medical field. \ - Many wizards have found use in it, to jolt a patient out of a coma, or to restart a heart which has stopped beating. \ - However, it is also a favorite of clowns, who use it as a less-obvious joybuzzer.\n\n\ - Oddly, some Geneticists have found latent genes in their test subjects which allow them to use a similar ability, \ - without the need for learning any magic or using any mana. It has yet to be determined if humanoidkind has an innate, untapped ability \ - to manipulate electricity that this spell and the genetic ability are tapping into, or if it is simply a coincidence." - - category = SPELLBOOK_CATEGORY_ELECTROKINESIS - - our_action_typepath = /datum/action/cooldown/spell/touch/shock/magical diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_geomancy.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_geomancy.dm deleted file mode 100644 index b9478acd43b3..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_geomancy.dm +++ /dev/null @@ -1,13 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_geomancy_items, generate_spellbook_items(SPELLBOOK_CATEGORY_GEOMANCY)) - -/datum/spellbook_item/spell/acid_touch - name = "Acid Touch" - description = "Empowers your finger with a sticky acid, melting anything (or anyone) you touch." - lore = "A very volatile spell which has resulted in many a wizard accidentily melting off their own hands. \ - The acid generated is comparable to that of sulfuric acid.\nThis has led to the spell gaining wide use \ - in the criminal underworld, as it is a very effective way to make entrances or exits, dispose of evidence, \ - or create a distraction." - - category = SPELLBOOK_CATEGORY_GEOMANCY - - our_action_typepath = /datum/action/cooldown/spell/touch/acid_touch diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_healing.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_healing.dm deleted file mode 100644 index 37c556d39118..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_healing.dm +++ /dev/null @@ -1,29 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_healing_items, generate_spellbook_items(SPELLBOOK_CATEGORY_LIFE_MAGIC)) - -/datum/spellbook_item/spell/healing_touch - name = "Healing Touch" - description = "Lay your hands upon a target to heal their wounds." - lore = "Often called for the action taken while invoking, \"Lay on Hands\", this spell is a staple of any healer's arsenal. \ - Healing Touch is often used by chaplains and priests to aid the ailing and wounded they encounter in their duties. \ - However, that's not to say that its use is exclusively for the holy, as some medical practitioners \ - (especially those who find themselves on the frontier, where supplies are scarce) \ - have been known to utilize it occasionally to expedite their work - \ - though many still find physical tools or chemicals to be more reliable, and thus, it's use is not as common as one might think." - - category = SPELLBOOK_CATEGORY_LIFE_MAGIC - - our_action_typepath = /datum/action/cooldown/spell/touch/healing_touch - -/datum/spellbook_item/spell/soothe - name = "Soothe" - description = "Attempt to soothe a target, stopping them from feeling rage, fear, doubt, or similar emotions for a short time. \ - This effect can be resisted by sentient targets, but also works on more simple-minded creatures." - lore = "A spell that is often used by by clergical figures, psychologists, or nurses to calm down those who cannot be reasoned with \ - due to its ability to provide tranquility to those in a state of panic or fear. \n\ - Likewise, those who work with animals may use it to pacify a rampaging beast or settle a frightened pet.\n\ - However, its ability to be resisted by sentient creatures who are in extreme mental duress, especially anger, \ - means it is not always reliable - and thus - conventional methods are often preferred." - - category = SPELLBOOK_CATEGORY_LIFE_MAGIC - - our_action_typepath = /datum/action/cooldown/spell/pointed/soothe_target diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_hydrokinesis.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_hydrokinesis.dm deleted file mode 100644 index 8eaaec1107dd..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_hydrokinesis.dm +++ /dev/null @@ -1,13 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_hydrokinesis_items, generate_spellbook_items(SPELLBOOK_CATEGORY_HYDROKINESIS)) - -/datum/spellbook_item/spell/soft_and_wet - name = "Water Control" - description = "Wet a dry spot, or dry a wet spot, from a distance. \ - Wetting a requires a water source - you can draw upon condensation in your surroundings, or supply your own." - lore = "Quite a mundane spell, Water Control does just that - control water, in whatever form it may be in. Except ice. \ - It allows you to break apart water molecules into vapor or condense them into liquid. \ - Hydromancers are often seen using this spell to put out fires, much to the chagrin of thermomancers." - - category = SPELLBOOK_CATEGORY_HYDROKINESIS - - our_action_typepath = /datum/action/cooldown/spell/pointed/soft_and_wet diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_lumenomancy.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_lumenomancy.dm deleted file mode 100644 index 3ce76b2f51c1..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_lumenomancy.dm +++ /dev/null @@ -1,32 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_lumenomancy_items, generate_spellbook_items(SPELLBOOK_CATEGORY_LUMENOMANCY)) - -/datum/spellbook_item/spell/conjure_item/flare - name = "Flare" - description = "Conjure lumens into a glob to be held or thrown to light an area." - lore = "A simple application of lumenomancy, although quite complex enough for those new to magic to have the resulting globule sustain itself for so long. \n\ - An extremely common spell, used to gauge a child's power if they are able to even emit a moment of light, it is well known among the wider magic community.\n\ - Effort is taken to understand lumens and conjuring it out of mana. Those that study might prefer to focus on another school of magic, causing them to skip proper flare casting.\n\ - A relatively safe spell that dissipates by itself under normal circumstances, the nebulous construct leaves no residue so clean up isn't needed.\n\ - Considered to be a helpful spell, its short lived life is mostly used to help locate more permanent lighting options.\n\ - Those interested in the lumenomancy school/predisposition use this spell to further their understanding of luminosity and their ability to warp its directions." - - category = SPELLBOOK_CATEGORY_LUMENOMANCY - has_params = TRUE - - our_action_typepath = /datum/action/cooldown/spell/conjure_item/flare -// Customization to allow lesser flare -/datum/spellbook_item/spell/conjure_item/flare/generate_customization_params() - . = list() - .["lesser"] = new /datum/spellbook_customization_entry/boolean("lesser", "Lesser, weaker, somewhat cheaper version", "A cheap less lasting flare that fizzles out faster than normally, along with a considerable cooldown between casts, for those just learning magic or unable to grasp the full concept of luminosity.") - -/datum/spellbook_item/spell/illusion - name = "Illusion" - description = "Summon an illusionary clone of yourself at the target location. Looks identical to you, \ - but will not hold up to physical scrutiny. Has a long range, but lasts for only a short time, and is less effective in darker areas." - lore = "Sometimes known as \"Mirror Image\" by more advanced pracitioners, Illusion is a well practiced spell which bends the light \ - in such a way to create an almost perfect copy of the caster. Of course, being effectively an advanced trick of the light, \ - the illusion is not capable of much besides being used to confuse and distract or otherwise look pretty." - - category = SPELLBOOK_CATEGORY_LUMENOMANCY - - our_action_typepath = /datum/action/cooldown/spell/pointed/illusion diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_manipulation.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_manipulation.dm new file mode 100644 index 000000000000..3eed8a3f005d --- /dev/null +++ b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_manipulation.dm @@ -0,0 +1,35 @@ +GLOBAL_LIST_INIT(spellbook_manipulation_items, generate_spellbook_items(SPELLBOOK_CATEGORY_MANIPULATION)) + +/datum/spellbook_item/spell/meditate + name = "Magic Meditation" + description = "Use mental focus to draw mana within yourself" + lore = "The most basic method of regenerating mana on your own. \ + Casting this invocation- while focusing- will allow you to draw mana from the ambient environment. \ + Do note that this will take a while between casts, and you should still find other methods of regeneration. \ + This can be empowered through various means, such as via a cloth mat." + + category = SPELLBOOK_CATEGORY_MANIPULATION + + our_action_typepath = /datum/action/cooldown/spell/charged/meditate + +/datum/spellbook_item/spell/mana_sense + name = "Mana Sense" + description = "Sense other mana pools present" + lore = "Using your magical attunement (or other aptitudes) \ + you can sense if a creature or object has a mana pool present; and what amount of mana the pool has. \ + Do note that this will require a reprieve between casts, and it will take a second to discern the amount of mana a pool has." + + category = SPELLBOOK_CATEGORY_MANIPULATION + + our_action_typepath = /datum/action/cooldown/spell/pointed/mana_sense + +/datum/spellbook_item/spell/lesser_splattercasting + name = "Lesser Splattercasting" + description = "Sacrifice some of your vital essence to regain mana" + lore = "A more consistent, but risky, form of regenerating magic. \ + This method mana charging is often seen used among many blood or sacrificial focused cults. \ + Often this spell is a sort of 'gateway drug' for many to begin practicing the dark arts of blood magic." + + category = SPELLBOOK_CATEGORY_MANIPULATION + + our_action_typepath = /datum/action/cooldown/spell/charged/meditate/lesser_splattercasting diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_misc.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_misc.dm deleted file mode 100644 index 0cfc6856f08b..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_misc.dm +++ /dev/null @@ -1,73 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_misc_items, generate_spellbook_items(SPELLBOOK_CATEGORY_MISC)) - -/datum/spellbook_item/spell/mage_hand - name = "Mage Hand" - description = "Magically manipulate an item from a distance." - lore = "The favorite of lazy magicians and tricksters alike, \ - Mage Hand is a simple spell that allows the caster to manipulate an item from a distance. \ - The spell is often used to retrieve items that are out of reach, play pranks on unsuspecting victims, \ - press some buttons on a distant keyboard, or to simply avoid having to get up from a comfortable chair.\n\ - Due to its simplicity, the spell is often taught to the young as a first spell - and due to this commonality, \ - it is very easily recognized by most." - - category = SPELLBOOK_CATEGORY_MISC - - our_action_typepath = /datum/action/cooldown/spell/apply_mutations/mage_hand - -/* /datum/spellbook_item/spell/leyline_charge - name = "Leyline Charge" - description = "Draw mana straight from the leylines themselves." - lore = "The most basic method of regenerating mana on your own. \ - Casting this invocation- while focusing- will allow you to regain mana from the leylines themselves. \ - Do not that this is a finnicky way of regaining mana, and you risk overloading if done improperly." - - category = SPELLBOOK_CATEGORY_MISC - - our_action_typepath = /datum/action/cooldown/spell/leyline_charge */ // disabled because leylines are weird - -/datum/spellbook_item/spell/meditate - name = "Magic Meditation" - description = "Use mental focus to draw mana within yourself" - lore = "The most basic method of regenerating mana on your own. \ - Casting this invocation- while focusing- will allow you to draw mana from the ambient environment. \ - Do note that this will take a while between casts, and you should still find other methods of regeneration." - - category = SPELLBOOK_CATEGORY_MISC - - our_action_typepath = /datum/action/cooldown/spell/meditate - -/datum/spellbook_item/spell/mana_sense - name = "Mana Sense" - description = "Sense other mana pools present" - lore = "Using your magical attunement (or other aptitudes) \ - you can sense if a creature or object has a mana pool present; and what amount of mana the pool has. \ - Do note that this will require a reprieve between casts, and it will take a second to discern the amount of mana a pool has." - - category = SPELLBOOK_CATEGORY_MISC - - our_action_typepath = /datum/action/cooldown/spell/pointed/mana_sense - -/datum/spellbook_item/spell/sending - name = "Sending" - description = "Its Telepathy, but with magic." - lore = "Using your magical attunement (or other aptitudes) \ - you can send a message to another creature within a short radius. " - - category = SPELLBOOK_CATEGORY_MISC - - our_action_typepath = /datum/action/cooldown/spell/list_target/telepathy/mana - -/datum/spellbook_item/spell/sense_equilibrium - name = "Sense Equilibrium" - description = "Divert pathways in a person's brain from one area to another, enhancing one at the cost of the other." - lore = "Shape the power of the mind to your will." // I ain't writing all that. - - category = SPELLBOOK_CATEGORY_MISC - has_params = TRUE - - our_action_typepath = /datum/action/cooldown/spell/list_target/sense_equilibrium - -// Customization to allow greater sense equilibrium -/datum/spellbook_item/spell/sense_equilibrium/generate_customization_params() - . = list() - .["greater"] = new /datum/spellbook_customization_entry/boolean("greater", "Greater, stronger, shorter lasting version", "A more expensive and shorter lasting form of Sense Equilibrium which allows the user to pinpoint the exact effect they wish the spell to have.") diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thaumaturgy.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thaumaturgy.dm deleted file mode 100644 index dfdef3ce1452..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thaumaturgy.dm +++ /dev/null @@ -1,14 +0,0 @@ -/*GLOBAL_LIST_INIT(spellbook_thaumaturgy_items, generate_spellbook_items(SPELLBOOK_CATEGORY_THAUMATURGY)) - -/datum/spellbook_item/spell/thaumatergic_sense - name = "Thaumatergic Sense" - description = "The ability to sense the amount of mana within mana pools." - lore = "" - - category = SPELLBOOK_CATEGORY_THAUMATURGY - - our_action_typepath = /datum/action/cooldown/spell/thaumatergic_sense - -/datum/spellbook_item/spell/thaumatergic_sense/apply_params(/datum/action/cooldown/spell/thaumatergic_sense/our_spell, ...) - -*/ diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thermokinesis.dm b/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thermokinesis.dm deleted file mode 100644 index 4b64aa2f25cb..000000000000 --- a/maplestation_modules/code/modules/client/preferences/spellbook/items/spellbook_item_thermokinesis.dm +++ /dev/null @@ -1,27 +0,0 @@ -GLOBAL_LIST_INIT(spellbook_thermokinesis_items, generate_spellbook_items(SPELLBOOK_CATEGORY_THERMOKINESIS)) - -/datum/spellbook_item/spell/convect - name = "Convect" - description = "Manipulate the temperature of anything you can touch." - lore = "Often considered the precursor to all thermal magic, convect is one of the most important fundumentals of thermokinesis. \ - An extremely common spell, at least for thermomancers, it is well known among the wider magic community and rather typical.\n\ - Latently available to some, with that latency being why it's so common. Those that learn through the latency typically require training to consistantly control it.\n\ - This latency, linked with it's relative simplicity of casting, causes stories of previous thaumic blanks suddenly bursting into flames/\ - freezing themselves (often due to intense emotion, though triggers can be diverse) to be common among the magic community.\n\ - While exceptions exist, most users can only manipulate temperature in the direction of their thermokinetic school/predisposition (fire/ice or both)." - - category = SPELLBOOK_CATEGORY_THERMOKINESIS - - our_action_typepath = /datum/action/cooldown/spell/pointed/convect - -/datum/spellbook_item/spell/finger_flame - name = "Finger Flame" - description = "With a snap, conjures a small flame at the tip of your fingers." - lore = "More of a party trick than a real spell, Finger Flame is known far and wide as the showiest trick in a thermomancer's book. \ - While not particularly useful, it's a fantastic way to get attention, intimidate someone, demonstrate your powers, or light a cigarette.\n\ - Its low potency makes Finger Flame hardly expensive or tiresome to cast and maintain, \ - making it a good way to practice your control over fire (or rather, to practice avoiding burning yourself)." - - category = SPELLBOOK_CATEGORY_THERMOKINESIS - - our_action_typepath = /datum/action/cooldown/spell/touch/finger_flame/mana diff --git a/maplestation_modules/code/modules/client/preferences/spellbook/spellbook_manager.dm b/maplestation_modules/code/modules/client/preferences/spellbook/spellbook_manager.dm index 74cd823bf7f5..168be6490355 100644 --- a/maplestation_modules/code/modules/client/preferences/spellbook/spellbook_manager.dm +++ b/maplestation_modules/code/modules/client/preferences/spellbook/spellbook_manager.dm @@ -141,15 +141,8 @@ // - Read the spellbook_item documentation to see what the entries do var/list/spellbook_tabs = list() - spellbook_tabs += list(list("name" = "Aeromancy", "title" = "Items related to manipulation of air and motion", "contents" = list_to_data(GLOB.spellbook_aeromancy_items))) - spellbook_tabs += list(list("name" = "Cryokinesis", "title" = "Items related to manipulation of ice", "contents" = list_to_data(GLOB.spellbook_cryokinesis_items))) - spellbook_tabs += list(list("name" = "Thermokinesis", "title" = "Items related to manipulation of temperature", "contents" = list_to_data(GLOB.spellbook_thermokinesis_items))) - spellbook_tabs += list(list("name" = "Hydrokinesis", "title" = "Items related to manipulation of water", "contents" = list_to_data(GLOB.spellbook_hydrokinesis_items))) - spellbook_tabs += list(list("name" = "Lumenomancy", "title" = "Items related to manipulation of light", "contents" = list_to_data(GLOB.spellbook_lumenomancy_items))) - spellbook_tabs += list(list("name" = "Geomancy", "title" = "Items related to manipulation of earth", "contents" = list_to_data(GLOB.spellbook_geomancy_items))) - spellbook_tabs += list(list("name" = "Electrokinesis", "title" = "Items related to manipulation of electricity", "contents" = list_to_data(GLOB.spellbook_electrokinesis_items))) - spellbook_tabs += list(list("name" = "Life Magic", "title" = "Items related to Life and Healing magic", "contents" = list_to_data(GLOB.spellbook_healing_items))) - spellbook_tabs += list(list("name" = "Misc. Spells", "title" = "Other miscellaneous spells, not associated with any attunements", "contents" = list_to_data(GLOB.spellbook_misc_items))) + spellbook_tabs += list(list("name" = "Cantrips", "title" = "Simple spells that require little preparation or components to cast", "contents" = list_to_data(GLOB.spellbook_cantrip_items))) + spellbook_tabs += list(list("name" = "Manipulation", "title" = "Capabilities that typically involve the manipulation of or other use of mana", "contents" = list_to_data(GLOB.spellbook_manipulation_items))) data["spellbook_tabs"] = spellbook_tabs diff --git a/maplestation_modules/code/modules/magic/components/has_mana.dm b/maplestation_modules/code/modules/magic/components/has_mana.dm deleted file mode 100644 index 3447259c0683..000000000000 --- a/maplestation_modules/code/modules/magic/components/has_mana.dm +++ /dev/null @@ -1,30 +0,0 @@ -/* Design notes: -* This component designates the parent datum as, through some mechanism, being a mana "source". -* -* When a request is put in to get available mana sources to a specific entity, datums with these componenets -* should be what is returned. -* HOW WE WILL GATHER DATUMS WITH THIS: As GetComponent is a crutch, this can likely be done through the use -* of firing a signal off the entity and having has_mana listen for it. (How? Have EVERY has_mana instance run a proc? -* THat can get out of hand fast. Need some way to only have things that might actually be available returned. Maybe -* we can, upon certain evenets occuring, such as an item being picked up, we can add it to a list associated with a -* specific entity?) -/** WHEN: It is likely the signal will be fired off by uses_mana components searching for available mana sources. When -* players desire to know their available mana, as well. -* -* has_mana instances should, at a minimum, have some way to generate mana. It doesn't necessarily have to store mana, just -* generate it. -* A possible use: Transmutation magic. A spell with the has_mana component. Upon a mana request being filed, a proc will be called that -* 1. will cast the spell, and 2. return a designated amount of mana. -* ANother use: Mana crystals. This one will have a variable holding mana, and apon mana request, will drain the designated amount from -* the crystal and provide it to the requestee. -*/ - -/// Designates the parent datum as, through some mechanism, being a mana "source". -/datum/component/has_mana - -// I'm not sure -/datum/component/has_mana/Initialize(...) - . = ..() - - RegisterSignal(???, putcomsighere, PROC_REF(mana_request_reaction)) -*/ diff --git a/maplestation_modules/code/modules/magic/mana/living_mana.dm b/maplestation_modules/code/modules/magic/mana/living_mana.dm index 5169b609d71b..7aa112dcfe99 100644 --- a/maplestation_modules/code/modules/magic/mana/living_mana.dm +++ b/maplestation_modules/code/modules/magic/mana/living_mana.dm @@ -12,6 +12,8 @@ exponential_decay_divisor = BASE_CARBON_MANA_EXPONENTIAL_DIVISOR + intrinsic_recharge_sources = MANA_ALL_LEYLINES + // carbons have softcap mults, this adds it to the pool. /mob/living/carbon/initialize_mana_pool() var/datum/mana_pool/mob/living/carbon/our_pool = ..() diff --git a/maplestation_modules/code/modules/magic/mana/magic_wands.dm b/maplestation_modules/code/modules/magic/mana/magic_wands.dm new file mode 100644 index 000000000000..7d7d162836bd --- /dev/null +++ b/maplestation_modules/code/modules/magic/mana/magic_wands.dm @@ -0,0 +1,77 @@ +// wands, basically magic wrenches, their main use is to initiate and manage player magic transfer +/obj/item/magic_wand + name = "Makeshift Wand" + desc = "A 'wand' made out of scraps and reused office materials. Unless this is a part of your religion or something, you should probably ditch this for something better when you can." + icon = 'maplestation_modules/icons/obj/magic/wands.dmi' + icon_state = "makeshift" + w_class = WEIGHT_CLASS_NORMAL // meant to be big and hard to store, additional reason to not use this + +/obj/item/magic_wand/interact_with_atom(atom/movable/interacting_with, mob/living/user, list/modifiers) + if(isturf(interacting_with)) + return + var/datum/mana_pool/target_mana_pool = interacting_with.mana_pool + var/datum/mana_pool/user_pool = user.mana_pool + + if(!target_mana_pool) + return // no response for this failing, as else it would proc on ~70% of things in the codebase + if(!user_pool) // potentially superfluous, but a failsafe + balloon_alert(user, "you have no mana pool!") + return + if(ismob(interacting_with)) // todo: add exceptions for if we want leeching from mob pools + balloon_alert(user, "can't take from this!") + return + + var/already_transferring = (user in target_mana_pool.transferring_to) + if (already_transferring) + balloon_alert(user, "canceled draw") + target_mana_pool.stop_transfer(user_pool) + return +/* if(!user.is_holding(src)) + balloon_alert(user, "firmly grasp it!") + return */ + + var/static/list/options = list("Yes", "No") + var/transfer_confirmation = (tgui_alert(user, "Do you want to transfer mana from [interacting_with]?", "Transfer Mana?", options) == "Yes") + if(!transfer_confirmation || QDELETED(user) || QDELETED(src) || !user.is_holding(src)) + return + balloon_alert(user, "transferring mana...") + target_mana_pool.start_transfer(user_pool) + +/* /obj/item/magic_wand/attack_self(mob/user, modifiers) + . = ..() + var/already_transferring = (user in mana_pool.transferring_to) + if (already_transferring) + balloon_alert(user, "canceled draw") + mana_pool.stop_transfer(user.mana_pool) + return */ + +/obj/item/magic_wand/techie + name = "Arcane Field Modulator" + desc = "An overengineered device produced and researched on board to manipulate and move residual mana within objects." + icon = 'maplestation_modules/icons/obj/magic/wands.dmi' + icon_state = "techie" + w_class = WEIGHT_CLASS_SMALL // Can actually fit in pockets + +/obj/item/magic_wand/wooden + name = "Gold-Capped Wooden Wand" + desc = "A traditional wood body and gold capped wand. Can still manipulate mana surprisingly well for its simplicity." + icon = 'maplestation_modules/icons/obj/magic/wands.dmi' + icon_state = "wooden" + w_class = WEIGHT_CLASS_SMALL + +// currently singleton, but decoupled for sanity's sake incase someone wants to do something similar +/obj/item/magic_wand/temporary + name = "Temporary Wand Basetype" + desc = "An ephemeral wand created by the power of Coderbus. Its life span is only brief, and its existence is fleeting. " + + item_flags = ABSTRACT|DROPDEL + +// given by the pseudo-spell gained from the psionic quirk +/obj/item/magic_wand/temporary/psionic + name = "Psychic Mana Tap" + desc = "An 'extension' of your mind, which allows you to freely draw mana from a capable source" + icon = 'icons/obj/weapons/hand.dmi' + lefthand_file = 'icons/mob/inhands/items/touchspell_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items/touchspell_righthand.dmi' + icon_state = "star" + inhand_icon_state = "hivehand" diff --git a/maplestation_modules/code/modules/magic/mana/mana_chemicals.dm b/maplestation_modules/code/modules/magic/mana/mana_chemicals.dm index dd82cf8c1cd9..e966c573656b 100644 --- a/maplestation_modules/code/modules/magic/mana/mana_chemicals.dm +++ b/maplestation_modules/code/modules/magic/mana/mana_chemicals.dm @@ -3,7 +3,7 @@ . = ..() //Its a magic drink. it regens mana, if mildly if(drinker?.mana_pool) - drinker.safe_adjust_personal_mana(1.5) + drinker.safe_adjust_personal_mana(1.5) // magic number here and not a var on the base chem to keep it modular, and because it'll only be seen here /datum/reagent/consumable/ethanol/pod_tesla/on_mob_life(mob/living/carbon/drinker, seconds_per_tick, times_fired) . = ..() @@ -75,10 +75,10 @@ color = "#4c1528" mana_adjust = -0.5 -/datum/reagent/volite_powder +/datum/reagent/medicine/quintessence/volite_powder name = "Volite Powder" description = "Pure Volite crystals which has been grinded up into a powder." taste_description = "lots of little sparks" ph = 8 color = "#22dcb5" - var/mana_adjust = 1 + mana_adjust = 1 diff --git a/maplestation_modules/code/modules/magic/mana/mana_pool.dm b/maplestation_modules/code/modules/magic/mana/mana_pool.dm index 485a8a200d47..bf3bf1eb9fb4 100644 --- a/maplestation_modules/code/modules/magic/mana/mana_pool.dm +++ b/maplestation_modules/code/modules/magic/mana/mana_pool.dm @@ -1,5 +1,9 @@ #define MANA_POOL_REPLACE_ALL_ATTUNEMENTS (1<<2) +/// the lowest decimal place we round to during dispersion +/// keep this to one decimal place unless you know what you're doing because anything more causes tomfoolery and really ugly decimals +#define MANA_DECIMAL_FLOOR 0.1 + /* DESIGN NOTES * This exists because mana will eventually have attunemenents and alignments that will incresae their efficiency in being used * on spells/by people with corresponding attunements/alignments, vice versa for conflicting. @@ -57,7 +61,15 @@ var/discharge_method = MANA_SEQUENTIAL /// The intrinsic sources of mana we will constantly try to draw from. Uses defines from magic_charge_bitflags.dm. - var/intrinsic_recharge_sources = MANA_ALL_LEYLINES + var/intrinsic_recharge_sources = NONE + + /// what ruleset do we abide by in regards to mana transferrence? flags in magic_bitflags.dm, and the default callback procs are later down this file + var/mana_transfer_ruleset = MANA_TRANSFER_ANARCHY + var/datum/callback/check_ruleset_callback // where we store what rule proc we use, don't touch this unless you're doing stuff that can't be done with other rulesets + + /// used by MANA_TRANSFER_MANUAL_RULES so this does nothing unless you're using that transfer ruleset. + /// and if so, what is that cap? + var/cap_transfer_limit /datum/mana_pool/New(atom/parent = null) . = ..() @@ -68,14 +80,19 @@ START_PROCESSING(SSmagic, src) + if(!check_ruleset_callback) + update_transfer_ruleset() + /datum/mana_pool/Destroy(force, ...) attunements = null attunements_to_generate = null - QDEL_LIST(transfer_rates) - QDEL_LIST(transfer_caps) - QDEL_LIST(transferring_to) - QDEL_LIST(transferring_from) // we already have a signal registered, so if we qdel we stop transfers + transfer_rates.Cut() + transfer_caps.Cut() + for (var/datum/mana_pool/pool_to_detach as anything in transferring_to) + stop_transfer(pool_to_detach, TRUE) + for (var/datum/mana_pool/pool_to_detach as anything in transferring_from) + pool_to_detach.stop_transfer(src, TRUE) STOP_PROCESSING(SSmagic, src) @@ -84,6 +101,7 @@ else parent.mana_pool = null parent = null + check_ruleset_callback = null return ..() @@ -103,7 +121,7 @@ //determines what the status displays, it'll be a generic/non-obvious value as a design choice if(amount) - if (amount < sc_very_low) + if (amount <= sc_very_low) general_amount_estimate = "VERY LOW" else if (amount > sc_very_low && amount < sc_low) general_amount_estimate = "LOW" @@ -125,13 +143,31 @@ return GLOB.default_attunements.Copy() +/datum/mana_pool/proc/update_transfer_ruleset() + switch (mana_transfer_ruleset) + if (MANA_TRANSFER_SOFTCAP) + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_softcap)) + if (MANA_TRANSFER_SOFTCAP_NO_PASS) + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_softcap_no_pass)) + if (MANA_TRANSFER_MANUAL_RULES) + if (!cap_transfer_limit) + stack_trace("Manual Transfer rules were set on [src] without a transfer limit defined!") // forgetting something? + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_anarchy))// failsafe, default to ruleless + else + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_manual_rules)) + if(MANA_TRANSFER_ANARCHY) + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_anarchy)) + else + stack_trace("Update Transfer Ruleset was called on [src] without a valid prefab ruleset defined!") + src.check_ruleset_callback = CALLBACK(src, PROC_REF(transfer_rule_anarchy)) // again, failsafe + // order of operations is as follows: // 1. we recharge // 2. we transfer mana // 3. we discharge excess mana /datum/mana_pool/process(seconds_per_tick) - - donation_budget_this_tick = (max_donation_rate_per_second * seconds_per_tick) //TODO: stop float imprecision + var/donation_this_tick = (max_donation_rate_per_second * seconds_per_tick) + donation_budget_this_tick = FLOOR(donation_this_tick, MANA_DECIMAL_FLOOR)//TODO: stop float imprecision but harder because i added a round? or not? if (ethereal_recharge_rate != 0) adjust_mana(ethereal_recharge_rate * seconds_per_tick, attunements_to_generate) @@ -141,6 +177,8 @@ for (var/datum/mana_pool/iterated_pool as anything in transferring_to) if (amount <= 0 || donation_budget_this_tick <= 0) break + if(!check_ruleset_callback?.Invoke(iterated_pool, (get_transfer_rate_for(iterated_pool) * seconds_per_tick))) + continue if (transferring_to[iterated_pool] & MANA_POOL_SKIP_NEXT_TRANSFER) transferring_to[iterated_pool] &= ~MANA_POOL_SKIP_NEXT_TRANSFER continue @@ -148,9 +186,14 @@ transfer_mana_to(iterated_pool, seconds_per_tick) if (MANA_DISPERSE_EVENLY) - var/mana_to_disperse = (SAFE_DIVIDE(donation_budget_this_tick, length(transferring_to))) + var/budgeted_mana_to_disperse = SAFE_DIVIDE(donation_budget_this_tick, length(transferring_to)) + var/mana_to_disperse = (FLOOR(budgeted_mana_to_disperse, MANA_DECIMAL_FLOOR)) for (var/datum/mana_pool/iterated_pool as anything in transferring_to) + if (amount <= 0 || donation_budget_this_tick <= 0) + break + if(!check_ruleset_callback?.Invoke(iterated_pool, mana_to_disperse)) + continue if (transferring_to[iterated_pool] & MANA_POOL_SKIP_NEXT_TRANSFER) transferring_to[iterated_pool] &= ~MANA_POOL_SKIP_NEXT_TRANSFER continue @@ -165,7 +208,7 @@ else if (parent.mana_overloaded) parent.stop_mana_overload() - if (amount > softcap) // why was this amount < softcap + if (amount > softcap) // exponential decay // exponentially decays amount when amount surpasses softcap, with [exponential_decay_divisor] being the (inverse) decay factor // can only decay however much amount we are over softcap @@ -230,10 +273,9 @@ if (target_pool in transferring_to) return MANA_POOL_ALREADY_TRANSFERRING + transferring_to += target_pool target_pool.incoming_transfer_start(src) - RegisterSignal(target_pool, COMSIG_QDELETING, PROC_REF(stop_transfer)) - if (force_process) transferring_to[target_pool] |= MANA_POOL_SKIP_NEXT_TRANSFER transfer_mana_to(target_pool) // you can potentially get all you need instantly @@ -241,7 +283,6 @@ return MANA_POOL_TRANSFER_START /datum/mana_pool/proc/stop_transfer(datum/mana_pool/target_pool, forced = FALSE) - SIGNAL_HANDLER if (!forced && !QDELETED(target_pool) && (transferring_to[target_pool] & MANA_POOL_SKIP_NEXT_TRANSFER)) return MANA_POOL_TRANSFER_SKIP_ACTIVE // nope! @@ -249,8 +290,6 @@ transferring_to -= target_pool target_pool.incoming_transfer_end(src) - UnregisterSignal(target_pool, COMSIG_QDELETING) - return MANA_POOL_TRANSFER_STOP /datum/mana_pool/proc/incoming_transfer_start(datum/mana_pool/donator) @@ -353,4 +392,35 @@ return (softcap / maximum_mana_capacity) * 100 +// default transfer rules, all call backs decided by what you put in mana_transfer_ruleset, set in check_ruleset_callback, called by most transfer things. +// these aren't used by default, and you can set you own for whatever pool you use: though feel to add those you use on multiple different subtypes here, because this is just a place where the most common ones are stored + +// FOR THE LOVE OF GOD READ THIS: MAKE SURE ALL OF THESE, AND ANY NEW CALLBACKS YOU MAKE, HAVE THE SAME ARGS, EVEN IF THEY'RE NOT USED. AND MAKE SURE ANY TIME YOU ADD A NEW INVOKE, IT SENDS THE SAME SET OF ARGS, IT WILL SAVE EVERYONE HEADACHES + +/datum/mana_pool/proc/transfer_rule_softcap(datum/mana_pool/pool, transferred_mana) + var/datum/mana_pool/target_pool = pool + var/softcap_check = (target_pool.amount >= target_pool.softcap) + if (softcap_check) + return FALSE + return TRUE + +/datum/mana_pool/proc/transfer_rule_softcap_no_pass(datum/mana_pool/pool, transferred_mana) + var/datum/mana_pool/target_pool = pool + var/softcap_check = (target_pool.amount >= target_pool.softcap) + var/softcap_pass_check = ((target_pool.amount + transferred_mana) > target_pool.softcap) + if ((softcap_check) || softcap_pass_check) + return FALSE + return TRUE + +/datum/mana_pool/proc/transfer_rule_manual_rules(datum/mana_pool/pool, transferred_mana) + var/datum/mana_pool/target_pool = pool + if (!cap_transfer_limit) // this should've been caught during init but i'm adding a second failsafe anyways + return FALSE // no runtime either, because this is processed each tick, it would be runtime hell + if (target_pool.amount >= cap_transfer_limit) + return FALSE + return TRUE + +/datum/mana_pool/proc/transfer_rule_anarchy(datum/mana_pool/pool, transferred_mana) + return TRUE // because no rules, no checks + #undef MANA_POOL_REPLACE_ALL_ATTUNEMENTS diff --git a/maplestation_modules/code/modules/magic/mana/sources/altars/_magic_altars.dm b/maplestation_modules/code/modules/magic/mana/sources/altars/_magic_altars.dm new file mode 100644 index 000000000000..4bc50320df6d --- /dev/null +++ b/maplestation_modules/code/modules/magic/mana/sources/altars/_magic_altars.dm @@ -0,0 +1,66 @@ +// Magic altars: the general term for structures that are used as part of a process for generating mana +// this is where the base types of non-special ones and relevant documentation will be stored + +/datum/mana_pool/magic_altar + maximum_mana_capacity = 500 + softcap = 500 + amount = 500 + max_donation_rate_per_second = 2 // pretty slow, but a solid source of mana + intrinsic_recharge_sources = NONE // it generate magic stoopid + discharge_destinations = NONE // yeah no i don't want the default to be dumping it into the leylines w/o being balanced around it + +/datum/mana_pool/magic_altar/can_transfer(datum/mana_pool/target_pool) + if (QDELETED(target_pool.parent)) + return FALSE + var/obj/structure/magic_altar/altar = parent + + if (altar.loc == target_pool.parent.loc) // yeah sure i copypasta from battery code, but if you manage to occupy the same tile as an altar you deserve a guranteed transfer + return TRUE + + if (get_dist(altar, target_pool.parent) > altar.max_allowed_transfer_distance) + return FALSE + return ..() + +/obj/structure/magic_altar/ + name = "magic altar basetype" + desc = "an honestly quite dull magic altar; actually better question, why is this visible in game? if you or an admin/coder aren't testing stuff this shouldn't be here" + icon = 'maplestation_modules/icons/obj/magic/altars.dmi' + icon_state = "goner" + density = TRUE + has_initial_mana_pool = TRUE + var/max_allowed_transfer_distance = MAGIC_ALTAR_MAX_TRANSFER_DISTANCE + +/obj/structure/magic_altar/get_initial_mana_pool_type() + return /datum/mana_pool/magic_altar + +/obj/structure/magic_altar/wrench_act(mob/living/user, obj/item/tool) + . = ..() + default_unfasten_wrench(user, tool, 5 SECONDS) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/power/magic_contraption // used for magitech stuff that needs to process. + name = "magic contraption basetype" + desc = "an honestly quite dull magic contraption; actually better question, why is this visible in game? if you or an admin/coder aren't testing stuff this shouldn't be here" + icon = 'maplestation_modules/icons/obj/magic/altars.dmi' + icon_state = "goner_machine" + + density = TRUE + use_power = NO_POWER_USE + anchored = FALSE + + has_initial_mana_pool = TRUE + var/max_allowed_transfer_distance = MAGIC_ALTAR_MAX_TRANSFER_DISTANCE + +/obj/machinery/power/magic_contraption/get_initial_mana_pool_type() + return /datum/mana_pool/magic_altar + +/obj/machinery/power/magic_contraption/wrench_act(mob/living/user, obj/item/tool) + . = ..() + if(default_unfasten_wrench(user, tool, 4 SECONDS)) + return ITEM_INTERACT_SUCCESS + +/obj/machinery/power/magic_contraption/crowbar_act(mob/living/user, obj/item/tool) + . = NONE + if(default_deconstruction_crowbar(tool)) + return ITEM_INTERACT_SUCCESS + diff --git a/maplestation_modules/code/modules/magic/mana/sources/altars/meditation_mat.dm b/maplestation_modules/code/modules/magic/mana/sources/altars/meditation_mat.dm new file mode 100644 index 000000000000..e544fb7d6a4a --- /dev/null +++ b/maplestation_modules/code/modules/magic/mana/sources/altars/meditation_mat.dm @@ -0,0 +1,108 @@ +/obj/machinery/meditation_mat + name = "Meditation Mat" + desc = "A simple purple cloth mat made to allow one to rest and meditate on the floor comfortably." + + icon = 'maplestation_modules/icons/obj/magic/altars.dmi' + icon_state = "meditation_mat" + + can_buckle = TRUE + buckle_lying = 0 + resistance_flags = NONE + use_power = NO_POWER_USE + + var/foldable_type = /obj/item/meditation_mat + +/obj/machinery/meditation_mat/examine(mob/user) + . = ..() + if(!isnull(foldable_type)) + . += span_notice("You can fold it up with a Right-click.") + if(!has_buckled_mobs() && can_buckle) + . += span_notice("While standing on [src], drag and drop your sprite onto [src] to buckle to it.") + +/obj/machinery/meditation_mat/attack_hand_secondary(mob/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(!ishuman(user) || !user.can_perform_action(src)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(has_buckled_mobs()) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + + user.visible_message(span_notice("[user] rolls up [src]."), span_notice("You roll up [src].")) + var/obj/machinery/meditation_mat/folded_mat = new foldable_type(get_turf(src)) + user.put_in_hands(folded_mat) + qdel(src) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + +/obj/machinery/meditation_mat/proc/apply_effects(mob/living/target) + if(target != occupant) + return + target.apply_status_effect(/datum/status_effect/meditation_mat, MEDITATION_MAT_EFFECT) + +/obj/machinery/meditation_mat/proc/remove_effects(mob/living/target) + target.remove_status_effect(/datum/status_effect/meditation_mat, MEDITATION_MAT_EFFECT) + +/obj/machinery/meditation_mat/post_buckle_mob(mob/living/meditator) + if(!can_be_occupant(meditator)) + return + set_occupant(meditator) + apply_effects(meditator) + +/obj/machinery/meditation_mat/post_unbuckle_mob(mob/living/meditator) + remove_effects(meditator) + if(meditator == occupant) + set_occupant(null) + +// status effect +/datum/status_effect/meditation_mat + id = "meditation_mat_status" + duration = -1 + alert_type = /atom/movable/screen/alert/status_effect/meditation_mat + +/datum/status_effect/meditation_mat/on_apply() + . = ..() + if(!.) + return + owner.add_traits(list( + TRAIT_EMPOWERED_MEDITATION, + ), TRAIT_STATUS_EFFECT(id)) + +/datum/status_effect/meditation_mat/on_remove() + owner.remove_traits(list( + TRAIT_EMPOWERED_MEDITATION, + ), TRAIT_STATUS_EFFECT(id)) + return . = ..() + +/atom/movable/screen/alert/status_effect/meditation_mat + name = "Focused Meditation" + desc = "You are kneeling? resting? napping? On the mat. Your ability to focus on specific mental capabilities is improved." + icon_state = "woozy" + +// folded item +/obj/item/meditation_mat + name = "Folded Meditation Mat" + desc = "A mat for meditation, rolled and folded up for easy transport." + icon = 'maplestation_modules/icons/obj/magic/objects.dmi' + icon_state = "mat_folded" + inhand_icon_state = "mat_folded" + lefthand_file = 'maplestation_modules/icons/mob/inhands/equipment_lefthand.dmi' + righthand_file = 'maplestation_modules/icons/mob/inhands/equipment_righthand.dmi' + w_class = WEIGHT_CLASS_NORMAL + +/obj/item/meditation_mat/attack_self(mob/user) + deploy_mat(user, user.loc) + +/obj/item/meditation_mat/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isopenturf(interacting_with)) + deploy_mat(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/meditation_mat/proc/deploy_mat(mob/user, atom/location) + var/obj/machinery/meditation_mat/deployed = new /obj/machinery/meditation_mat(location) + deployed.add_fingerprint(user) + qdel(src) + +/obj/item/stack/sheet/cloth/get_main_recipes() + . = ..() + . += list(new /datum/stack_recipe("meditation mat", /obj/item/meditation_mat, 8)) diff --git a/maplestation_modules/code/modules/magic/mana/sources/altars/nature_shrine.dm b/maplestation_modules/code/modules/magic/mana/sources/altars/nature_shrine.dm new file mode 100644 index 000000000000..c6e2bedae349 --- /dev/null +++ b/maplestation_modules/code/modules/magic/mana/sources/altars/nature_shrine.dm @@ -0,0 +1,87 @@ +// nature shrine, consumes flowers to generate mana. +// this lists of flowers based on the amount of mana generated + +/datum/mana_pool/magic_altar/nature + maximum_mana_capacity = 750 + softcap = 500 + amount = 0 + max_donation_rate_per_second = 4 + +/obj/structure/magic_altar/nature + name = "The Stump Which Watches" + desc = "A peculiar stump. It feels like the hole in the center is looking at you. It appears you can cover its gaze with some flowers, though." + icon_state = "magicstump_base" + var/drop_amount = 3 + + var/static/list/nature_shrine_mana_low = typecacheof(list( + /obj/item/food/grown/poppy, + /obj/item/food/grown/sunflower + )) + var/nature_shrine_mana_low_count = 10 + var/static/list/nature_shrine_mana_med = typecacheof(list( + /obj/item/food/grown/poppy/lily, + /obj/item/food/grown/poppy/geranium, + /obj/item/food/grown/moonflower, + )) + var/nature_shrine_mana_med_count = 20 + var/static/list/nature_shrine_mana_high = typecacheof(list( + /obj/item/food/grown/poppy/geranium/fraxinella, + /obj/item/food/grown/trumpet, + /obj/item/grown/novaflower, + )) + var/nature_shrine_mana_high_count = 30 + +/obj/structure/magic_altar/nature/get_initial_mana_pool_type() + return /datum/mana_pool/magic_altar/nature + +/obj/structure/magic_altar/nature/Initialize(mapload) + . = ..() + + var/static/list/tool_behaviors + if(!tool_behaviors) + tool_behaviors = string_assoc_nested_list(list( + TOOL_CROWBAR = list( + SCREENTIP_CONTEXT_RMB = "Deconstruct", + ), + + TOOL_WRENCH = list( + SCREENTIP_CONTEXT_RMB = "Anchor/Unanchor", + ), + )) + AddElement(/datum/element/contextual_screentip_tools, tool_behaviors) + +/obj/structure/magic_altar/nature/item_interaction(mob/living/user, obj/item/sacrifice, list/modifiers) + ..() + if (is_type_in_typecache(sacrifice, nature_shrine_mana_high)) // todo: add feedback to the player for this + accept_sacrifice(sacrifice, nature_shrine_mana_high) + return + if (is_type_in_typecache(sacrifice, nature_shrine_mana_med)) + accept_sacrifice(sacrifice, nature_shrine_mana_med) + return + if (is_type_in_typecache(sacrifice, nature_shrine_mana_low)) + accept_sacrifice(sacrifice, nature_shrine_mana_low) + return + +/obj/structure/magic_altar/nature/proc/accept_sacrifice(obj/item/sacrifice, mana_value) + QDEL_NULL(sacrifice) + mana_pool.amount += mana_value + +/obj/structure/magic_altar/nature/crowbar_act(mob/living/user, obj/item/tool) + balloon_alert(user, "deconstructing stump...") + if(!tool.use_tool(src, user, 5 SECONDS, volume=50)) + return + balloon_alert(user, "stump deconstructed") + tool.play_tool_sound(src) + new /obj/item/stack/sheet/mineral/wood(get_turf(src), drop_amount) + new /obj/item/mana_battery/mana_crystal/standard(get_turf(src), 1) + qdel(src) + return ITEM_INTERACT_SUCCESS + +/obj/structure/magic_altar/nature/wrench_act(mob/living/user, obj/item/tool) + . = ..() + switch(default_unfasten_wrench(user, tool, 4 SECONDS)) + if(SUCCESSFUL_UNFASTEN) + return ITEM_INTERACT_SUCCESS + if(FAILED_UNFASTEN) + return ITEM_INTERACT_BLOCKING + return . diff --git a/maplestation_modules/code/modules/magic/mana/sources/altars/stellar_oculory.dm b/maplestation_modules/code/modules/magic/mana/sources/altars/stellar_oculory.dm new file mode 100644 index 000000000000..9abe91844614 --- /dev/null +++ b/maplestation_modules/code/modules/magic/mana/sources/altars/stellar_oculory.dm @@ -0,0 +1,104 @@ +// Stellar oculory. A more technomagic themed altar, which generates mana from exposure to starlight, based heavily off of starlight regeneration. +#define COMSIG_STELLAR_OCULORY_PULSE_MANA "oculory_pulse_mana" +#define STELLAR_OCULORY_BASE_MANA 225 + +/datum/mana_pool/magic_altar/stellar + maximum_mana_capacity = STELLAR_OCULORY_BASE_MANA + softcap = STELLAR_OCULORY_BASE_MANA // identical to max cap, as it its a passive generator, and not an active one. + amount = 0 + max_donation_rate_per_second = 4 + +/obj/machinery/power/magic_contraption/stellar + name = "stellar oculory" + desc = "an advanced machine which focuses starlight into mana for use." + icon_state = "stellar" + base_icon_state = "stellar" + circuit = /obj/item/circuitboard/machine/stellar_oculory + var/active = TRUE + + var/pulse_delay = 20 SECONDS + var/last_pulse = 0 + + var/high_pulse_value = 25 // full starlight + var/medium_pulse_value = 15 // partial starlight + var/low_pulse_value = 5 // basically a pity value + + var/last_pulse_value = NO_STARLIGHT // how strong was our last starlight pulse? this is used for checks for stuff like examines + var/starlight_check_range = 3 + +/obj/machinery/power/magic_contraption/stellar/get_initial_mana_pool_type() + return /datum/mana_pool/magic_altar/stellar + +/obj/machinery/power/magic_contraption/stellar/interact(mob/user) + if(panel_open) + return balloon_alert(user, "close the panel first!") + if(active) + active = FALSE + icon_state = "stellar_inactive" + return balloon_alert(user, "deactivated the oculory") + if(!active) + active = TRUE + icon_state = "stellar" + return balloon_alert(user, "activated the oculory") + +/obj/machinery/power/magic_contraption/stellar/process(seconds_per_tick) + if(!active) + return + if(!check_delay()) + return + if(mana_pool.maximum_mana_capacity == mana_pool.amount) + return + var/starlight_level = src.checkstarlight(starlight_check_range) + pulse_mana(starlight_level) + +/obj/machinery/power/magic_contraption/stellar/proc/check_delay() + if((last_pulse + pulse_delay) <= world.time) + return TRUE + return FALSE + +/obj/machinery/power/magic_contraption/stellar/proc/pulse_mana(starlight_level) + var/pulse_value = 0 + switch(starlight_level) + if(FULL_STARLIGHT) + last_pulse_value = FULL_STARLIGHT + pulse_value = high_pulse_value + if(PARTIAL_STARLIGHT) + last_pulse_value = PARTIAL_STARLIGHT + pulse_value = medium_pulse_value + if(NO_STARLIGHT) + last_pulse_value = NO_STARLIGHT + pulse_value = low_pulse_value + // anims here + // also update sprite + mana_pool.amount += pulse_value + last_pulse = world.time + +/obj/machinery/power/magic_contraption/stellar/examine(mob/user) + . = ..() + if(!active) + return . += "The oculory is currently powered off." + switch(last_pulse_value) + if(FULL_STARLIGHT) + . += span_warning("The oculory is beaming with starlight!") + if(PARTIAL_STARLIGHT) + . += "The oculory is functioning under normal conditions." + if(NO_STARLIGHT) + . += span_warning("The oculory needs to gather more starlight.") + +/obj/item/circuitboard/machine/stellar_oculory + name = "\improper Stellar oculory (Machine Board)" + greyscale_colors = CIRCUIT_COLOR_MAGIC + build_path = /obj/machinery/power/magic_contraption/stellar + req_components = list( + /datum/stock_part/capacitor/tier3 = 3, + /datum/stock_part/servo/tier3 = 1, + /obj/item/stack/sheet/mineral/gold = 2, + /obj/item/mana_battery/mana_crystal/standard = 1, + ) +/obj/machinery/power/magic_contraption/stellar/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if (active) + user.balloon_alert(user, "deactivate first!") + return . + if(default_deconstruction_screwdriver(user, "stellar_t", "stellar", tool)) + return ITEM_INTERACT_SUCCESS diff --git a/maplestation_modules/code/modules/magic/mana/sources/leylines/leylines.dm b/maplestation_modules/code/modules/magic/mana/sources/leylines/leylines.dm index 9389c5143930..f7c89034e913 100644 --- a/maplestation_modules/code/modules/magic/mana/sources/leylines/leylines.dm +++ b/maplestation_modules/code/modules/magic/mana/sources/leylines/leylines.dm @@ -39,6 +39,11 @@ GLOBAL_LIST_EMPTY_TYPED(all_leylines, /datum/mana_pool/leyline) transfer_method = MANA_DISPERSE_EVENLY discharge_destinations = NONE + // leylines have a **ton** of implications and are global, so we're doing the safest one possible for now + // also this is insurance against "overload teetering" which was a problem during their first modern implementation + mana_transfer_ruleset = MANA_TRANSFER_SOFTCAP_NO_PASS + + cap_transfer_limit = BASE_MANA_SOFTCAP /datum/mana_pool/leyline/New() GLOB.all_leylines += src diff --git a/maplestation_modules/code/modules/magic/mana/sources/mana_batteries.dm b/maplestation_modules/code/modules/magic/mana/sources/mana_batteries.dm index 8744957b2072..3ca8f588b4bd 100644 --- a/maplestation_modules/code/modules/magic/mana/sources/mana_batteries.dm +++ b/maplestation_modules/code/modules/magic/mana/sources/mana_batteries.dm @@ -1,5 +1,7 @@ /datum/mana_pool/mana_battery amount = 0 + intrinsic_recharge_sources = NONE + discharge_destinations = NONE /datum/mana_pool/mana_battery/can_transfer(datum/mana_pool/target_pool) if (QDELETED(target_pool.parent)) @@ -92,7 +94,7 @@ name = "Stabilized Volite Crystal" desc = "A stabilized Volite Crystal, one of the few objects capable of stably storing mana without binding." icon_state = "standard" - grind_results = list(/datum/reagent/volite_powder = 10) + grind_results = list(/datum/reagent/medicine/quintessence/volite_powder = 10) /obj/item/mana_battery/mana_crystal/standard/get_initial_mana_pool_type() return /datum/mana_pool/mana_battery/mana_crystal/standard @@ -103,7 +105,7 @@ name = "Small Volite Crystal" desc = "A miniaturized Volite crystal, formed using the run-off of cutting larger ones. Able to hold mana still, although not as much as a proper formation." icon_state = "small" - grind_results = list(/datum/reagent/volite_powder = 5) + grind_results = list(/datum/reagent/medicine/quintessence/volite_powder = 5) w_class = WEIGHT_CLASS_SMALL /obj/item/mana_battery/mana_crystal/small/get_initial_mana_pool_type() @@ -113,7 +115,7 @@ name = "Cut Volite Crystal" desc = "A cut and shaped Volite Crystal, using a standardized square cut. It lacks power until it is slotted into a proper amulet." icon_state = "cut" - grind_results = list(/datum/reagent/volite_powder = 10) + grind_results = list(/datum/reagent/medicine/quintessence/volite_powder = 10) /obj/item/mana_battery/mana_crystal/cut/get_initial_mana_pool_type() return /datum/mana_pool/mana_battery/mana_crystal/small @@ -122,7 +124,7 @@ name = "Volitious Lignite" desc = "A natural source of Volite. It is formed not unlike coal, where magical plants has been compressed over millions of years by rock." icon_state = "lignite" - grind_results = list(/datum/reagent/volite_powder = 5, /datum/reagent/carbon = 5) + grind_results = list(/datum/reagent/medicine/quintessence/volite_powder = 5, /datum/reagent/carbon = 5) ///Just like coal, if the temperature of the object is over 300, then ignite /obj/item/mana_battery/mana_crystal/lignite/attackby(obj/item/W, mob/user, params) @@ -160,10 +162,13 @@ /datum/mana_pool/mana_star // a special type of mana battery that regenerates passively- but cannot be given mana - maximum_mana_capacity = 400 // 400 by default - softcap = 400 + maximum_mana_capacity = 100 + softcap = 100 // should be equal to maximum cap in this case amount = 0 - ethereal_recharge_rate = 2 // forgot this was a thing LMFAO + ethereal_recharge_rate = 0.5 + + intrinsic_recharge_sources = NONE // it already regens mana natively, and should generally be reliable + discharge_destinations = NONE /obj/item/clothing/neck/mana_star name = "Volite Amulet" diff --git a/maplestation_modules/code/modules/magic/story_spells/eyes_of_night.dm b/maplestation_modules/code/modules/magic/story_spells/eyes_of_night.dm new file mode 100644 index 000000000000..8d50e68d567e --- /dev/null +++ b/maplestation_modules/code/modules/magic/story_spells/eyes_of_night.dm @@ -0,0 +1,53 @@ +#define EYESOFNIGHT_ATTUNEMENT_DARK 0.5 +#define EYESOFNIGHT_MANA_COST 20 + +/datum/action/cooldown/spell/eyes_of_night + name = "Eyes Of Night" + desc = "Strengthens your ability to see through darkness, making the world seem brighter." + button_icon = 'icons/mob/actions/actions_changeling.dmi' + button_icon_state = "augmented_eyesight" + + cooldown_time = 30 SECONDS // should generally match duration, as this costs mana to use + spell_requirements = NONE + var/mana_cost = EYESOFNIGHT_MANA_COST + + /// The duration of the night vision + var/vision_duration = 30 SECONDS + + +/datum/action/cooldown/spell/eyes_of_night/New(Target) + . = ..() + + var/list/datum/attunement/attunements = GLOB.default_attunements.Copy() + attunements[MAGIC_ELEMENT_DARK] += EYESOFNIGHT_ATTUNEMENT_DARK + + AddComponent(/datum/component/uses_mana/spell, \ + activate_check_failure_callback = CALLBACK(src, PROC_REF(spell_cannot_activate)), \ + get_user_callback = CALLBACK(src, PROC_REF(get_owner)), \ + mana_required = mana_cost, \ + attunements = attunements, \ + ) + +/datum/action/cooldown/spell/eyes_of_night/Remove(mob/living/remove_from) + REMOVE_TRAIT(remove_from, TRAIT_TRUE_NIGHT_VISION, MAGIC_TRAIT) + remove_from.update_sight() + return ..() + +/datum/action/cooldown/spell/eyes_of_night/is_valid_target(atom/cast_on) + return isliving(cast_on) && !HAS_TRAIT(cast_on, TRAIT_THERMAL_VISION) + +/datum/action/cooldown/spell/eyes_of_night/cast(mob/living/cast_on) + . = ..() + ADD_TRAIT(cast_on, TRAIT_TRUE_NIGHT_VISION, MAGIC_TRAIT) + cast_on.update_sight() + to_chat(cast_on, span_info("You focus your eyes intensely, the shadows around you slowly withdrawing")) + addtimer(CALLBACK(src, PROC_REF(deactivate), cast_on), vision_duration) + +/datum/action/cooldown/spell/eyes_of_night/proc/deactivate(mob/living/cast_on) + if(QDELETED(cast_on) || !HAS_TRAIT_FROM(cast_on, TRAIT_TRUE_NIGHT_VISION, MAGIC_TRAIT)) + return + + REMOVE_TRAIT(cast_on, TRAIT_TRUE_NIGHT_VISION, MAGIC_TRAIT) + cast_on.update_sight() + to_chat(cast_on, span_info("You blink a few times, your vision returning to normal.")) + diff --git a/maplestation_modules/code/modules/magic/story_spells/light_breaker.dm b/maplestation_modules/code/modules/magic/story_spells/light_breaker.dm new file mode 100644 index 000000000000..bf8a6e43ff45 --- /dev/null +++ b/maplestation_modules/code/modules/magic/story_spells/light_breaker.dm @@ -0,0 +1,36 @@ +#define LIGHT_BREAKER_ATTUNEMENT_DARK 0.3 +#define LIGHT_BREAKER_MANA_COST 25 + +/datum/action/cooldown/spell/pointed/projectile/light_breaker + name = "Light Breaker" + desc = "Propel forward a lance which shatters most lights it can hit." + button_icon = 'icons/mob/actions/actions_ecult.dmi' + button_icon_state = "mad_touch" + sound = 'sound/effects/parry.ogg' + + cooldown_time = 30 SECONDS + spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC + + invocation = "Op'tc Br'k" + invocation_type = INVOCATION_SHOUT + school = SCHOOL_EVOCATION + var/mana_cost = LIGHT_BREAKER_MANA_COST + + active_msg = "You prepare to throw a light shattering lance." + deactive_msg = "You stop preparing to throw a light shattering lance." + + cast_range = 8 + projectile_type = /obj/projectile/energy/fisher + +/datum/action/cooldown/spell/pointed/projectile/light_breaker/New(Target, original) + . = ..() + + var/list/datum/attunement/attunements = GLOB.default_attunements.Copy() + attunements[MAGIC_ELEMENT_DARK] += LIGHT_BREAKER_ATTUNEMENT_DARK + + AddComponent(/datum/component/uses_mana/spell, \ + activate_check_failure_callback = CALLBACK(src, PROC_REF(spell_cannot_activate)), \ + get_user_callback = CALLBACK(src, PROC_REF(get_owner)), \ + mana_required = mana_cost, \ + attunements = attunements, \ + ) diff --git a/maplestation_modules/code/modules/magic/story_spells/mage_hand.dm b/maplestation_modules/code/modules/magic/story_spells/mage_hand.dm index 3554df0936d2..bf5b876f3345 100644 --- a/maplestation_modules/code/modules/magic/story_spells/mage_hand.dm +++ b/maplestation_modules/code/modules/magic/story_spells/mage_hand.dm @@ -1,4 +1,5 @@ #define MAGE_HAND_MANA_COST 20 +#define MAGE_HAND_PSIONIC_MANA_REFUND 5 // more significant cost because its more powerful // Yeah, it's just a spell that gives you telekinesis for a short period, sue me /datum/action/cooldown/spell/apply_mutations/mage_hand @@ -70,4 +71,14 @@ /datum/mutation/human/telekinesis/mage_hand/get_visual_indicator() return +/datum/action/cooldown/spell/apply_mutations/mage_hand/after_cast(...) + . = ..() + // ditto, with the comments on this part in sending/telepathy's file + var/mob/living/carbon/psychic = owner + if(!psychic) + return + if(HAS_TRAIT(psychic, TRAIT_FULL_PSIONIC)) + psychic.safe_adjust_personal_mana(MAGE_HAND_PSIONIC_MANA_REFUND) + #undef MAGE_HAND_MANA_COST +#undef MAGE_HAND_PSIONIC_MANA_REFUND diff --git a/maplestation_modules/code/modules/magic/story_spells/mana_charge.dm b/maplestation_modules/code/modules/magic/story_spells/mana_charge.dm index 693616165df5..ea40bd009653 100644 --- a/maplestation_modules/code/modules/magic/story_spells/mana_charge.dm +++ b/maplestation_modules/code/modules/magic/story_spells/mana_charge.dm @@ -1,68 +1,72 @@ -// spell that recharges your mana by drawing from leylines, temporarily inaccessible because leyline access is weird, and they're underpowered rn -/datum/action/cooldown/spell/leyline_charge - name = "Leyline Charge" - desc = "Regenerate some of your mana by channeling straight from the leylines themselves." +// recover mana on your own. longer recharge. +/datum/action/cooldown/spell/charged/meditate + name = "Meditation" + desc = "Regenerate some of your mana by focusing within yourself. Takes a period of time to cast." button_icon = 'icons/effects/effects.dmi' button_icon_state = "plasmasoul" sound = 'sound/magic/staff_healing.ogg' school = SCHOOL_UNSET // no idea where this would go tbh - cooldown_time = 2 MINUTES + channel_flags = IGNORE_HELD_ITEM + cooldown_time = 4 MINUTES invocation_type = INVOCATION_NONE spell_requirements = NONE + var/base_mana_recharge = 30 // the mana this recharges before a random varience - invocation = "AS'P'RE" - invocation_type = INVOCATION_WHISPER - var/channel_time = 7 SECONDS + var/random_value_floor = 0 + var/random_value_ceiling = 25 + var/empowered_meditation_increase = 35 // when the player has empowered meditation through some means, this value is used instead of the above values in determining bonus + invocation_self_message = "You begin focusing your mind on manipulating ambient mana." + channel_time = 12 SECONDS -/datum/action/cooldown/spell/leyline_charge/before_cast(mob/living/cast_on) + var/allow_empowerment = TRUE // does this version allow for empowerment from stuff like the meditation mat? + +/datum/action/cooldown/spell/charged/meditate/before_cast(mob/living/cast_on) . = ..() if (!cast_on.mana_pool) cast_on.balloon_alert(cast_on, "no mana pool!") - return - if(!do_after(cast_on, channel_time)) // don't want this casted mid combat return . | SPELL_CANCEL_CAST -/datum/action/cooldown/spell/leyline_charge/cast(mob/living/cast_on) +/datum/action/cooldown/spell/charged/meditate/cast(mob/living/cast_on) . = ..() - var/randy_value = rand(0,25) // generate a random number, which will be- - var/mana_to_gain = randy_value + 20 // added to the base amount, to get a semi-inconsistent regen amount - var/list/datum/mana_pool/leyline/accessable_leylines = list(get_accessable_leylines()) - if(!accessable_leylines.len) - cast_on.balloon_alert(cast_on, "no accessable leylines!") - return - var/datum/mana_pool/leyline/random_leyline = accessable_leylines[rand(0, accessable_leylines.len)] // get a random leyline - random_leyline.transfer_specific_mana(cast_on.mana_pool, mana_to_gain, decrement_budget = TRUE) + var/randy_value = 0 + if(HAS_TRAIT(cast_on, TRAIT_EMPOWERED_MEDITATION) && allow_empowerment) + randy_value = empowered_meditation_increase + else + randy_value = rand(random_value_floor, random_value_ceiling) + var/mana_to_gain = randy_value + base_mana_recharge + cast_on.mana_pool.adjust_mana(mana_to_gain) -// recover mana on your own. longer recharge. more is planned, hopefully -/datum/action/cooldown/spell/meditate - name = "Meditation" - desc = "Regenerate some of your mana by focusing within yourself. Takes a period of time to cast." - button_icon = 'icons/effects/effects.dmi' - button_icon_state = "plasmasoul" - sound = 'sound/magic/staff_healing.ogg' +// recover mana using your own blood. no protections from using this at low blood volume. +/datum/action/cooldown/spell/charged/meditate/lesser_splattercasting + name = "Lesser Splattercasting" + desc = "Drain some of your own blood to recover mana. This does not prevent you from bleeding out." + button_icon = 'icons/effects/bleed.dmi' + button_icon_state = "bleed10" + sound = 'sound/weapons/slice.ogg' - school = SCHOOL_UNSET // no idea where this would go tbh - cooldown_time = 4 MINUTES - invocation_type = INVOCATION_NONE - spell_requirements = NONE + cooldown_time = 2 MINUTES // shorter as its not from no where + base_mana_recharge = 40 + var/base_bloodloss = 50 // the blood drained before a random variable is added. - invocation = "Focus...." - invocation_type = INVOCATION_WHISPER - var/channel_time = 12 SECONDS + invocation_self_message = "You prepare an incantation to trade some of your blood for mana." + channel_time = 8 SECONDS -/datum/action/cooldown/spell/meditate/before_cast(mob/living/cast_on) +/datum/action/cooldown/spell/charged/meditate/lesser_splattercasting/before_cast(mob/living/cast_on) . = ..() - if (!cast_on.mana_pool) - cast_on.balloon_alert(cast_on, "no mana pool!") - return - to_chat(cast_on, span_alert("You begin focusing your mind on manipulating ambient mana.")) - if(!do_after(cast_on, channel_time)) // don't want this casted mid combat + if (HAS_TRAIT(cast_on, TRAIT_NOBLOOD)) + cast_on.balloon_alert(cast_on, "no blood to use!") + return . | SPELL_CANCEL_CAST + var/highest_blood_drain = base_bloodloss + random_value_ceiling // what is the highest amount of blood we can drain + if (cast_on.blood_volume <= highest_blood_drain) + cast_on.balloon_alert(cast_on, "too little blood!") // this is a failsafe added because someone (you know who you are) managed to get negative blood by using another exploit, which is now patched return . | SPELL_CANCEL_CAST -/datum/action/cooldown/spell/meditate/cast(mob/living/cast_on) +/datum/action/cooldown/spell/charged/meditate/lesser_splattercasting/cast(mob/living/cast_on) . = ..() - var/randy_value = rand(0,25) - var/mana_to_gain = randy_value + 40 - cast_on.mana_pool.adjust_mana(mana_to_gain) + var/random_bloodloss_value = rand(random_value_floor, random_value_ceiling) + var/blood_drain = base_bloodloss + random_bloodloss_value + cast_on.blood_volume -= blood_drain + var/turf/location = get_turf(cast_on) + cast_on.add_splatter_floor(location) diff --git a/maplestation_modules/code/modules/magic/story_spells/mana_tap.dm b/maplestation_modules/code/modules/magic/story_spells/mana_tap.dm new file mode 100644 index 000000000000..a5a94c90ff38 --- /dev/null +++ b/maplestation_modules/code/modules/magic/story_spells/mana_tap.dm @@ -0,0 +1,15 @@ +/datum/action/cooldown/spell/touch/mana_tap + name = "Mana Tap" + desc = "Extend a psychic tap to allow you to manipulate mana without a simple object. Ideal for drawing from the mana sources of mana in space." + button_icon = 'maplestation_modules/icons/mob/actions/actions_cantrips.dmi' + button_icon_state = "spark_psi" + sound = null + check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_HANDS_BLOCKED + school = SCHOOL_CONJURATION + cooldown_time = 10 SECONDS + invocation_type = INVOCATION_NONE + spell_requirements = NONE + + hand_path = /obj/item/magic_wand/temporary/psionic + draw_message = null + drop_message = null diff --git a/maplestation_modules/code/modules/magic/story_spells/telepathy.dm b/maplestation_modules/code/modules/magic/story_spells/telepathy.dm index 4baa261fce9e..71c23643ec31 100644 --- a/maplestation_modules/code/modules/magic/story_spells/telepathy.dm +++ b/maplestation_modules/code/modules/magic/story_spells/telepathy.dm @@ -1,4 +1,5 @@ #define SENDING_MANA_COST 7 +#define SENDING_PSIONIC_MANA_REFUND 7 // partially for the gimmick, and because this was cheap to begin with /datum/action/cooldown/spell/list_target/telepathy/mana name = "Sending" @@ -14,4 +15,14 @@ mana_required = mana_cost, \ ) +/datum/action/cooldown/spell/list_target/telepathy/mana/after_cast(...) + . = ..() + var/mob/living/carbon/psychic = owner + if(!psychic) + return + // originally planned for it to replace the cost, but this is more reliable for reducing the cost (and owner is added after the component, so its null) + if(HAS_TRAIT(psychic, TRAIT_FULL_PSIONIC)) // if we have sufficient psionic quirks, we get a refund on the mana. feel free to update this if more varieties are added + psychic.safe_adjust_personal_mana(SENDING_PSIONIC_MANA_REFUND) + #undef SENDING_MANA_COST +#undef SENDING_PSIONIC_MANA_REFUND diff --git a/maplestation_modules/code/modules/research/designs/magic_designs.dm b/maplestation_modules/code/modules/research/designs/magic_designs.dm new file mode 100644 index 000000000000..71e07fb43d97 --- /dev/null +++ b/maplestation_modules/code/modules/research/designs/magic_designs.dm @@ -0,0 +1,45 @@ +/datum/design/proto_mana_lens + name = "Prototype Mana Lens" + desc = "The first prototype of a device capable of reading the prescence of mana." + id = "mana_lens" + build_type = PROTOLATHE + materials = list(/datum/material/iron =SHEET_MATERIAL_AMOUNT * 1.5, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2.5, /datum/material/gold = SMALL_MATERIAL_AMOUNT) + build_path = /obj/item/mana_lens + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/artificial_volite_large + name = "Artificial Volite Gem" + desc = "Produce a volite gem through non-magical manufacturing. Far less efficient than the magical way, of course." + id = "artificial_volite_large" + build_type = PROTOLATHE + materials = list(/datum/material/bluespace = SMALL_MATERIAL_AMOUNT * 2, /datum/material/uranium = SMALL_MATERIAL_AMOUNT * 2, /datum/material/gold = SMALL_MATERIAL_AMOUNT * 2) + build_path = /obj/item/mana_battery/mana_crystal/standard + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING // because this is meant to be inefficient (and uses bluespace crystals) this should be locked to the two departments that generally manage these + +/datum/design/artificial_volite_small + name = "Small Artificial Volite Gem" + desc = "Produce a miniaturized volite gem through non-magical manufacturing. Far less efficient than the magical way, of course." + id = "artificial_volite_small" + build_type = PROTOLATHE + materials = list(/datum/material/bluespace = SMALL_MATERIAL_AMOUNT, /datum/material/uranium = SMALL_MATERIAL_AMOUNT, /datum/material/gold = SMALL_MATERIAL_AMOUNT) + build_path = /obj/item/mana_battery/mana_crystal/small + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/techie_magic_wand + name = "Arcane Field Modulator" + desc = "An overengineered device produced and researched on board to manipulate and move residual mana within objects." + id = "techie_magic_wand" + build_type = PROTOLATHE + materials = list(/datum/material/silver = SMALL_MATERIAL_AMOUNT, /datum/material/iron = SMALL_MATERIAL_AMOUNT * 2.5) + build_path = /obj/item/magic_wand/techie + departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/board/stellar_oculory + name = "Stellar oculory" + desc = "The circuit board for a stellar oculory." + id = "stellar_oculory" + build_path = /obj/item/circuitboard/machine/stellar_oculory + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_RESEARCH + ) + departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_SCIENCE diff --git a/maplestation_modules/code/modules/research/techweb/magic_nodes.dm b/maplestation_modules/code/modules/research/techweb/magic_nodes.dm new file mode 100644 index 000000000000..bb20bd51d37a --- /dev/null +++ b/maplestation_modules/code/modules/research/techweb/magic_nodes.dm @@ -0,0 +1,31 @@ +/datum/techweb_node/mana_base_node + id = TECHWEB_NODE_MANA_BASE + display_name = "Early Magical Tech" + description = "The first bits of technology surronding magic." + prereq_ids = list(TECHWEB_NODE_FUNDIMENTAL_SCI) + design_ids = list( + "mana_lens", + "techie_magic_wand", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/artificial_volite + id = TECHWEB_NODE_ARTIFICIAL_VOLITE + display_name = "Artificial Volite Synthesis" + description = "Produce volite gemstones through an admittedly inefficient process." + prereq_ids = list(TECHWEB_NODE_MANA_BASE, TECHWEB_NODE_BLUESPACE_THEORY) + design_ids = list( + "artificial_volite_large", + "artificial_volite_small", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/stellar_oculory + id = TECHWEB_NODE_STELLAR_OCULORY + display_name = "Starlight-Mana Conversion" + description = "Convert trace arcane essence from nearby starlight into usable mana." + prereq_ids = list(TECHWEB_NODE_MANA_BASE, TECHWEB_NODE_PARTS_ADV) + design_ids = list( + "stellar_oculory", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) diff --git a/maplestation_modules/icons/mob/actions/actions_cantrips.dmi b/maplestation_modules/icons/mob/actions/actions_cantrips.dmi index 54e955cce411..673ed1b3cb56 100644 Binary files a/maplestation_modules/icons/mob/actions/actions_cantrips.dmi and b/maplestation_modules/icons/mob/actions/actions_cantrips.dmi differ diff --git a/maplestation_modules/icons/mob/inhands/equipment_lefthand.dmi b/maplestation_modules/icons/mob/inhands/equipment_lefthand.dmi new file mode 100644 index 000000000000..4a8af63c44a4 Binary files /dev/null and b/maplestation_modules/icons/mob/inhands/equipment_lefthand.dmi differ diff --git a/maplestation_modules/icons/mob/inhands/equipment_righthand.dmi b/maplestation_modules/icons/mob/inhands/equipment_righthand.dmi new file mode 100644 index 000000000000..889ccc6086ac Binary files /dev/null and b/maplestation_modules/icons/mob/inhands/equipment_righthand.dmi differ diff --git a/maplestation_modules/icons/obj/magic/altars.dmi b/maplestation_modules/icons/obj/magic/altars.dmi new file mode 100644 index 000000000000..45dd35847daf Binary files /dev/null and b/maplestation_modules/icons/obj/magic/altars.dmi differ diff --git a/maplestation_modules/icons/obj/magic/objects.dmi b/maplestation_modules/icons/obj/magic/objects.dmi new file mode 100644 index 000000000000..33cd95483444 Binary files /dev/null and b/maplestation_modules/icons/obj/magic/objects.dmi differ diff --git a/maplestation_modules/icons/obj/magic/wands.dmi b/maplestation_modules/icons/obj/magic/wands.dmi new file mode 100644 index 000000000000..0c8d3e417e9e Binary files /dev/null and b/maplestation_modules/icons/obj/magic/wands.dmi differ diff --git a/maplestation_modules/icons/obj/service/library.dmi b/maplestation_modules/icons/obj/service/library.dmi new file mode 100644 index 000000000000..870215b632f7 Binary files /dev/null and b/maplestation_modules/icons/obj/service/library.dmi differ