diff --git a/code/datums/spells/infinite_guns.dm b/code/datums/spells/infinite_guns.dm
index 3573bf70f99..56b0cae5cfd 100644
--- a/code/datums/spells/infinite_guns.dm
+++ b/code/datums/spells/infinite_guns.dm
@@ -8,6 +8,7 @@
clothes_req = TRUE
cooldown_min = 10 //Gun wizard
action_icon_state = "bolt_action"
+ var/gun_type = /obj/item/gun/projectile/shotgun/boltaction/enchanted
/obj/effect/proc_holder/spell/infinite_guns/create_new_targeting()
return new /datum/spell_targeting/self
@@ -17,5 +18,38 @@
C.drop_item()
C.swap_hand()
C.drop_item()
- var/obj/item/gun/projectile/shotgun/boltaction/enchanted/GUN = new
+ var/obj/item/gun/projectile/shotgun/boltaction/enchanted/GUN = new gun_type()
C.put_in_hands(GUN)
+
+/obj/effect/proc_holder/spell/infinite_guns/fireball
+ name = "Rapid-fire Fireball"
+ desc = "Multiple Fireballs. Need I explain more? Requires both hands free to use."
+
+ school = "evocation"
+ base_cooldown = 30 SECONDS
+ clothes_req = FALSE
+ invocation = "ONI SOMA-SOMA-SOMA"
+ invocation_type = "shout"
+ action_icon_state = "explosion"
+ gun_type = /obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/fireball
+
+/obj/item/gun/projectile/shotgun/boltaction/enchanted/arcane_barrage/fireball
+ name = "small ball of fire"
+ desc = "A small flame, ready to launch from your hand."
+ icon = 'icons/obj/cigarettes.dmi'
+ icon_state = "match_unathi"
+ item_state = "disintegrate"
+ lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/items_righthand.dmi'
+ color = "#e1ff00" // red + yellow = orange
+ guns_left = 20
+ fire_sound = 'sound/magic/Fireball.ogg'
+ mag_type = /obj/item/ammo_box/magazine/internal/boltaction/enchanted/arcane_barrage/fireball
+ flags = NOBLUDGEON | DROPDEL
+
+/obj/item/ammo_box/magazine/internal/boltaction/enchanted/arcane_barrage/fireball
+ ammo_type = /obj/item/ammo_casing/magic/arcane_barrage/fireball
+
+/obj/item/ammo_casing/magic/arcane_barrage/fireball
+ projectile_type = /obj/item/projectile/magic/fireball
+ muzzle_flash_effect = null
diff --git a/code/datums/spells/wizard_spells.dm b/code/datums/spells/wizard_spells.dm
index 77a8ccfd9b9..1e5abe773d9 100644
--- a/code/datums/spells/wizard_spells.dm
+++ b/code/datums/spells/wizard_spells.dm
@@ -323,7 +323,7 @@
invocation_type = "shout"
cooldown_min = 20 //10 deciseconds reduction per rank
- selection_activated_message = "Your prepare to cast your fireball spell! Left-click to cast at a target!"
+ selection_activated_message = "You prepare to cast your fireball spell! Left-click to cast at a target!"
selection_deactivated_message = "You extinguish your fireball...for now."
var/fireball_type = /obj/item/projectile/magic/fireball
@@ -367,9 +367,18 @@
fireball_type = /obj/item/projectile/homing/magic/toolbox
invocation = "ROBUSTIO!"
- selection_activated_message = "Your prepare to cast your homing toolbox! Left-click to cast at a target!"
+ selection_activated_message = "You prepare to cast your homing toolbox! Left-click to cast at a target!"
selection_deactivated_message = "You unrobust your toolbox...for now."
+/obj/effect/proc_holder/spell/fireball/homing
+ name = "Greater Homing Fireball"
+ desc = "This spell fires a strong homing fireball at a target."
+ invocation = "ZI-ONI SOMA"
+ fireball_type = /obj/item/projectile/homing/magic/homing_fireball
+
+ selection_activated_message = "You prepare to cast your greater homing fireball spell! Left-click to cast at a target!"
+ base_cooldown = 6 SECONDS
+
/obj/effect/proc_holder/spell/aoe/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
diff --git a/code/game/gamemodes/wizard/wizloadouts.dm b/code/game/gamemodes/wizard/wizloadouts.dm
index ce2150d4e98..836fb7b988b 100644
--- a/code/game/gamemodes/wizard/wizloadouts.dm
+++ b/code/game/gamemodes/wizard/wizloadouts.dm
@@ -120,3 +120,41 @@
if(!user)
return
ADD_TRAIT(user, SM_HALLUCINATION_IMMUNE, MAGIC_TRAIT)
+
+/datum/spellbook_entry/loadout/fireball
+ name = "Fireball. Fireball. Fireball."
+ desc = "Who cares about the rest of the spells. Become an expert in fire magic. Devote yourself to the craft. The only spell you need anyways is Fireball.
\
+ Provides fire immunity, homing fireballs, rapid-fire fireballs, and some fireball wands. Provides no mobility spells. Replaces your robes with infernal versions."
+ spells_path = list(/obj/effect/proc_holder/spell/sacred_flame, /obj/effect/proc_holder/spell/fireball/homing, /obj/effect/proc_holder/spell/infinite_guns/fireball)
+ category = "Unique"
+ destroy_spellbook = TRUE
+
+/datum/spellbook_entry/loadout/fireball/OnBuy(mob/living/carbon/human/user, obj/item/spellbook/book)
+ if(user.wear_suit)
+ var/jumpsuit = user.wear_suit
+ user.unEquip(user.wear_suit, TRUE)
+ qdel(jumpsuit)
+ if(user.head)
+ var/head = user.head
+ user.unEquip(user.head, TRUE)
+ qdel(head)
+
+ // Part of Sacred Flame
+ to_chat(user, "You feel fireproof.")
+ ADD_TRAIT(user, TRAIT_RESISTHEAT, MAGIC_TRAIT)
+ ADD_TRAIT(user, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT)
+
+ user.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red/fireball(user), SLOT_HUD_OUTER_SUIT)
+ user.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red/fireball(user), SLOT_HUD_HEAD)
+
+ user.equip_or_collect(new /obj/item/storage/belt/wands/fireballs(), SLOT_HUD_BELT)
+
+/obj/item/clothing/suit/wizrobe/red/fireball
+ name = "infernal robe"
+ desc = "A magnificent, red, glowing robe that seems to radiate heat."
+ flags = NODROP
+
+/obj/item/clothing/head/wizard/red/fireball
+ name = "infernal hat"
+ desc = "A pointy red wizard hat, indicating a magician of great power."
+ flags = NODROP
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index f1f4f87634e..1e2dc9bff03 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -622,6 +622,20 @@
W.charges = W.max_charges
update_icon()
+/obj/item/storage/belt/wands/fireballs
+ name = "infernal belt"
+ desc = "\"Use Fireball and only Fireball. Nothing but fireball. Just Fireball. Just Fireball.\""
+ icon_state = "militarybelt"
+ item_state = "military"
+ can_hold = list(/obj/item/gun/magic/wand/fireball)
+
+/obj/item/storage/belt/wands/fireballs/populate_contents()
+ for(var/count in 1 to storage_slots)
+ var/obj/item/gun/magic/wand/fireball/W = new /obj/item/gun/magic/wand/fireball(src)
+ W.max_charges = initial(W.max_charges)
+ W.charges = W.max_charges
+ update_icon()
+
/obj/item/storage/belt/fannypack
name = "fannypack"
desc = "A dorky fannypack for keeping small items in."
diff --git a/code/modules/projectiles/projectile/homing_projectiles.dm b/code/modules/projectiles/projectile/homing_projectiles.dm
index b97afec55d4..e2e5d623182 100644
--- a/code/modules/projectiles/projectile/homing_projectiles.dm
+++ b/code/modules/projectiles/projectile/homing_projectiles.dm
@@ -50,3 +50,23 @@
var/mob/living/carbon/human/H = target
var/obj/item/organ/external/E = pick(H.bodyparts)
E.add_embedded_object(T)
+
+/obj/item/projectile/homing/magic/homing_fireball
+ name = "greater bolt of fireball"
+ icon_state = "fireball"
+ damage = 20
+ damage_type = BRUTE
+ nodamage = FALSE
+
+ //explosion values
+ var/explosion_devastate = 0
+ var/explosion_heavy = 1
+ var/explosion_light = 3
+ var/explosion_flash = 4
+ var/explosion_fire = 3
+
+/obj/item/projectile/homing/magic/homing_fireball/on_hit(mob/living/target)
+ . = ..()
+ explosion(get_turf(target), explosion_devastate, explosion_heavy, explosion_light, explosion_flash, 0, flame_range = explosion_fire)
+ if(istype(target)) //multiple flavors of pain
+ target.adjustFireLoss(10) // does 20 brute, and 10 burn + explosion. Pretty brutal.
diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi
index 381b39730fd..59118dbe591 100644
Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ