From 4ac8a4164c5e7ebee7c2c98501b2080c4cc82d7d Mon Sep 17 00:00:00 2001 From: Incoming Date: Wed, 4 Dec 2013 21:00:36 -0500 Subject: [PATCH] Summon Magic / Charge / Wands&Staffs / One time spellbooks / New Apprentice --- Summon Magic: This new wizard spell works much like summon guns except it instead brings the crew magical tools and weapons. There are preexisting artifacts (minus some that would cause huge confusion/balance issues) as well as new spellbooks, wands, and a staff. The chance of survivor antag is the same as summon guns. --- Charge: This new spell allows for the recharging of otherwise unrefillable wands, but there's a heavy chance that the total number of charges will decrease with each casting until eventually they're impossible to keep recharging. As a bonus the charge spell can also be used to charge batteries and things that run on batteries (such as energy weapons). This carries the same max charge weardown penalties however. Lastly this spell allows a wizard to charge other wizards with a grab, reseting their spell cooldown. They cannot use it to charge themselves. It has a 60 second cooldown. The wizard cannot buy this spell himself, it only comes randomly to the crew during Summon Magic and with the new apprentice loadout. --- Wands&Staffs: Magic weapons have been overhauled into their own catagory so there won't be any more weirdness with batteries in staves or apparent magic resistance on things that reflect energy weapons. Wands have been added, these wands come precharged with a number of shots that can be fired off at their leasure but cannot be recharged once emptied (unless the charge spell is used). They come in a varity of exciting flavors: *Death: Slays instantly but has very few shots (1 to 3) *Resurrection: Revives and/or heals instantly but has very few shots (1 to 3) *Polymorph: Same function as the staff of change *Teleport: Weaponized blink spell that doesn't respect space tiles and can also warp away machinery or items (but not turf) *Door Creation: Puts easy access wooden doors in walls *Fireball: Same function (but slightly lower damage) as the fireball spell *Nothing: Lame and useless Wands can also be used on the user (unlike staves) by clicking on them. Warning messages have been added to a few wands so people don't accidentally zap themselves with the wand of death unless they really want to. Wands cannot be aquired by the wizard directly, and are only spawned during castings of summon magic. There is also a new staff, the staff of healing, which works as a recharging version of the wand of resurrection. The new apprentice starts with one of these, and they can also be found during summon magic. The wizard cannot purchase it directly, and as a stave he could not use it on himself anyways. --- One time spellbooks: Found exclusively in summon magic are one time use spellbooks that can teach any player a robeless spell. Once read the book vanishes. Books come in the following flavors: *fireball *smoke *blind *mindswap *forcewall *knock *curse of the horsemen *charge (described above) --- New apprentice: A fourth loadout for apprentice wizards has been added. This wizard is intended as a support role and comes with forcewall (for cover) and charge (used to keep him and the wizard well stocked in laser weaponry or to restore the wizard's cooldowns). It also comes equiped with a free Staff of Healing for keeping the wizard alive. Shoot the medic first folks. --- code/datums/spells/charge.dm | 74 ++++++ code/game/gamemodes/wizard/artefact.dm | 7 + code/game/gamemodes/wizard/rightandwrong.dm | 141 ++++++---- code/game/gamemodes/wizard/spellbook.dm | 95 ++++++- code/game/machinery/recharger.dm | 2 - code/game/machinery/turrets.dm | 2 +- .../projectiles/guns/energy/special.dm | 49 ---- code/modules/projectiles/guns/magic.dm | 56 ++++ code/modules/projectiles/guns/magic/staff.dm | 23 ++ code/modules/projectiles/guns/magic/wand.dm | 227 ++++++++++++++++ code/modules/projectiles/projectile/magic.dm | 249 ++++++++++++++++++ tgstation.dme | 49 +--- 12 files changed, 828 insertions(+), 146 deletions(-) create mode 100644 code/datums/spells/charge.dm create mode 100644 code/modules/projectiles/guns/magic.dm create mode 100644 code/modules/projectiles/guns/magic/staff.dm create mode 100644 code/modules/projectiles/guns/magic/wand.dm create mode 100644 code/modules/projectiles/projectile/magic.dm diff --git a/code/datums/spells/charge.dm b/code/datums/spells/charge.dm new file mode 100644 index 00000000000..0ace8c7d9cd --- /dev/null +++ b/code/datums/spells/charge.dm @@ -0,0 +1,74 @@ +/obj/effect/proc_holder/spell/targeted/charge + name = "Charge" + desc = "This spell can be used to charge up spent magical artifacts, among other things." + + school = "transmutation" + charge_max = 600 + clothes_req = 0 + invocation = "DIRI CEL" + invocation_type = "whisper" + range = -1 + cooldown_min = 400 //50 deciseconds reduction per rank + include_user = 1 + + +/obj/effect/proc_holder/spell/targeted/charge/cast(list/targets) + for(var/mob/living/user in targets) + var/list/hand_items = list(user.get_active_hand(),user.get_inactive_hand()) + var/charged_item = null + var/burnt_out = 0 + world << "[user.l_hand] and [user.r_hand]" + for(var/obj/item in hand_items) + if(istype(item, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = item + if(G.affecting) + var/mob/M = G.affecting + if(M.spell_list.len != 0) + for(var/obj/effect/proc_holder/spell/S in M.spell_list) + S.charge_counter = S.charge_max + M <<"\blue you feel raw magic flowing through you, it feels good!" + else + M <<"\blue you feel very strange for a moment, but then it passes." + burnt_out = 1 + charged_item = M + break + else if(istype(item, /obj/item/weapon/gun/magic)) + var/obj/item/weapon/gun/magic/I = item + if(prob(80)) + I.max_charges-- + if(I.max_charges <= 0) + I.max_charges = 0 + burnt_out = 1 + I.charges = I.max_charges + charged_item = I + break + else if(istype(item, /obj/item/weapon/cell/)) + var/obj/item/weapon/cell/C = item + if(prob(80)) + C.maxcharge -= 200 + if(C.maxcharge <= 1) //Div by 0 protection + C.maxcharge = 1 + burnt_out = 1 + C.charge = C.maxcharge + charged_item = C + break + else if(item.contents) + var/obj/I = null + for(I in item.contents) + if(istype(I, /obj/item/weapon/cell/)) + var/obj/item/weapon/cell/C = I + if(prob(80)) + C.maxcharge -= 200 + if(C.maxcharge <= 1) //Div by 0 protection + C.maxcharge = 1 + burnt_out = 1 + C.charge = C.maxcharge + item.update_icon() + charged_item = item + break + if(!charged_item) + user << "\blue you feel magical power surging to your hands, but the feeling rapidly fades..." + else if(burnt_out) + user << "\red [charged_item] doesn't seem to be reacting to the spell..." + else + user << "\blue [charged_item] suddenly feels very warm!" diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 5bad56a6135..3d404dfc846 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -27,6 +27,8 @@ dat += "Your apprentice is skilled in offensive magic. They know Magic Missile and Fireball.
" dat += "Bluespace Manipulation
" dat += "Your apprentice is able to defy physics, melting through solid objects and travelling great distances in the blink of an eye. They know Teleport and Ethereal Jaunt.
" + dat += "Healing
" + dat += "Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.
" dat += "Robeless
" dat += "Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.
" user << browse(dat, "window=radio") @@ -66,6 +68,11 @@ M.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(M) M.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(M) M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt." + if("healing") + M.spell_list += new /obj/effect/proc_holder/spell/targeted/charge(M) + M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(M) + M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand) + M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall." if("robeless") M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(M) M.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(M) diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm index c18732cdb01..4b0d7633e82 100644 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ b/code/game/gamemodes/wizard/rightandwrong.dm @@ -1,8 +1,8 @@ -/mob/proc/rightandwrong() - usr << "You summoned guns!" - message_admins("[key_name_admin(usr, 1)] summoned guns!") +/mob/proc/rightandwrong(var/summon_type) //0 = Summon Guns, 1 = Summon Magic + usr << "You summoned [summon_type ? "magic" : "guns"]!" + message_admins("[key_name_admin(usr, 1)] summoned [summon_type ? "magic" : "guns"]!") for(var/mob/living/carbon/human/H in player_list) if(H.stat == 2 || !(H.client)) continue if(is_special_character(H)) continue @@ -18,46 +18,95 @@ for(var/datum/objective/OBJ in H.mind.objectives) H << "Objective #[obj_count]: [OBJ.explanation_text]" obj_count++ - var/randomize = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw") - switch (randomize) - if("taser") - new /obj/item/weapon/gun/energy/taser(get_turf(H)) - if("egun") - new /obj/item/weapon/gun/energy/gun(get_turf(H)) - if("laser") - new /obj/item/weapon/gun/energy/laser(get_turf(H)) - if("revolver") - new /obj/item/weapon/gun/projectile/revolver(get_turf(H)) - if("detective") - new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H)) - if("smg") - new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H)) - if("nuclear") - new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H)) - if("deagle") - new /obj/item/weapon/gun/projectile/automatic/deagle/camo(get_turf(H)) - if("gyrojet") - new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H)) - if("pulse") - new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H)) - if("silenced") - new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H)) - new /obj/item/weapon/silencer(get_turf(H)) - if("cannon") - new /obj/item/weapon/gun/energy/lasercannon(get_turf(H)) - if("doublebarrel") - new /obj/item/weapon/gun/projectile/revolver/doublebarrel(get_turf(H)) - if("shotgun") - new /obj/item/weapon/gun/projectile/shotgun/(get_turf(H)) - if("combatshotgun") - new /obj/item/weapon/gun/projectile/shotgun/combat(get_turf(H)) - if("mateba") - new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H)) - if("smg") - new /obj/item/weapon/gun/projectile/automatic(get_turf(H)) - if("uzi") - new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H)) - if("crossbow") - new /obj/item/weapon/gun/energy/crossbow(get_turf(H)) - if("saw") - new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H)) \ No newline at end of file + var/randomizeguns = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw") + var/randomizemagic = pick("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge","wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffchange", "staffanimation", "staffhealing", "armor", "scrying") + if(!summon_type) + switch (randomizeguns) + if("taser") + new /obj/item/weapon/gun/energy/taser(get_turf(H)) + if("egun") + new /obj/item/weapon/gun/energy/gun(get_turf(H)) + if("laser") + new /obj/item/weapon/gun/energy/laser(get_turf(H)) + if("revolver") + new /obj/item/weapon/gun/projectile/revolver(get_turf(H)) + if("detective") + new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H)) + if("smg") + new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H)) + if("nuclear") + new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H)) + if("deagle") + new /obj/item/weapon/gun/projectile/automatic/deagle/camo(get_turf(H)) + if("gyrojet") + new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H)) + if("pulse") + new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H)) + if("silenced") + new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H)) + new /obj/item/weapon/silencer(get_turf(H)) + if("cannon") + new /obj/item/weapon/gun/energy/lasercannon(get_turf(H)) + if("doublebarrel") + new /obj/item/weapon/gun/projectile/revolver/doublebarrel(get_turf(H)) + if("shotgun") + new /obj/item/weapon/gun/projectile/shotgun/(get_turf(H)) + if("combatshotgun") + new /obj/item/weapon/gun/projectile/shotgun/combat(get_turf(H)) + if("mateba") + new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H)) + if("smg") + new /obj/item/weapon/gun/projectile/automatic(get_turf(H)) + if("uzi") + new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H)) + if("crossbow") + new /obj/item/weapon/gun/energy/crossbow(get_turf(H)) + if("saw") + new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H)) + else + switch (randomizemagic) + if("fireball") + new /obj/item/weapon/spellbook/oneuse/fireball(get_turf(H)) + if("smoke") + new /obj/item/weapon/spellbook/oneuse/smoke(get_turf(H)) + if("blind") + new /obj/item/weapon/spellbook/oneuse/blind(get_turf(H)) + if("mindswap") + new /obj/item/weapon/spellbook/oneuse/mindswap(get_turf(H)) + if("forcewall") + new /obj/item/weapon/spellbook/oneuse/forcewall(get_turf(H)) + if("knock") + new /obj/item/weapon/spellbook/oneuse/knock(get_turf(H)) + if("horsemask") + new /obj/item/weapon/spellbook/oneuse/horsemask(get_turf(H)) + if("charge") + new /obj/item/weapon/spellbook/oneuse/charge(get_turf(H)) + if("wandnothing") + new /obj/item/weapon/gun/magic/wand(get_turf(H)) + if("wanddeath") + new /obj/item/weapon/gun/magic/wand/death(get_turf(H)) + if("wandresurrection") + new /obj/item/weapon/gun/magic/wand/resurrection(get_turf(H)) + if("wandpolymorph") + new /obj/item/weapon/gun/magic/wand/polymorph(get_turf(H)) + if("wandteleport") + new /obj/item/weapon/gun/magic/wand/teleport(get_turf(H)) + if("wanddoor") + new /obj/item/weapon/gun/magic/wand/door(get_turf(H)) + if("staffchange") + new /obj/item/weapon/gun/magic/staff/change(get_turf(H)) + if("staffanimation") + new /obj/item/weapon/gun/magic/staff/animate(get_turf(H)) + if("staffhealing") + new /obj/item/weapon/gun/magic/staff/healing(get_turf(H)) + if("armor") + new /obj/item/clothing/suit/space/rig/wizard(get_turf(H)) + new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(H)) + if("scrying") + new /obj/item/weapon/scrying(get_turf(H)) + if (!(XRAY in H.mutations)) + H.mutations.Add(XRAY) + H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) + H.see_in_dark = 8 + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + H << "\blue The walls suddenly disappear." diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 156554d486d..055e887981f 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -86,6 +86,9 @@ dat += "Summon Guns (One time use, global spell)
" dat += "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!
" + dat += "Summon Magic (One time use, global spell)
" + dat += "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time.
" + dat += "
" dat += "Artefacts:
" dat += "Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
" @@ -150,7 +153,7 @@ uses-- /* */ - var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", fleshtostone = "Flesh to Stone", summonguns = "Summon Guns", staffchange = "Staff of Change", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation") + var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", fleshtostone = "Flesh to Stone", summonguns = "Summon Guns", summonmagic = "Summon Magic", staffchange = "Staff of Change", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation") var/already_knows = 0 for(var/obj/effect/proc_holder/spell/aspell in H.spell_list) if(available_spells[href_list["spell_choice"]] == initial(aspell.name)) @@ -246,12 +249,17 @@ temp = "You have learned flesh to stone." if("summonguns") feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - H.rightandwrong() + H.rightandwrong(0) max_uses-- temp = "You have cast summon guns." + if("summonmagic") + feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.rightandwrong(1) + max_uses-- + temp = "You have cast summon magic." if("staffchange") feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff(get_turf(H)) + new /obj/item/weapon/gun/magic/staff/change(get_turf(H)) temp = "You have purchased a staff of change." max_uses-- if("soulstone") @@ -270,7 +278,7 @@ max_uses-- if("staffanimation") feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells - new /obj/item/weapon/gun/energy/staff/animate(get_turf(H)) + new /obj/item/weapon/gun/magic/staff/animate(get_turf(H)) temp = "You have purchased a staff of animation." max_uses-- if("contract") @@ -295,3 +303,82 @@ attack_self(H) return + +//Single Use Spellbooks// + +/obj/item/weapon/spellbook/oneuse + var/spell = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic + var/spellname = "sandbox" + name = "spellbook of " + uses = 1 + max_uses = 1 + desc = "This template spellbook was never meant for the eyes of man..." + +/obj/item/weapon/spellbook/oneuse/New() + ..() + name += spellname + +/obj/item/weapon/spellbook/oneuse/attack_self(mob/user as mob) + var/obj/effect/proc_holder/spell/S = new spell + for(var/obj/effect/proc_holder/spell/knownspell in user.spell_list) + if(knownspell.type == S.type) + if(user.mind) + if(user.mind.special_role == "apprentice" || user.mind.special_role == "wizard") + user <<"\blue You're already far more versed in this spell than this flimsy how-to book can provide." + else + user <<"\blue You've already read this one." + return + user.spell_list += S + user <<"\blue you rapidly read through the arcane book. Suddenly it vanishes and you realize you understand [spellname]!" + del (src) + +/obj/item/weapon/spellbook/oneuse/attackby() + return + +/obj/item/weapon/spellbook/oneuse/fireball + spell = /obj/effect/proc_holder/spell/dumbfire/fireball + spellname = "fireball" + icon_state ="book2" + desc = "This book feels warm to the touch." + +/obj/item/weapon/spellbook/oneuse/smoke + spell = /obj/effect/proc_holder/spell/targeted/smoke + spellname = "smoke" + icon_state ="book5" + desc = "This book is overflowing with the dank arts." + +/obj/item/weapon/spellbook/oneuse/blind + spell = /obj/effect/proc_holder/spell/targeted/trigger/blind + spellname = "blind" + icon_state ="book1" + desc = "This book looks blurry, no matter how you look at it." + +/obj/item/weapon/spellbook/oneuse/mindswap + spell = /obj/effect/proc_holder/spell/targeted/mind_transfer + spellname = "mindswap" + icon_state ="book6" + desc = "This book's cover is pristine, though its pages look ragged and torn." + +/obj/item/weapon/spellbook/oneuse/forcewall + spell = /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall + spellname = "forcewall" + icon_state ="book4" + desc = "This book has a dedication to mimes everywhere inside the front cover." + +/obj/item/weapon/spellbook/oneuse/knock + spell = /obj/effect/proc_holder/spell/aoe_turf/knock + spellname = "knock" + icon_state ="book7" + desc = "This book is hard to hold closed properly." + +/obj/item/weapon/spellbook/oneuse/horsemask + spell = /obj/effect/proc_holder/spell/targeted/horsemask + spellname = "horses" + icon_state ="book3" + desc = "This book is more horse than your mind has room for." + +/obj/item/weapon/spellbook/oneuse/charge + spell = /obj/effect/proc_holder/spell/targeted/charge + spellname = "charging" + icon_state ="bookInfections" + desc = "This book is made of 100% post-consumer wizard." \ No newline at end of file diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 4968f427ea2..11668d874c5 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -25,8 +25,6 @@ if (istype(G, /obj/item/weapon/gun/energy/gun/nuclear) || istype(G, /obj/item/weapon/gun/energy/crossbow)) user << "Your gun's recharge port was removed to make room for a miniaturized reactor." return - if (istype(G, /obj/item/weapon/gun/energy/staff)) - return user.drop_item() G.loc = src charging = G diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 39da02b0e1d..2316f12f45a 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -219,7 +219,7 @@ if(3) A = new /obj/item/projectile/beam/pulse( loc ) if(4) - A = new /obj/item/projectile/change( loc ) + A = new /obj/item/projectile/magic/change( loc ) if(5) A = new /obj/item/projectile/bluetag( loc ) if(6) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 6b0d70beece..c1ed4531c26 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -26,55 +26,6 @@ charge_cost = 100 projectile_type = "/obj/item/projectile/energy/declone" -obj/item/weapon/gun/energy/staff - name = "staff of change" - desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" - icon = 'icons/obj/gun.dmi' - icon_state = "staffofchange" - item_state = "staffofchange" - fire_sound = 'sound/weapons/emitter.ogg' - flags = FPRINT | TABLEPASS | CONDUCT - slot_flags = SLOT_BACK - w_class = 5 - charge_cost = 200 - projectile_type = "/obj/item/projectile/change" - origin_tech = null - clumsy_check = 0 - var/charge_tick = 0 - - - New() - ..() - processing_objects.Add(src) - - - Del() - processing_objects.Remove(src) - ..() - - - process() - charge_tick++ - if(charge_tick < 4) return 0 - charge_tick = 0 - if(!power_supply) return 0 - power_supply.give(200) - return 1 - - update_icon() - return - - shoot_with_empty_chamber(mob/living/user as mob|obj) - user << "The [name] whizzles quietly." - return - -/obj/item/weapon/gun/energy/staff/animate - name = "staff of animation" - desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." - projectile_type = "/obj/item/projectile/animate" - icon_state = "staffofanimation" - item_state = "staffofanimation" - /obj/item/weapon/gun/energy/floragun name = "floral somatoray" desc = "A tool that discharges controlled radiation which induces mutation in plant cells." diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm new file mode 100644 index 00000000000..c719bd4f663 --- /dev/null +++ b/code/modules/projectiles/guns/magic.dm @@ -0,0 +1,56 @@ +/obj/item/weapon/gun/magic + name = "staff of nothing" + desc = "This staff is boring to watch because even though it came first you've seen everything it can do in other staves for years." + icon = 'icons/obj/gun.dmi' + icon_state = "staffofchange" + item_state = "staffofchange" + fire_sound = 'sound/weapons/emitter.ogg' + flags = FPRINT | TABLEPASS | CONDUCT + w_class = 5 + var/projectile_type = "/obj/item/projectile/magic" + var/max_charges = 6 + var/charges = 0 + var/recharge_rate = 4 + var/charge_tick = 0 + var/can_charge = 1 + origin_tech = null + clumsy_check = 0 + +/obj/item/weapon/gun/magic/emp_act(severity) + return + +/obj/item/weapon/gun/magic/process_chambered() + if(in_chamber) return 1 + if(!charges) return 0 + if(!projectile_type) return 0 + in_chamber = new projectile_type(src) + return 1 + +/obj/item/weapon/gun/magic/afterattack() + ..() + if(charges ) charges-- + +/obj/item/weapon/gun/magic/New() + ..() + charges = max_charges + if(can_charge) processing_objects.Add(src) + + +/obj/item/weapon/gun/magic/Del() + if(can_charge) processing_objects.Remove(src) + ..() + + +/obj/item/weapon/gun/magic/process() + charge_tick++ + if(charge_tick < recharge_rate || charges >= max_charges) return 0 + charge_tick = 0 + charges++ + return 1 + +/obj/item/weapon/gun/magic/update_icon() + return + +/obj/item/weapon/gun/magic/shoot_with_empty_chamber(mob/living/user as mob|obj) + user << "The [name] whizzles quietly." + return \ No newline at end of file diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm new file mode 100644 index 00000000000..cff5d6e603d --- /dev/null +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -0,0 +1,23 @@ +obj/item/weapon/gun/magic/staff/change + name = "staff of change" + desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself" + projectile_type = "/obj/item/projectile/magic/change" + icon_state = "staffofchange" + item_state = "staffofchange" + slot_flags = SLOT_BACK + +obj/item/weapon/gun/magic/staff/animate + name = "staff of animation" + desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines." + projectile_type = "/obj/item/projectile/magic/animate" + icon_state = "staffofanimation" + item_state = "staffofanimation" + slot_flags = SLOT_BACK + +obj/item/weapon/gun/magic/staff/healing + name = "staff of healing" + desc = "An artefact that spits bolts of restoring magic which can remove ailments of all kinds and even raise the dead." + projectile_type = "/obj/item/projectile/magic/resurrection" + icon_state = "staffofanimation" + item_state = "staffofanimation" + slot_flags = SLOT_BACK \ No newline at end of file diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm new file mode 100644 index 00000000000..479e1fda0c7 --- /dev/null +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -0,0 +1,227 @@ +/obj/item/weapon/gun/magic/wand/ + name = "wand of nothing" + desc = "It's not just a stick, it's a MAGIC stick!" + projectile_type = "/obj/item/projectile/magic" + icon_state = "staffofanimation" + item_state = "staffofanimation" + w_class = 2 + can_charge = 0 + max_charges = 100 //100, 50, 50, 34 (max charge distribution by 25%ths) + w_class = 2 + +/obj/item/weapon/gun/magic/wand/New() + if(prob(75)) //25% chance of listed max charges, 50% chance of 1/2 max charges, 25% chance of 1/3 max charges + if(prob(33)) + max_charges = Ceiling(max_charges / 3) + else + max_charges = Ceiling(max_charges / 2) + ..() + +/obj/item/weapon/gun/magic/wand/examine() + ..() + usr << "Has [charges] charge\s remaining." + return + +/obj/item/weapon/gun/magic/wand/attack_self(mob/living/user as mob) + if(charges) + zap_self(user) + else + user << "The [name] whizzles quietly." + ..() + +/obj/item/weapon/gun/magic/wand/proc/zap_self(mob/living/user as mob) + user.visible_message("\blue [user] zaps \himself with [src]!") + +/obj/item/weapon/gun/magic/wand/death + name = "wand of death" + desc = "This deadly wand overwhelms the victim's body with pure energy, slaying them without fail." + projectile_type = "/obj/item/projectile/magic/death" + icon_state = "staffofanimation" + item_state = "staffofanimation" + max_charges = 3 //3, 2, 2, 1 + +/obj/item/weapon/gun/magic/wand/death/zap_self(mob/living/user as mob) + if(alert(user, "You really want to zap yourself with the wand of death?",, "Yes", "No") == "Yes" && charges && user.get_active_hand() == src && isliving(user)) + var/message ="\red You irradiate yourself with pure energy! " + message += pick("Do not pass go. Do not collect 200 zorkmids.","You feel more confident in your spell casting skills.","You Die...","Do you want your possessions identified?") + user << message + user.adjustOxyLoss(500) + charges-- + ..() + +/obj/item/weapon/gun/magic/wand/resurrection + name = "wand of resurrection" + desc = "This wand uses healing magics to heal and revive. They are rarely utilized within the Wizard Federation for some reason." + projectile_type = "/obj/item/projectile/magic/resurrection" + icon_state = "staffofanimation" + item_state = "staffofanimation" + max_charges = 3 //3, 2, 2, 1 + +/obj/item/weapon/gun/magic/wand/resurrection/zap_self(mob/living/user as mob) + user.setToxLoss(0) + user.setOxyLoss(0) + user.setCloneLoss(0) + user.SetParalysis(0) + user.SetStunned(0) + user.SetWeakened(0) + user.radiation = 0 + user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss()) + user.reagents.clear_reagents() + user << "You feel great!" + charges-- + ..() + +/obj/item/weapon/gun/magic/wand/polymorph + name = "wand of polymorph" + desc = "This wand inflicts is attuned to chaos and will radically alter the victim's form." + projectile_type = "/obj/item/projectile/magic/change" + icon_state = "staffofanimation" + item_state = "staffofanimation" + max_charges = 10 //10, 5, 5, 4 + +/obj/item/weapon/gun/magic/wand/polymorph/zap_self(mob/living/user as mob) + if(alert(user, "Your new form might not have arms to zap with... Continue?",, "Yes", "No") == "Yes" && charges && user.get_active_hand() == src && isliving(user)) + if(user.monkeyizing) return + user.monkeyizing = 1 + user.canmove = 0 + user.icon = null + user.overlays.Cut() + user.invisibility = 101 + for(var/obj/item/W in user) + if(istype(W, /obj/item/weapon/implant)) //TODO: Carn. give implants a dropped() or something + del(W) + continue + W.layer = initial(W.layer) + W.loc = user.loc + W.dropped(user) + + var/mob/living/new_mob + + var/randomize = pick("monkey","robot","slime","xeno","human","animal") + switch(randomize) + if("monkey") + new_mob = new /mob/living/carbon/monkey(user.loc) + new_mob.universal_speak = 1 + if("robot") + new_mob = new /mob/living/silicon/robot(user.loc) + new_mob.gender = user.gender + new_mob.invisibility = 0 + new_mob.job = "Cyborg" + var/mob/living/silicon/robot/Robot = new_mob + Robot.mmi = new /obj/item/device/mmi(new_mob) + Robot.mmi.transfer_identity(user) //Does not transfer key/client. + if("slime") + if(prob(50)) new_mob = new /mob/living/carbon/slime/adult(user.loc) + else new_mob = new /mob/living/carbon/slime(user.loc) + new_mob.universal_speak = 1 + if("xeno") + if(prob(50)) + new_mob = new /mob/living/carbon/alien/humanoid/hunter(user.loc) + else + new_mob = new /mob/living/carbon/alien/humanoid/sentinel(user.loc) + new_mob.universal_speak = 1 + if("animal") + var/animal = pick("parrot","corgi","crab","pug","cat","carp","bear","mushroom","tomato","mouse","chicken","cow","lizard","chick") + switch(animal) + if("parrot") new_mob = new /mob/living/simple_animal/parrot(user.loc) + if("corgi") new_mob = new /mob/living/simple_animal/corgi(user.loc) + if("crab") new_mob = new /mob/living/simple_animal/crab(user.loc) + if("pug") new_mob = new /mob/living/simple_animal/pug(user.loc) + if("cat") new_mob = new /mob/living/simple_animal/cat(user.loc) + if("carp") new_mob = new /mob/living/simple_animal/hostile/carp(user.loc) + if("bear") new_mob = new /mob/living/simple_animal/hostile/bear(user.loc) + if("mushroom") new_mob = new /mob/living/simple_animal/mushroom(user.loc) + if("tomato") new_mob = new /mob/living/simple_animal/tomato(user.loc) + if("mouse") new_mob = new /mob/living/simple_animal/mouse(user.loc) + if("chicken") new_mob = new /mob/living/simple_animal/chicken(user.loc) + if("cow") new_mob = new /mob/living/simple_animal/cow(user.loc) + if("lizard") new_mob = new /mob/living/simple_animal/lizard(user.loc) + else new_mob = new /mob/living/simple_animal/chick(user.loc) + new_mob.universal_speak = 1 + if("human") + new_mob = new /mob/living/carbon/human(user.loc) + + var/datum/preferences/A = new() //Randomize appearance for the human + A.copy_to(new_mob) + + var/mob/living/carbon/human/H = new_mob + ready_dna(H) + if(H.dna) + H.dna.mutantrace = pick("lizard","golem","slime","plant","fly","shadow","adamantine","skeleton",8;"") + H.update_body() + else + return + + for (var/obj/effect/proc_holder/spell/S in user.spell_list) + new_mob.spell_list += new S.type + + new_mob.a_intent = "harm" + if(user.mind) + user.mind.transfer_to(new_mob) + else + new_mob.key = user.key + + new_mob << "Your form morphs into that of a [randomize]." + + del(user) + return new_mob + charges-- + ..() + +/obj/item/weapon/gun/magic/wand/teleport + name = "wand of teleportation" + desc = "This wand will wrench targets through space and time to move them somewhere else." + projectile_type = "/obj/item/projectile/magic/teleport" + icon_state = "staffofanimation" + item_state = "staffofanimation" + max_charges = 10 //10, 5, 5, 4 + +/obj/item/weapon/gun/magic/wand/teleport/zap_self(mob/living/user as mob) + var/list/turfs = new/list() + var/inner_tele_radius = 0 + var/outer_tele_radius = 6 + for(var/turf/T in range(user,outer_tele_radius)) + if(T in range(user,inner_tele_radius)) continue + if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.yYou feel great!" + else + target << "You rise with a start, you're alive!!!" + +/obj/item/projectile/magic/teleport + name = "bolt of teleportation" + icon_state = "bluespace" + damage = 0 + damage_type = OXY + nodamage = 1 + flag = "magic" + var/inner_tele_radius = 0 + var/outer_tele_radius = 6 + +/obj/item/projectile/magic/teleport/on_hit(var/mob/target) + if(isturf(target)) + return + + var/list/turfs = new/list() + for(var/turf/T in range(target,outer_tele_radius)) + if(T in range(target,inner_tele_radius)) continue + if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.yYour form morphs into that of a [randomize].
" + + del(M) + return new_mob + +/obj/item/projectile/magic/animate + name = "bolt of animation" + icon_state = "red_1" + damage = 0 + damage_type = BURN + nodamage = 1 + flag = "magic" + +/obj/item/projectile/magic/animate/Bump(var/atom/change) + . = ..() + if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, protected_objects)) + var/obj/O = change + new /mob/living/simple_animal/hostile/mimic/copy(O.loc, O, firer) + else if(istype(change, /mob/living/simple_animal/hostile/mimic/copy)) + // Change our allegiance! + var/mob/living/simple_animal/hostile/mimic/copy/C = change + C.ChangeOwner(firer) \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 5bd8184b7dd..cbbb0dab917 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -6,48 +6,6 @@ // BEGIN_FILE_DIR #define FILE_DIR . -#define FILE_DIR "html" -#define FILE_DIR "icons" -#define FILE_DIR "icons/ass" -#define FILE_DIR "icons/effects" -#define FILE_DIR "icons/mecha" -#define FILE_DIR "icons/misc" -#define FILE_DIR "icons/mob" -#define FILE_DIR "icons/obj" -#define FILE_DIR "icons/obj/assemblies" -#define FILE_DIR "icons/obj/atmospherics" -#define FILE_DIR "icons/obj/clothing" -#define FILE_DIR "icons/obj/doors" -#define FILE_DIR "icons/obj/flora" -#define FILE_DIR "icons/obj/machines" -#define FILE_DIR "icons/obj/pipes" -#define FILE_DIR "icons/obj/power_cond" -#define FILE_DIR "icons/pda_icons" -#define FILE_DIR "icons/spideros_icons" -#define FILE_DIR "icons/stamp_icons" -#define FILE_DIR "icons/Testing" -#define FILE_DIR "icons/turf" -#define FILE_DIR "icons/vending_icons" -#define FILE_DIR "nano" -#define FILE_DIR "nano/images" -#define FILE_DIR "sound" -#define FILE_DIR "sound/AI" -#define FILE_DIR "sound/ambience" -#define FILE_DIR "sound/effects" -#define FILE_DIR "sound/hallucinations" -#define FILE_DIR "sound/items" -#define FILE_DIR "sound/machines" -#define FILE_DIR "sound/mecha" -#define FILE_DIR "sound/misc" -#define FILE_DIR "sound/piano" -#define FILE_DIR "sound/violin" -#define FILE_DIR "sound/voice" -#define FILE_DIR "sound/voice/complionator" -#define FILE_DIR "sound/vox_fem" -#define FILE_DIR "sound/weapons" -#define FILE_DIR "tools" -#define FILE_DIR "tools/AddToChangelog" -#define FILE_DIR "tools/AddToChangelog/AddToChangelog" // END_FILE_DIR // BEGIN_PREFERENCES @@ -216,6 +174,7 @@ #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" #include "code\datums\spells\area_teleport.dm" +#include "code\datums\spells\charge.dm" #include "code\datums\spells\conjure.dm" #include "code\datums\spells\construct_spells.dm" #include "code\datums\spells\dumbfire.dm" @@ -1122,6 +1081,7 @@ #include "code\modules\projectiles\ammunition\bullets.dm" #include "code\modules\projectiles\ammunition\magazines.dm" #include "code\modules\projectiles\guns\energy.dm" +#include "code\modules\projectiles\guns\magic.dm" #include "code\modules\projectiles\guns\projectile.dm" #include "code\modules\projectiles\guns\energy\laser.dm" #include "code\modules\projectiles\guns\energy\nuclear.dm" @@ -1129,15 +1089,16 @@ #include "code\modules\projectiles\guns\energy\special.dm" #include "code\modules\projectiles\guns\energy\stun.dm" #include "code\modules\projectiles\guns\energy\temperature.dm" +#include "code\modules\projectiles\guns\magic\staff.dm" +#include "code\modules\projectiles\guns\magic\wand.dm" #include "code\modules\projectiles\guns\projectile\automatic.dm" #include "code\modules\projectiles\guns\projectile\pistol.dm" #include "code\modules\projectiles\guns\projectile\revolver.dm" #include "code\modules\projectiles\guns\projectile\shotgun.dm" -#include "code\modules\projectiles\projectile\animate.dm" #include "code\modules\projectiles\projectile\beams.dm" #include "code\modules\projectiles\projectile\bullets.dm" -#include "code\modules\projectiles\projectile\change.dm" #include "code\modules\projectiles\projectile\energy.dm" +#include "code\modules\projectiles\projectile\magic.dm" #include "code\modules\projectiles\projectile\special.dm" #include "code\modules\reagents\Chemistry-Colours.dm" #include "code\modules\reagents\Chemistry-Holder.dm"