//////////////////////////////////////////// Setup ////////////////////////////////////////////////// /proc/equip_wizard(mob/living/carbon/human/wizard_mob, var/robe = 0, var/vr = 0) if (!ishuman(wizard_mob)) return if (vr && wizard_mob.mind && wizard_mob.mind.is_wizard) // you're already a wizard you shithead, get out of here return var/datum/abilityHolder/H = wizard_mob.add_ability_holder(/datum/abilityHolder/wizard) if (!vr) // normal spells for normal wizards H.addAbility(/datum/targetable/spell/phaseshift) H.addAbility(/datum/targetable/spell/magicmissile) H.addAbility(/datum/targetable/spell/clairvoyance) else // vr wizards only get magic missile H.addAbility(/datum/targetable/spell/magicmissile) if (wizard_mob.mind) wizard_mob.mind.is_wizard = H SPAWN_DBG (25) // Don't remove. if (wizard_mob) wizard_mob.assign_gimmick_skull() // For variety and hunters (Convair880). wizard_mob.bioHolder.mobAppearance.customization_first_color = "#FFFFFF" wizard_mob.bioHolder.mobAppearance.customization_second_color = "#FFFFFF" wizard_mob.cust_two_state = "wiz" wizard_mob.set_face_icon_dirty() var/obj/item/SWF_uplink/SB = new /obj/item/SWF_uplink(wizard_mob, in_vr = vr) if (wizard_mob.mind) SB.wizard_key = wizard_mob.mind.key //so that this proc will work for wizards made mid-round who are wearing stuff for(var/obj/item/I in list(wizard_mob.w_uniform, wizard_mob.wear_suit,wizard_mob.head, wizard_mob.ears, wizard_mob.back, wizard_mob.shoes, wizard_mob.r_hand, wizard_mob.l_hand, wizard_mob.r_store, wizard_mob.l_store,wizard_mob.belt)) wizard_mob.u_equip(I) I.set_loc(wizard_mob.loc) I.dropped(wizard_mob) I.layer = initial(I.layer) if(robe) wizard_mob.equip_if_possible(new /obj/item/clothing/suit/wizrobe(wizard_mob), wizard_mob.slot_wear_suit) wizard_mob.equip_if_possible(new /obj/item/clothing/under/shorts/black(wizard_mob), wizard_mob.slot_w_uniform) wizard_mob.equip_if_possible(new /obj/item/clothing/head/wizard(wizard_mob), wizard_mob.slot_head) if(wizard_mob.traitHolder && wizard_mob.traitHolder.hasTrait("deaf")) wizard_mob.equip_if_possible(new /obj/item/device/radio/headset/deaf(wizard_mob), wizard_mob.slot_ears) else wizard_mob.equip_if_possible(new /obj/item/device/radio/headset(wizard_mob), wizard_mob.slot_ears) wizard_mob.equip_if_possible(new /obj/item/storage/backpack(wizard_mob), wizard_mob.slot_back) wizard_mob.equip_if_possible(new /obj/item/clothing/shoes/sandal(wizard_mob), wizard_mob.slot_shoes) wizard_mob.equip_if_possible(new /obj/item/staff(wizard_mob), wizard_mob.slot_r_hand) wizard_mob.equip_if_possible(new /obj/item/paper/Wizardry101(wizard_mob), wizard_mob.slot_l_store) if (vr) wizard_mob.equip_if_possible(SB, wizard_mob.slot_l_hand) else wizard_mob.equip_if_possible(new /obj/item/teleportation_scroll(wizard_mob), wizard_mob.slot_l_hand) wizard_mob.equip_if_possible(SB, wizard_mob.slot_belt) wizard_mob.set_clothing_icon_dirty() boutput(wizard_mob, "You're a wizard now. You have a few starting spells; use the [SB] to choose the rest!") if (!vr) SHOW_WIZARD_TIPS(wizard_mob) return ////////////////////////////////////////////// Helper procs //////////////////////////////////////////////////// /mob/proc/wizard_spellpower() return 0 /mob/living/carbon/human/wizard_spellpower() var/magcount = 0 if (!src) return 0 // ?? if (src.bioHolder.HasEffect("arcane_power") == 2) magcount += 10 for (var/obj/item/clothing/C in src.contents) if (C.magical) magcount += 1 if (istype(src.r_hand, /obj/item/staff)) magcount += 2 if (istype(src.l_hand, /obj/item/staff)) magcount += 2 if (magcount >= 4) return 1 else return 0 /mob/living/critter/wizard_spellpower() var/magcount = 0 for (var/obj/item/clothing/C in src.contents) if (C.magical) magcount += 1 if (src.find_type_in_hand(/obj/item/staff)) magcount += 2 if (magcount >= 4) return 1 else return 0 /mob/proc/wizard_castcheck(var/offensive = 0) return 0 /mob/living/carbon/human/wizard_castcheck(var/offensive = 0) if(src.stat) boutput(src, "You can't cast spells while incapacitated.") return 0 if (src.bioHolder.HasEffect("arcane_power") == 2) return 1 if(!istype(src.wear_suit, /obj/item/clothing/suit/wizrobe)) boutput(src, "You don't feel strong enough without a magical robe.") return 0 if(!istype(src.head, /obj/item/clothing/head/wizard)) boutput(src, "You don't feel strong enough without a magical hat.") return 0 var/area/getarea = get_area(src) if(offensive && getarea.sanctuary) boutput( src, "You cannot cast offensive spells in a sanctuary." ) return 0 if(getarea.name == "Chapel" || getarea.name == "Chapel Office") boutput(src, "You cannot cast spells on hallowed ground!")// Maybe if the station were more corrupted...") return 0 if (offensive == 1 && src.bioHolder.HasEffect("arcane_shame")) boutput(src, "You are too consumed with shame to cast that spell!") return 0 return 1 /mob/living/critter/wizard_castcheck(var/offensive = 0) if(src.stat) boutput(src, "You can't cast spells while incapacitated.") return 0 // if(!find_in_equipment(/obj/item/clothing/suit/wizrobe)) // boutput(src, "You don't feel strong enough without a magical robe.") // return 0 if(!find_in_equipment(/obj/item/clothing/head/wizard)) boutput(src, "You don't feel strong enough without a magical hat.") return 0 var/area/getarea = get_area(src) if(offensive && getarea.sanctuary) boutput( src, "You cannot cast spells in a sanctuary." ) return 0 if(getarea.name == "Chapel" || getarea.name == "Chapel Office") boutput(src, "You cannot cast spells on hallowed ground!")// Maybe if the station were more corrupted...") return 0 return 1 //////////////////////////////////////////// Ability holder ///////////////////////////////////////// /obj/screen/ability/topBar/spell clicked(params) var/datum/targetable/spell/spell = owner var/datum/abilityHolder/holder = owner.holder if (!istype(spell)) return if (!spell.holder) return if(params["shift"] && params["ctrl"]) if(owner.waiting_for_hotkey) holder.cancel_action_binding() return else owner.waiting_for_hotkey = 1 src.updateIcon() boutput(usr, "Please press a number to bind this ability to...") return if (!isturf(usr.loc)) return if (world.time < spell.last_cast) return if (spell.targeted && usr:targeting_spell == owner) usr:targeting_spell = null usr.update_cursor() return var/mob/user = spell.holder.owner if (!istype(spell, /datum/targetable/spell/prismatic_spray/admin) && !user.wizard_castcheck(spell.offensive)) return if (spell.targeted) usr:targeting_spell = owner usr.update_cursor() else SPAWN_DBG(0) spell.handleCast() /datum/abilityHolder/wizard usesPoints = 0 topBarRendered = 1 tabName = "Wizard" /////////////////////////////////////////////// Wizard spell parent //////////////////////////// /datum/targetable/spell preferred_holder_type = /datum/abilityHolder/wizard var requires_robes = 0 offensive = 0 cooldown_staff = 0 prepared_count = 0 casting_time = 0 voice_grim = null voice_fem = null voice_other = null proc/calculate_cooldown() var/cool = src.cooldown var/mob/user = src.holder.owner if (user && user.bioHolder) switch (user.bioHolder.HasEffect("arcane_power")) if (1) cool /= 2 if (2) cool = 1 if (src.cooldown_staff && !user.wizard_spellpower()) cool *= 1.5 return cool dispose() if (object) qdel(object) doCooldown() src.last_cast = world.time + calculate_cooldown() SPAWN_DBG(calculate_cooldown() + 5) holder.updateButtons() //mbc : i don't see why the wizard needs a specialized tryCast() proc. someone fix it later for me! tryCast(atom/target) if (!holder || !holder.owner) return 1 var/datum/abilityHolder/wizard/H = holder if (H.locked && src.ignore_holder_lock != 1) boutput(holder.owner, "You're already casting an ability.") return 1 // ASSHOLES if (src.last_cast > world.time) return 1 if (isunconscious(holder.owner)) boutput(holder.owner, "You cannot cast this ability while you are unconscious.") src.holder.locked = 0 return 999 if (!holder.cast_while_dead && isdead(holder.owner)) boutput(holder.owner, "You cannot cast this ability while you are dead.") src.holder.locked = 0 return 999 if (!istype(src, /datum/targetable/spell/prismatic_spray/admin) && !H.owner.wizard_castcheck()) // oh god this is ugly but it's technically not duplicating code so it fixes to problem with the move to ability buttons src.holder.locked = 0 return 999 var/turf/T = get_turf(holder.owner) if( offensive && T.loc:sanctuary ) boutput(holder.owner, "You cannot cast offensive spells on someone in a sanctuary.") if (src.restricted_area_check) if (!T || !isturf(T)) boutput(holder.owner, "That ability doesn't seem to work here.") return 1 switch (src.restricted_area_check) if (1) if (isrestrictedz(T.z)) var/area/Arr = get_area(T) if (!istype(Arr, /area/wizard_station)) boutput(holder.owner, "That ability doesn't seem to work here.") return 1 if (2) var/area/A = get_area(T) if (A && istype(A, /area/sim)) boutput(holder.owner, "You can't use this ability in virtual reality.") return 1 if (src.dont_lock_holder != 1) H.locked = 1 if (src.cooldown_staff && !holder.owner.wizard_spellpower()) boutput(holder.owner, "Your spell takes longer to recharge without a staff to focus it!") var/val = cast(target) H.locked = 0 return val updateObject() if (!holder || !holder.owner) qdel(src) if (!src.object) src.object = new /obj/screen/ability/topBar/spell() object.icon = src.icon if (src.last_cast > world.time) object.name = "[src.name] ([round((src.last_cast-world.time)/10)])" object.icon_state = src.icon_state + "_cd" else object.name = src.name object.icon_state = src.icon_state object.owner = src castcheck() return !istype(src, /datum/targetable/spell/prismatic_spray/admin) && holder.owner.wizard_castcheck(src.offensive) cast() if(ishuman(holder.owner)) var/mob/living/carbon/human/O = holder.owner if(O && istype(O.wear_suit, /obj/item/clothing/suit/wizrobe/necro) && istype(O.head, /obj/item/clothing/head/wizard/necro)) playsound(holder.owner.loc, voice_grim, 50, 0, -1) else if(holder.owner.gender == "female") playsound(holder.owner.loc, voice_fem, 50, 0, -1) else playsound(holder.owner.loc, voice_other, 50, 0, -1)