mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 11:34:19 +01:00
Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into stationgoals
# Conflicts: # _maps/map_files/cyberiad/z2.dmm # code/__DEFINES/is_helpers.dm # code/__DEFINES/misc.dm # code/_globalvars/lists/objects.dm # code/modules/mob/living/living_defines.dm # icons/effects/beam.dmi
This commit is contained in:
@@ -187,6 +187,40 @@
|
||||
|
||||
/datum/action/item_action/toggle_hardsuit_mode
|
||||
name = "Toggle Hardsuit Mode"
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire
|
||||
name = "Toggle Friendly Fire \[ON\]"
|
||||
desc = "Toggles if the staff causes friendly fire."
|
||||
button_icon_state = "vortex_ff_on"
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/Trigger()
|
||||
if(..())
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon()
|
||||
if(istype(target, /obj/item/weapon/hierophant_staff))
|
||||
var/obj/item/weapon/hierophant_staff/H = target
|
||||
if(H.friendly_fire_check)
|
||||
button_icon_state = "vortex_ff_off"
|
||||
name = "Toggle Friendly Fire \[OFF\]"
|
||||
button.name = name
|
||||
else
|
||||
button_icon_state = "vortex_ff_on"
|
||||
name = "Toggle Friendly Fire \[ON\]"
|
||||
button.name = name
|
||||
..()
|
||||
|
||||
/datum/action/item_action/vortex_recall
|
||||
name = "Vortex Recall"
|
||||
desc = "Recall yourself, and anyone nearby, to an attuned hierophant rune at any time.<br>If no such rune exists, will produce a rune at your location."
|
||||
button_icon_state = "vortex_recall"
|
||||
|
||||
/datum/action/item_action/vortex_recall/IsAvailable()
|
||||
if(istype(target, /obj/item/weapon/hierophant_staff))
|
||||
var/obj/item/weapon/hierophant_staff/H = target
|
||||
if(H.teleporting)
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/toggle
|
||||
|
||||
@@ -323,6 +357,11 @@
|
||||
..()
|
||||
name = "Toggle [target.name]"
|
||||
button.name = name
|
||||
|
||||
/datum/action/item_action/organ_action/use/New(Target)
|
||||
..()
|
||||
name = "Use [target.name]"
|
||||
button.name = name
|
||||
|
||||
// for clothing accessories like holsters
|
||||
/datum/action/item_action/accessory
|
||||
|
||||
@@ -245,8 +245,8 @@
|
||||
id = "trash"
|
||||
//Note that this filters out blueprints because they are a paper item. Do NOT throw out the station blueprints unless you be trollin'.
|
||||
blacklist = null
|
||||
whitelist = list(/obj/item/trash,/obj/item/toy,/obj/item/weapon/reagent_containers/food/snacks/ectoplasm,/obj/item/weapon/bananapeel,/obj/item/weapon/broken_bottle,/obj/item/weapon/bikehorn,
|
||||
/obj/item/weapon/cigbutt,/obj/item/weapon/contraband,/obj/item/weapon/corncob,/obj/item/weapon/paper,/obj/item/weapon/shard,
|
||||
whitelist = list(/obj/item/trash,/obj/item/toy,/obj/item/weapon/reagent_containers/food/snacks/ectoplasm,/obj/item/weapon/grown/bananapeel,/obj/item/weapon/broken_bottle,/obj/item/weapon/bikehorn,
|
||||
/obj/item/weapon/cigbutt,/obj/item/weapon/contraband,/obj/item/weapon/grown/corncob,/obj/item/weapon/paper,/obj/item/weapon/shard,
|
||||
/obj/item/weapon/sord,/obj/item/weapon/photo,/obj/item/weapon/folder,
|
||||
/obj/item/areaeditor/blueprints,/obj/item/weapon/contraband,/obj/item/weapon/kitchen,/obj/item/weapon/book,/obj/item/clothing/mask/facehugger)
|
||||
|
||||
@@ -267,9 +267,9 @@
|
||||
whitelist = list(/obj/item/device,/obj/item/weapon/card,/obj/item/weapon/cartridge,/obj/item/weapon/cautery,/obj/item/weapon/stock_parts/cell,/obj/item/weapon/circuitboard,
|
||||
/obj/item/weapon/aiModule,/obj/item/weapon/airalarm_electronics,/obj/item/weapon/airlock_electronics,/obj/item/weapon/circular_saw,
|
||||
/obj/item/weapon/crowbar,/obj/item/weapon/disk,/obj/item/weapon/firealarm_electronics,/obj/item/weapon/hand_tele,
|
||||
/obj/item/weapon/hand_labeler,/obj/item/weapon/hemostat,/obj/item/weapon/mop,/obj/item/weapon/locator,/obj/item/weapon/minihoe,
|
||||
/obj/item/weapon/hand_labeler,/obj/item/weapon/hemostat,/obj/item/weapon/mop,/obj/item/weapon/locator,/obj/item/weapon/cultivator,
|
||||
/obj/item/stack/packageWrap,/obj/item/weapon/pen,/obj/item/weapon/pickaxe,/obj/item/weapon/pinpointer,
|
||||
/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/retractor,/obj/item/weapon/rsf,/obj/item/weapon/rsp,/obj/item/weapon/scalpel,
|
||||
/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/retractor,/obj/item/weapon/rsf,/obj/item/weapon/scalpel,
|
||||
/obj/item/weapon/screwdriver,/obj/item/weapon/shovel,/obj/item/weapon/soap,/obj/item/weapon/stamp,/obj/item/weapon/storage/bag/tray,/obj/item/weapon/weldingtool,
|
||||
/obj/item/weapon/wirecutters,/obj/item/weapon/wrench,/obj/item/weapon/extinguisher)
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
|
||||
|
||||
/datum
|
||||
var/var_edited = 0 //Warrenty void if seal is broken
|
||||
|
||||
/datum/proc/on_varedit(modified_var) //called whenever a var is edited
|
||||
var_edited = 1
|
||||
|
||||
/client/proc/debug_variables(datum/D in world)
|
||||
set category = "Debug"
|
||||
set name = "View Variables"
|
||||
|
||||
@@ -132,6 +132,8 @@
|
||||
|
||||
//For spawning mineral sheets; internal use only
|
||||
/datum/material_container/proc/retrieve(sheet_amt, datum/material/M)
|
||||
if(!M.sheet_type)
|
||||
return 0
|
||||
if(sheet_amt > 0)
|
||||
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
@@ -271,4 +273,10 @@
|
||||
/datum/material/tranquillite/New()
|
||||
..()
|
||||
material_type = MAT_TRANQUILLITE
|
||||
sheet_type = /obj/item/stack/sheet/mineral/tranquillite
|
||||
sheet_type = /obj/item/stack/sheet/mineral/tranquillite
|
||||
|
||||
/datum/material/biomass
|
||||
|
||||
/datum/material/biomass/New()
|
||||
..()
|
||||
material_type = MAT_BIOMASS
|
||||
+31
-54
@@ -34,14 +34,12 @@
|
||||
* */
|
||||
|
||||
/datum/recipe
|
||||
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
|
||||
var/list/items // example: = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
|
||||
var/list/fruit // example: = list("fruit" = 3)
|
||||
var/result // example: = /obj/item/weapon/reagent_containers/food/snacks/donut
|
||||
var/time = 100 // 1/10 part of second
|
||||
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
|
||||
var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
|
||||
var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut
|
||||
var/time = 100 // 1/10 part of second
|
||||
var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash
|
||||
|
||||
|
||||
/datum/recipe/proc/check_reagents(datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous
|
||||
. = 1
|
||||
for(var/r_r in reagents)
|
||||
@@ -55,44 +53,25 @@
|
||||
return -1
|
||||
return .
|
||||
|
||||
/datum/recipe/proc/check_fruit(obj/container)
|
||||
/datum/recipe/proc/check_items(obj/container) //1=precisely, 0=insufficiently, -1=superfluous
|
||||
if(!items)
|
||||
if(locate(/obj/) in container)
|
||||
return -1
|
||||
else
|
||||
return 1
|
||||
. = 1
|
||||
if(fruit && fruit.len)
|
||||
var/list/checklist = list()
|
||||
// You should trust Copy().
|
||||
checklist = fruit.Copy()
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in container)
|
||||
if(!G.seed || !G.seed.kitchen_tag || isnull(checklist[G.seed.kitchen_tag]))
|
||||
continue
|
||||
checklist[G.seed.kitchen_tag]--
|
||||
for(var/ktag in checklist)
|
||||
if(!isnull(checklist[ktag]))
|
||||
if(checklist[ktag] < 0)
|
||||
. = 0
|
||||
else if(checklist[ktag] > 0)
|
||||
. = -1
|
||||
break
|
||||
return .
|
||||
|
||||
/datum/recipe/proc/check_items(obj/container)
|
||||
. = 1
|
||||
if(items && items.len)
|
||||
var/list/checklist = list()
|
||||
checklist = items.Copy() // You should really trust Copy
|
||||
for(var/obj/O in container)
|
||||
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
|
||||
continue // Fruit is handled in check_fruit().
|
||||
var/found = 0
|
||||
for(var/i = 1; i < checklist.len+1; i++)
|
||||
var/item_type = checklist[i]
|
||||
if(istype(O,item_type))
|
||||
checklist.Cut(i, i+1)
|
||||
found = 1
|
||||
break
|
||||
if(!found)
|
||||
. = 0
|
||||
if(checklist.len)
|
||||
var/list/checklist = items.Copy()
|
||||
for(var/obj/O in container)
|
||||
var/found = 0
|
||||
for(var/type in checklist)
|
||||
if(istype(O,type))
|
||||
checklist-=type
|
||||
found = 1
|
||||
break
|
||||
if(!found)
|
||||
. = -1
|
||||
if(checklist.len)
|
||||
return 0
|
||||
return .
|
||||
|
||||
//general version
|
||||
@@ -102,7 +81,6 @@
|
||||
O.reagents.trans_to(result_obj, O.reagents.total_volume)
|
||||
qdel(O)
|
||||
container.reagents.clear_reagents()
|
||||
score_meals++
|
||||
return result_obj
|
||||
|
||||
// food-related
|
||||
@@ -115,27 +93,29 @@
|
||||
O.reagents.trans_to(result_obj, O.reagents.total_volume)
|
||||
qdel(O)
|
||||
container.reagents.clear_reagents()
|
||||
score_meals++
|
||||
return result_obj
|
||||
|
||||
/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1)
|
||||
/proc/select_recipe(list/datum/recipe/avaiable_recipes, obj/obj, exact = 1 as num)
|
||||
if(!exact)
|
||||
exact = -1
|
||||
var/list/datum/recipe/possible_recipes = new
|
||||
for(var/datum/recipe/recipe in avaiable_recipes)
|
||||
if(recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact && recipe.check_fruit(obj)==exact)
|
||||
if(recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact)
|
||||
possible_recipes+=recipe
|
||||
if(possible_recipes.len==0)
|
||||
return null
|
||||
else if(possible_recipes.len==1)
|
||||
return possible_recipes[1]
|
||||
else //okay, let's select the most complicated recipe
|
||||
var/highest_count = 0
|
||||
var/r_count = 0
|
||||
var/i_count = 0
|
||||
. = possible_recipes[1]
|
||||
for(var/datum/recipe/recipe in possible_recipes)
|
||||
var/count = ((recipe.items)?(recipe.items.len):0) + ((recipe.reagents)?(recipe.reagents.len):0) + ((recipe.fruit)?(recipe.fruit.len):0)
|
||||
if(count >= highest_count)
|
||||
highest_count = count
|
||||
var/N_i = (recipe.items)?(recipe.items.len):0
|
||||
var/N_r = (recipe.reagents)?(recipe.reagents.len):0
|
||||
if(N_i > i_count || (N_i== i_count && N_r > r_count ))
|
||||
r_count = N_r
|
||||
i_count = N_i
|
||||
. = recipe
|
||||
return .
|
||||
|
||||
@@ -149,7 +129,4 @@
|
||||
var/count = 0
|
||||
if(items && items.len)
|
||||
count += items.len
|
||||
if(fruit && fruit.len)
|
||||
for(var/ktag in fruit)
|
||||
count += fruit[ktag]
|
||||
return count
|
||||
return count
|
||||
+80
-24
@@ -3,9 +3,53 @@
|
||||
|
||||
/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.next_click = world.time + 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"
|
||||
@@ -26,6 +70,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
|
||||
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
|
||||
@@ -54,13 +100,15 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
var/action_icon = 'icons/mob/actions.dmi'
|
||||
var/action_icon_state = "spell_default"
|
||||
var/action_background_icon_state = "bg_spell"
|
||||
|
||||
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(istype(user, /mob/living/carbon/human))
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/caster = user
|
||||
if(caster.remoteview_target)
|
||||
caster.remoteview_target = null
|
||||
@@ -83,26 +131,31 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
|
||||
if(!ghost)
|
||||
if(user.stat && !stat_allowed)
|
||||
to_chat(user, "Not when you're incapacitated.")
|
||||
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/spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list()))
|
||||
if(clothes_req && !(spell && istype(spell)))//clothes check
|
||||
if(!istype(user, /mob/living/carbon/human))
|
||||
to_chat(user, "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans.")
|
||||
|
||||
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
|
||||
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard))
|
||||
to_chat(user, "<span class='notice'>I don't feel strong enough without my robe.</span>")
|
||||
return 0
|
||||
if(!istype(user:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/rig/wizard))
|
||||
to_chat(user, "I don't feel strong enough without my robe.")
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
|
||||
to_chat(user, "<span class='notice'>I don't feel strong enough without my sandals.</span>")
|
||||
return 0
|
||||
if(!istype(user:shoes, /obj/item/clothing/shoes/sandal))
|
||||
to_chat(user, "I don't feel strong enough without my sandals.")
|
||||
return 0
|
||||
if(!istype(user:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/rig/wizard))
|
||||
if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard))
|
||||
to_chat(user, "<span class='notice'>I don't feel strong enough without my hat.</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)
|
||||
@@ -130,6 +183,9 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
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)
|
||||
@@ -167,10 +223,14 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
spawn(0)
|
||||
if(charge_type == "recharge" && recharge)
|
||||
start_recharge()
|
||||
|
||||
if(sound)
|
||||
playMagSound()
|
||||
|
||||
if(prob(critfailchance))
|
||||
critfail(targets)
|
||||
else
|
||||
cast(targets)
|
||||
cast(targets, user = user)
|
||||
after_cast(targets)
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
|
||||
@@ -216,7 +276,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
smoke.set_up(smoke_amt, 0, location) // same here
|
||||
smoke.start()
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/proc/cast(list/targets, mob/user = usr)
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/critfail(list/targets)
|
||||
@@ -270,9 +330,6 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
switch(max_targets)
|
||||
if(0) //unlimited
|
||||
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
||||
for(var/F in user.faction)
|
||||
if(F in target.faction)
|
||||
continue
|
||||
targets += target
|
||||
if(1) //single target can be picked
|
||||
if(range < 0)
|
||||
@@ -326,7 +383,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
revert_cast(user)
|
||||
return
|
||||
|
||||
perform(targets)
|
||||
perform(targets, user=user)
|
||||
|
||||
return
|
||||
|
||||
@@ -341,7 +398,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
revert_cast()
|
||||
return
|
||||
|
||||
perform(targets)
|
||||
perform(targets, user=user)
|
||||
|
||||
return
|
||||
|
||||
@@ -377,7 +434,6 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
return 0
|
||||
|
||||
if(ishuman(user))
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
|
||||
@@ -393,8 +449,8 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
|
||||
if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard))
|
||||
return 0
|
||||
else
|
||||
if(clothes_req)
|
||||
if(clothes_req || human_req)
|
||||
return 0
|
||||
if(isbrain(user) || ispAI(user))
|
||||
if(nonabstract_req && (isbrain(user) || ispAI(user)))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport
|
||||
name = "Area teleport"
|
||||
desc = "This spell teleports you to a type of area of your selection."
|
||||
|
||||
nonabstract_req = 1
|
||||
|
||||
var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list
|
||||
var/invocation_area = 1 //if the invocation appends the selected area
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1)
|
||||
|
||||
var/sound1 = 'sound/weapons/ZapBang.ogg'
|
||||
var/sound2 = 'sound/weapons/ZapBang.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1, mob/living/user = usr)
|
||||
var/thearea = before_cast(targets)
|
||||
if(!thearea || !cast_check(1))
|
||||
revert_cast()
|
||||
@@ -32,7 +37,8 @@
|
||||
|
||||
return thearea
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea)
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea,mob/living/user = usr)
|
||||
playsound(get_turf(user), sound1, 50,1)
|
||||
for(var/mob/living/target in targets)
|
||||
var/list/L = list()
|
||||
for(var/turf/T in get_area_turfs(thearea.type))
|
||||
@@ -64,7 +70,8 @@
|
||||
break
|
||||
|
||||
if(!success)
|
||||
target.loc = pick(L)
|
||||
target.forceMove(pick(L))
|
||||
playsound(get_turf(user), sound2, 50,1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
/obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr)
|
||||
for(var/obj/effect/decal/cleanable/target in range(range, get_turf(user)))
|
||||
if(istype(target,/obj/effect/decal/cleanable/blood) && !(istype(target,/obj/effect/decal/cleanable/blood/oil) || istype(target,/obj/effect/decal/cleanable/blood/gibs/robot)))
|
||||
perform(target)
|
||||
if(target.can_bloodcrawl_in())
|
||||
perform(target, user = user)
|
||||
return
|
||||
revert_cast()
|
||||
to_chat(user, "<span class='warning'>There must be a nearby source of blood!</span>")
|
||||
|
||||
@@ -13,15 +13,17 @@
|
||||
var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet
|
||||
//should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example
|
||||
var/delay = 1//Go Go Gadget Inheritance
|
||||
|
||||
var/cast_sound = 'sound/items/welder.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets,mob/living/user = usr)
|
||||
playsound(get_turf(user), cast_sound, 50,1)
|
||||
for(var/turf/T in targets)
|
||||
if(T.density && !summon_ignore_density)
|
||||
targets -= T
|
||||
playsound(get_turf(src), 'sound/items/welder.ogg', 50, 1)
|
||||
playsound(get_turf(src), cast_sound, 50, 1)
|
||||
|
||||
if(do_after(usr,delay, target = usr))
|
||||
if(do_after(user,delay, target = user))
|
||||
for(var/i=0,i<summon_amt,i++)
|
||||
if(!targets.len)
|
||||
break
|
||||
@@ -30,8 +32,8 @@
|
||||
if(summon_ignore_prev_spawn_points)
|
||||
targets -= spawn_place
|
||||
if(ispath(summoned_object_type,/turf))
|
||||
if(istype(get_turf(usr),/turf/simulated/shuttle))
|
||||
to_chat(usr, "\red You can't build things on shuttles!")
|
||||
if(istype(get_turf(user),/turf/simulated/shuttle))
|
||||
to_chat(user, "\red You can't build things on shuttles!")
|
||||
break
|
||||
var/turf/O = spawn_place
|
||||
var/N = summoned_object_type
|
||||
@@ -42,6 +44,7 @@
|
||||
for(var/varName in newVars)
|
||||
if(varName in summoned_object.vars)
|
||||
summoned_object.vars[varName] = newVars[varName]
|
||||
summoned_object.admin_spawned = TRUE
|
||||
|
||||
if(summon_lifespan)
|
||||
spawn(summon_lifespan)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
if(new_turf.density)
|
||||
break
|
||||
T = new_turf
|
||||
perform(list(T))
|
||||
perform(list(T), user = user)
|
||||
|
||||
/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr)
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
projectile.dir = get_dir(projectile, target)
|
||||
projectile.name = proj_name
|
||||
|
||||
var/current_loc = usr.loc
|
||||
var/current_loc = user.loc
|
||||
|
||||
projectile.loc = current_loc
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
projectile.cast(current_loc)
|
||||
break
|
||||
|
||||
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - usr
|
||||
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - user
|
||||
if(L && L.stat != DEAD)
|
||||
projectile.cast(L.loc)
|
||||
break
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
action_icon_state = "emp"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets, mob/user = usr)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
empulse(target.loc, emp_heavy, emp_light)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
range = -1
|
||||
cooldown_min = 100 //50 deciseconds reduction per rank
|
||||
include_user = 1
|
||||
nonabstract_req = 1
|
||||
centcom_cancast = 0 //Prevent people from getting to centcom
|
||||
|
||||
var phaseshift = 0
|
||||
@@ -17,7 +18,7 @@
|
||||
|
||||
action_icon_state = "jaunt"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets, mob/user = usr) //magnets, so mostly hardcoded
|
||||
for(var/mob/living/target in targets)
|
||||
if(!target.can_safely_leave_loc()) // No more brainmobs hopping out of their brains
|
||||
to_chat(target, "<span class='warning'>You are somehow too bound to your current location to abandon it.</span>")
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
var/ex_light = 3
|
||||
var/ex_flash = 4
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/explosion/cast(list/targets, mob/user = usr)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
6th bit - ?
|
||||
*/
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets, mob/user = usr)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
for(var/x in mutations)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
selection_type = "range"
|
||||
|
||||
action_icon_state = "barn"
|
||||
sound = 'sound/magic/HorseHead_curse.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
|
||||
if(!targets.len)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
var/summon_type = null //this will put an obj at the target's location
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets, mob/user = usr)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
switch(destroys)
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
cooldown_min = 20 //20 deciseconds reduction per rank
|
||||
|
||||
action_icon_state = "knock"
|
||||
sound = 'sound/magic/Knock.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets, mob/user = usr)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/door/door in T.contents)
|
||||
spawn(1)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
var/ready = 0
|
||||
var/image/halo = null
|
||||
action_icon_state = "lightning"
|
||||
var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea.
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/lightnian
|
||||
clothes_req = 0
|
||||
@@ -31,8 +32,10 @@
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/proc/StartChargeup(mob/user = usr)
|
||||
ready = 1
|
||||
to_chat(user, "<span class='notice'>You start gathering the power.</span>")
|
||||
Snd = new/sound('sound/magic/lightning_chargeup.ogg',channel = 7)
|
||||
halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER)
|
||||
user.overlays.Add(halo)
|
||||
playsound(get_turf(user), Snd, 50, 0)
|
||||
start_time = world.time
|
||||
if(do_mob(user,user,100,uninterruptible=1))
|
||||
if(ready)
|
||||
@@ -59,11 +62,14 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/targeted/lightning/cast(list/targets, mob/user = usr)
|
||||
ready = 0
|
||||
var/mob/living/carbon/target = targets[1]
|
||||
Snd=sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
|
||||
playsound(get_turf(user),Snd,50,0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
|
||||
if(get_dist(user,target)>range)
|
||||
to_chat(user, "<span class='notice'>They are too far away!</span>")
|
||||
Reset(user)
|
||||
return
|
||||
|
||||
playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1)
|
||||
user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
|
||||
|
||||
var/energy = min(world.time - start_time,100)
|
||||
@@ -75,10 +81,10 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
|
||||
var/mob/living/carbon/current = target
|
||||
if(bounces < 1)
|
||||
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
|
||||
playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
|
||||
else
|
||||
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
|
||||
playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
|
||||
var/list/possible_targets = new
|
||||
for(var/mob/living/M in view_or_range(range,target,"view"))
|
||||
if(user == M || target == M && los_check(current,M)) // || origin == M ? Not sure double shockings is good or not
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
charge_max = 300
|
||||
clothes_req = 0
|
||||
range = 0
|
||||
|
||||
cast_sound = null
|
||||
human_req = 1
|
||||
|
||||
action_icon_state = "mime"
|
||||
action_background_icon_state = "bg_mime"
|
||||
|
||||
@@ -34,6 +36,7 @@
|
||||
charge_max = 3000
|
||||
range = -1
|
||||
include_user = 1
|
||||
human_req = 1
|
||||
|
||||
action_icon_state = "mime"
|
||||
action_background_icon_state = "bg_mime"
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
projectile.dir = get_dir(target,projectile)
|
||||
projectile.name = proj_name
|
||||
|
||||
var/current_loc = usr.loc
|
||||
var/current_loc = user.loc
|
||||
|
||||
projectile.loc = current_loc
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
qdel(trail)
|
||||
|
||||
if(projectile.loc in range(target.loc,proj_trigger_range))
|
||||
projectile.perform(list(target))
|
||||
projectile.perform(list(target), user = user)
|
||||
break
|
||||
|
||||
current_loc = projectile.loc
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift
|
||||
name = "Shapechange"
|
||||
desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed."
|
||||
clothes_req = 0
|
||||
human_req = 0
|
||||
charge_max = 200
|
||||
cooldown_min = 50
|
||||
range = -1
|
||||
include_user = 1
|
||||
invocation = "RAC'WA NO!"
|
||||
invocation_type = "shout"
|
||||
action_icon_state = "shapeshift"
|
||||
|
||||
var/shapeshift_type
|
||||
var/list/current_shapes = list()
|
||||
var/list/current_casters = list()
|
||||
var/list/possible_shapes = list(/mob/living/simple_animal/mouse,
|
||||
/mob/living/simple_animal/pet/corgi,
|
||||
/mob/living/simple_animal/bot/ed209,
|
||||
/mob/living/simple_animal/hostile/construct/armoured)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/M in targets)
|
||||
if(!shapeshift_type)
|
||||
var/list/animal_list = list()
|
||||
for(var/path in possible_shapes)
|
||||
var/mob/living/simple_animal/A = path
|
||||
animal_list[initial(A.name)] = path
|
||||
shapeshift_type = input(M, "Choose Your Animal Form!", "It's Morphing Time!", null) as anything in animal_list
|
||||
if(!shapeshift_type) //If you aren't gonna decide I am!
|
||||
shapeshift_type = pick(animal_list)
|
||||
shapeshift_type = animal_list[shapeshift_type]
|
||||
if(M in current_shapes)
|
||||
Restore(M)
|
||||
else
|
||||
Shapeshift(M)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Shapeshift(mob/living/caster)
|
||||
for(var/mob/living/M in caster)
|
||||
if(M.status_flags & GODMODE)
|
||||
to_chat(caster, "<span class='warning'>You're already shapeshifted!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/shape = new shapeshift_type(caster.loc)
|
||||
caster.loc = shape
|
||||
caster.status_flags |= GODMODE
|
||||
|
||||
current_shapes |= shape
|
||||
current_casters |= caster
|
||||
clothes_req = 0
|
||||
human_req = 0
|
||||
|
||||
caster.mind.transfer_to(shape)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Restore(mob/living/shape)
|
||||
var/mob/living/caster
|
||||
for(var/mob/living/M in shape)
|
||||
if(M in current_casters)
|
||||
caster = M
|
||||
break
|
||||
if(!caster)
|
||||
return
|
||||
caster.loc = shape.loc
|
||||
caster.status_flags &= ~GODMODE
|
||||
|
||||
clothes_req = initial(clothes_req)
|
||||
human_req = initial(human_req)
|
||||
current_casters.Remove(caster)
|
||||
current_shapes.Remove(shape)
|
||||
|
||||
shape.mind.transfer_to(caster)
|
||||
qdel(shape) //Gib it maybe ?
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/dragon
|
||||
name = "Dragon Form"
|
||||
desc = "Take on the shape a lesser ash drake."
|
||||
invocation = "RAAAAAAAAWR!"
|
||||
|
||||
shapeshift_type = /mob/living/simple_animal/hostile/megafauna/dragon/lesser
|
||||
list/current_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser)
|
||||
list/current_casters = list()
|
||||
list/possible_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser)
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
action_icon_state = "summons"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summonitem/cast(list/targets)
|
||||
for(var/mob/living/user in targets)
|
||||
var/list/hand_items = list(user.get_active_hand(),user.get_inactive_hand())
|
||||
/obj/effect/proc_holder/spell/targeted/summonitem/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
var/list/hand_items = list(target.get_active_hand(),target.get_inactive_hand())
|
||||
var/butterfingers = 0
|
||||
var/message
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
if(issilicon(M)) //Items in silicons warp the whole silicon
|
||||
M.loc.visible_message("<span class='warning'>[M] suddenly disappears!</span>")
|
||||
M.loc = user.loc
|
||||
M.loc = target.loc
|
||||
M.loc.visible_message("<span class='caution'>[M] suddenly appears!</span>")
|
||||
item_to_retrive = null
|
||||
break
|
||||
@@ -68,10 +68,10 @@
|
||||
/*if(C.internal_organs_by_name && item_to_retrive in C.internal_organs_by_name ) //This won't work, as we use organ datums instead of objects. --DZD
|
||||
C.internal_organs_by_name -= item_to_retrive
|
||||
if(istype(marked_item, /obj/item/brain)) //If this code ever runs I will be happy
|
||||
var/obj/item/brain/B = new /obj/item/brain(user.loc)
|
||||
var/obj/item/brain/B = new /obj/item/brain(target.loc)
|
||||
B.transfer_identity(C)
|
||||
C.death()
|
||||
add_logs(user, C, "magically debrained", addition="INTENT: [uppertext(user.a_intent)]")*/
|
||||
add_logs(target, C, "magically debrained", addition="INTENT: [uppertext(target.a_intent)]")*/
|
||||
if(C.stomach_contents && item_to_retrive in C.stomach_contents)
|
||||
C.stomach_contents -= item_to_retrive
|
||||
|
||||
@@ -91,19 +91,21 @@
|
||||
item_to_retrive.loc.visible_message("<span class='warning'>The [item_to_retrive.name] suddenly disappears!</span>")
|
||||
|
||||
|
||||
if(user.hand) //left active hand
|
||||
if(!user.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
|
||||
if(!user.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
|
||||
if(target.hand) //left active hand
|
||||
if(!target.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
|
||||
if(!target.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
|
||||
butterfingers = 1
|
||||
else //right active hand
|
||||
if(!user.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
|
||||
if(!user.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
|
||||
if(!target.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
|
||||
if(!target.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
|
||||
butterfingers = 1
|
||||
if(butterfingers)
|
||||
item_to_retrive.loc = user.loc
|
||||
item_to_retrive.loc = target.loc
|
||||
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears!</span>")
|
||||
playsound(get_turf(target),'sound/magic/SummonItems_generic.ogg',50,1)
|
||||
else
|
||||
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears in [user]'s hand!</span>")
|
||||
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears in [target]'s hand!</span>")
|
||||
playsound(get_turf(target),'sound/magic/SummonItems_generic.ogg',50,1)
|
||||
|
||||
if(message)
|
||||
to_chat(user, message)
|
||||
to_chat(target, message)
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets)
|
||||
for(var/mob/living/carbon/user in targets)
|
||||
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/carbon/target in targets)
|
||||
if(!attached_hand)
|
||||
if(!ChargeHand(user))
|
||||
if(!ChargeHand(target))
|
||||
return 0
|
||||
while(attached_hand) //hibernate untill the spell is actually used
|
||||
charge_counter = 0
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
starting_spells = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
for(var/obj/effect/proc_holder/spell/spell in contents)
|
||||
spell.perform(list(target),0)
|
||||
spell.perform(list(target), 0, user = user)
|
||||
for(var/obj/effect/proc_holder/spell/spell in linked_spells)
|
||||
spell.perform(list(target),0)
|
||||
spell.perform(list(target), 0, user = user)
|
||||
|
||||
return
|
||||
@@ -1,14 +1,19 @@
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport
|
||||
name = "Turf Teleport"
|
||||
desc = "This spell teleports the target to the turf in range."
|
||||
nonabstract_req = 1
|
||||
|
||||
var/inner_tele_radius = 1
|
||||
var/outer_tele_radius = 2
|
||||
|
||||
var/include_space = 0 //whether it includes space tiles in possible teleport locations
|
||||
var/include_dense = 0 //whether it includes dense tiles in possible teleport locations
|
||||
|
||||
var/sound1 = 'sound/weapons/ZapBang.ogg'
|
||||
var/sound2 = 'sound/weapons/ZapBang.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets,mob/living/user = usr)
|
||||
playsound(get_turf(user), sound1, 50,1)
|
||||
for(var/mob/living/target in targets)
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in range(target,outer_tele_radius))
|
||||
@@ -31,4 +36,5 @@
|
||||
if(!picked || !isturf(picked))
|
||||
return
|
||||
|
||||
target.loc = picked
|
||||
target.forceMove(picked)
|
||||
playsound(get_turf(user), sound2, 50,1)
|
||||
|
||||
@@ -25,9 +25,12 @@
|
||||
proj_trail_icon_state = "magicmd"
|
||||
|
||||
action_icon_state = "magicm"
|
||||
|
||||
sound = 'sound/magic/MAGIC_MISSILE.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
|
||||
amt_weakened = 3
|
||||
sound = 'sound/magic/MM_Hit.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/noclothes
|
||||
name = "No Clothes"
|
||||
@@ -52,8 +55,9 @@
|
||||
cooldown_min = 300 //25 deciseconds reduction per rank
|
||||
|
||||
action_icon_state = "mutate"
|
||||
sound = 'sound/magic/Mutate.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/mutate/cast(list/targets)
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/mutate/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/target in targets)
|
||||
target.dna.SetSEState(HULKBLOCK, 1)
|
||||
genemutcheck(target, HULKBLOCK, null, MUTCHK_FORCED)
|
||||
@@ -93,6 +97,8 @@
|
||||
|
||||
emp_heavy = 6
|
||||
emp_light = 10
|
||||
|
||||
sound = 'sound/magic/Disable_Tech.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport/blink
|
||||
name = "Blink"
|
||||
@@ -117,6 +123,9 @@
|
||||
centcom_cancast = 0 //prevent people from getting to centcom
|
||||
|
||||
action_icon_state = "blink"
|
||||
|
||||
sound1 = 'sound/magic/blink.ogg'
|
||||
sound2 = 'sound/magic/blink.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/teleport
|
||||
name = "Teleport"
|
||||
@@ -135,6 +144,9 @@
|
||||
smoke_amt = 5
|
||||
|
||||
action_icon_state = "spell_teleport"
|
||||
|
||||
sound1 = 'sound/magic/Teleport_diss.ogg'
|
||||
sound2 = 'sound/magic/Teleport_app.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall
|
||||
name = "Forcewall"
|
||||
@@ -152,6 +164,7 @@
|
||||
summon_lifespan = 300
|
||||
|
||||
action_icon_state = "shield"
|
||||
cast_sound = 'sound/magic/ForceWall.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
|
||||
name = "Stop Time"
|
||||
@@ -180,7 +193,8 @@
|
||||
|
||||
summon_type = list(/mob/living/simple_animal/hostile/carp)
|
||||
|
||||
|
||||
cast_sound = 'sound/magic/Summon_Karp.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct
|
||||
name = "Artificer"
|
||||
desc = "This spell conjures a construct which may be controlled by Shades"
|
||||
@@ -195,6 +209,7 @@
|
||||
summon_type = list(/obj/structure/constructshell)
|
||||
|
||||
action_icon_state = "artificer"
|
||||
cast_sound = 'sound/magic/SummonItems_generic.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature
|
||||
name = "Summon Creature Swarm"
|
||||
@@ -209,6 +224,7 @@
|
||||
range = 3
|
||||
|
||||
summon_type = list(/mob/living/simple_animal/hostile/creature)
|
||||
cast_sound = 'sound/magic/SummonItems_generic.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/blind
|
||||
name = "Blind"
|
||||
@@ -229,12 +245,14 @@
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
|
||||
amt_eye_blind = 10
|
||||
amt_eye_blurry = 20
|
||||
sound = 'sound/magic/Blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/blind
|
||||
disabilities = BLIND
|
||||
duration = 300
|
||||
sound = 'sound/magic/Blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/dumbfire/fireball
|
||||
/obj/effect/proc_holder/spell/fireball
|
||||
name = "Fireball"
|
||||
desc = "This spell fires a fireball at a target and does not require wizard garb."
|
||||
|
||||
@@ -245,29 +263,65 @@
|
||||
invocation_type = "shout"
|
||||
range = 20
|
||||
cooldown_min = 20 //10 deciseconds reduction per rank
|
||||
var/fireball_type = /obj/item/projectile/magic/fireball
|
||||
action_icon_state = "fireball0"
|
||||
sound = 'sound/magic/Fireball.ogg'
|
||||
|
||||
proj_icon_state = "fireball"
|
||||
proj_name = "a fireball"
|
||||
proj_type = "/obj/effect/proc_holder/spell/turf/fireball"
|
||||
active = FALSE
|
||||
|
||||
proj_lifespan = 200
|
||||
proj_step_delay = 1
|
||||
/obj/effect/proc_holder/spell/fireball/Click()
|
||||
var/mob/living/user = usr
|
||||
if(!istype(user))
|
||||
return
|
||||
|
||||
action_icon_state = "fireball"
|
||||
var/msg
|
||||
|
||||
/obj/effect/proc_holder/spell/turf/fireball/cast(var/turf/T)
|
||||
explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
|
||||
if(!can_cast(user))
|
||||
msg = "<span class='warning'>You can no longer cast Fireball.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
return
|
||||
|
||||
if(active)
|
||||
msg = "<span class='notice'>You extinguish your fireball...for now.</span>"
|
||||
remove_ranged_ability(user, msg)
|
||||
else
|
||||
msg = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
|
||||
add_ranged_ability(user, msg)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/fireball
|
||||
amt_dam_brute = 20
|
||||
amt_dam_fire = 25
|
||||
/obj/effect/proc_holder/spell/fireball/update_icon()
|
||||
if(!action)
|
||||
return
|
||||
action.button_icon_state = "fireball[active]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/explosion/fireball
|
||||
ex_severe = -1
|
||||
ex_heavy = -1
|
||||
ex_light = 2
|
||||
ex_flash = 5
|
||||
/obj/effect/proc_holder/spell/fireball/InterceptClickOn(mob/living/user, params, atom/target)
|
||||
if(..())
|
||||
return FALSE
|
||||
|
||||
if(!cast_check(0, user))
|
||||
remove_ranged_ability(user)
|
||||
return FALSE
|
||||
|
||||
var/list/targets = list(target)
|
||||
perform(targets, user = user)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/cast(list/targets, mob/living/user = usr)
|
||||
var/target = targets[1] //There is only ever one target for fireball
|
||||
var/turf/T = user.loc
|
||||
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
|
||||
if(!isturf(U) || !isturf(T))
|
||||
return 0
|
||||
|
||||
var/obj/item/projectile/magic/fireball/FB = new fireball_type(user.loc)
|
||||
FB.current = get_turf(user)
|
||||
FB.preparePixelProjectile(target, get_turf(target), user)
|
||||
FB.fire()
|
||||
user.newtonian_move(get_dir(U, T))
|
||||
remove_ranged_ability(user)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse
|
||||
name = "Repulse"
|
||||
@@ -282,12 +336,13 @@
|
||||
var/maxthrow = 5
|
||||
|
||||
action_icon_state = "repulse"
|
||||
sound = 'sound/magic/Repulse.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets)
|
||||
var/mob/user = usr
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets, mob/user = usr)
|
||||
var/list/thrownatoms = list()
|
||||
var/atom/throwtarget
|
||||
var/distfromcaster
|
||||
playMagSound()
|
||||
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
|
||||
for(var/atom/movable/AM in T)
|
||||
thrownatoms += AM
|
||||
@@ -314,3 +369,24 @@
|
||||
M.Weaken(2)
|
||||
to_chat(M, "<span class='userdanger'>You're thrown back by a mystical force!</span>")
|
||||
spawn(0) AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/sacred_flame
|
||||
name = "Sacred Flame"
|
||||
desc = "Makes everyone around you more flammable, and lights yourself on fire."
|
||||
charge_max = 60
|
||||
clothes_req = 0
|
||||
invocation = "FI'RAN DADISKO"
|
||||
invocation_type = "shout"
|
||||
max_targets = 0
|
||||
range = 6
|
||||
include_user = 1
|
||||
selection_type = "view"
|
||||
action_icon_state = "sacredflame"
|
||||
sound = 'sound/magic/Fireball.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/sacred_flame/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/L in targets)
|
||||
L.adjust_fire_stacks(20)
|
||||
if(isliving(user))
|
||||
var/mob/living/U = user
|
||||
U.IgniteMob()
|
||||
+34
-22
@@ -1024,8 +1024,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/ammonia,
|
||||
/obj/item/weapon/reagent_containers/glass/bottle/ammonia,
|
||||
/obj/item/weapon/hatchet,
|
||||
/obj/item/weapon/minihoe,
|
||||
/obj/item/device/analyzer/plant_analyzer,
|
||||
/obj/item/weapon/cultivator,
|
||||
/obj/item/device/plant_analyzer,
|
||||
/obj/item/clothing/gloves/botanic_leather,
|
||||
/obj/item/clothing/suit/apron) // Updated with new things
|
||||
cost = 15
|
||||
@@ -1044,35 +1044,39 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
|
||||
|
||||
/datum/supply_packs/organic/hydroponics/seeds
|
||||
name = "Seeds Crate"
|
||||
contains = list(/obj/item/seeds/chiliseed,
|
||||
/obj/item/seeds/berryseed,
|
||||
/obj/item/seeds/cornseed,
|
||||
/obj/item/seeds/eggplantseed,
|
||||
/obj/item/seeds/tomatoseed,
|
||||
/obj/item/seeds/soyaseed,
|
||||
/obj/item/seeds/wheatseed,
|
||||
/obj/item/seeds/carrotseed,
|
||||
/obj/item/seeds/sunflowerseed,
|
||||
/obj/item/seeds/chantermycelium,
|
||||
/obj/item/seeds/potatoseed,
|
||||
/obj/item/seeds/sugarcaneseed)
|
||||
contains = list(/obj/item/seeds/chili,
|
||||
/obj/item/seeds/berry,
|
||||
/obj/item/seeds/corn,
|
||||
/obj/item/seeds/eggplant,
|
||||
/obj/item/seeds/tomato,
|
||||
/obj/item/seeds/soya,
|
||||
/obj/item/seeds/wheat,
|
||||
/obj/item/seeds/wheat/rice,
|
||||
/obj/item/seeds/carrot,
|
||||
/obj/item/seeds/sunflower,
|
||||
/obj/item/seeds/chanter,
|
||||
/obj/item/seeds/potato,
|
||||
/obj/item/seeds/sugarcane)
|
||||
cost = 10
|
||||
containername = "seeds crate"
|
||||
|
||||
/datum/supply_packs/organic/hydroponics/exoticseeds
|
||||
name = "Exotic Seeds Crate"
|
||||
contains = list(/obj/item/seeds/nettleseed,
|
||||
contains = list(/obj/item/seeds/nettle,
|
||||
/obj/item/seeds/replicapod,
|
||||
/obj/item/seeds/replicapod,
|
||||
/obj/item/seeds/replicapod,
|
||||
/obj/item/seeds/plumpmycelium,
|
||||
/obj/item/seeds/libertymycelium,
|
||||
/obj/item/seeds/amanitamycelium,
|
||||
/obj/item/seeds/reishimycelium,
|
||||
/obj/item/seeds/bananaseed,
|
||||
/obj/item/seeds/nymph,
|
||||
/obj/item/seeds/nymph,
|
||||
/obj/item/seeds/nymph,
|
||||
/obj/item/seeds/plump,
|
||||
/obj/item/seeds/liberty,
|
||||
/obj/item/seeds/amanita,
|
||||
/obj/item/seeds/reishi,
|
||||
/obj/item/seeds/banana,
|
||||
/obj/item/seeds/eggplant/eggy,
|
||||
/obj/item/seeds/random,
|
||||
/obj/item/seeds/random,
|
||||
)
|
||||
/obj/item/seeds/random)
|
||||
cost = 15
|
||||
containername = "exotic seeds crate"
|
||||
|
||||
@@ -1628,6 +1632,14 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
|
||||
cost = 15
|
||||
containername = "snacks supply crate"
|
||||
|
||||
/datum/supply_packs/vending/chinese
|
||||
name = "Chinese Supply Crate"
|
||||
contains = list(/obj/item/weapon/vending_refill/chinese,
|
||||
/obj/item/weapon/vending_refill/chinese,
|
||||
/obj/item/weapon/vending_refill/chinese)
|
||||
cost = 15
|
||||
containername = "chinese supply crate"
|
||||
|
||||
/datum/supply_packs/vending/cola
|
||||
name = "Softdrinks Supply Crate"
|
||||
contains = list(/obj/item/weapon/vending_refill/cola,
|
||||
|
||||
@@ -305,7 +305,7 @@ var/list/uplink_items = list()
|
||||
name = "Ambrosia Cruciatus Seeds"
|
||||
desc = "Part of the notorious Ambrosia family, this species is nearly indistinguishable from Ambrosia Vulgaris- but its' branches contain a revolting toxin. Eight units are enough to drive victims insane."
|
||||
reference = "BRO"
|
||||
item = /obj/item/seeds/ambrosiavulgarisseed/cruciatus
|
||||
item = /obj/item/seeds/ambrosia/cruciatus
|
||||
cost = 2
|
||||
job = list("Botanist")
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
var/weather_duration_upper = 1500 //See above - this is the highest possible duration
|
||||
var/weather_sound
|
||||
var/weather_overlay
|
||||
var/weather_color = null
|
||||
|
||||
var/end_message = "<span class='danger'>The wind relents its assault.</span>" //Displayed once the wather is over
|
||||
var/end_duration = 300 //In deciseconds, how long the "wind-down" graphic will appear before vanishing entirely
|
||||
@@ -28,8 +29,9 @@
|
||||
|
||||
var/area_type = /area/space //Types of area to affect
|
||||
var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
|
||||
var/target_level = MAIN_STATION //The z-level to affect
|
||||
|
||||
var/target_z = MAIN_STATION //The z-level to affect
|
||||
var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
|
||||
|
||||
var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that.
|
||||
var/aesthetic = FALSE //If the weather has no purpose other than looks
|
||||
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
|
||||
@@ -50,15 +52,20 @@
|
||||
if(stage == STARTUP_STAGE)
|
||||
return
|
||||
stage = STARTUP_STAGE
|
||||
var/list/affectareas = list()
|
||||
for(var/V in get_areas(area_type))
|
||||
affectareas += V
|
||||
for(var/V in protected_areas)
|
||||
affectareas -= get_areas(V)
|
||||
for(var/V in affectareas)
|
||||
var/area/A = V
|
||||
if(is_on_level_name(A,target_level))
|
||||
if(is_on_level_name(A,target_z))
|
||||
impacted_areas |= A
|
||||
weather_duration = rand(weather_duration_lower, weather_duration_upper)
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_level))
|
||||
if(is_on_level_name(M,target_z))
|
||||
if(telegraph_message)
|
||||
to_chat(M, telegraph_message)
|
||||
if(telegraph_sound)
|
||||
@@ -72,7 +79,7 @@
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_level))
|
||||
if(is_on_level_name(M,target_z))
|
||||
if(weather_message)
|
||||
to_chat(M, weather_message)
|
||||
if(weather_sound)
|
||||
@@ -87,7 +94,7 @@
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_level))
|
||||
if(is_on_level_name(M,target_z))
|
||||
if(end_message)
|
||||
to_chat(M, end_message)
|
||||
if(end_sound)
|
||||
@@ -102,7 +109,7 @@
|
||||
update_areas()
|
||||
|
||||
/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob?
|
||||
if(!is_on_level_name(L,target_level))
|
||||
if(!is_on_level_name(L,target_z))
|
||||
return
|
||||
if(immunity_type in L.weather_immunities)
|
||||
return
|
||||
@@ -119,6 +126,7 @@
|
||||
N.layer = overlay_layer
|
||||
N.icon = 'icons/effects/weather_effects.dmi'
|
||||
N.invisibility = 0
|
||||
N.color = weather_color
|
||||
switch(stage)
|
||||
if(STARTUP_STAGE)
|
||||
N.icon_state = telegraph_overlay
|
||||
@@ -127,6 +135,7 @@
|
||||
if(WIND_DOWN_STAGE)
|
||||
N.icon_state = end_overlay
|
||||
if(END_STAGE)
|
||||
N.color = null
|
||||
N.icon_state = initial(N.icon_state)
|
||||
N.icon = 'icons/turf/areas.dmi'
|
||||
N.layer = 10 //Just default back to normal area stuff since I assume setting a var is faster than initial
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_level = MAIN_STATION
|
||||
target_z = MAIN_STATION
|
||||
|
||||
overlay_layer = 2 //Covers floors only
|
||||
immunity_type = "lava"
|
||||
@@ -50,7 +50,7 @@
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_level = MAIN_STATION
|
||||
target_z = MAIN_STATION
|
||||
|
||||
/datum/weather/advanced_darkness/update_areas()
|
||||
for(var/V in impacted_areas)
|
||||
@@ -87,7 +87,7 @@
|
||||
end_overlay = "light_ash"
|
||||
|
||||
area_type = /area/mine/dangerous
|
||||
target_level = MINING
|
||||
target_z = MINING
|
||||
|
||||
immunity_type = "ash"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user