mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2025-12-27 18:51:53 +00:00
Fixes more compile errors. Down to 65 now. updates << into to_chat Down to 60 errors, also starts to port the codex gigas and law 666 for cyborg devils. Fixes more compile errors. Down to 41 now. Replaces timers with spawns, and <<s with to_chats 40 compile errors. Down to 34 compile errors. whoops, actually down to 34 now. Down to 25 compile errors. Down to 15 compile errors, I'llprobably need some help at this point. Woo! Down to 7 compile errors. Ported over devil hud. Number of errors up to 19. WOO! It compiles. It's completely untested, but it compiles. Adds devils to traitor panel Implements iron, silver and salt banes. implements flashing lights bane Selling your soul prevents cloning, and some other methods of revival. Implements harvest bane Merged and sorted icons/obj/bureaucracy.dmi Adds toy codex gigas Fixes compile errors, adds codex gigas sprite. Lots of bug fixes. Contracts work, devil revival is more consistant, etc Adds missing icons for flaming contracts, summon pitchfork, summon wealth, employment cabinet, and sintouch. Converts DEEP LORE explanations from hell to inferno incorporated. Banishes the compile errors. Devils come from hell again. replaces offer drink obligation with a much more lore appropriate devil's fiddle reference Also fixes contract bashing brain damage chance. Undoes some changes I accidentally did to example config files. Fixes up a few remaining bugs. Puts in the codex gigas and employment contract cabinets. -- Lemon - I kinda skipped this one, I'll patch it back in later because map conflicts are suffering incarnate Solves the devil law problem in a REALLY hacky snowflake way. Fixes a few methods in which a hellbound can be revived. Devils respawn with a limited number of appropriate items, instead of COMPLETELY naked upon corpse destruction. Also adds lines to example config. Updates devil laws to be less hacky. Objective to sintouch x mortals now greentexts correctly. Contracts no longer cause brain damage. I didn't realize it was lethal on this codebase. Oops. Splits dust(visual_only) into dust() and dust_animation() procs Fixes some defines. Adds undef statements to improve compile times. Fixes race changes from demonic form changes. Fixes small runtime error. (Which somehow didn't break anything?) Implements lots of small changes/corrections suggested by CrazyLemon64 I still need to test these changes, along with other potential issues he brought up. Fixes harvest bane and power contracts. Also adds a few </span> tag enders. Corrects some edge cases with revival contracts. Fixes compile error. Reverts unneccecary change to item/weapon/reagent_containers Cleans up the code for readability. Prevents cloning of hellbound individuals. Latejoins now properly have employment contracts added to employment cabinets (provided they still exist) Infernal contracts are no longer rendered unreadable by fire and alcohol. All fireproof paper remains readable after being fireballed, not just infernal contracts. (Though infernal contracts are the only fireproof paper atm) Fixes an edge case problem with cloning. Adds is_revivable proc to mind. Removes snowflake code involving preventing soulseller resurrection. Indulges in the sin of sloth, and copies tg's lazy list macros Proc calls that transform the user no longer go to a null target Fixes devil UI, human regression will keep appearance, and adds danceoff Devil's base forms no longer suffocate inside the devil Fixes runtimes, gets stuff working The arch devil can now blast down walls with their pitchfork EXTERMINATE ALL SPIRITS Activates devil clause in voice of god Fawks Mcclood Feature P A R I T Y Fixes devil bugs from testing - Does a death refactor to make sure that diabolical resurrection works - Walls no longer leave girders when blasted by the devil - Getting a new body gives you a rudimentary amount of equipment to work with to get out of maintenance or whereever Does all the icons in a single commit on their own because icon conflicts suck Starting point of extra devil rebalance/fixes Ports devil friends Also oops tramples all over Fethas' corpse PR that's still up I need to take care of that one Styling fixes
479 lines
17 KiB
Plaintext
479 lines
17 KiB
Plaintext
#define TARGET_CLOSEST 1
|
|
#define TARGET_RANDOM 2
|
|
|
|
/obj/effect/proc_holder
|
|
var/panel = "Debug"//What panel the proc holder needs to go on.
|
|
var/active = FALSE //Used by toggle based abilities.
|
|
var/ranged_mousepointer
|
|
|
|
var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now
|
|
|
|
/obj/effect/proc_holder/proc/InterceptClickOn(mob/living/user, params, atom/A)
|
|
if(user.ranged_ability != src)
|
|
to_chat(user, "<span class='warning'><b>[user.ranged_ability.name]</b> has been disabled.")
|
|
user.ranged_ability.remove_ranged_ability(user)
|
|
return TRUE //TRUE for failed, FALSE for passed.
|
|
user.changeNext_click(CLICK_CD_CLICK_ABILITY)
|
|
user.face_atom(A)
|
|
return FALSE
|
|
|
|
/obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, var/msg)
|
|
if(!user || !user.client)
|
|
return
|
|
if(user.ranged_ability && user.ranged_ability != src)
|
|
to_chat(user, "<span class='warning'><b>[user.ranged_ability.name]</b> has been replaced by <b>[name]</b>.")
|
|
user.ranged_ability.remove_ranged_ability(user)
|
|
user.ranged_ability = src
|
|
user.client.click_intercept = user.ranged_ability
|
|
add_mousepointer(user.client)
|
|
active = TRUE
|
|
if(msg)
|
|
to_chat(user, msg)
|
|
update_icon()
|
|
|
|
/obj/effect/proc_holder/proc/add_mousepointer(client/C)
|
|
if(C && ranged_mousepointer && C.mouse_pointer_icon == initial(C.mouse_pointer_icon))
|
|
C.mouse_pointer_icon = ranged_mousepointer
|
|
|
|
/obj/effect/proc_holder/proc/remove_mousepointer(client/C)
|
|
if(C && ranged_mousepointer && C.mouse_pointer_icon == ranged_mousepointer)
|
|
C.mouse_pointer_icon = initial(C.mouse_pointer_icon)
|
|
|
|
/obj/effect/proc_holder/proc/remove_ranged_ability(mob/living/user, var/msg)
|
|
if(!user || !user.client || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
|
|
return
|
|
user.ranged_ability = null
|
|
user.client.click_intercept = null
|
|
remove_mousepointer(user.client)
|
|
active = FALSE
|
|
if(msg)
|
|
to_chat(user, msg)
|
|
update_icon()
|
|
|
|
/obj/effect/proc_holder/spell
|
|
name = "Spell"
|
|
desc = "A wizard spell"
|
|
panel = "Spells"//What panel the proc holder needs to go on.
|
|
density = 0
|
|
opacity = 0
|
|
|
|
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
|
|
|
|
var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that
|
|
|
|
var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges"
|
|
var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges"
|
|
var/still_recharging_msg = "<span class='notice'>The spell is still recharging.</span>"
|
|
|
|
var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var"
|
|
var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used
|
|
|
|
var/ghost = 0 // Skip life check.
|
|
var/clothes_req = 1 //see if it requires clothes
|
|
var/human_req = 0 //spell can only be cast by humans
|
|
var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities
|
|
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
|
|
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
|
|
var/invocation_emote_self = null
|
|
var/invocation_type = "none" //can be none, whisper and shout
|
|
var/range = 7 //the range of the spell; outer radius for aoe spells
|
|
var/message = "" //whatever it says to the guy affected by it
|
|
var/selection_type = "view" //can be "range" or "view"
|
|
var/spell_level = 0 //if a spell can be taken multiple times, this raises
|
|
var/level_max = 4 //The max possible level_max is 4
|
|
var/cooldown_min = 0 //This defines what spell quickened four timeshas as a cooldown. Make sure to set this for every spell
|
|
|
|
var/overlay = 0
|
|
var/overlay_icon = 'icons/obj/wizard.dmi'
|
|
var/overlay_icon_state = "spell"
|
|
var/overlay_lifespan = 0
|
|
|
|
var/sparks_spread = 0
|
|
var/sparks_amt = 0 //cropped at 10
|
|
var/smoke_spread = 0 //1 - harmless, 2 - harmful
|
|
var/smoke_amt = 0 //cropped at 10
|
|
|
|
var/critfailchance = 0
|
|
var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
|
|
|
|
var/datum/action/spell_action/action = null
|
|
var/action_icon = 'icons/mob/actions/actions.dmi'
|
|
var/action_icon_state = "spell_default"
|
|
var/action_background_icon_state = "bg_spell"
|
|
var/special_availability_check = 0//Whether the spell needs to bypass the action button's IsAvailable()
|
|
|
|
var/sound = null //The sound the spell makes when it is cast
|
|
|
|
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0, mob/living/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
|
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
|
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
|
|
return 0
|
|
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/caster = user
|
|
if(caster.remoteview_target)
|
|
caster.remoteview_target = null
|
|
caster.reset_perspective(0)
|
|
return 0
|
|
|
|
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
|
return 0
|
|
|
|
if(!skipcharge)
|
|
switch(charge_type)
|
|
if("recharge")
|
|
if(charge_counter < charge_max)
|
|
to_chat(user, still_recharging_msg)
|
|
return 0
|
|
if("charges")
|
|
if(!charge_counter)
|
|
to_chat(user, "<span class='notice'>[name] has no charges left.</span>")
|
|
return 0
|
|
|
|
if(!ghost)
|
|
if(user.stat && !stat_allowed)
|
|
to_chat(user, "<span class='notice'>You can't cast this spell while incapacitated.</span>")
|
|
return 0
|
|
if(ishuman(user) && (invocation_type == "whisper" || invocation_type == "shout") && user.is_muzzled())
|
|
to_chat(user, "Mmmf mrrfff!")
|
|
return 0
|
|
|
|
var/obj/effect/proc_holder/spell/noclothes/clothes_spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list()))
|
|
if((ishuman(user) && clothes_req) && !istype(clothes_spell))//clothes check
|
|
var/mob/living/carbon/human/H = user
|
|
var/obj/item/clothing/robe = H.wear_suit
|
|
var/obj/item/clothing/hat = H.head
|
|
var/obj/item/clothing/shoes = H.shoes
|
|
if(!robe || !hat || !shoes)
|
|
to_chat(user, "<span class='notice'>Your outfit isn't complete, you should put on your robe and wizard hat, as well as sandals.</span>")
|
|
return 0
|
|
if(!robe.magical || !hat.magical || !shoes.magical)
|
|
to_chat(user, "<span class='notice'>Your outfit isn't magical enough, you should put on your robe and wizard hat, as well as your sandals.</span>")
|
|
return 0
|
|
else if(!ishuman(user))
|
|
if(clothes_req || human_req)
|
|
to_chat(user, "<span class='notice'>This spell can only be cast by humans!</span>")
|
|
return 0
|
|
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
|
to_chat(user, "<span class='notice'>This spell can only be cast by physical beings!</span>")
|
|
return 0
|
|
|
|
if(!skipcharge)
|
|
switch(charge_type)
|
|
if("recharge")
|
|
charge_counter = 0 //doesn't start recharging until the targets selecting ends
|
|
if("charges")
|
|
charge_counter-- //returns the charge if the targets selecting fails
|
|
if("holdervar")
|
|
adjust_var(user, holder_var_type, holder_var_amount)
|
|
|
|
return 1
|
|
|
|
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
|
|
switch(invocation_type)
|
|
if("shout")
|
|
if(!user.IsVocal())
|
|
user.custom_emote(1, "makes frantic gestures!")
|
|
else
|
|
if(prob(50))//Auto-mute? Fuck that noise
|
|
user.say(invocation)
|
|
else
|
|
user.say(replacetext(invocation," ","`"))
|
|
if("whisper")
|
|
if(prob(50))
|
|
user.whisper(invocation)
|
|
else
|
|
user.whisper(replacetext(invocation," ","`"))
|
|
if("emote")
|
|
user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm
|
|
|
|
/obj/effect/proc_holder/spell/proc/playMagSound()
|
|
playsound(get_turf(usr), sound,50,1)
|
|
|
|
/obj/effect/proc_holder/spell/New()
|
|
..()
|
|
action = new(src)
|
|
|
|
still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
|
|
charge_counter = charge_max
|
|
|
|
/obj/effect/proc_holder/spell/Destroy()
|
|
QDEL_NULL(action)
|
|
return ..()
|
|
|
|
/obj/effect/proc_holder/spell/Click()
|
|
if(cast_check())
|
|
choose_targets()
|
|
return 1
|
|
|
|
/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/proc/start_recharge()
|
|
if(action)
|
|
action.UpdateButtonIcon()
|
|
while(charge_counter < charge_max)
|
|
sleep(1)
|
|
charge_counter++
|
|
if(action)
|
|
action.UpdateButtonIcon()
|
|
|
|
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr) //if recharge is started is important for the trigger spells
|
|
before_cast(targets)
|
|
invocation()
|
|
if(user && user.ckey)
|
|
user.create_attack_log("<font color='red'>[key_name(user)] cast the spell [name].</font>")
|
|
spawn(0)
|
|
if(charge_type == "recharge" && recharge)
|
|
start_recharge()
|
|
|
|
if(sound)
|
|
playMagSound()
|
|
|
|
if(prob(critfailchance))
|
|
critfail(targets)
|
|
else
|
|
cast(targets, user = user)
|
|
after_cast(targets)
|
|
|
|
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
|
|
if(overlay)
|
|
for(var/atom/target in targets)
|
|
var/location
|
|
if(istype(target,/mob/living))
|
|
location = target.loc
|
|
else if(istype(target,/turf))
|
|
location = target
|
|
var/obj/effect/overlay/spell = new /obj/effect/overlay(location)
|
|
spell.icon = overlay_icon
|
|
spell.icon_state = overlay_icon_state
|
|
spell.anchored = 1
|
|
spell.density = 0
|
|
spawn(overlay_lifespan)
|
|
qdel(spell)
|
|
|
|
/obj/effect/proc_holder/spell/proc/after_cast(list/targets)
|
|
for(var/atom/target in targets)
|
|
var/location
|
|
if(istype(target,/mob/living))
|
|
location = target.loc
|
|
else if(istype(target,/turf))
|
|
location = target
|
|
if(istype(target,/mob/living) && message)
|
|
to_chat(target, text("[message]"))
|
|
if(sparks_spread)
|
|
do_sparks(sparks_amt, 0, location)
|
|
if(smoke_spread)
|
|
if(smoke_spread == 1)
|
|
var/datum/effect_system/smoke_spread/smoke = new
|
|
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
|
smoke.start()
|
|
else if(smoke_spread == 2)
|
|
var/datum/effect_system/smoke_spread/bad/smoke = new
|
|
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
|
smoke.start()
|
|
else if(smoke_spread == 3)
|
|
var/datum/effect_system/smoke_spread/sleeping/smoke = new
|
|
smoke.set_up(smoke_amt, 0, location) // same here
|
|
smoke.start()
|
|
|
|
/obj/effect/proc_holder/spell/proc/cast(list/targets, mob/user = usr)
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/proc/critfail(list/targets)
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
|
|
switch(charge_type)
|
|
if("recharge")
|
|
charge_counter = charge_max
|
|
if("charges")
|
|
charge_counter++
|
|
if("holdervar")
|
|
adjust_var(user, holder_var_type, -holder_var_amount)
|
|
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/proc/updateButtonIcon()
|
|
if(action)
|
|
action.UpdateButtonIcon()
|
|
|
|
/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types
|
|
switch(type)
|
|
if("bruteloss")
|
|
target.adjustBruteLoss(amount)
|
|
if("fireloss")
|
|
target.adjustFireLoss(amount)
|
|
if("toxloss")
|
|
target.adjustToxLoss(amount)
|
|
if("oxyloss")
|
|
target.adjustOxyLoss(amount)
|
|
if("stunned")
|
|
target.AdjustStunned(amount)
|
|
if("weakened")
|
|
target.AdjustWeakened(amount)
|
|
if("paralysis")
|
|
target.AdjustParalysis(amount)
|
|
else
|
|
target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
|
|
var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
|
|
var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
|
|
var/include_user = 0 //if it includes usr in the target list
|
|
var/random_target = 0 // chooses random viable target instead of asking the caster
|
|
var/random_target_priority = TARGET_CLOSEST // if random_target is enabled how it will pick the target
|
|
var/humans_only = 0 //for avoiding simple animals and only doing "human" mobs, 0 = all mobs, 1 = humans only
|
|
|
|
/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends)
|
|
var/inner_radius = -1 //for all your ring spell needs
|
|
|
|
/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr)
|
|
var/list/targets = list()
|
|
|
|
switch(max_targets)
|
|
if(0) //unlimited
|
|
|
|
if(!humans_only)
|
|
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
|
targets += target
|
|
else
|
|
for(var/mob/living/carbon/human/target in view_or_range(range, user, selection_type))
|
|
targets += target
|
|
|
|
if(1) //single target can be picked
|
|
if(range < 0)
|
|
targets += user
|
|
else
|
|
var/possible_targets = list()
|
|
|
|
if(!humans_only)
|
|
for(var/mob/living/M in view_or_range(range, user, selection_type))
|
|
if(!include_user && user == M)
|
|
continue
|
|
possible_targets += M
|
|
else
|
|
for(var/mob/living/carbon/human/M in view_or_range(range, user, selection_type))
|
|
if(!include_user && user == M)
|
|
continue
|
|
possible_targets += M
|
|
|
|
//targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets
|
|
//Adds a safety check post-input to make sure those targets are actually in range.
|
|
var/mob/M
|
|
if(!random_target)
|
|
M = input("Choose the target for the spell.", "Targeting") as mob in possible_targets
|
|
else
|
|
switch(random_target_priority)
|
|
if(TARGET_RANDOM)
|
|
M = pick(possible_targets)
|
|
if(TARGET_CLOSEST)
|
|
for(var/mob/living/L in possible_targets)
|
|
if(M)
|
|
if(get_dist(user,L) < get_dist(user,M))
|
|
if(los_check(user,L))
|
|
M = L
|
|
else
|
|
if(los_check(user,L))
|
|
M = L
|
|
if(M in view_or_range(range, user, selection_type)) targets += M
|
|
|
|
else
|
|
var/list/possible_targets = list()
|
|
if(!humans_only)
|
|
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
|
possible_targets += target
|
|
else
|
|
for(var/mob/living/carbon/human/target in view_or_range(range, user, selection_type))
|
|
possible_targets += target
|
|
for(var/i=1,i<=max_targets,i++)
|
|
if(!possible_targets.len)
|
|
break
|
|
if(target_ignore_prev)
|
|
var/target = pick(possible_targets)
|
|
possible_targets -= target
|
|
targets += target
|
|
else
|
|
targets += pick(possible_targets)
|
|
|
|
if(!include_user && (user in targets))
|
|
targets -= user
|
|
|
|
if(!targets.len) //doesn't waste the spell
|
|
revert_cast(user)
|
|
return
|
|
|
|
perform(targets, user=user)
|
|
|
|
return
|
|
|
|
/obj/effect/proc_holder/spell/aoe_turf/choose_targets(mob/user = usr)
|
|
var/list/targets = list()
|
|
|
|
for(var/turf/target in view_or_range(range,user,selection_type))
|
|
if(!(target in view_or_range(inner_radius,user,selection_type)))
|
|
targets += target
|
|
|
|
if(!targets.len) //doesn't waste the spell
|
|
revert_cast()
|
|
return
|
|
|
|
perform(targets, user=user)
|
|
|
|
return
|
|
|
|
|
|
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
|
|
//Checks for obstacles from A to B
|
|
var/obj/dummy = new(A.loc)
|
|
dummy.pass_flags |= PASSTABLE
|
|
for(var/turf/turf in getline(A,B))
|
|
for(var/atom/movable/AM in turf)
|
|
if(!AM.CanPass(dummy,turf,1))
|
|
qdel(dummy)
|
|
return 0
|
|
qdel(dummy)
|
|
return 1
|
|
|
|
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
|
|
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
|
|
return 0
|
|
|
|
if(is_admin_level(user.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
|
|
return 0
|
|
|
|
switch(charge_type)
|
|
if("recharge")
|
|
if(charge_counter < charge_max)
|
|
return 0
|
|
if("charges")
|
|
if(!charge_counter)
|
|
return 0
|
|
|
|
if(user.stat && !stat_allowed)
|
|
return 0
|
|
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
|
|
if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
|
|
return 0
|
|
|
|
var/clothcheck = locate(/obj/effect/proc_holder/spell/noclothes) in user.mob_spell_list
|
|
var/clothcheck2 = user.mind && (locate(/obj/effect/proc_holder/spell/noclothes) in user.mind.spell_list)
|
|
if(clothes_req && !clothcheck && !clothcheck2) //clothes check
|
|
var/obj/item/clothing/robe = H.wear_suit
|
|
var/obj/item/clothing/hat = H.head
|
|
var/obj/item/clothing/shoes = H.shoes
|
|
if(!robe || !hat || !shoes)
|
|
return 0
|
|
if(!robe.magical || !hat.magical || !shoes.magical)
|
|
return 0
|
|
else
|
|
if(clothes_req || human_req)
|
|
return 0
|
|
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
|
return 0
|
|
return 1
|