Skip to content
This repository has been archived by the owner on Jun 29, 2024. It is now read-only.

Spellbooks #748

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions code/__DEFINES/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,11 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//alternate appearance flags
#define AA_TARGET_SEE_APPEARANCE (1<<0)
#define AA_MATCH_TARGET_OVERLAYS (1<<1)

// spell rarities
#define SPELL_COMMON (1 << 0)
#define SPELL_UNCOMMON (1 << 1)
#define SPELL_RARE (1 << 2)
#define SPELL_EPIC (1 << 3)
#define SPELL_LEGENDARY (1 << 4)
#define SPELL_ALL (SPELL_COMMON | SPELL_UNCOMMON | SPELL_RARE | SPELL_EPIC | SPELL_LEGENDARY)
1 change: 1 addition & 0 deletions code/__DEFINES/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ GLOBAL_LIST_INIT(ghost_accs_options, list(GHOST_ACCS_NONE, GHOST_ACCS_DIR, GHOST
#define GHOST_MAX_VIEW_RANGE_DEFAULT 10
#define GHOST_MAX_VIEW_RANGE_MEMBER 14

GLOBAL_LIST_INIT(learnables, list())

GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DEFAULT_SPRITE, GHOST_OTHERS_THEIR_SETTING)) //Same as ghost_accs_options.

Expand Down
2 changes: 2 additions & 0 deletions code/__HELPERS/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
for(var/god in subtypesof(/datum/patrongods))
var/datum/patrongods/A = new god()
GLOB.patronlist[A.name] = A

GLOB.learnables = Get_Learnable_Spells()

//creates every subtype of prototype (excluding prototype) and adds it to list L.
//if no list/L is provided, one is created.
Expand Down
8 changes: 8 additions & 0 deletions code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@
else if(dx<0)
.+=360

/proc/Get_Learnable_Spells()
var/ret = list()
for(var/S in GLOB.spells)
var/obj/effect/proc_holder/spell/spell = S
if(spell.learnable)
ret += spell
return ret

/proc/Get_Pixel_Angle(y, x)//for getting the angle when animating something's pixel_x and pixel_y
if(!y)
return (x>=0)?90:270
Expand Down
2 changes: 2 additions & 0 deletions code/datums/mutations/antenna.dm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
name = "Mindread"
desc = ""
charge_max = 50
learnable = TRUE
rarity = 0
range = 7
clothes_req = FALSE
action_icon_state = "mindread"
Expand Down
41 changes: 41 additions & 0 deletions code/game/objects/items/granters.dm
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,47 @@
drop_sound = 'sound/foley/dropsound/paper_drop.ogg'
pickup_sound = 'sound/blank.ogg'

/obj/item/book/granter/spell/generic
name = "Spellbook"
desc = "A book of potential known only to those that can decipher its secrets."
icon = 'icons/obj/library.dmi'
icon_state = "book1"
oneuse = TRUE
drop_sound = 'sound/foley/dropsound/paper_drop.ogg'
pickup_sound = 'sound/blank.ogg'
var/obj/effect/proc_holder/spell/target = null

/obj/item/book/granter/spell/generic/Initialize(loc, rarity = SPELL_ALL)
. = ..()
target = pick(GLOB.learnables)
var/obj/effect/proc_holder/spell/S = new target
spellname = S.name
name = "Book of [spellname]"

/obj/item/book/granter/spell/generic/already_known(mob/user)
if(!target)
return TRUE
for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
if(knownspell.type == target)
to_chat(user,"<span class='warning'>You already know this one!</span>")
return TRUE
return FALSE

/obj/item/book/granter/spell/generic/on_reading_start(mob/user)
to_chat(user, "<span class='notice'>I start reading about [spellname]...</span>")

/obj/item/book/granter/spell/generic/on_reading_finished(mob/user)
. = ..()
if(oneuse)
name = "Siphoned Book of [target.name]"
desc = "A book once inscribed with magical scripture. The surface is now barren of knowledge, siphoned by someone else. It's utterly useless."
user.visible_message("<span class='warning'>[src] has had its magic ink ripped from the book!</span>")
to_chat(user, "<span class='notice'>Your knowledge expands, you understand how to cast [spellname]!</span>")
var/S = new target
user.mind.AddSpell(S)
user.log_message("learned the spell [target.name] ([target])", LOG_ATTACK, color="orange")
onlearned(user)

/obj/item/book/granter/spell/blackstone/onlearned(mob/living/carbon/user)
..()
if(oneuse == TRUE)
Expand Down
46 changes: 46 additions & 0 deletions code/game/objects/items/rogueitems/books.dm
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,52 @@
var/qdel_source = FALSE

/obj/item/manuscript/attackby(obj/item/I, mob/living/user)
if(resistance_flags & ON_FIRE)
return ..()

if(is_blind(user))
return ..()

if(istype(I, /obj/item/natural/feather/magic))
var/qualifying = 0
var/exp_gain = 0
var/obj/item/natural/feather/magic/F = I

if(prob(5)) // They rolled a nat20
qualifying = SPELL_EPIC | SPELL_LEGENDARY
exp_gain = 100
to_chat(user, "You feel your feather moving with a life of its own, as you struggle to comprehend what you write.")
else
var/skill_score = 0
var/spell_score = 0
if(/datum/skill/magic/arcane in user.mind.known_skills)
skill_score = user.mind.known_skills[/datum/skill/magic/arcane] * 0.1
spell_score = number_of_pages * 10 + skill_score
if(spell_score >= 10) // No, this doesn't make sense right now. I'm going to sleep on it
qualifying |= SPELL_COMMON // and figure out how to balance this thing.
if(spell_score >= 50)
qualifying |= SPELL_UNCOMMON
if(spell_score >= 95)
qualifying |= SPELL_RARE
if(spell_score >= 105)
qualifying |= SPELL_EPIC
if(spell_score >= 115)
qualifying |= SPELL_LEGENDARY

if(qualifying)
var/obj/item/book/granter/spell/generic/SB = new /obj/item/book/granter/spell/generic(get_turf(I.loc), qualifying)
if(user.Adjacent(SB))
SB.add_fingerprint(user)
user.put_in_hands(SB)
if(exp_gain)
user.mind.adjust_experience(/datum/skill/magic/arcane, exp_gain)
to_chat(user, "As you finish writing, the feather glows and envelops the manuscript, becoming a new spellbook.")
// else something here about the feather not being able to write a spellbook
if(F.uses >= F.max_uses)
to_chat(user, "The feather's magic glows dimly, and then it turns into dust.")
new /obj/item/ash(get_turf(user.loc))
qdel(F)
return
// why is a book crafting kit using the craft system, but crafting a book isn't? Well the crafting system for *some reason* is made in such a way as to make reworking it to allow you to put reqs vars in the crafted item near *impossible.*
if(istype(I, /obj/item/book_crafting_kit))
var/obj/item/book/rogue/playerbook/PB = new /obj/item/book/rogue/playerbook(get_turf(I.loc), TRUE, user, compiled_pages)
Expand Down
10 changes: 9 additions & 1 deletion code/game/objects/items/rogueitems/natural/feather.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@
max_integrity = 20
muteinmouth = TRUE
spitoutmouth = FALSE
w_class = WEIGHT_CLASS_TINY
w_class = WEIGHT_CLASS_TINY

/obj/item/natural/feather/magic
name = "magic feather"
color = "#ffee00"
desc = "A fluffy feather that seems to shimmer with a faint magical aura."
var/uses = 0
var/max_uses = 3 // TODO: Balance this

8 changes: 8 additions & 0 deletions code/modules/roguetown/roguecrafting/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,11 @@
/obj/item/natural/cloth = 1)
tools = list(/obj/item/needle = 1)
req_table = TRUE

/datum/crafting_recipe/roguetown/magic_feather
name = "magic feather"
result = /obj/item/natural/feather/magic
reqs = list(
/obj/item/reagent_containers/powder = 1,
/obj/item/natural/feather = 1
)
8 changes: 8 additions & 0 deletions code/modules/spells/roguetown/necromancer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
releasedrain = 30
chargetime = 5
range = 7
learnable = TRUE
rarity = 0
warnie = "sydwarning"
movement_interrupt = FALSE
chargedloop = null
Expand Down Expand Up @@ -37,6 +39,8 @@
overlay_state = "raiseskele"
releasedrain = 30
chargetime = 15
learnable = TRUE
rarity = 0
range = 7
warnie = "sydwarning"
movement_interrupt = FALSE
Expand All @@ -63,6 +67,8 @@
desc = ""
clothes_req = FALSE
range = 7
learnable = TRUE
rarity = 0
overlay_state = "raiseskele"
sound = list('sound/magic/magnet.ogg')
releasedrain = 40
Expand All @@ -86,6 +92,8 @@
name = "Ray of Sickness"
desc = ""
clothes_req = FALSE
learnable = TRUE
rarity = 0
range = 15
projectile_type = /obj/projectile/magic/sickness
overlay_state = "raiseskele"
Expand Down
8 changes: 8 additions & 0 deletions code/modules/spells/roguetown/wizard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
name = "Bolt of Lightning"
desc = ""
clothes_req = FALSE
learnable = TRUE
rarity = 0
overlay_state = "lightning"
sound = 'sound/magic/lightning.ogg'
range = 8
Expand Down Expand Up @@ -154,6 +156,8 @@
/obj/effect/proc_holder/spell/invoked/projectile/fireball
name = "Fireball"
desc = ""
learnable = TRUE
rarity = 80
clothes_req = FALSE
range = 8
projectile_type = /obj/projectile/magic/aoe/fireball/rogue
Expand Down Expand Up @@ -205,6 +209,8 @@
desc = ""
clothes_req = FALSE
range = 8
learnable = TRUE
rarity = 10
projectile_type = /obj/projectile/magic/aoe/fireball/rogue/great
overlay_state = "fireball"
sound = list('sound/magic/fireball.ogg')
Expand All @@ -230,6 +236,8 @@
name = "Fetch"
desc = ""
clothes_req = FALSE
learnable = TRUE
rarity = 0
range = 15
projectile_type = /obj/projectile/magic/fetch
overlay_state = ""
Expand Down
3 changes: 2 additions & 1 deletion code/modules/spells/spell.dm
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#define TARGET_CLOSEST 1
#define TARGET_RANDOM 2


/obj/effect/proc_holder
var/panel = "Debug"//What panel the proc holder needs to go on.
var/active = FALSE //Used by toggle based abilities.
Expand Down Expand Up @@ -129,6 +128,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
opacity = 0

var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
var/learnable = FALSE // The spell is acquirable outside of admin intervention or through spawning. Default to "No" because many shouldn't be learned.
var/rarity = 0 // Percentage chance to scribe.

var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that

Expand Down
2 changes: 1 addition & 1 deletion tools/mapmerge2/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#pygit2==0.27.2
pygit2==0.27.2
bidict==0.13.1
Pillow==6.2.0