Refactors Spell and Martial Art Books to use Action Granters!

This commit is contained in:
Armhulen
2018-03-27 10:51:14 -07:00
committed by CitadelStationBot
parent 77f40b6be9
commit 2d8b007086
25 changed files with 1177 additions and 167 deletions

View File

@@ -194,21 +194,5 @@
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.")
to_chat(usr, "<span class='notice'>Pressure</span>: Disarm Grab. Decent stamina damage.")
to_chat(usr, "<span class='notice'>Consecutive CQC</span>: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
to_chat(usr, "<b><i>In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.</i></b>")
/obj/item/cqc_manual
name = "old manual"
desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat."
icon = 'icons/obj/library.dmi'
icon_state ="cqcmanual"
/obj/item/cqc_manual/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
to_chat(user, "<span class='boldannounce'>You remember the basics of CQC.</span>")
var/datum/martial_art/cqc/D = new(null)
D.teach(user)
visible_message("<span class='warning'>[src] beeps ominously, and a moment later it bursts up in flames.</span>")
qdel(src)
new /obj/effect/decal/cleanable/ash(user.drop_location())

View File

@@ -21,7 +21,7 @@
return TRUE
/obj/item/mushpunch
name = "mysterious mushroom"
name = "odd mushroom"
desc = "<I>Sapienza Ophioglossoides</I>:An odd mushroom from the flesh of a mushroom person. it has apparently retained some innate power of it's owner, as it quivers with barely-contained POWER!"
icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
icon_state = "mycelium-angel"

View File

@@ -92,23 +92,3 @@
to_chat(usr, "<span class='notice'>Tornado Sweep</span>: Harm Harm Disarm. Repulses target and everyone back.")
to_chat(usr, "<span class='notice'>Throwback</span>: Disarm Harm Disarm. Throws the target and an item at them.")
to_chat(usr, "<span class='notice'>The Plasma Fist</span>: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.")
/obj/item/plasma_fist_scroll
name = "frayed scroll"
desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism."
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
var/used = 0
/obj/item/plasma_fist_scroll/attack_self(mob/user)
if(!ishuman(user))
return
if(!used)
var/mob/living/carbon/human/H = user
var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null)
F.teach(H)
to_chat(H, "<span class='boldannounce'>You have learned the ancient martial art of Plasma Fist.</span>")
used = 1
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"

View File

@@ -156,24 +156,6 @@
to_chat(usr, "<span class='notice'>Head Kick</span>: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.")
to_chat(usr, "<span class='notice'>Elbow Drop</span>: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.")
/obj/item/sleeping_carp_scroll
name = "mysterious scroll"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
/obj/item/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
var/message = "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
to_chat(user, message)
var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null)
theSleepingCarp.teach(user)
qdel(src)
visible_message("<span class='warning'>[src] lights up in fire and quickly burns to ash.</span>")
new /obj/effect/decal/cleanable/ash(user.drop_location())
/obj/item/twohanded/bostaff
name = "bo staff"
desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate."

View File

@@ -0,0 +1,394 @@
///books that teach things (intrinsic actions like bar flinging, spells like fireball or smoke, or martial arts)///
/obj/item/book/granter
due_date = 0 // Game time in deciseconds
unique = 1 // 0 Normal book, 1 Should not be treated as normal book, unable to be copied, unable to be modified
var/list/remarks = list() //things to read about while learning.
var/pages_to_mastery = 3 //Essentially controls how long a mob must keep the book in his hand to actually successfully learn
var/reading = FALSE //sanity
var/oneuse = TRUE //default this is true, but admins can var this to 0 if we wanna all have a pass around of the rod form book
var/used = FALSE //only really matters if oneuse but it might be nice to know if someone's used it for admin investigations perhaps
/obj/item/book/granter/proc/turn_page(mob/user)
playsound(user, pick('sound/effects/pageturn1.ogg','sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg'), 30, 1)
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>[pick(remarks)]</span>")
return TRUE
return FALSE
/obj/item/book/granter/proc/recoil(mob/user) //nothing so some books can just return
/obj/item/book/granter/proc/onlearned(mob/user)
used = TRUE
/obj/item/book/granter/attack_self(mob/user)
if(reading == TRUE)
to_chat(user, "<span class='warning'>You're already reading this!</span>")
return FALSE
return TRUE
///ACTION BUTTONS///
/obj/item/book/granter/action
var/granted_action
var/actionname = "catching bugs" //might not seem needed but this makes it so you can safely name aciton buttons toggle this or that without it fucking up the granter, also caps
/obj/item/book/granter/action/attack_self(mob/user)
. = ..()
if(!.)
return
if(!granted_action)
return
var/datum/action/G = new granted_action
for(var/datum/action/A in user.actions)
if(A.type == G.type)
to_chat(user, "<span class='notice'>You already know all about [actionname].</span>")
qdel(G)
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about [actionname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(G)
return
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [actionname]!</span>")
reading = FALSE
G.Grant(user)
/obj/item/book/granter/action/drink_fling
granted_action = /datum/action/innate/drink_fling
name = "Tapper: This One's For You"
desc = "A seminal work on the dying art of booze sliding."
icon_state = "barbook"
actionname = "drink flinging"
oneuse = FALSE
remarks = list("The trick is keeping a low center of gravity it seems...", "The viscosity of the liquid is important...", "Accounting for crosswinds... really?", "Drag coefficients of various popular drinking glasses...", "What the heck is laminar flow and why does it matter here?", "Greasing the bar seems like it'd be cheating...", "I don't think I'll be working with superfluids...")
/datum/action/innate/drink_fling
name = "Drink Flinging"
desc = "Toggles your ability to satifyingly throw glasses without spilling them."
button_icon_state = "drinkfling_off"
check_flags = 0
/datum/action/innate/drink_fling/Activate()
button_icon_state = "drinkfling_on"
active = TRUE
UpdateButtonIcon()
/datum/action/innate/drink_fling/Deactivate()
button_icon_state = "drinkfling_off"
active = FALSE
UpdateButtonIcon()
///SPELLS///
/obj/item/book/granter/spell
var/spell
var/spellname = "conjure bugs"
/obj/item/book/granter/spell/attack_self(mob/user)
. = ..()
if(!.)
return
if(!spell)
return
var/obj/effect/proc_holder/spell/S = new spell
for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
if(knownspell.type == S.type)
if(user.mind)
if(iswizard(user))
to_chat(user,"<span class='notice'>You're already far more versed in this spell than this flimsy howto book can provide.</span>")
else
to_chat(user,"<span class='notice'>You've already read this one.</span>")
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about casting [spellname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(S)
return
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>You feel like you've experienced enough to cast [spellname]!</span>")
reading = FALSE
user.mind.AddSpell(S)
user.log_message("<font color='orange'>learned the spell [spellname] ([S]).</font>", INDIVIDUAL_ATTACK_LOG)
onlearned(user)
/obj/item/book/granter/spell/recoil(mob/user)
user.visible_message("<span class='warning'>[src] glows in a black light!</span>")
/obj/item/book/granter/spell/onlearned(mob/user)
..()
if(oneuse)
user.visible_message("<span class='caution'>[src] glows dark for a second!</span>")
/obj/item/book/granter/spell/fireball
spell = /obj/effect/proc_holder/spell/aimed/fireball
spellname = "fireball"
icon_state ="bookfireball"
desc = "This book feels warm to the touch."
remarks = list("Aim...AIM, FOOL!", "Just catching them on fire won't do...", "Accounting for crosswinds... really?", "I think I just burned my hand...", "Why the dumb stance? It's just a flick of the hand...", "OMEE... ONI... Ugh...", "What's the difference between a fireball and a pyroblast...")
/obj/item/book/granter/spell/fireball/recoil(mob/user)
..()
explosion(user.loc, 1, 0, 2, 3, FALSE, FALSE, 2)
qdel(src)
/obj/item/book/granter/spell/sacredflame
spell = /obj/effect/proc_holder/spell/targeted/sacred_flame
spellname = "sacred flame"
icon_state ="booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."
remarks = list("Well, it's one way to stop an attacker...", "I'm gonna need some good gear to stop myself from burning to death...", "Keep a fire extingusher handy, got it...", "I think I just burned my hand...", "Apply flame directly to chest for proper ignition...", "No pain, no gain...", "One with the flame...")
/obj/item/book/granter/spell/smoke
spell = /obj/effect/proc_holder/spell/targeted/smoke
spellname = "smoke"
icon_state ="booksmoke"
desc = "This book is overflowing with the dank arts."
remarks = list("Smoke Bomb! Heh...", "Smoke bomb would do just fine too...", "Wait, there's a machine that does the same thing in chemistry?", "This book smells awful...", "Why all these weed jokes? Just tell me how to cast it...", "Wind will ruin the whole spell, good thing we're in space... Right?", "So this is how the spider clan does it...")
/obj/item/book/granter/spell/smoke/lesser //Chaplain smoke book
spell = /obj/effect/proc_holder/spell/targeted/smoke/lesser
/obj/item/book/granter/spell/smoke/recoil(mob/user)
..()
to_chat(user,"<span class='caution'>Your stomach rumbles...</span>")
if(user.nutrition)
user.nutrition = 200
if(user.nutrition <= 0)
user.nutrition = 0
/obj/item/book/granter/spell/blind
spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
spellname = "blind"
icon_state ="bookblind"
desc = "This book looks blurry, no matter how you look at it."
remarks = list("Well I can't learn anything if I can't read the damn thing!", "Why would you use a dark font on a dark background...", "Ah, I can't see an Oh, I'm fine...", "I can't see my hand...!", "I'm manually blinking, damn you book...", "I can't read this page, but somehow I feel like I learned something from it...", "Hey, who turned off the lights?")
/obj/item/book/granter/spell/blind/recoil(mob/user)
..()
to_chat(user,"<span class='warning'>You go blind!</span>")
user.blind_eyes(10)
/obj/item/book/granter/spell/mindswap
spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
spellname = "mindswap"
icon_state ="bookmindswap"
desc = "This book's cover is pristine, though its pages look ragged and torn."
var/mob/stored_swap //Used in used book recoils to store an identity for mindswaps
remarks = list("If you mindswap from a mouse, they will be helpless when you recover...", "Wait, where am I...?", "This book is giving me a horrible headache...", "This page is blank, but I feel words popping into my head...", "GYNU... GYRO... Ugh...", "The voices in my head need to stop, I'm trying to read here...", "I don't think anyone will be happy when I cast this spell...")
/obj/item/book/granter/spell/mindswap/onlearned()
spellname = pick("fireball","smoke","blind","forcewall","knock","barnyard","charge")
icon_state = "book[spellname]"
name = "spellbook of [spellname]" //Note, desc doesn't change by design
..()
/obj/item/book/granter/spell/mindswap/recoil(mob/user)
..()
if(stored_swap in GLOB.dead_mob_list)
stored_swap = null
if(!stored_swap)
stored_swap = user
to_chat(user,"<span class='warning'>For a moment you feel like you don't even know who you are anymore.</span>")
return
if(stored_swap == user)
to_chat(user,"<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
return
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new
swapper.cast(user, stored_swap, TRUE)
to_chat(stored_swap,"<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
to_chat(user,"<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>")
stored_swap = null
/obj/item/book/granter/spell/forcewall
spell = /obj/effect/proc_holder/spell/targeted/forcewall
spellname = "forcewall"
icon_state ="bookforcewall"
desc = "This book has a dedication to mimes everywhere inside the front cover."
remarks = list("I can go through the wall! Neat.", "Why are there so many mime references...?", "This would cause much grief in a hallway...", "This is some suprisingly strong magic to create a wall nobody can pass through...", "Why the dumb stance? It's just a flick of the hand...", "Why are the pages so hard to turn, is this even paper?", "I can't mo Oh, i'm fine...")
/obj/item/book/granter/spell/forcewall/recoil(mob/living/user)
..()
to_chat(user,"<span class='warning'>You suddenly feel very solid!</span>")
user.Stun(40, ignore_canstun = TRUE)
user.petrify(30)
/obj/item/book/granter/spell/knock
spell = /obj/effect/proc_holder/spell/aoe_turf/knock
spellname = "knock"
icon_state ="bookknock"
desc = "This book is hard to hold closed properly."
remarks = list("Open Sesame!", "So THAT'S the magic password!", "Slow down, book. I still haven't finished this page...", "The book won't stop moving!", "I think this is hurting the spine of the book...", "I can't get to the next page, it's stuck t I'm good, it just turned to the next page on it's own.", "Yeah, staff of doors does the same thing. Go figure...")
/obj/item/book/granter/spell/knock/recoil(mob/living/user)
..()
to_chat(user,"<span class='warning'>You're knocked down!</span>")
user.Knockdown(40)
/obj/item/book/granter/spell/barnyard
spell = /obj/effect/proc_holder/spell/targeted/barnyardcurse
spellname = "barnyard"
icon_state ="bookhorses"
desc = "This book is more horse than your mind has room for."
remarks = list("Moooooooo!","Moo!","Moooo!", "NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!", "Oink!", "Squeeeeeeee!", "Oink Oink!", "Ree!!", "Reee!!", "REEE!!", "REEEEE!!")
/obj/item/book/granter/spell/barnyard/recoil(mob/living/carbon/user)
if(ishuman(user))
to_chat(user,"<font size='15' color='red'><b>HORSIE HAS RISEN</b></font>")
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
magichead.flags_1 |= NODROP_1 //curses!
magichead.flags_inv &= ~HIDEFACE //so you can still see their face
magichead.voicechange = TRUE //NEEEEIIGHH
if(!user.dropItemToGround(user.wear_mask))
qdel(user.wear_mask)
user.equip_to_slot_if_possible(magichead, slot_wear_mask, TRUE, TRUE)
qdel(src)
else
to_chat(user,"<span class='notice'>I say thee neigh</span>") //It still lives here
/obj/item/book/granter/spell/charge
spell = /obj/effect/proc_holder/spell/targeted/charge
spellname = "charge"
icon_state ="bookcharge"
desc = "This book is made of 100% postconsumer wizard."
remarks = list("I feel ALIVE!", "I CAN TASTE THE MANA!", "What a RUSH!", "I'm FLYING through these pages!", "THIS GENIUS IS MAKING IT!", "This book is ACTION PAcKED!", "HE'S DONE IT", "LETS GOOOOOOOOOOOO")
/obj/item/book/granter/spell/charge/recoil(mob/user)
..()
to_chat(user,"<span class='warning'>[src] suddenly feels very warm!</span>")
empulse(src, 1, 1)
/obj/item/book/granter/spell/summonitem
spell = /obj/effect/proc_holder/spell/targeted/summonitem
spellname = "instant summons"
icon_state ="booksummons"
desc = "This book is bright and garish, very hard to miss."
remarks = list("I can't look away from the book!", "The words seem to pop around the page...", "I just need to focus on one item...", "Make sure to have a good grip on it when casting...", "Slow down, book. I still haven't finished this page...", "Sounds pretty great with some other magical artifacts...", "Magicians must love this one.")
/obj/item/book/granter/spell/summonitem/recoil(mob/user)
..()
to_chat(user,"<span class='warning'>[src] suddenly vanishes!</span>")
qdel(src)
/obj/item/book/granter/spell/random
icon_state = "random_book"
/obj/item/book/granter/spell/random/Initialize()
. = ..()
var/static/banned_spells = list(/obj/item/book/granter/spell/mimery_blockade, /obj/item/book/granter/spell/mimery_guns)
var/real_type = pick(subtypesof(/obj/item/book/granter/spell) - banned_spells)
new real_type(loc)
return INITIALIZE_HINT_QDEL
///MARTIAL ARTS///
/obj/item/book/granter/martial
var/martial
var/martialname = "bug jitsu"
var/greet = "You feel like you have mastered the art in breaking code. Nice work, jackass."
/obj/item/book/granter/martial/attack_self(mob/user)
. = ..()
if(!.)
return
if(!martial)
return
var/datum/martial_art/MA = new martial
if(user.mind.martial_art)
for(var/datum/martial_art/knownmartial in user.mind.martial_art)
if(knownmartial.type == MA.type)
to_chat(user,"<span class='warning'>You already know [martialname]!</span>")
return
if(used == TRUE && oneuse == TRUE)
recoil(user)
else
to_chat(user, "<span class='notice'>You start reading about [martialname]...</span>")
reading = TRUE
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
reading = FALSE
qdel(MA)
return
if(do_after(user,50, user))
to_chat(user, "[greet]")
reading = FALSE
MA.teach(user)
user.log_message("<font color='orange'>learned the martial art [martialname] ([MA]).</font>", INDIVIDUAL_ATTACK_LOG)
onlearned(user)
/obj/item/book/granter/martial/cqc
martial = /datum/martial_art/cqc
name = "old manual"
martialname = "close quarters combat"
desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat."
greet = "<span class='boldannounce'>You've mastered the basics of CQC.</span>"
icon_state = "cqcmanual"
remarks = list("Kick... Slam...", "Lock... Kick...", "Strike their abdomen, neck and back for critical damage...", "Slam... Lock...", "I could probably combine this with some other martial arts!", "Words that kill...", "The last and final moment is yours...")
/obj/item/book/granter/martial/cqc/onlearned(mob/living/carbon/user)
..()
if(oneuse == TRUE)
to_chat(user, "<span class='warning'>[src] beeps ominously...</span>")
/obj/item/book/granter/martial/cqc/recoil(mob/living/carbon/user)
to_chat(user, "<span class='warning'>[src] explodes!</span>")
playsound(src,'sound/effects/explosion1.ogg',40,1)
user.flash_act(1, 1)
user.adjustBruteLoss(6)
user.adjustFireLoss(6)
qdel(src)
/obj/item/book/granter/martial/carp
martial = /datum/martial_art/the_sleeping_carp
name = "mysterious scroll"
martialname = "sleeping carp"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
greet = "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
remarks = list("I must prove myself worthy to the masters of the sleeping carp...", "Stance means everything...", "Focus... And you'll be able to incapacitate any foe in seconds...", "I must pierce armor for maximum damage...", "I don't think this would combine with other martial arts...", "Grab them first so they don't retaliate...", "I must prove myself worthy of this power...")
/obj/item/book/granter/martial/carp/onlearned(mob/living/carbon/user)
..()
if(oneuse == TRUE)
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
/obj/item/book/granter/martial/plasma_fist
martial = /datum/martial_art/plasma_fist
name = "frayed scroll"
martialname = "plasma fist"
desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism."
greet = "<span class='boldannounce'>You have learned the ancient martial art of Plasma Fist. Your combos are extremely hard to pull off, but include some of the most deadly moves ever seen including \
the plasma fist, which when pulled off will make someone violently explode.</span>"
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
remarks = list("Balance...", "Power...", "Control...", "Mastery...", "Vigilance...", "Skill...")
/obj/item/book/granter/martial/plasma_fist/onlearned(mob/living/carbon/user)
..()
if(oneuse == TRUE)
desc = "It's completely blank."
name = "empty scroll"
icon_state = "blankscroll"
// I did not include mushpunch's grant, it is not a book and the item does it just fine.

View File

@@ -957,60 +957,3 @@
author = "Engineering Encyclopedia"
title = "Hacking"
page_link = "Hacking"
///Reusable books that grant actions (knowledge is power)
/obj/item/book/action_granting
due_date = 0 // Game time in 1/10th seconds
unique = 1 // 0 - Normal book, 1 - Should not be treated as normal book, unable to be copied, unable to be modified
var/datum/action/granted_action = null
var/list/remarks = list() //things to read about while learning.
var/pages_to_mastery = 3 //Essentially controls how long a mob must keep the book in his hand to actually successfully learn
/obj/item/book/action_granting/attack_self(mob/user)
if(!granted_action)
return
var/datum/action/G = new granted_action
for(var/datum/action/A in user.actions)
if(A.type == G.type)
to_chat(user, "<span class='notice'>You already know all about [G.name].</span>")
qdel(G)
return
to_chat(user, "<span class='notice'>You start reading about [G.name]...</span>")
for(var/i=1, i<=pages_to_mastery, i++)
if(!turn_page(user))
to_chat(user, "<span class='notice'>You stop reading...</span>")
qdel(G)
return
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [G.name]!</span>")
G.Grant(user)
/obj/item/book/action_granting/proc/turn_page(mob/user)
playsound(user, pick('sound/effects/pageturn1.ogg','sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg'), 30, 1)
if(do_after(user,50, user))
to_chat(user, "<span class='notice'>[pick(remarks)]</span>")
return 1
return 0
/obj/item/book/action_granting/drink_fling
name = "Tapper: This One's For You"
desc = "A seminal work on the dying art of booze sliding."
icon_state = "barbook"
granted_action = /datum/action/innate/drink_fling
remarks = list("The trick is keeping a low center of gravity it seems...", "The viscosity of the liquid is important...", "Accounting for crosswinds... really?", "Drag coefficients of various popular drinking glasses...", "What the heck is laminar flow and why does it matter here?", "Greasing the bar seems like it'd be cheating...", "I don't think I'll be working with superfluids...")
/datum/action/innate/drink_fling
name = "Drink Flinging"
desc = "Toggles your ability to satifyingly throw glasses without spilling them."
button_icon_state = "drinkfling_off"
check_flags = 0
/datum/action/innate/drink_fling/Activate()
button_icon_state = "drinkfling_on"
active = TRUE
UpdateButtonIcon()
/datum/action/innate/drink_fling/Deactivate()
button_icon_state = "drinkfling_off"
active = FALSE
UpdateButtonIcon()

View File

@@ -97,7 +97,7 @@
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
new /obj/item/card/id/syndicate(src)
new /obj/item/clothing/shoes/chameleon/noslip(src) //because slipping while being a dark lord sucks
new /obj/item/spellbook/oneuse/summonitem(src)
new /obj/item/book/granter/spell/summonitem(src)
if("sniper") //This shit is unique so can't really balance it around tc, also no silencer because getting killed without ANY indicator on what killed you sucks
new /obj/item/gun/ballistic/automatic/sniper_rifle(src) // 12 tc
@@ -303,8 +303,8 @@
new /obj/item/gun/ballistic/revolver/reverse(src)
/obj/item/storage/box/syndie_kit/mimery/PopulateContents()
new /obj/item/spellbook/oneuse/mimery_blockade(src)
new /obj/item/spellbook/oneuse/mimery_guns(src)
new /obj/item/book/granter/spell/mimery_blockade(src)
new /obj/item/book/granter/spell/mimery_guns(src)
/obj/item/storage/box/syndie_kit/imp_radio/PopulateContents()
new /obj/item/implanter/radio/syndicate(src)

View File

@@ -1,3 +1,4 @@
<<<<<<< HEAD
/datum/spellbook_entry
var/name = "Entry Name"
@@ -906,3 +907,721 @@
spellname = "sacred flame"
icon_state ="booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."
=======
/datum/spellbook_entry
var/name = "Entry Name"
var/spell_type = null
var/desc = ""
var/category = "Offensive"
var/cost = 2
var/refundable = 1
var/surplus = -1 // -1 for infinite, not used by anything atm
var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
var/list/no_coexistance_typecache //Used so you can't have specific spells together
/datum/spellbook_entry/New()
..()
no_coexistance_typecache = typecacheof(no_coexistance_typecache)
/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied
return 1
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances
if(book.uses<cost || limit == 0)
return 0
for(var/spell in user.mind.spell_list)
if(is_type_in_typecache(spell, no_coexistance_typecache))
return 0
return 1
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success
if(!S || QDELETED(S))
S = new spell_type()
//Check if we got the spell already
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name)) // Not using directly in case it was learned from one spellbook then upgraded in another
if(aspell.spell_level >= aspell.level_max)
to_chat(user, "<span class='warning'>This spell cannot be improved further.</span>")
return 0
else
aspell.name = initial(aspell.name)
aspell.spell_level++
aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min)/ aspell.level_max)
if(aspell.charge_max < aspell.charge_counter)
aspell.charge_counter = aspell.charge_max
switch(aspell.spell_level)
if(1)
to_chat(user, "<span class='notice'>You have improved [aspell.name] into Efficient [aspell.name].</span>")
aspell.name = "Efficient [aspell.name]"
if(2)
to_chat(user, "<span class='notice'>You have further improved [aspell.name] into Quickened [aspell.name].</span>")
aspell.name = "Quickened [aspell.name]"
if(3)
to_chat(user, "<span class='notice'>You have further improved [aspell.name] into Free [aspell.name].</span>")
aspell.name = "Free [aspell.name]"
if(4)
to_chat(user, "<span class='notice'>You have further improved [aspell.name] into Instant [aspell.name].</span>")
aspell.name = "Instant [aspell.name]"
if(aspell.spell_level >= aspell.level_max)
to_chat(user, "<span class='notice'>This spell cannot be strengthened any further.</span>")
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]"))
return 1
//No same spell found - just learn it
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
user.mind.AddSpell(S)
to_chat(user, "<span class='notice'>You have learned [S.name].</span>")
return 1
/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user,obj/item/spellbook/book)
if(!refundable)
return 0
if(!S)
S = new spell_type()
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
return 1
return 0
/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user,obj/item/spellbook/book) //return point value or -1 for failure
var/area/wizard_station/A = locate() in GLOB.sortedAreas
if(!(user in A.contents))
to_chat(user, "<span class='warning'>You can only refund spells at the wizard lair</span>")
return -1
if(!S)
S = new spell_type()
var/spell_levels = 0
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
user.mind.spell_list.Remove(aspell)
qdel(S)
return cost * (spell_levels+1)
return -1
/datum/spellbook_entry/proc/GetInfo()
if(!S)
S = new spell_type()
var/dat =""
dat += "<b>[initial(S.name)]</b>"
if(S.charge_type == "recharge")
dat += " Cooldown:[S.charge_max/10]"
dat += " Cost:[cost]<br>"
dat += "<i>[S.desc][desc]</i><br>"
dat += "[S.clothes_req?"Needs wizard garb":"Can be cast without wizard garb"]<br>"
return dat
/datum/spellbook_entry/fireball
name = "Fireball"
spell_type = /obj/effect/proc_holder/spell/aimed/fireball
/datum/spellbook_entry/spell_cards
name = "Spell Cards"
spell_type = /obj/effect/proc_holder/spell/aimed/spell_cards
/datum/spellbook_entry/rod_form
name = "Rod Form"
spell_type = /obj/effect/proc_holder/spell/targeted/rod_form
/datum/spellbook_entry/magicm
name = "Magic Missile"
spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile
category = "Defensive"
/datum/spellbook_entry/disintegrate
name = "Disintegrate"
spell_type = /obj/effect/proc_holder/spell/targeted/touch/disintegrate
/datum/spellbook_entry/disabletech
name = "Disable Tech"
spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech
category = "Defensive"
cost = 1
/datum/spellbook_entry/repulse
name = "Repulse"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse
category = "Defensive"
/datum/spellbook_entry/lightningPacket
name = "Lightning bolt! Lightning bolt!"
spell_type = /obj/effect/proc_holder/spell/targeted/conjure_item/spellpacket
category = "Defensive"
/datum/spellbook_entry/timestop
name = "Time Stop"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
category = "Defensive"
/datum/spellbook_entry/smoke
name = "Smoke"
spell_type = /obj/effect/proc_holder/spell/targeted/smoke
category = "Defensive"
cost = 1
/datum/spellbook_entry/blind
name = "Blind"
spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
cost = 1
/datum/spellbook_entry/mindswap
name = "Mindswap"
spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
category = "Mobility"
/datum/spellbook_entry/forcewall
name = "Force Wall"
spell_type = /obj/effect/proc_holder/spell/targeted/forcewall
category = "Defensive"
cost = 1
/datum/spellbook_entry/blink
name = "Blink"
spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink
category = "Mobility"
/datum/spellbook_entry/teleport
name = "Teleport"
spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport
category = "Mobility"
/datum/spellbook_entry/mutate
name = "Mutate"
spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate
/datum/spellbook_entry/jaunt
name = "Ethereal Jaunt"
spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt
category = "Mobility"
/datum/spellbook_entry/knock
name = "Knock"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock
category = "Mobility"
cost = 1
/datum/spellbook_entry/fleshtostone
name = "Flesh to Stone"
spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
/datum/spellbook_entry/summonitem
name = "Summon Item"
spell_type = /obj/effect/proc_holder/spell/targeted/summonitem
category = "Assistance"
cost = 1
/datum/spellbook_entry/lichdom
name = "Bind Soul"
spell_type = /obj/effect/proc_holder/spell/targeted/lichdom
category = "Defensive"
/datum/spellbook_entry/teslablast
name = "Tesla Blast"
spell_type = /obj/effect/proc_holder/spell/targeted/tesla
/datum/spellbook_entry/lightningbolt
name = "Lightning Bolt"
spell_type = /obj/effect/proc_holder/spell/aimed/lightningbolt
cost = 3
/datum/spellbook_entry/lightningbolt/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success
. = ..()
user.flags_2 |= TESLA_IGNORE_2
/datum/spellbook_entry/infinite_guns
name = "Lesser Summon Guns"
spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun
cost = 3
no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage
/datum/spellbook_entry/arcane_barrage
name = "Arcane Barrage"
spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage
cost = 3
no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun
/datum/spellbook_entry/barnyard
name = "Barnyard Curse"
spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse
/datum/spellbook_entry/charge
name = "Charge"
spell_type = /obj/effect/proc_holder/spell/targeted/charge
category = "Assistance"
cost = 1
/datum/spellbook_entry/shapeshift
name = "Wild Shapeshift"
spell_type = /obj/effect/proc_holder/spell/targeted/shapeshift
category = "Assistance"
cost = 1
/datum/spellbook_entry/spacetime_dist
name = "Spacetime Distortion"
spell_type = /obj/effect/proc_holder/spell/spacetime_dist
category = "Defensive"
cost = 1
/datum/spellbook_entry/the_traps
name = "The Traps!"
spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps
category = "Defensive"
cost = 1
/datum/spellbook_entry/item
name = "Buy Item"
refundable = 0
buy_word = "Summon"
var/item_path= null
/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
new item_path(get_turf(user))
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
return 1
/datum/spellbook_entry/item/GetInfo()
var/dat =""
dat += "<b>[name]</b>"
dat += " Cost:[cost]<br>"
dat += "<i>[desc]</i><br>"
if(surplus>=0)
dat += "[surplus] left.<br>"
return dat
/datum/spellbook_entry/item/staffchange
name = "Staff of Change"
desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
item_path = /obj/item/gun/magic/staff/change
/datum/spellbook_entry/item/staffanimation
name = "Staff of Animation"
desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines."
item_path = /obj/item/gun/magic/staff/animate
category = "Assistance"
/datum/spellbook_entry/item/staffchaos
name = "Staff of Chaos"
desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended."
item_path = /obj/item/gun/magic/staff/chaos
/datum/spellbook_entry/item/spellblade
name = "Spellblade"
desc = "A sword capable of firing blasts of energy which rip targets limb from limb."
item_path = /obj/item/gun/magic/staff/spellblade
/datum/spellbook_entry/item/staffdoor
name = "Staff of Door Creation"
desc = "A particular staff that can mold solid metal into ornate doors. Useful for getting around in the absence of other transportation. Does not work on glass."
item_path = /obj/item/gun/magic/staff/door
cost = 1
category = "Mobility"
/datum/spellbook_entry/item/staffhealing
name = "Staff of Healing"
desc = "An altruistic staff that can heal the lame and raise the dead."
item_path = /obj/item/gun/magic/staff/healing
cost = 1
category = "Defensive"
/datum/spellbook_entry/item/scryingorb
name = "Scrying Orb"
desc = "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision."
item_path = /obj/item/scrying
category = "Defensive"
/datum/spellbook_entry/item/soulstones
name = "Six Soul Stone Shards and the spell Artificer"
desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot."
item_path = /obj/item/storage/belt/soulstone/full
category = "Assistance"
/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
. =..()
if(.)
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null))
return .
/datum/spellbook_entry/item/necrostone
name = "A Necromantic Stone"
desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command."
item_path = /obj/item/device/necromantic_stone
category = "Assistance"
/datum/spellbook_entry/item/wands
name = "Wand Assortment"
desc = "A collection of wands that allow for a wide variety of utility. Wands have a limited number of charges, so be conservative in use. Comes in a handy belt."
item_path = /obj/item/storage/belt/wands/full
category = "Defensive"
/datum/spellbook_entry/item/armor
name = "Mastercrafted Armor Set"
desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space."
item_path = /obj/item/clothing/suit/space/hardsuit/wizard
category = "Defensive"
/datum/spellbook_entry/item/armor/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
. = ..()
if(.)
new /obj/item/clothing/shoes/sandal/magic(get_turf(user)) //In case they've lost them.
new /obj/item/clothing/gloves/color/purple(get_turf(user))//To complete the outfit
/datum/spellbook_entry/item/contract
name = "Contract of Apprenticeship"
desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
item_path = /obj/item/antag_spawner/contract
category = "Assistance"
/datum/spellbook_entry/item/guardian
name = "Guardian Deck"
desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \
It would be wise to avoid buying these with anything capable of causing you to swap bodies with others."
item_path = /obj/item/guardiancreator/choose/wizard
category = "Assistance"
/datum/spellbook_entry/item/guardian/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
. = ..()
if(.)
new /obj/item/paper/guides/antag/guardian/wizard(get_turf(user))
/datum/spellbook_entry/item/bloodbottle
name = "Bottle of Blood"
desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim."
item_path = /obj/item/antag_spawner/slaughter_demon
limit = 3
category = "Assistance"
/datum/spellbook_entry/item/hugbottle
name = "Bottle of Tickles"
desc = "A bottle of magically infused fun, the smell of which will \
attract adorable extradimensional beings when broken. These beings \
are similar to slaughter demons, but they do not permamently kill \
their victims, instead putting them in an extradimensional hugspace, \
to be released on the demon's death. Chaotic, but not ultimately \
damaging. The crew's reaction to the other hand could be very \
destructive."
item_path = /obj/item/antag_spawner/slaughter_demon/laughter
cost = 1 //non-destructive; it's just a jape, sibling!
limit = 3
category = "Assistance"
/datum/spellbook_entry/item/mjolnir
name = "Mjolnir"
desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power."
item_path = /obj/item/twohanded/mjollnir
/datum/spellbook_entry/item/singularity_hammer
name = "Singularity Hammer"
desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everything nearby to the point of impact."
item_path = /obj/item/twohanded/singularityhammer
/datum/spellbook_entry/item/battlemage
name = "Battlemage Armour"
desc = "An ensorcelled suit of armour, protected by a powerful shield. The shield can completly negate sixteen attacks before being permanently depleted."
item_path = /obj/item/clothing/suit/space/hardsuit/shielded/wizard
limit = 1
category = "Defensive"
/datum/spellbook_entry/item/battlemage_charge
name = "Battlemage Armour Charges"
desc = "A powerful defensive rune, it will grant eight additional charges to a suit of battlemage armour."
item_path = /obj/item/wizard_armour_charge
category = "Defensive"
cost = 1
/datum/spellbook_entry/item/warpwhistle
name = "Warp Whistle"
desc = "A strange whistle that will transport you to a distant safe place on the station. There is a window of vulnerability at the beginning of every use."
item_path = /obj/item/warpwhistle
category = "Mobility"
cost = 1
/datum/spellbook_entry/summon
name = "Summon Stuff"
category = "Rituals"
refundable = 0
buy_word = "Cast"
var/active = 0
/datum/spellbook_entry/summon/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book)
return ..() && !active
/datum/spellbook_entry/summon/GetInfo()
var/dat =""
dat += "<b>[name]</b>"
if(cost>0)
dat += " Cost:[cost]<br>"
else
dat += " No Cost<br>"
dat += "<i>[desc]</i><br>"
if(active)
dat += "<b>Already cast!</b><br>"
return dat
/datum/spellbook_entry/summon/ghosts
name = "Summon Ghosts"
desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilties to frustrate you."
cost = 0
/datum/spellbook_entry/summon/ghosts/IsAvailible()
if(!SSticker.mode)
return FALSE
else
return TRUE
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
new /datum/round_event/wizard/ghost()
active = TRUE
to_chat(user, "<span class='notice'>You have cast summon ghosts!</span>")
playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1)
return TRUE
/datum/spellbook_entry/summon/guns
name = "Summon Guns"
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!"
/datum/spellbook_entry/summon/guns/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_guns)
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
rightandwrong(SUMMON_GUNS, user, 25)
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon guns!</span>")
return 1
/datum/spellbook_entry/summon/magic
name = "Summon Magic"
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
/datum/spellbook_entry/summon/magic/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_magic)
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
rightandwrong(SUMMON_MAGIC, user, 25)
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon magic!</span>")
return 1
/datum/spellbook_entry/summon/events
name = "Summon Events"
desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events."
var/times = 0
/datum/spellbook_entry/summon/events/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_events)
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
summonevents()
times++
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon events.</span>")
return 1
/datum/spellbook_entry/summon/events/GetInfo()
. = ..()
if(times>0)
. += "You cast it [times] times.<br>"
return .
/obj/item/spellbook
name = "spell book"
desc = "An unearthly tome that glows with power."
icon = 'icons/obj/library.dmi'
icon_state ="book"
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/uses = 10
var/temp = null
var/tab = null
var/mob/living/carbon/human/owner
var/list/datum/spellbook_entry/entries = list()
var/list/categories = list()
/obj/item/spellbook/examine(mob/user)
..()
if(owner)
to_chat(user, "There is a small signature on the front cover: \"[owner]\".")
else
to_chat(user, "It appears to have no author.")
/obj/item/spellbook/Initialize()
. = ..()
prepare_spells()
/obj/item/spellbook/proc/prepare_spells()
var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon
for(var/T in entry_types)
var/datum/spellbook_entry/E = new T
if(E.IsAvailible())
entries |= E
categories |= E.category
else
qdel(E)
tab = categories[1]
/obj/item/spellbook/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/antag_spawner/contract))
var/obj/item/antag_spawner/contract/contract = O
if(contract.used)
to_chat(user, "<span class='warning'>The contract has been used, you can't get your points back now!</span>")
else
to_chat(user, "<span class='notice'>You feed the contract back into the spellbook, refunding your points.</span>")
uses++
for(var/datum/spellbook_entry/item/contract/CT in entries)
if(!isnull(CT.limit))
CT.limit++
qdel(O)
else if(istype(O, /obj/item/antag_spawner/slaughter_demon))
to_chat(user, "<span class='notice'>On second thought, maybe summoning a demon is a bad idea. You refund your points.</span>")
uses++
for(var/datum/spellbook_entry/item/bloodbottle/BB in entries)
if(!isnull(BB.limit))
BB.limit++
qdel(O)
/obj/item/spellbook/proc/GetCategoryHeader(category)
var/dat = ""
switch(category)
if("Offensive")
dat += "Spells and items geared towards debilitating and destroying.<BR><BR>"
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.<BR>"
dat += "For spells: the number after the spell name is the cooldown time.<BR>"
dat += "You can reduce this number by spending more points on the spell.<BR>"
if("Defensive")
dat += "Spells and items geared towards improving your survivabilty or reducing foes' ability to attack.<BR><BR>"
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.<BR>"
dat += "For spells: the number after the spell name is the cooldown time.<BR>"
dat += "You can reduce this number by spending more points on the spell.<BR>"
if("Mobility")
dat += "Spells and items geared towards improving your ability to move. It is a good idea to take at least one.<BR><BR>"
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.<BR>"
dat += "For spells: the number after the spell name is the cooldown time.<BR>"
dat += "You can reduce this number by spending more points on the spell.<BR>"
if("Assistance")
dat += "Spells and items geared towards bringing in outside forces to aid you or improving upon your other items and abilties.<BR><BR>"
dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.<BR>"
dat += "For spells: the number after the spell name is the cooldown time.<BR>"
dat += "You can reduce this number by spending more points on the spell.<BR>"
if("Challenges")
dat += "The Wizard Federation typically has hard limits on the potency and number of spells brought to the station based on risk.<BR>"
dat += "Arming the station against you will increases the risk, but will grant you one more charge for your spellbook.<BR>"
if("Rituals")
dat += "These powerful spells change the very fabric of reality. Not always in your favour.<BR>"
return dat
/obj/item/spellbook/proc/wrap(content)
var/dat = ""
dat +="<html><head><title>Spellbook</title></head>"
dat += {"
<head>
<style type="text/css">
body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
ul#tabs li { display: inline; }
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
ul#tabs li a:hover { background-color: #f1f0ee; }
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
div.tabContent.hide { display: none; }
</style>
</head>
"}
dat += {"[content]</body></html>"}
return dat
/obj/item/spellbook/attack_self(mob/user)
if(!owner)
to_chat(user, "<span class='notice'>You bind the spellbook to yourself.</span>")
owner = user
return
if(user != owner)
to_chat(user, "<span class='warning'>The [name] does not recognize you as its owner and refuses to open!</span>")
return
user.set_machine(src)
var/dat = ""
dat += "<ul id=\"tabs\">"
var/list/cat_dat = list()
for(var/category in categories)
cat_dat[category] = "<hr>"
dat += "<li><a [tab==category?"class=selected":""] href='byond://?src=[REF(src)];page=[category]'>[category]</a></li>"
dat += "<li><a><b>Points remaining : [uses]</b></a></li>"
dat += "</ul>"
var/datum/spellbook_entry/E
for(var/i=1,i<=entries.len,i++)
var/spell_info = ""
E = entries[i]
spell_info += E.GetInfo()
if(E.CanBuy(user,src))
spell_info+= "<a href='byond://?src=[REF(src)];buy=[i]'>[E.buy_word]</A><br>"
else
spell_info+= "<span>Can't [E.buy_word]</span><br>"
if(E.CanRefund(user,src))
spell_info+= "<a href='byond://?src=[REF(src)];refund=[i]'>Refund</A><br>"
spell_info += "<hr>"
if(cat_dat[E.category])
cat_dat[E.category] += spell_info
for(var/category in categories)
dat += "<div class=\"[tab==category?"tabContent":"tabContent hide"]\" id=\"[category]\">"
dat += GetCategoryHeader(category)
dat += cat_dat[category]
dat += "</div>"
user << browse(wrap(dat), "window=spellbook;size=700x500")
onclose(user, "spellbook")
return
/obj/item/spellbook/Topic(href, href_list)
..()
var/mob/living/carbon/human/H = usr
if(H.stat || H.restrained())
return
if(!ishuman(H))
return 1
if(H.mind.special_role == "apprentice")
temp = "If you got caught sneaking a peek from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not."
return
var/datum/spellbook_entry/E = null
if(loc == H || (in_range(src, H) && isturf(loc)))
H.set_machine(src)
if(href_list["buy"])
E = entries[text2num(href_list["buy"])]
if(E && E.CanBuy(H,src))
if(E.Buy(H,src))
if(E.limit)
E.limit--
uses -= E.cost
else if(href_list["refund"])
E = entries[text2num(href_list["refund"])]
if(E && E.refundable)
var/result = E.Refund(H,src)
if(result > 0)
if(!isnull(E.limit))
E.limit += result
uses += result
else if(href_list["page"])
tab = sanitize(href_list["page"])
attack_self(H)
return
>>>>>>> 5ed2a56... Refactors Spell and Martial Art Books to use Action Granters! (#36442)

View File

@@ -260,7 +260,7 @@
new /obj/item/gun/ballistic/revolver/mateba(drop_location())
if(15)
//Random One-use spellbook
new /obj/item/spellbook/oneuse/random(drop_location())
new /obj/item/book/granter/spell/random(drop_location())
if(16)
//Servant & Servant Summon
var/mob/living/carbon/human/H = new(drop_location())

View File

@@ -477,8 +477,8 @@
name = "dungeon lite"
loot = list(/obj/item/melee/classic_baton = 11,
/obj/item/melee/classic_baton/telescopic = 12,
/obj/item/spellbook/oneuse/smoke = 10,
/obj/item/spellbook/oneuse/blind = 10,
/obj/item/book/granter/spell/smoke = 10,
/obj/item/book/granter/spell/blind = 10,
/obj/item/storage/firstaid/regular = 45,
/obj/item/storage/firstaid/toxin = 35,
/obj/item/storage/firstaid/brute = 27,
@@ -501,9 +501,9 @@
/obj/item/gun/magic/wand/fireball/inert = 3,
/obj/item/pneumatic_cannon = 15,
/obj/item/melee/transforming/energy/sword = 7,
/obj/item/spellbook/oneuse/knock = 15,
/obj/item/spellbook/oneuse/summonitem = 20,
/obj/item/spellbook/oneuse/forcewall = 17,
/obj/item/book/granter/spell/knock = 15,
/obj/item/book/granter/spell/summonitem = 20,
/obj/item/book/granter/spell/forcewall = 17,
/obj/item/storage/backpack/holding = 12,
/obj/item/grenade/spawnergrenade/manhacks = 6,
/obj/item/grenade/spawnergrenade/spesscarp = 7,
@@ -512,7 +512,7 @@
/obj/item/stack/sheet/mineral/uranium{amount = 15} = 10,
/obj/item/stack/sheet/mineral/plasma{amount = 15} = 10,
/obj/item/stack/sheet/mineral/gold{amount = 15} = 10,
/obj/item/spellbook/oneuse/barnyard = 4,
/obj/item/book/granter/spell/barnyard = 4,
/obj/item/pickaxe/drill/diamonddrill = 6,
/obj/item/borg/upgrade/vtec = 7,
/obj/item/borg/upgrade/disablercooler = 7)
@@ -530,9 +530,9 @@
/obj/item/gun/magic/wand/resurrection/inert = 15,
/obj/item/gun/magic/wand/resurrection = 10,
/obj/item/device/radio/uplink/old = 2,
/obj/item/spellbook/oneuse/charge = 12,
/obj/item/book/granter/spell/charge = 12,
/obj/item/grenade/clusterbuster/spawner_manhacks = 15,
/obj/item/spellbook/oneuse/fireball = 10,
/obj/item/book/granter/spell/fireball = 10,
/obj/item/pickaxe/drill/jackhammer = 30,
/obj/item/borg/upgrade/syndicate = 13,
/obj/item/borg/upgrade/selfrepair = 17)

View File

@@ -1532,7 +1532,7 @@
/obj/item/vending_refill/coffee,
/obj/item/vending_refill/coffee,
/obj/item/vending_refill/coffee,
/obj/item/book/action_granting/drink_fling)
/obj/item/book/granter/action/drink_fling)
crate_name = "bartending supply crate"
/datum/supply_pack/organic/vending/cigarette

View File

@@ -167,7 +167,7 @@ Bartender
ears = /obj/item/device/radio/headset/headset_srv
uniform = /obj/item/clothing/under/rank/bartender
suit = /obj/item/clothing/suit/armor/vest
backpack_contents = list(/obj/item/storage/box/beanbag=1,/obj/item/book/action_granting/drink_fling=1)
backpack_contents = list(/obj/item/storage/box/beanbag=1,/obj/item/book/granter/action/drink_fling=1)
shoes = /obj/item/clothing/shoes/laceup
/*

View File

@@ -274,7 +274,7 @@
icon_state = "x2"
var/possible = list(/obj/item/ship_in_a_bottle,
/obj/item/gun/energy/pulse,
/obj/item/sleeping_carp_scroll,
/obj/item/book/granter/martial/carp,
/obj/item/melee/supermatter_sword,
/obj/item/shield/changeling,
/obj/item/lava_staff,

View File

@@ -69,7 +69,7 @@
new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src)
if(25)
new /obj/item/spellbook/oneuse/summonitem(src)
new /obj/item/book/granter/spell/summonitem(src)
if(26)
new /obj/item/book_of_babel(src)
if(27)
@@ -693,7 +693,7 @@
if(2)
new /obj/item/lava_staff(src)
if(3)
new /obj/item/spellbook/oneuse/sacredflame(src)
new /obj/item/book/granter/spell/sacredflame(src)
new /obj/item/gun/magic/wand/fireball(src)
if(4)
new /obj/item/dragons_blood(src)

View File

@@ -16,7 +16,7 @@
for(var/mob/living/L in targets)
var/list/hand_items = list(L.get_active_held_item(),L.get_inactive_held_item())
var/charged_item = null
var/burnt_out = 0
var/burnt_out = FALSE
if(L.pulling && isliving(L.pulling))
var/mob/living/M = L.pulling
@@ -34,26 +34,30 @@
break
for(var/obj/item in hand_items)
if(istype(item, /obj/item/spellbook))
if(istype(item, /obj/item/spellbook/oneuse))
var/obj/item/spellbook/oneuse/I = item
if(prob(80))
L.visible_message("<span class='warning'>[I] catches fire!</span>")
qdel(I)
else
I.used = 0
charged_item = I
break
to_chat(L, "<span class='danger'>Glowing red letters appear on the front cover...</span>")
to_chat(L, "<span class='warning'>[pick("NICE TRY BUT NO!","CLEVER BUT NOT CLEVER ENOUGH!", "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", "CUTE! VERY CUTE!", "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?")]</span>")
burnt_out = TRUE
else if(istype(item, /obj/item/book/granter/spell))
var/obj/item/book/granter/spell/I = item
if(!I.oneuse)
to_chat(L, "<span class='notice'>This book is infinite use and can't be recharged, yet the magic has improved the book somehow...</span>")
burnt_out = TRUE
I.pages_to_mastery--
break
if(prob(80))
L.visible_message("<span class='warning'>[I] catches fire!</span>")
qdel(I)
else
to_chat(L, "<span class='danger'>Glowing red letters appear on the front cover...</span>")
to_chat(L, "<span class='warning'>[pick("NICE TRY BUT NO!","CLEVER BUT NOT CLEVER ENOUGH!", "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", "CUTE! VERY CUTE!", "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?")]</span>")
burnt_out = 1
I.used = FALSE
charged_item = I
break
else if(istype(item, /obj/item/gun/magic))
var/obj/item/gun/magic/I = item
if(prob(80) && !I.can_charge)
I.max_charges--
if(I.max_charges <= 0)
I.max_charges = 0
burnt_out = 1
burnt_out = TRUE
I.charges = I.max_charges
if(istype(item, /obj/item/gun/magic/wand) && I.max_charges != 0)
var/obj/item/gun/magic/W = item
@@ -61,14 +65,14 @@
I.recharge_newshot()
charged_item = I
break
else if(istype(item, /obj/item/stock_parts/cell/))
else if(istype(item, /obj/item/stock_parts/cell))
var/obj/item/stock_parts/cell/C = item
if(!C.self_recharge)
if(prob(80))
C.maxcharge -= 200
if(C.maxcharge <= 1) //Div by 0 protection
C.maxcharge = 1
burnt_out = 1
burnt_out = TRUE
C.charge = C.maxcharge
charged_item = C
break
@@ -82,7 +86,7 @@
C.maxcharge -= 200
if(C.maxcharge <= 1) //Div by 0 protection
C.maxcharge = 1
burnt_out = 1
burnt_out = TRUE
C.charge = C.maxcharge
if(istype(C.loc, /obj/item/gun))
var/obj/item/gun/G = C.loc

View File

@@ -127,16 +127,19 @@
..()
/obj/item/spellbook/oneuse/mimery_blockade
/obj/item/book/granter/spell/mimery_blockade
spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
spellname = ""
name = "Guide to Advanced Mimery Vol 1"
desc = "The pages don't make any sound when turned."
icon_state ="bookmime"
remarks = list("...")
/obj/item/spellbook/oneuse/mimery_guns
/obj/item/book/granter/spell/mimery_guns
spell = /obj/effect/proc_holder/spell/aimed/finger_guns
spellname = ""
name = "Guide to Advanced Mimery Vol 2"
desc = "There aren't any words written..."
icon_state ="bookmime"
remarks = list("...")

View File

@@ -47,15 +47,15 @@ GLOBAL_LIST_INIT(summoned_guns, list(
/obj/item/gun/energy/gravity_gun))
GLOBAL_LIST_INIT(summoned_magic, list(
/obj/item/spellbook/oneuse/fireball,
/obj/item/spellbook/oneuse/smoke,
/obj/item/spellbook/oneuse/blind,
/obj/item/spellbook/oneuse/mindswap,
/obj/item/spellbook/oneuse/forcewall,
/obj/item/spellbook/oneuse/knock,
/obj/item/spellbook/oneuse/barnyard,
/obj/item/spellbook/oneuse/charge,
/obj/item/spellbook/oneuse/summonitem,
/obj/item/book/granter/spell/fireball,
/obj/item/book/granter/spell/smoke,
/obj/item/book/granter/spell/blind,
/obj/item/book/granter/spell/mindswap,
/obj/item/book/granter/spell/forcewall,
/obj/item/book/granter/spell/knock,
/obj/item/book/granter/spell/barnyard,
/obj/item/book/granter/spell/charge,
/obj/item/book/granter/spell/summonitem,
/obj/item/gun/magic/wand,
/obj/item/gun/magic/wand/death,
/obj/item/gun/magic/wand/resurrection,

View File

@@ -630,7 +630,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Martial Arts Scroll"
desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
item = /obj/item/sleeping_carp_scroll
item = /obj/item/book/granter/martial/carp
cost = 17
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
@@ -638,7 +638,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/stealthy_weapons/cqc
name = "CQC Manual"
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing."
item = /obj/item/cqc_manual
item = /obj/item/book/granter/martial/cqc
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
cost = 13
surplus = 0