Merge branch '13113'
This commit is contained in:
@@ -14,6 +14,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/list/objectives = list()
|
||||
var/antag_memory = ""//These will be removed with antag datum
|
||||
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
|
||||
var/antag_hud_type
|
||||
var/antag_hud_name
|
||||
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
|
||||
var/hijack_speed = 0
|
||||
|
||||
@@ -77,6 +79,17 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
hud.leave_hud(mob_override)
|
||||
set_antag_hud(mob_override, null)
|
||||
|
||||
// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
|
||||
/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE)
|
||||
var/mob/living/carbon/human/H = mob_override
|
||||
if(H && istype(H) && owner.assigned_role == "Clown")
|
||||
if(removing) // They're a clown becoming an antag, remove clumsy
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
if(!silent && message)
|
||||
to_chat(H, "<span class='boldnotice'>[message]</span>")
|
||||
else
|
||||
H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
|
||||
|
||||
//Assign default team and creates one for one of a kind team antagonists
|
||||
/datum/antagonist/proc/create_team(datum/team/team)
|
||||
return
|
||||
|
||||
229
code/modules/antagonists/eldritch_cult/eldritch_antag.dm
Normal file
229
code/modules/antagonists/eldritch_cult/eldritch_antag.dm
Normal file
@@ -0,0 +1,229 @@
|
||||
/datum/antagonist/heretic
|
||||
name = "Heretic"
|
||||
roundend_category = "Heretics"
|
||||
antagpanel_category = "Heretic"
|
||||
antag_moodlet = /datum/mood_event/heretics
|
||||
job_rank = ROLE_HERETIC
|
||||
antag_hud_type = ANTAG_HUD_HERETIC
|
||||
antag_hud_name = "heretic"
|
||||
var/give_equipment = TRUE
|
||||
var/list/researched_knowledge = list()
|
||||
var/total_sacrifices = 0
|
||||
var/ascended = FALSE
|
||||
|
||||
/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin)
|
||||
give_equipment = TRUE
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
|
||||
log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
|
||||
|
||||
/datum/antagonist/heretic/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
|
||||
to_chat(owner, "<span class='boldannounce'>You are the Heretic!</span><br>\
|
||||
<B>The old ones gave you these tasks to fulfill:</B>")
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='cult'>The book whispers, the forbidden knowledge walks once again!<br>\
|
||||
Your book allows you to research abilities, but be careful, you cannot undo what has been done.<br>\
|
||||
You gain charges by either collecting influences or sacrificing people tracked by the living heart<br> \
|
||||
You can find a basic guide at : https://tgstation13.org/wiki/Heresy_101 </span>")
|
||||
|
||||
/datum/antagonist/heretic/on_gain()
|
||||
var/mob/living/current = owner.current
|
||||
if(ishuman(current))
|
||||
forge_primary_objectives()
|
||||
gain_knowledge(/datum/eldritch_knowledge/spell/basic)
|
||||
gain_knowledge(/datum/eldritch_knowledge/living_heart)
|
||||
gain_knowledge(/datum/eldritch_knowledge/codex_cicatrix)
|
||||
gain_knowledge(/datum/eldritch_knowledge/eldritch_blade)
|
||||
current.log_message("has been converted to the cult of the forgotten ones!", LOG_ATTACK, color="#960000")
|
||||
GLOB.reality_smash_track.AddMind(owner)
|
||||
START_PROCESSING(SSprocessing,src)
|
||||
if(give_equipment)
|
||||
equip_cultist()
|
||||
owner.teach_crafting_recipe(/datum/crafting_recipe/heretic/codex)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/heretic/on_removal()
|
||||
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
EK.on_lose(owner.current)
|
||||
|
||||
if(!silent)
|
||||
to_chat(owner.current, "<span class='userdanger'>Your mind begins to flare as the otherwordly knowledge escapes your grasp!</span>")
|
||||
owner.current.log_message("has renounced the cult of the old ones!", LOG_ATTACK, color="#960000")
|
||||
GLOB.reality_smash_track.RemoveMind(owner)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/antagonist/heretic/proc/equip_cultist()
|
||||
var/mob/living/carbon/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
. += ecult_give_item(/obj/item/forbidden_book, H)
|
||||
. += ecult_give_item(/obj/item/living_heart, H)
|
||||
|
||||
/datum/antagonist/heretic/proc/ecult_give_item(obj/item/item_path, mob/living/carbon/human/H)
|
||||
var/list/slots = list(
|
||||
"backpack" = SLOT_IN_BACKPACK,
|
||||
"left pocket" = SLOT_L_STORE,
|
||||
"right pocket" = SLOT_R_STORE
|
||||
)
|
||||
|
||||
var/T = new item_path(H)
|
||||
var/item_name = initial(item_path.name)
|
||||
var/where = H.equip_in_one_of_slots(T, slots)
|
||||
if(!where)
|
||||
to_chat(H, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
|
||||
return FALSE
|
||||
else
|
||||
to_chat(H, "<span class='danger'>You have a [item_name] in your [where].</span>")
|
||||
if(where == "backpack")
|
||||
SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/heretic/process()
|
||||
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
EK.on_life(owner.current)
|
||||
|
||||
/datum/antagonist/heretic/proc/forge_primary_objectives()
|
||||
var/list/assasination = list()
|
||||
var/list/protection = list()
|
||||
for(var/i in 1 to 2)
|
||||
var/pck = pick("assasinate","protect")
|
||||
switch(pck)
|
||||
if("assasinate")
|
||||
var/datum/objective/assassinate/A = new
|
||||
A.owner = owner
|
||||
var/list/owners = A.get_owners()
|
||||
A.find_target(owners,protection)
|
||||
assasination += A.target
|
||||
objectives += A
|
||||
if("protect")
|
||||
var/datum/objective/protect/P = new
|
||||
P.owner = owner
|
||||
var/list/owners = P.get_owners()
|
||||
P.find_target(owners,assasination)
|
||||
protection += P.target
|
||||
objectives += P
|
||||
|
||||
|
||||
var/datum/objective/sacrifice_ecult/SE = new
|
||||
SE.owner = owner
|
||||
SE.update_explanation_text()
|
||||
objectives += SE
|
||||
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
escape_objective.owner = owner
|
||||
objectives += escape_objective
|
||||
|
||||
/datum/antagonist/heretic/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, current)
|
||||
handle_clown_mutation(current, mob_override ? null : "Knowledge described in the book allowed you to overcome your clownish nature, allowing you to use complex items effectively.")
|
||||
current.faction |= "heretics"
|
||||
|
||||
/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
var/mob/living/current = owner.current
|
||||
if(mob_override)
|
||||
current = mob_override
|
||||
remove_antag_hud(antag_hud_type, current)
|
||||
handle_clown_mutation(current, removing = FALSE)
|
||||
current.faction -= "heretics"
|
||||
|
||||
/datum/antagonist/heretic/get_admin_commands()
|
||||
. = ..()
|
||||
.["Equip"] = CALLBACK(src,.proc/equip_cultist)
|
||||
|
||||
/datum/antagonist/heretic/roundend_report()
|
||||
var/list/parts = list()
|
||||
|
||||
var/cultiewin = TRUE
|
||||
|
||||
parts += printplayer(owner)
|
||||
parts += "<b>Sacrifices Made:</b> [total_sacrifices]"
|
||||
|
||||
if(length(objectives))
|
||||
var/count = 1
|
||||
for(var/o in objectives)
|
||||
var/datum/objective/objective = o
|
||||
if(objective.check_completion())
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</b></span>"
|
||||
else
|
||||
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
cultiewin = FALSE
|
||||
count++
|
||||
if(ascended)
|
||||
parts += "<span class='greentext big'>HERETIC HAS ASCENDED!</span>"
|
||||
else
|
||||
if(cultiewin)
|
||||
parts += "<span class='greentext'>The heretic was successful!</span>"
|
||||
else
|
||||
parts += "<span class='redtext'>The heretic has failed.</span>"
|
||||
|
||||
parts += "<b>Knowledge Researched:</b> "
|
||||
|
||||
var/list/knowledge_message = list()
|
||||
var/list/knowledge = get_all_knowledge()
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/EK = knowledge[X]
|
||||
knowledge_message += "[EK.name]"
|
||||
parts += knowledge_message.Join(", ")
|
||||
|
||||
return parts.Join("<br>")
|
||||
////////////////
|
||||
// Knowledge //
|
||||
////////////////
|
||||
|
||||
/datum/antagonist/heretic/proc/gain_knowledge(datum/eldritch_knowledge/EK)
|
||||
if(get_knowledge(EK))
|
||||
return FALSE
|
||||
var/datum/eldritch_knowledge/initialized_knowledge = new EK
|
||||
researched_knowledge[initialized_knowledge.type] = initialized_knowledge
|
||||
initialized_knowledge.on_gain(owner.current)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/heretic/proc/get_researchable_knowledge()
|
||||
var/list/researchable_knowledge = list()
|
||||
var/list/banned_knowledge = list()
|
||||
for(var/X in researched_knowledge)
|
||||
var/datum/eldritch_knowledge/EK = researched_knowledge[X]
|
||||
researchable_knowledge |= EK.next_knowledge
|
||||
banned_knowledge |= EK.banned_knowledge
|
||||
banned_knowledge |= EK.type
|
||||
researchable_knowledge -= banned_knowledge
|
||||
return researchable_knowledge
|
||||
|
||||
/datum/antagonist/heretic/proc/get_knowledge(wanted)
|
||||
return researched_knowledge[wanted]
|
||||
|
||||
/datum/antagonist/heretic/proc/get_all_knowledge()
|
||||
return researched_knowledge
|
||||
|
||||
////////////////
|
||||
// Objectives //
|
||||
////////////////
|
||||
|
||||
/datum/objective/sacrifice_ecult
|
||||
name = "sacrifice"
|
||||
|
||||
/datum/objective/sacrifice_ecult/update_explanation_text()
|
||||
. = ..()
|
||||
target_amount = rand(2,4)
|
||||
explanation_text = "Sacrifice at least [target_amount] people."
|
||||
|
||||
/datum/objective/sacrifice_ecult/check_completion()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
var/datum/antagonist/heretic/cultie = owner.has_antag_datum(/datum/antagonist/heretic)
|
||||
if(!cultie)
|
||||
return FALSE
|
||||
return cultie.total_sacrifices >= target_amount
|
||||
145
code/modules/antagonists/eldritch_cult/eldritch_book.dm
Normal file
145
code/modules/antagonists/eldritch_cult/eldritch_book.dm
Normal file
@@ -0,0 +1,145 @@
|
||||
/obj/item/forbidden_book
|
||||
name = "Codex Cicatrix"
|
||||
desc = "Book describing the secrets of the veil."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "book"
|
||||
item_state = "book"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///Last person that touched this
|
||||
var/mob/living/last_user
|
||||
///how many charges do we have?
|
||||
var/charge = 0
|
||||
///Where we cannot create the rune?
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava))
|
||||
|
||||
/obj/item/forbidden_book/Destroy()
|
||||
last_user = null
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/item/forbidden_book/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
. += "The Tome holds [charge] charges."
|
||||
. += "Use it on the floor to create a transmutation rune, used to perform rituals."
|
||||
. += "Hit an influence in the black part with it to gain a charge."
|
||||
. += "Hit a transmutation rune to destroy it."
|
||||
|
||||
/obj/item/forbidden_book/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!proximity_flag || !IS_HERETIC(user))
|
||||
return
|
||||
if(istype(target,/obj/effect/eldritch))
|
||||
remove_rune(target,user)
|
||||
if(istype(target,/obj/effect/reality_smash))
|
||||
get_power_from_influence(target,user)
|
||||
if(istype(target,/turf/open))
|
||||
draw_rune(target,user)
|
||||
|
||||
///Gives you a charge and destroys a corresponding influence
|
||||
/obj/item/forbidden_book/proc/get_power_from_influence(atom/target, mob/user)
|
||||
var/obj/effect/reality_smash/RS = target
|
||||
to_chat(target, "<span class='danger'>You start drawing power from influence...</span>")
|
||||
if(do_after(user,10 SECONDS,TRUE,RS))
|
||||
qdel(RS)
|
||||
charge += 1
|
||||
|
||||
///Draws a rune on a selected turf
|
||||
/obj/item/forbidden_book/proc/draw_rune(atom/target,mob/user)
|
||||
|
||||
for(var/turf/T in range(1,target))
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
to_chat(target, "<span class='warning'>The terrain doesn't support runes!</span>")
|
||||
return
|
||||
var/A = get_turf(target)
|
||||
to_chat(user, "<span class='danger'>You start drawing a rune...</span>")
|
||||
|
||||
if(do_after(user,30 SECONDS,FALSE, user))
|
||||
|
||||
new /obj/effect/eldritch/big(A)
|
||||
|
||||
///Removes runes from the selected turf
|
||||
/obj/item/forbidden_book/proc/remove_rune(atom/target,mob/user)
|
||||
|
||||
to_chat(user, "<span class='danger'>You start removing a rune...</span>")
|
||||
if(do_after(user,2 SECONDS,FALSE, user))
|
||||
qdel(target)
|
||||
|
||||
/obj/item/forbidden_book/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
if(!IS_HERETIC(user))
|
||||
return FALSE
|
||||
last_user = user
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
icon_state = "book_open"
|
||||
flick("book_opening", src)
|
||||
ui = new(user, src, "ForbiddenLore", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/forbidden_book/ui_data(mob/user)
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/list/to_know = list()
|
||||
for(var/Y in cultie.get_researchable_knowledge())
|
||||
to_know += new Y
|
||||
var/list/known = cultie.get_all_knowledge()
|
||||
var/list/data = list()
|
||||
var/list/lore = list()
|
||||
|
||||
data["charges"] = charge
|
||||
|
||||
for(var/X in to_know)
|
||||
lore = list()
|
||||
var/datum/eldritch_knowledge/EK = X
|
||||
lore["type"] = EK.type
|
||||
lore["name"] = EK.name
|
||||
lore["cost"] = EK.cost
|
||||
lore["disabled"] = EK.cost <= charge ? FALSE : TRUE
|
||||
lore["path"] = EK.route
|
||||
lore["state"] = "Research"
|
||||
lore["flavour"] = EK.gain_text
|
||||
lore["desc"] = EK.desc
|
||||
data["to_know"] += list(lore)
|
||||
|
||||
for(var/X in known)
|
||||
lore = list()
|
||||
var/datum/eldritch_knowledge/EK = known[X]
|
||||
lore["name"] = EK.name
|
||||
lore["cost"] = EK.cost
|
||||
lore["disabled"] = TRUE
|
||||
lore["path"] = EK.route
|
||||
lore["state"] = "Researched"
|
||||
lore["flavour"] = EK.gain_text
|
||||
lore["desc"] = EK.desc
|
||||
data["to_know"] += list(lore)
|
||||
|
||||
if(!length(data["to_know"]))
|
||||
data["to_know"] = null
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/forbidden_book/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("research")
|
||||
var/datum/antagonist/heretic/cultie = last_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/ekname = params["name"]
|
||||
for(var/X in cultie.get_researchable_knowledge())
|
||||
var/datum/eldritch_knowledge/EK = X
|
||||
if(initial(EK.name) != ekname)
|
||||
continue
|
||||
if(cultie.gain_knowledge(EK))
|
||||
charge -= text2num(params["cost"])
|
||||
return TRUE
|
||||
|
||||
update_icon() // Not applicable to all objects.
|
||||
|
||||
/obj/item/forbidden_book/ui_close(mob/user)
|
||||
flick("book_closing",src)
|
||||
icon_state = initial(icon_state)
|
||||
return ..()
|
||||
|
||||
/obj/item/forbidden_book/debug
|
||||
charge = 100
|
||||
289
code/modules/antagonists/eldritch_cult/eldritch_effects.dm
Normal file
289
code/modules/antagonists/eldritch_cult/eldritch_effects.dm
Normal file
@@ -0,0 +1,289 @@
|
||||
/obj/effect/eldritch
|
||||
name = "Generic rune"
|
||||
desc = "Weird combination of shapes and symbols etched into the floor itself. The indentation is filled with thick black tar-like fluid."
|
||||
anchored = TRUE
|
||||
icon_state = ""
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
layer = SIGIL_LAYER
|
||||
///Used mainly for summoning ritual to prevent spamming the rune to create millions of monsters.
|
||||
var/is_in_use = FALSE
|
||||
|
||||
/obj/effect/eldritch/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
try_activate(user)
|
||||
|
||||
/obj/effect/eldritch/proc/try_activate(mob/living/user)
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
if(!is_in_use)
|
||||
INVOKE_ASYNC(src, .proc/activate , user)
|
||||
|
||||
/obj/effect/eldritch/attacked_by(obj/item/I, mob/living/user)
|
||||
. = ..()
|
||||
if(istype(I,/obj/item/nullrod))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/eldritch/proc/activate(mob/living/user)
|
||||
is_in_use = TRUE
|
||||
// Have fun trying to read this proc.
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
var/list/atoms_in_range = list()
|
||||
|
||||
for(var/A in range(1, src))
|
||||
var/atom/atom_in_range = A
|
||||
if(istype(atom_in_range,/area))
|
||||
continue
|
||||
if(istype(atom_in_range,/turf)) // we dont want turfs
|
||||
continue
|
||||
if(istype(atom_in_range,/mob/living))
|
||||
var/mob/living/living_in_range = atom_in_range
|
||||
if(living_in_range.stat != DEAD || living_in_range == user) // we only accept corpses, no living beings allowed.
|
||||
continue
|
||||
atoms_in_range += atom_in_range
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/current_eldritch_knowledge = knowledge[X]
|
||||
|
||||
//has to be done so that we can freely edit the local_required_atoms without fucking up the eldritch knowledge
|
||||
var/list/local_required_atoms = list()
|
||||
|
||||
if(!current_eldritch_knowledge.required_atoms || current_eldritch_knowledge.required_atoms.len == 0)
|
||||
continue
|
||||
|
||||
local_required_atoms += current_eldritch_knowledge.required_atoms
|
||||
|
||||
var/list/selected_atoms = list()
|
||||
|
||||
if(!current_eldritch_knowledge.recipe_snowflake_check(atoms_in_range,drop_location(),selected_atoms))
|
||||
continue
|
||||
|
||||
for(var/LR in local_required_atoms)
|
||||
var/list/local_required_atom_list = LR
|
||||
|
||||
for(var/LAIR in atoms_in_range)
|
||||
var/atom/local_atom_in_range = LAIR
|
||||
if(is_type_in_list(local_atom_in_range,local_required_atom_list))
|
||||
selected_atoms |= local_atom_in_range
|
||||
local_required_atoms -= list(local_required_atom_list)
|
||||
|
||||
if(length(local_required_atoms) > 0)
|
||||
continue
|
||||
|
||||
flick("[icon_state]_active",src)
|
||||
playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE)
|
||||
//we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently.
|
||||
var/list/atoms_to_disappear = selected_atoms.Copy()
|
||||
for(var/to_disappear in atoms_to_disappear)
|
||||
var/atom/atom_to_disappear = to_disappear
|
||||
//temporary so we dont have to deal with the bs of someone picking those up when they may be deleted
|
||||
atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT
|
||||
if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc))
|
||||
current_eldritch_knowledge.cleanup_atoms(selected_atoms)
|
||||
is_in_use = FALSE
|
||||
|
||||
for(var/to_appear in atoms_to_disappear)
|
||||
var/atom/atom_to_appear = to_appear
|
||||
//we need to reappear the item just in case the ritual didnt consume everything... or something.
|
||||
atom_to_appear.invisibility = initial(atom_to_appear.invisibility)
|
||||
|
||||
return
|
||||
is_in_use = FALSE
|
||||
to_chat(user,"<span class='warning'>Your ritual failed! You used either wrong components or are missing something important!</span>")
|
||||
|
||||
/obj/effect/eldritch/big
|
||||
name = "transmutation circle"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "eldritch_rune1"
|
||||
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
|
||||
pixel_y = -32
|
||||
|
||||
/**
|
||||
* #Reality smash tracker
|
||||
*
|
||||
* Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created.
|
||||
*
|
||||
* Tracks relevant data, generates relevant data, useful tool
|
||||
*/
|
||||
/datum/reality_smash_tracker
|
||||
///list of tracked reality smashes
|
||||
var/list/smashes = list()
|
||||
///List of mobs with ability to see the smashes
|
||||
var/list/targets = list()
|
||||
|
||||
/datum/reality_smash_tracker/Destroy(force, ...)
|
||||
if(GLOB.reality_smash_track == src)
|
||||
stack_trace("/datum/reality_smash_tracker was deleted. Heretics may no longer access any influences. Fix it or call coder support")
|
||||
QDEL_LIST(smashes)
|
||||
targets.Cut()
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Automatically fixes the target and smash network
|
||||
*
|
||||
* Fixes any bugs that are caused by late Generate() or exchanging clients
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/ReworkNetwork()
|
||||
listclearnulls(smashes)
|
||||
for(var/mind in targets)
|
||||
if(isnull(mind))
|
||||
stack_trace("A null somehow landed in a list of minds")
|
||||
continue
|
||||
for(var/X in smashes)
|
||||
var/obj/effect/reality_smash/reality_smash = X
|
||||
reality_smash.AddMind(mind)
|
||||
|
||||
/**
|
||||
* Generates a set amount of reality smashes based on the N value
|
||||
*
|
||||
* Automatically creates more reality smashes
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/_Generate()
|
||||
var/targ_len = length(targets)
|
||||
var/smash_len = length(smashes)
|
||||
var/number = targ_len * 6 - smash_len
|
||||
|
||||
for(var/i in 0 to number)
|
||||
|
||||
var/turf/chosen_location = get_safe_random_station_turf()
|
||||
//we also dont want them close to each other, at least 1 tile of seperation
|
||||
var/obj/effect/reality_smash/what_if_i_have_one = locate() in range(1, chosen_location)
|
||||
var/obj/effect/broken_illusion/what_if_i_had_one_but_got_used = locate() in range(1, chosen_location)
|
||||
if(what_if_i_have_one || what_if_i_had_one_but_got_used) //we dont want to spawn
|
||||
continue
|
||||
var/obj/effect/reality_smash/RS = new/obj/effect/reality_smash(chosen_location)
|
||||
smashes += RS
|
||||
ReworkNetwork()
|
||||
|
||||
|
||||
/**
|
||||
* Adds a mind to the list of people that can see the reality smashes
|
||||
*
|
||||
* Use this whenever you want to add someone to the list
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/AddMind(var/datum/mind/M)
|
||||
RegisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork)
|
||||
targets |= M
|
||||
_Generate()
|
||||
for(var/X in smashes)
|
||||
var/obj/effect/reality_smash/reality_smash = X
|
||||
reality_smash.AddMind(M)
|
||||
|
||||
|
||||
/**
|
||||
* Removes a mind from the list of people that can see the reality smashes
|
||||
*
|
||||
* Use this whenever you want to remove someone from the list
|
||||
*/
|
||||
/datum/reality_smash_tracker/proc/RemoveMind(var/datum/mind/M)
|
||||
UnregisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN)
|
||||
targets -= M
|
||||
for(var/obj/effect/reality_smash/RS in smashes)
|
||||
RS.RemoveMind(M)
|
||||
|
||||
/obj/effect/broken_illusion
|
||||
name = "pierced reality"
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "pierced_illusion"
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/effect/broken_illusion/attack_hand(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
return ..()
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(IS_HERETIC(human_user))
|
||||
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
|
||||
else
|
||||
var/obj/item/bodypart/arm = human_user.get_active_hand()
|
||||
if(prob(25))
|
||||
to_chat(human_user,"<span class='userdanger'>An otherwordly presence tears your arm apart into atoms as you try to touch the hole in the very fabric of reality!</span>")
|
||||
arm.dismember()
|
||||
qdel(arm)
|
||||
else
|
||||
to_chat(human_user,"<span class='danger'>You pull your hand away from the hole as eldritch energy flails out, trying to latch onto existence itself!</span>")
|
||||
|
||||
/obj/effect/broken_illusion/attack_tk(mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
if(IS_HERETIC(human_user))
|
||||
to_chat(human_user,"<span class='boldwarning'>You know better than to tempt forces out of your control.</span>")
|
||||
else
|
||||
//a very elaborate way to suicide
|
||||
to_chat(human_user,"<span class='userdanger'>Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!</span>")
|
||||
human_user.ghostize()
|
||||
var/obj/item/bodypart/head/head = locate() in human_user.bodyparts
|
||||
if(head)
|
||||
head.dismember()
|
||||
qdel(head)
|
||||
else
|
||||
human_user.gib()
|
||||
|
||||
var/datum/effect_system/reagents_explosion/explosion = new()
|
||||
explosion.set_up(1, get_turf(human_user), 1, 0)
|
||||
explosion.start()
|
||||
|
||||
/obj/effect/broken_illusion/examine(mob/user)
|
||||
if(!IS_HERETIC(user) && ishuman(user))
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
to_chat(human_user,"<span class='userdanger'>Your brain hurts when you look at this!</span>")
|
||||
human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,30)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/reality_smash
|
||||
name = "/improper reality smash"
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
anchored = TRUE
|
||||
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
///We cannot use icon_state since this is invisible, functions the same way but with custom behaviour.
|
||||
var/image_state = "reality_smash"
|
||||
///Who can see us?
|
||||
var/list/minds = list()
|
||||
///Tracked image
|
||||
var/image/img
|
||||
|
||||
/obj/effect/reality_smash/Initialize()
|
||||
. = ..()
|
||||
img = image(icon, src, image_state, OBJ_LAYER)
|
||||
generate_name()
|
||||
|
||||
/obj/effect/reality_smash/Destroy()
|
||||
on_destroy()
|
||||
return ..()
|
||||
|
||||
///Custom effect that happens on destruction
|
||||
/obj/effect/reality_smash/proc/on_destroy()
|
||||
for(var/cm in minds)
|
||||
var/datum/mind/cultie = cm
|
||||
if(cultie.current?.client)
|
||||
cultie.current.client.images -= img
|
||||
//clear the list
|
||||
minds -= cultie
|
||||
GLOB.reality_smash_track.smashes -= src
|
||||
img = null
|
||||
new /obj/effect/broken_illusion(drop_location())
|
||||
|
||||
///Makes the mind able to see this effect
|
||||
/obj/effect/reality_smash/proc/AddMind(var/datum/mind/cultie)
|
||||
minds |= cultie
|
||||
if(cultie.current.client)
|
||||
cultie.current.client.images |= img
|
||||
|
||||
|
||||
|
||||
///Makes the mind not able to see this effect
|
||||
/obj/effect/reality_smash/proc/RemoveMind(var/datum/mind/cultie)
|
||||
minds -= cultie
|
||||
if(cultie.current.client)
|
||||
cultie.current.client.images -= img
|
||||
|
||||
|
||||
|
||||
///Generates random name
|
||||
/obj/effect/reality_smash/proc/generate_name()
|
||||
var/static/list/prefix = list("Omniscient","Thundering","Enlightening","Intrusive","Rejectful","Atomized","Subtle","Rising","Lowering","Fleeting","Towering","Blissful","Arrogant","Threatening","Peaceful","Aggressive")
|
||||
var/static/list/postfix = list("Flaw","Presence","Crack","Heat","Cold","Memory","Reminder","Breeze","Grasp","Sight","Whisper","Flow","Touch","Veil","Thought","Imperfection","Blemish","Blush")
|
||||
|
||||
name = pick(prefix) + " " + pick(postfix)
|
||||
142
code/modules/antagonists/eldritch_cult/eldritch_items.dm
Normal file
142
code/modules/antagonists/eldritch_cult/eldritch_items.dm
Normal file
@@ -0,0 +1,142 @@
|
||||
/obj/item/living_heart
|
||||
name = "living heart"
|
||||
desc = "Link to the worlds beyond."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "living_heart"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///Target
|
||||
var/mob/living/carbon/human/target
|
||||
|
||||
/obj/item/living_heart/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(!IS_HERETIC(user))
|
||||
return
|
||||
if(!target)
|
||||
to_chat(user,"<span class='warning'>No target could be found. Put the living heart on the rune and use the rune to recieve a target.</span>")
|
||||
return
|
||||
var/dist = get_dist(user.loc,target.loc)
|
||||
var/dir = get_dir(user.loc,target.loc)
|
||||
|
||||
switch(dist)
|
||||
if(0 to 15)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is near you. They are to the [dir2text(dir)] of you!</span>")
|
||||
if(16 to 31)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is somewhere in your vicinty. They are to the [dir2text(dir)] of you!</span>")
|
||||
if(32 to 127)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is far away from you. They are to the [dir2text(dir)] of you!</span>")
|
||||
else
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is beyond our reach.</span>")
|
||||
|
||||
if(target.stat == DEAD)
|
||||
to_chat(user,"<span class='warning'>[target.real_name] is dead. Bring them onto a transmutation rune!</span>")
|
||||
|
||||
/obj/item/melee/sickly_blade
|
||||
name = "eldritch blade"
|
||||
desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eldritch_blade"
|
||||
item_state = "eldritch_blade"
|
||||
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
|
||||
inhand_x_dimension = 64
|
||||
inhand_y_dimension = 64
|
||||
flags_1 = CONDUCT_1
|
||||
sharpness = SHARP_EDGED
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 17
|
||||
throwforce = 10
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended")
|
||||
|
||||
/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user)
|
||||
if(!IS_HERETIC(user))
|
||||
to_chat(user,"<span class='danger'>You feel a pulse of some alien intellect lash out at your mind!</span>")
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.AdjustParalyzed(5 SECONDS)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
if(!cultie || !proximity_flag)
|
||||
return
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/eldritch_knowledge_datum = knowledge[X]
|
||||
eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
|
||||
/obj/item/melee/sickly_blade/rust
|
||||
name = "rusted blade"
|
||||
desc = "This crescent blade is decrepit, wasting to dust. Yet still it bites, catching flesh with jagged, rotten teeth."
|
||||
icon_state = "rust_blade"
|
||||
item_state = "rust_blade"
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 75, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
|
||||
throwforce = 17
|
||||
|
||||
/obj/item/melee/sickly_blade/ash
|
||||
name = "ashen blade"
|
||||
desc = "Molten and unwrought, a hunk of metal warped to cinders and slag. Unmade, it aspires to be more than it is, and shears soot-filled wounds with a blunt edge."
|
||||
icon_state = "ash_blade"
|
||||
item_state = "ash_blade"
|
||||
force = 20
|
||||
|
||||
/obj/item/melee/sickly_blade/flesh
|
||||
name = "flesh blade"
|
||||
desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the excruciations it has endured from dead origins."
|
||||
icon_state = "flesh_blade"
|
||||
item_state = "flesh_blade"
|
||||
wound_bonus = 5
|
||||
bare_wound_bonus = 15
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet
|
||||
name = "warm eldritch medallion"
|
||||
desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulse of a thousand others."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eye_medalion"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
///What trait do we want to add upon equipiing
|
||||
var/trait = TRAIT_THERMAL_VISION
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(ishuman(user) && user.mind && slot == SLOT_NECK && IS_HERETIC(user))
|
||||
ADD_TRAIT(user, trait, CLOTHING_TRAIT)
|
||||
user.update_sight()
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/dropped(mob/user)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(user, trait, CLOTHING_TRAIT)
|
||||
user.update_sight()
|
||||
|
||||
/obj/item/clothing/neck/eldritch_amulet/piercing
|
||||
name = "piercing eldritch medallion"
|
||||
desc = "A strange medallion. Peering through the crystalline surface, the light refracts into new and terrifying spectrums of color. You see yourself, reflected off cascading mirrors, warped into improbable shapes."
|
||||
trait = TRAIT_XRAY_VISION
|
||||
|
||||
/obj/item/clothing/head/hooded/cult_hoodie/eldritch
|
||||
name = "ominous hood"
|
||||
icon_state = "eldritch"
|
||||
desc = "A torn, dust-caked hood. Strange eyes line the inside."
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
flash_protect = 2
|
||||
|
||||
/obj/item/clothing/suit/hooded/cultrobes/eldritch
|
||||
name = "ominous armor"
|
||||
desc = "A ragged, dusty set of robes. Strange eyes line the inside."
|
||||
icon_state = "eldritch_armor"
|
||||
item_state = "eldritch_armor"
|
||||
flags_inv = HIDESHOES|HIDEJUMPSUIT
|
||||
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS
|
||||
allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book)
|
||||
hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch
|
||||
// slightly better than normal cult robes
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/eldritch
|
||||
name = "flask of eldritch essence"
|
||||
desc = "Toxic to the close minded. Healing to those with knowledge of the beyond."
|
||||
icon = 'icons/obj/eldritch.dmi'
|
||||
icon_state = "eldrich_flask"
|
||||
list_reagents = list(/datum/reagent/eldritch = 50)
|
||||
303
code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
Normal file
303
code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm
Normal file
@@ -0,0 +1,303 @@
|
||||
|
||||
/**
|
||||
* #Eldritch Knwoledge
|
||||
*
|
||||
* Datum that makes eldritch cultist interesting.
|
||||
*
|
||||
* Eldritch knowledge aren't instantiated anywhere roundstart, and are initalized and destroyed as the round goes on.
|
||||
*/
|
||||
/datum/eldritch_knowledge
|
||||
///Name of the knowledge
|
||||
var/name = "Basic knowledge"
|
||||
///Description of the knowledge
|
||||
var/desc = "Basic knowledge of forbidden arts."
|
||||
///What shows up
|
||||
var/gain_text = ""
|
||||
///Cost of knowledge in souls
|
||||
var/cost = 0
|
||||
///Next knowledge in the research tree
|
||||
var/list/next_knowledge = list()
|
||||
///What knowledge is incompatible with this. This will simply make it impossible to research knowledges that are in banned_knowledge once this gets researched.
|
||||
var/list/banned_knowledge = list()
|
||||
///Used with rituals, how many items this needs
|
||||
var/list/required_atoms = list()
|
||||
///What do we get out of this
|
||||
var/list/result_atoms = list()
|
||||
///What path is this on defaults to "Side"
|
||||
var/route = PATH_SIDE
|
||||
|
||||
/datum/eldritch_knowledge/New()
|
||||
. = ..()
|
||||
var/list/temp_list
|
||||
for(var/X in required_atoms)
|
||||
var/atom/A = X
|
||||
temp_list += list(typesof(A))
|
||||
required_atoms = temp_list
|
||||
|
||||
/**
|
||||
* What happens when this is assigned to an antag datum
|
||||
*
|
||||
* This proc is called whenever a new eldritch knowledge is added to an antag datum
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_gain(mob/user)
|
||||
to_chat(user, "<span class='warning'>[gain_text]</span>")
|
||||
return
|
||||
/**
|
||||
* What happens when you loose this
|
||||
*
|
||||
* This proc is called whenever antagonist looses his antag datum, put cleanup code in here
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_lose(mob/user)
|
||||
return
|
||||
/**
|
||||
* What happens every tick
|
||||
*
|
||||
* This proc is called on SSprocess in eldritch cultist antag datum. SSprocess happens roughly every second
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_life(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* Special check for recipes
|
||||
*
|
||||
* If you are adding a more complex summoning or something that requires a special check that parses through all the atoms in an area override this.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/recipe_snowflake_check(list/atoms,loc)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* What happens once the recipe is succesfully finished
|
||||
*
|
||||
* By default this proc creates atoms from result_atoms list. Override this is you want something else to happen.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
if(result_atoms.len == 0)
|
||||
return FALSE
|
||||
|
||||
for(var/A in result_atoms)
|
||||
new A(loc)
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Used atom cleanup
|
||||
*
|
||||
* Overide this proc if you dont want ALL ATOMS to be destroyed. useful in many situations.
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/cleanup_atoms(list/atoms)
|
||||
for(var/X in atoms)
|
||||
var/atom/A = X
|
||||
if(!isliving(A))
|
||||
atoms -= A
|
||||
qdel(A)
|
||||
return
|
||||
|
||||
/**
|
||||
* Mansus grasp act
|
||||
*
|
||||
* Gives addtional effects to mansus grasp spell
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
return FALSE
|
||||
|
||||
|
||||
/**
|
||||
* Sickly blade act
|
||||
*
|
||||
* Gives addtional effects to sickly blade weapon
|
||||
*/
|
||||
/datum/eldritch_knowledge/proc/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
return
|
||||
|
||||
//////////////
|
||||
///Subtypes///
|
||||
//////////////
|
||||
|
||||
/datum/eldritch_knowledge/spell
|
||||
var/obj/effect/proc_holder/spell/spell_to_add
|
||||
|
||||
/datum/eldritch_knowledge/spell/on_gain(mob/user)
|
||||
var/obj/effect/proc_holder/S = new spell_to_add
|
||||
user.mind.AddSpell(S)
|
||||
return ..()
|
||||
|
||||
/datum/eldritch_knowledge/spell/on_lose(mob/user)
|
||||
user.mind.RemoveSpell(spell_to_add)
|
||||
return ..()
|
||||
|
||||
/datum/eldritch_knowledge/curse
|
||||
var/timer = 5 MINUTES
|
||||
var/list/fingerprints = list()
|
||||
|
||||
/datum/eldritch_knowledge/curse/recipe_snowflake_check(list/atoms, loc)
|
||||
fingerprints = list()
|
||||
for(var/X in atoms)
|
||||
var/atom/A = X
|
||||
fingerprints |= A.fingerprints
|
||||
listclearnulls(fingerprints)
|
||||
if(fingerprints.len == 0)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/curse/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
|
||||
var/list/compiled_list = list()
|
||||
|
||||
for(var/H in GLOB.human_list)
|
||||
var/mob/living/carbon/human/human_to_check = H
|
||||
if(fingerprints[md5(human_to_check.dna.uni_identity)])
|
||||
compiled_list |= human_to_check.real_name
|
||||
compiled_list[human_to_check.real_name] = human_to_check
|
||||
|
||||
if(compiled_list.len == 0)
|
||||
to_chat(user, "<span class='warning'>The items don't posses required fingerprints.</span>")
|
||||
return FALSE
|
||||
|
||||
var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc)
|
||||
if(!chosen_mob)
|
||||
return FALSE
|
||||
curse(compiled_list[chosen_mob])
|
||||
addtimer(CALLBACK(src, .proc/uncurse, compiled_list[chosen_mob]),timer)
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/curse/proc/curse(mob/living/chosen_mob)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/curse/proc/uncurse(mob/living/chosen_mob)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/summon
|
||||
//Mob to summon
|
||||
var/mob/living/mob_to_summon
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/summon/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
//we need to spawn the mob first so that we can use it in pollCandidatesForMob, we will move it from nullspace down the code
|
||||
var/mob/living/summoned = new mob_to_summon(loc)
|
||||
message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [summoned.name]", ROLE_HERETIC, null, FALSE, 100, summoned)
|
||||
if(!LAZYLEN(candidates))
|
||||
to_chat(user,"<span class='warning'>No ghost could be found...</span>")
|
||||
qdel(summoned)
|
||||
return FALSE
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
log_game("[key_name_admin(C)] has taken control of ([key_name_admin(summoned)]), their master is [user.real_name]")
|
||||
summoned.ghostize(FALSE)
|
||||
summoned.key = C.key
|
||||
summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
return TRUE
|
||||
|
||||
//Ascension knowledge
|
||||
/datum/eldritch_knowledge/final
|
||||
var/finished = FALSE
|
||||
|
||||
/datum/eldritch_knowledge/final/recipe_snowflake_check(list/atoms, loc,selected_atoms)
|
||||
if(finished)
|
||||
return FALSE
|
||||
var/counter = 0
|
||||
for(var/mob/living/carbon/human/H in atoms)
|
||||
selected_atoms |= H
|
||||
counter++
|
||||
if(counter == 3)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/eldritch_knowledge/final/on_finished_recipe( mob/living/user, list/atoms, loc)
|
||||
finished = TRUE
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/final/cleanup_atoms(list/atoms)
|
||||
. = ..()
|
||||
for(var/mob/living/carbon/human/H in atoms)
|
||||
atoms -= H
|
||||
H.gib()
|
||||
|
||||
|
||||
///////////////
|
||||
///Base lore///
|
||||
///////////////
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic
|
||||
name = "Break of Dawn"
|
||||
desc = "Starts your journey in the mansus. Allows you to select a target using a living heart on a transmutation rune."
|
||||
gain_text = "Gates of Mansus open up to your mind."
|
||||
next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh)
|
||||
cost = 0
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
|
||||
required_atoms = list(/obj/item/living_heart)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/recipe_snowflake_check(list/atoms, loc)
|
||||
. = ..()
|
||||
for(var/obj/item/living_heart/LH in atoms)
|
||||
if(!LH.target)
|
||||
return TRUE
|
||||
if(LH.target in atoms)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
. = TRUE
|
||||
var/mob/living/carbon/carbon_user = user
|
||||
for(var/obj/item/living_heart/LH in atoms)
|
||||
|
||||
if(LH.target && LH.target.stat == DEAD)
|
||||
to_chat(carbon_user,"<span class='danger'>Your patrons accepts your offer...</span>")
|
||||
var/mob/living/carbon/human/H = LH.target
|
||||
H.become_husk()
|
||||
LH.target = null
|
||||
var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
|
||||
EC.total_sacrifices++
|
||||
for(var/X in carbon_user.get_all_gear())
|
||||
if(!istype(X,/obj/item/forbidden_book))
|
||||
continue
|
||||
var/obj/item/forbidden_book/FB = X
|
||||
FB.charge++
|
||||
FB.charge++
|
||||
break
|
||||
|
||||
if(!LH.target)
|
||||
var/datum/objective/A = new
|
||||
A.owner = user.mind
|
||||
var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code
|
||||
LH.target = targeted.current
|
||||
qdel(A)
|
||||
if(LH.target)
|
||||
to_chat(user,"<span class='warning'>Your new target has been selected, go and sacrifice [LH.target.real_name]!</span>")
|
||||
|
||||
else
|
||||
to_chat(user,"<span class='warning'>target could not be found for living heart.</span>")
|
||||
|
||||
/datum/eldritch_knowledge/spell/basic/cleanup_atoms(list/atoms)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/living_heart
|
||||
name = "Living Heart"
|
||||
desc = "Allows you to create additional living hearts, using a heart, a pool of blood and a poppy. Living hearts when used on a transmutation rune will grant you a person to hunt and sacrifice on the rune. Every sacrifice gives you an additional charge in the book."
|
||||
gain_text = "Disconnected, yet it still beats."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/organ/heart,/obj/effect/decal/cleanable/blood,/obj/item/reagent_containers/food/snacks/grown/poppy)
|
||||
result_atoms = list(/obj/item/living_heart)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/codex_cicatrix
|
||||
name = "Codex Cicatrix"
|
||||
desc = "Allows you to create a spare Codex Cicatrix if you have lost one, using a bible, human skin, a pen and a pair of eyes."
|
||||
gain_text = "Their hands are at your throat, yet you see them not."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/stack/sheet/animalhide/human,/obj/item/storage/book/bible,/obj/item/pen)
|
||||
result_atoms = list(/obj/item/forbidden_book)
|
||||
route = "Start"
|
||||
|
||||
/datum/eldritch_knowledge/eldritch_blade
|
||||
name = "Eldritch Blade"
|
||||
desc = "Allows you to create a sickly, eldritch blade by transmuting a glass shard and a metal rod atop a transmutation rune."
|
||||
gain_text = "The first step starts with sacrifice."
|
||||
cost = 0
|
||||
required_atoms = list(/obj/item/shard,/obj/item/stack/rods)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade)
|
||||
route = "Start"
|
||||
668
code/modules/antagonists/eldritch_cult/eldritch_magic.dm
Normal file
668
code/modules/antagonists/eldritch_cult/eldritch_magic.dm
Normal file
@@ -0,0 +1,668 @@
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
|
||||
name = "Ashen Passage"
|
||||
desc = "Low range spell allowing you to pass through a few walls."
|
||||
school = "transmutation"
|
||||
invocation = "DULK'ES PRE'ZIMAS"
|
||||
invocation_type = "whisper"
|
||||
charge_max = 150
|
||||
range = -1
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "ash_shift"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
jaunt_in_time = 13
|
||||
jaunt_duration = 10
|
||||
jaunt_in_type = /obj/effect/temp_visual/dir_setting/ash_shift
|
||||
jaunt_out_type = /obj/effect/temp_visual/dir_setting/ash_shift/out
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long
|
||||
jaunt_duration = 50
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/play_sound()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/ash_shift
|
||||
name = "ash_shift"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "ash_shift2"
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/ash_shift/out
|
||||
icon_state = "ash_shift"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp
|
||||
name = "Mansus Grasp"
|
||||
desc = "Touch spell that allows you to channel the power of the Old Gods through you."
|
||||
hand_path = /obj/item/melee/touch_attack/mansus_fist
|
||||
school = "evocation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mansus_grasp"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/item/melee/touch_attack/mansus_fist
|
||||
name = "Mansus Grasp"
|
||||
desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown, major stamina damage aswell as some Brute. It gains additional beneficial effects with certain knowledges you can research."
|
||||
icon_state = "disintegrate"
|
||||
item_state = "disintegrate"
|
||||
catchphrase = "T'IESA SIE'KTI VISATA"
|
||||
|
||||
/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
|
||||
if(!proximity_flag || target == user)
|
||||
return
|
||||
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return ..()
|
||||
var/datum/mind/M = user.mind
|
||||
var/datum/antagonist/heretic/cultie = M.has_antag_datum(/datum/antagonist/heretic)
|
||||
|
||||
var/use_charge = FALSE
|
||||
if(iscarbon(target))
|
||||
use_charge = TRUE
|
||||
var/mob/living/carbon/C = target
|
||||
C.adjustBruteLoss(15)
|
||||
C.DefaultCombatKnockdown(50, override_stamdmg = 0)
|
||||
C.adjustStaminaLoss(60)
|
||||
var/list/knowledge = cultie.get_all_knowledge()
|
||||
|
||||
for(var/X in knowledge)
|
||||
var/datum/eldritch_knowledge/EK = knowledge[X]
|
||||
if(EK.on_mansus_grasp(target, user, proximity_flag, click_parameters))
|
||||
use_charge = TRUE
|
||||
if(use_charge)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion
|
||||
name = "Aggressive Spread"
|
||||
desc = "Spreads rust onto nearby turfs."
|
||||
school = "transmutation"
|
||||
charge_max = 300 //twice as long as mansus grasp
|
||||
clothes_req = FALSE
|
||||
invocation = "PLI'STI MINO DOMI'KA"
|
||||
invocation_type = "whisper"
|
||||
range = 3
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "corrode"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/cast(list/targets, mob/user = usr)
|
||||
playsound(user, 'sound/items/welder.ogg', 75, TRUE)
|
||||
for(var/turf/T in targets)
|
||||
///What we want is the 3 tiles around the user and the tile under him to be rusted, so min(dist,1)-1 causes us to get 0 for these tiles, rest of the tiles are based on chance
|
||||
var/chance = 100 - (max(get_dist(T,user),1)-1)*100/(range+1)
|
||||
if(!prob(chance))
|
||||
continue
|
||||
T.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small
|
||||
name = "Rust Conversion"
|
||||
desc = "Spreads rust onto nearby turfs."
|
||||
range = 2
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
desc = "Touch spell that heals you while damaging the enemy, has a chance to transfer wounds between you and your enemy."
|
||||
hand_path = /obj/item/melee/touch_attack/blood_siphon
|
||||
school = "evocation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
invocation_type = "none"
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "blood_siphon"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/item/melee/touch_attack/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
desc = "A sinister looking aura that distorts the flow of reality around it."
|
||||
icon_state = "disintegrate"
|
||||
item_state = "disintegrate"
|
||||
catchphrase = "SUN'AI'KINI'MAS"
|
||||
|
||||
/obj/item/melee/touch_attack/blood_siphon/afterattack(atom/target, mob/user, proximity_flag, proximity)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
playsound(user, 'sound/effects/curseattack.ogg', 75, TRUE)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return ..()
|
||||
var/mob/living/carbon/C2 = user
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.adjustBruteLoss(20)
|
||||
C2.adjustBruteLoss(-20)
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C1 = target
|
||||
for(var/obj/item/bodypart/bodypart in C2.bodyparts)
|
||||
for(var/i in bodypart.wounds)
|
||||
var/datum/wound/iter_wound = i
|
||||
if(prob(50))
|
||||
continue
|
||||
var/obj/item/bodypart/target_bodypart = locate(bodypart.type) in C1.bodyparts
|
||||
if(!target_bodypart)
|
||||
continue
|
||||
iter_wound.remove_wound()
|
||||
iter_wound.apply_wound(target_bodypart)
|
||||
|
||||
C1.blood_volume -= 20
|
||||
if(C2.blood_volume < BLOOD_VOLUME_MAXIMUM) //we dont want to explode after all
|
||||
C2.blood_volume += 20
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/rust_wave
|
||||
name = "Patron's Reach"
|
||||
desc = "Channels energy into your gauntlet - firing it results in a wave of rust being created in it's wake."
|
||||
projectile_type = /obj/item/projectile/magic/spell/rust_wave
|
||||
charge_max = 350
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
base_icon_state = "rust_wave"
|
||||
action_icon_state = "rust_wave"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
sound = 'sound/effects/curse5.ogg'
|
||||
active_msg = "You extend your hand out, preparing to send out a wave of rust."
|
||||
deactive_msg = "You extinguish that energy, for now..."
|
||||
invocation = "RUD'ZI VAR'ZTAS"
|
||||
invocation_type = "whisper"
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave
|
||||
name = "rust bolt"
|
||||
icon_state = "eldritch_projectile"
|
||||
alpha = 180
|
||||
damage = 30
|
||||
damage_type = TOX
|
||||
nodamage = 0
|
||||
hitsound = 'sound/effects/curseattack.ogg'
|
||||
range = 15
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave/Moved(atom/OldLoc, Dir)
|
||||
. = ..()
|
||||
playsound(src, 'sound/items/welder.ogg', 75, TRUE)
|
||||
var/list/turflist = list()
|
||||
var/turf/T1
|
||||
turflist += get_turf(src)
|
||||
T1 = get_step(src,turn(dir,90))
|
||||
turflist += T1
|
||||
turflist += get_step(T1,turn(dir,90))
|
||||
T1 = get_step(src,turn(dir,-90))
|
||||
turflist += T1
|
||||
turflist += get_step(T1,turn(dir,-90))
|
||||
for(var/X in turflist)
|
||||
if(!X || prob(25))
|
||||
continue
|
||||
var/turf/T = X
|
||||
T.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/rust_wave/short
|
||||
name = "Small Patron's Reach"
|
||||
projectile_type = /obj/item/projectile/magic/spell/rust_wave/short
|
||||
|
||||
/obj/item/projectile/magic/spell/rust_wave/short
|
||||
range = 7
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave
|
||||
name = "Cleave"
|
||||
desc = "Causes severe bleeding on a target and people around them"
|
||||
school = "transmutation"
|
||||
charge_max = 350
|
||||
clothes_req = FALSE
|
||||
invocation = "PLES'TI VI'RIBUS"
|
||||
invocation_type = "whisper"
|
||||
range = 9
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "cleave"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/cast(list/targets, mob/user)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='warning'>No target found in range!</span>")
|
||||
return FALSE
|
||||
if(!can_target(targets[1], user))
|
||||
return FALSE
|
||||
|
||||
for(var/mob/living/carbon/human/C in range(1,targets[1]))
|
||||
targets |= C
|
||||
|
||||
|
||||
for(var/X in targets)
|
||||
var/mob/living/carbon/human/target = X
|
||||
if(target == user)
|
||||
continue
|
||||
if(target.anti_magic_check())
|
||||
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
|
||||
target.visible_message("<span class='danger'>[target]'s veins flash with fire, but their magic protection repulses the blaze!</span>", \
|
||||
"<span class='danger'>Your veins flash with fire, but your magic protection repels the blaze!</span>")
|
||||
continue
|
||||
|
||||
target.visible_message("<span class='danger'>[target]'s veins are shredded from within as an unholy blaze erupts from their blood!</span>", \
|
||||
"<span class='danger'>Your veins burst from within and unholy flame erupts from your blood!</span>")
|
||||
var/obj/item/bodypart/bodypart = pick(target.bodyparts)
|
||||
var/datum/wound/slash/critical/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
target.adjustFireLoss(20)
|
||||
new /obj/effect/temp_visual/cleave(target.drop_location())
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(target,/mob/living/carbon/human))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are unable to cleave [target]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/cleave/long
|
||||
charge_max = 650
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch
|
||||
name = "Touch of Madness"
|
||||
desc = "Touch spell that drains your enemies sanity."
|
||||
school = "transmutation"
|
||||
charge_max = 150
|
||||
clothes_req = FALSE
|
||||
invocation_type = "none"
|
||||
range = 2
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mad_touch"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!istype(target,/mob/living/carbon/human))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are unable to touch [target]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/touch/mad_touch/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
for(var/mob/living/carbon/target in targets)
|
||||
if(ishuman(targets))
|
||||
var/mob/living/carbon/human/tar = target
|
||||
if(tar.anti_magic_check())
|
||||
tar.visible_message("<span class='danger'>Spell bounces off of [target]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
return
|
||||
if(target.mind && !target.mind.has_antag_datum(/datum/antagonist/heretic))
|
||||
to_chat(user,"<span class='warning'>[target.name] has been cursed!</span>")
|
||||
SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final
|
||||
name = "Nightwatcher's Rite"
|
||||
desc = "Powerful spell that releases 5 streams of fire away from you."
|
||||
school = "transmutation"
|
||||
invocation = "IGNIS'INTI"
|
||||
invocation_type = "whisper"
|
||||
charge_max = 300
|
||||
range = 15
|
||||
clothes_req = FALSE
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "flames"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/cast(list/targets, mob/user)
|
||||
for(var/X in targets)
|
||||
var/T
|
||||
T = line_target(-25, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(10, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(0, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(-10, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
T = line_target(25, range, X, user)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, user,T)
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/proc/line_target(offset, range, atom/at , atom/user)
|
||||
if(!at)
|
||||
return
|
||||
var/angle = ATAN2(at.x - user.x, at.y - user.y) + offset
|
||||
var/turf/T = get_turf(user)
|
||||
for(var/i in 1 to range)
|
||||
var/turf/check = locate(user.x + cos(angle) * i, user.y + sin(angle) * i, user.z)
|
||||
if(!check)
|
||||
break
|
||||
T = check
|
||||
return (getline(user, T) - get_turf(user))
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/ash_final/proc/fire_line(atom/source, list/turfs)
|
||||
var/list/hit_list = list()
|
||||
for(var/turf/T in turfs)
|
||||
if(istype(T, /turf/closed))
|
||||
break
|
||||
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L.anti_magic_check())
|
||||
L.visible_message("<span class='danger'>Spell bounces off of [L]!</span>","<span class='danger'>The spell bounces off of you!</span>")
|
||||
continue
|
||||
if(L in hit_list || L == source)
|
||||
continue
|
||||
hit_list += L
|
||||
L.adjustFireLoss(20)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by [source]'s fire breath!</span>")
|
||||
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
if(M in hit_list)
|
||||
continue
|
||||
hit_list += M
|
||||
M.take_damage(45, BURN, "melee", 1)
|
||||
sleep(1.5)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
sound = 'sound/magic/enter_blood.ogg'
|
||||
possible_shapes = list(/mob/living/simple_animal/mouse,\
|
||||
/mob/living/simple_animal/pet/dog/corgi,\
|
||||
/mob/living/simple_animal/hostile/carp,\
|
||||
/mob/living/simple_animal/bot/secbot, \
|
||||
/mob/living/simple_animal/pet/fox,\
|
||||
/mob/living/simple_animal/pet/cat )
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion/eldritch
|
||||
name = "Energetic Pulse"
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 300
|
||||
emp_heavy = 6
|
||||
emp_light = 10
|
||||
sound = 'sound/effects/lingscreech.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade
|
||||
name = "Fire Cascade"
|
||||
desc = "creates hot turfs around you."
|
||||
school = "transmutation"
|
||||
charge_max = 300 //twice as long as mansus grasp
|
||||
clothes_req = FALSE
|
||||
invocation = "IGNIS'SAVARIN"
|
||||
invocation_type = "whisper"
|
||||
range = 4
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "fire_ring"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/cast(list/targets, mob/user = usr)
|
||||
INVOKE_ASYNC(src, .proc/fire_cascade, user,range)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/proc/fire_cascade(atom/centre,max_range)
|
||||
playsound(get_turf(centre), 'sound/items/welder.ogg', 75, TRUE)
|
||||
var/_range = 1
|
||||
for(var/i = 0, i <= max_range,i++)
|
||||
for(var/turf/T in spiral_range_turfs(_range,centre))
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/livies in T.contents - centre)
|
||||
livies.adjustFireLoss(10)
|
||||
_range++
|
||||
sleep(3)
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big
|
||||
range = 6
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/telepathy/eldritch
|
||||
invocation = ""
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn
|
||||
name = "Oath of Fire"
|
||||
desc = "For a minute you will passively create a ring of fire around you."
|
||||
invocation = "IGNIS'AISTRA'LISTRE"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 700
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "fire_ring"
|
||||
///how long it lasts
|
||||
var/duration = 1 MINUTES
|
||||
///who casted it right now
|
||||
var/mob/current_user
|
||||
///Determines if you get the fire ring effect
|
||||
var/has_fire_ring = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
current_user = user
|
||||
has_fire_ring = TRUE
|
||||
addtimer(CALLBACK(src, .proc/remove, user), duration, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/proc/remove()
|
||||
has_fire_ring = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fire_sworn/process()
|
||||
. = ..()
|
||||
if(!has_fire_ring)
|
||||
return
|
||||
for(var/turf/T in range(1,current_user))
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/livies in T.contents - current_user)
|
||||
livies.adjustFireLoss(5)
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/worm_contract
|
||||
name = "Force Contract"
|
||||
desc = "Forces all the worm parts to collapse onto a single turf"
|
||||
invocation_type = "none"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 300
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "worm_contract"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/worm_contract/cast(list/targets, mob/user)
|
||||
. = ..()
|
||||
if(!istype(user,/mob/living/simple_animal/hostile/eldritch/armsy))
|
||||
to_chat(user, "<span class='userdanger'>You try to contract your muscles but nothing happens...</span>")
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/armsy = user
|
||||
armsy.contract_next_chain_into_single_tile()
|
||||
|
||||
/obj/effect/temp_visual/cleave
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "cleave"
|
||||
duration = 6
|
||||
|
||||
/obj/effect/temp_visual/eldritch_smoke
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "smoke"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fiery_rebirth
|
||||
name = "Nightwatcher's Rebirth"
|
||||
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
|
||||
invocation = "PETHRO'MINO'IGNI"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
charge_max = 600
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "smoke"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/fiery_rebirth/cast(list/targets, mob/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
for(var/mob/living/carbon/target in view(7,user))
|
||||
if(target.stat == DEAD || !target.on_fire)
|
||||
continue
|
||||
//This is essentially a death mark, use this to finish your opponent quicker.
|
||||
if(target.InCritical())
|
||||
target.death()
|
||||
target.adjustFireLoss(20)
|
||||
new /obj/effect/temp_visual/eldritch_smoke(target.drop_location())
|
||||
human_user.ExtinguishMob()
|
||||
human_user.adjustBruteLoss(-10, FALSE)
|
||||
human_user.adjustFireLoss(-10, FALSE)
|
||||
human_user.adjustStaminaLoss(-10, FALSE)
|
||||
human_user.adjustToxLoss(-10, FALSE)
|
||||
human_user.adjustOxyLoss(-10)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link
|
||||
name = "Mansus Link"
|
||||
desc = "Piercing through reality, connecting minds. This spell allows you to add people to a mansus net, allowing them to communicate with eachother"
|
||||
school = "transmutation"
|
||||
charge_max = 300
|
||||
clothes_req = FALSE
|
||||
invocation = "SUSEI' METO MIN'TIS"
|
||||
invocation_type = "whisper"
|
||||
range = 10
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "mansus_link"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/can_target(atom/target, mob/user, silent)
|
||||
if(!isliving(target))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/manse_link/cast(list/targets, mob/user)
|
||||
var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator = user
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
|
||||
to_chat(originator, "<span class='notice'>You begin linking [target]'s mind to yours...</span>")
|
||||
to_chat(target, "<span class='warning'>You feel your mind being pulled... connected... intertwined with the very fabric of reality...</span>")
|
||||
if(!do_after(originator, 6 SECONDS, target))
|
||||
return
|
||||
if(!originator.link_mob(target))
|
||||
to_chat(originator, "<span class='warning'>You can't seem to link [target]'s mind...</span>")
|
||||
to_chat(target, "<span class='warning'>The foreign presence leaves your mind.</span>")
|
||||
return
|
||||
to_chat(originator, "<span class='notice'>You connect [target]'s mind to your mansus link!</span>")
|
||||
|
||||
|
||||
/datum/action/innate/mansus_speech
|
||||
name = "Mansus Link"
|
||||
desc = "Send a psychic message to everyone connected to your mansus link."
|
||||
button_icon_state = "link_speech"
|
||||
icon_icon = 'icons/mob/actions/actions_slime.dmi'
|
||||
background_icon_state = "bg_ecult"
|
||||
var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator
|
||||
|
||||
/datum/action/innate/mansus_speech/New(_originator)
|
||||
. = ..()
|
||||
originator = _originator
|
||||
|
||||
/datum/action/innate/mansus_speech/Activate()
|
||||
var/mob/living/living_owner = owner
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
CRASH("Uh oh the mansus link got somehow activated without it being linked to a raw prophet or the mob not being in a list of mobs that should be able to do it.")
|
||||
|
||||
var/message = sanitize(input("Message:", "Telepathy from the Manse") as text|null)
|
||||
|
||||
if(QDELETED(living_owner))
|
||||
return
|
||||
|
||||
if(!originator?.linked_mobs[living_owner])
|
||||
to_chat(living_owner, "<span class='warning'>The link seems to have been severed...</span>")
|
||||
Remove(living_owner)
|
||||
return
|
||||
if(message)
|
||||
var/msg = "<i><font color=#568b00>\[Mansus Link\] <b>[living_owner]:</b> [message]</font></i>"
|
||||
log_directed_talk(living_owner, originator, msg, LOG_SAY, "Mansus Link")
|
||||
to_chat(originator.linked_mobs, msg)
|
||||
|
||||
for(var/dead_mob in GLOB.dead_mob_list)
|
||||
var/link = FOLLOW_LINK(dead_mob, living_owner)
|
||||
to_chat(dead_mob, "[link] [msg]")
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch
|
||||
range = 10
|
||||
invocation = "AK'LIS"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/entropic
|
||||
icon = 'icons/effects/160x160.dmi'
|
||||
icon_state = "entropic_plume"
|
||||
duration = 3 SECONDS
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/entropic/setDir(dir)
|
||||
. = ..()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
pixel_x = -64
|
||||
if(SOUTH)
|
||||
pixel_x = -64
|
||||
pixel_y = -128
|
||||
if(EAST)
|
||||
pixel_y = -64
|
||||
if(WEST)
|
||||
pixel_y = -64
|
||||
pixel_x = -128
|
||||
|
||||
/obj/effect/temp_visual/glowing_rune
|
||||
icon = 'icons/effects/eldritch.dmi'
|
||||
icon_state = "small_rune_1"
|
||||
duration = 1 MINUTES
|
||||
layer = LOW_SIGIL_LAYER
|
||||
|
||||
/obj/effect/temp_visual/glowing_rune/Initialize()
|
||||
. = ..()
|
||||
pixel_y = rand(-6,6)
|
||||
pixel_x = rand(-6,6)
|
||||
icon_state = "small_rune_[rand(12)]"
|
||||
update_icon()
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume
|
||||
name = "Entropic Plume"
|
||||
desc = "Spews forth a disorienting plume that causes enemies to strike each other, briefly blinds them(increasing with range) and poisons them(decreasing with range). Also spreads rust in the path of the plume."
|
||||
school = "illusion"
|
||||
invocation = "RU'KAS NU'DYTI"
|
||||
invocation_type = "whisper"
|
||||
clothes_req = FALSE
|
||||
action_background_icon_state = "bg_ecult"
|
||||
action_icon = 'icons/mob/actions/actions_ecult.dmi'
|
||||
action_icon_state = "entropic_plume"
|
||||
charge_max = 300
|
||||
cone_levels = 5
|
||||
respect_density = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/cast(list/targets,mob/user = usr)
|
||||
. = ..()
|
||||
new /obj/effect/temp_visual/dir_setting/entropic(get_step(user,user.dir), user.dir)
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_turf_cone_effect(turf/target_turf, level)
|
||||
. = ..()
|
||||
target_turf.rust_heretic_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_mob_cone_effect(mob/living/victim, level)
|
||||
. = ..()
|
||||
if(victim.anti_magic_check() || IS_HERETIC(victim) || victim.mind?.has_antag_datum(/datum/antagonist/heretic_monster))
|
||||
return
|
||||
victim.apply_status_effect(STATUS_EFFECT_AMOK)
|
||||
victim.apply_status_effect(STATUS_EFFECT_CLOUDSTRUCK, (level*10))
|
||||
if(iscarbon(victim))
|
||||
var/mob/living/carbon/carbon_victim = victim
|
||||
carbon_victim.reagents.add_reagent(/datum/reagent/eldritch, min(1, 6-level))
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/calculate_cone_shape(current_level)
|
||||
if(current_level == cone_levels)
|
||||
return 5
|
||||
else if(current_level == cone_levels-1)
|
||||
return 3
|
||||
else
|
||||
return 2
|
||||
@@ -0,0 +1,43 @@
|
||||
///Tracking reasons
|
||||
/datum/antagonist/heretic_monster
|
||||
name = "Eldritch Horror"
|
||||
roundend_category = "Heretics"
|
||||
antagpanel_category = "Heretic Beast"
|
||||
antag_moodlet = /datum/mood_event/heretics
|
||||
job_rank = ROLE_HERETIC
|
||||
antag_hud_type = ANTAG_HUD_HERETIC
|
||||
antag_hud_name = "heretic_beast"
|
||||
var/datum/antagonist/master
|
||||
|
||||
/datum/antagonist/heretic_monster/admin_add(datum/mind/new_owner,mob/admin)
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].")
|
||||
log_admin("[key_name(admin)] has heresized [key_name(new_owner)].")
|
||||
|
||||
/datum/antagonist/heretic_monster/greet()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
|
||||
to_chat(owner, "<span class='boldannounce'>You became an Eldritch Horror!</span>")
|
||||
|
||||
/datum/antagonist/heretic_monster/on_removal()
|
||||
if(owner)
|
||||
to_chat(owner, "<span class='boldannounce'>Your master is no longer [master.owner.current.real_name]</span>")
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/heretic_monster/proc/set_owner(datum/antagonist/_master)
|
||||
master = _master
|
||||
var/datum/objective/master_obj = new
|
||||
master_obj.owner = src
|
||||
master_obj.explanation_text = "Assist your master in any way you can!"
|
||||
objectives += master_obj
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<span class='boldannounce'>Your master is [master.owner.current.real_name]</span>")
|
||||
return
|
||||
|
||||
/datum/antagonist/heretic_monster/apply_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, owner.current)
|
||||
|
||||
/datum/antagonist/heretic_monster/remove_innate_effects(mob/living/mob_override)
|
||||
. = ..()
|
||||
remove_antag_hud(antag_hud_type, owner.current)
|
||||
183
code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
Normal file
183
code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm
Normal file
@@ -0,0 +1,183 @@
|
||||
/datum/eldritch_knowledge/base_ash
|
||||
name = "Nightwatcher's Secret"
|
||||
desc = "Inducts you into the Path of Ash. Allows you to transmute a match with an eldritch blade into an ashen blade."
|
||||
gain_text = "The City guard knows their watch. If you ask them at night they may tell you about the ashy lantern."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/ashen_grasp)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/match)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/ash)
|
||||
cost = 1
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/spell/ashen_shift
|
||||
name = "Ashen Shift"
|
||||
gain_text = "Ash is all the same, how can one man master it all?"
|
||||
desc = "A short range jaunt that will enable you to escape from danger."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash
|
||||
next_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/essence,/datum/eldritch_knowledge/ashen_eyes)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ashen_grasp
|
||||
name = "Grasp of Ash"
|
||||
gain_text = "Gates have opened, minds have flooded, yet I remain."
|
||||
desc = "Empowers your mansus grasp to knock enemies down and throw them away."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ashen_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!iscarbon(target))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = target
|
||||
var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(E)
|
||||
. = TRUE
|
||||
E.on_effect()
|
||||
for(var/X in user.mind.spell_list)
|
||||
if(!istype(X,/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp))
|
||||
continue
|
||||
var/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp/MG = X
|
||||
MG.charge_counter = min(round(MG.charge_counter + MG.charge_max * 0.75),MG.charge_max) // refunds 75% of charge.
|
||||
var/atom/throw_target = get_edge_target_turf(C, user.dir)
|
||||
if(!C.anchored)
|
||||
. = TRUE
|
||||
C.throw_at(throw_target, rand(4,8), 14, user)
|
||||
return
|
||||
|
||||
/datum/eldritch_knowledge/ashen_eyes
|
||||
name = "Ashen Eyes"
|
||||
gain_text = "Piercing eyes may guide me through the mundane."
|
||||
desc = "Allows you to craft thermal vision amulet by transmutating eyes with a glass shard."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift,/datum/eldritch_knowledge/flesh_ghoul)
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/shard)
|
||||
result_atoms = list(/obj/item/clothing/neck/eldritch_amulet)
|
||||
|
||||
/datum/eldritch_knowledge/ash_mark
|
||||
name = "Mark of Ash"
|
||||
gain_text = "Spread the famine."
|
||||
desc = "Your sickly blade now applies ash mark on hit. Use your mansus grasp to proc the mark. Mark of Ash causes stamina damage, and fire loss, and spreads to a nearby carbon. Damage decreases with how many times the mark has spread."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/ash,5)
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness
|
||||
name = "Curse of Blindness"
|
||||
gain_text = "The blind man walks through the world, unnoticed by the masses."
|
||||
desc = "Curse someone with 2 minutes of complete blindness by sacrificing a pair of eyes, a screwdriver and a pool of blood, with an object that the victim has touched with their bare hands."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/screwdriver,/obj/effect/decal/cleanable/blood)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/curse/paralysis)
|
||||
timer = 2 MINUTES
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.become_blind(MAGIC_TRAIT)
|
||||
|
||||
/datum/eldritch_knowledge/curse/blindness/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.cure_blind(MAGIC_TRAIT)
|
||||
|
||||
/datum/eldritch_knowledge/spell/flame_birth
|
||||
name = "Fiery Rebirth"
|
||||
gain_text = "Nightwatcher was a man of principles, and yet he arose from the chaos he vowed to protect from."
|
||||
desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/fiery_rebirth
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/final/ash_final)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_blade_upgrade
|
||||
name = "Blazing Steel"
|
||||
gain_text = "May the sun burn the heretics."
|
||||
desc = "Your blade of choice will now add firestacks."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/flame_birth)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
|
||||
route = PATH_ASH
|
||||
|
||||
/datum/eldritch_knowledge/ash_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
C.adjust_fire_stacks(1)
|
||||
C.IgniteMob()
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion
|
||||
name = "Curse of Corrosion"
|
||||
gain_text = "Cursed land, cursed man, cursed mind."
|
||||
desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a spill of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/wirecutters,/obj/effect/decal/cleanable/blood,/obj/item/organ/heart,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/spell/area_conversion)
|
||||
timer = 2 MINUTES
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.apply_status_effect(/datum/status_effect/corrosion_curse)
|
||||
|
||||
/datum/eldritch_knowledge/curse/corrosion/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
chosen_mob.remove_status_effect(/datum/status_effect/corrosion_curse)
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis
|
||||
name = "Curse of Paralysis"
|
||||
gain_text = "Corrupt their flesh, make them bleed."
|
||||
desc = "Curse someone for 5 minutes of inability to walk. Using a knife, pool of blood, left leg, right leg, a hatchet and an item that the victim touched with their bare hands. "
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/kitchen/knife,/obj/effect/decal/cleanable/blood,/obj/item/bodypart/l_leg,/obj/item/bodypart/r_leg,/obj/item/hatchet)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/summon/raw_prophet)
|
||||
timer = 5 MINUTES
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis/curse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
|
||||
ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
|
||||
chosen_mob.update_mobility()
|
||||
|
||||
/datum/eldritch_knowledge/curse/paralysis/uncurse(mob/living/chosen_mob)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT)
|
||||
REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT)
|
||||
chosen_mob.update_mobility()
|
||||
|
||||
/datum/eldritch_knowledge/spell/cleave
|
||||
name = "Blood Cleave"
|
||||
gain_text = "At first I was unfamiliar with these instruments of war, but the priest told me how to use them."
|
||||
desc = "Grants a spell that will inflict wounds and bleeding upon the target, as well as in a short radius around them."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/pointed/cleave
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume,/datum/eldritch_knowledge/spell/flame_birth)
|
||||
|
||||
/datum/eldritch_knowledge/final/ash_final
|
||||
name = "Ashlord's Rite"
|
||||
gain_text = "The forgotten lords have spoken! The Lord of Ash has come! Fear the flame!"
|
||||
desc = "Bring three corpses onto a transmutation rune, after ascending you will become immune to fire, space, temperature and other environmental hazards. You will develop resistance to all other damages. You will be granted two spells, one which can bring forth a cascade of massive fire, and another which will surround your body in precious flames for a minute."
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
cost = 5
|
||||
route = PATH_ASH
|
||||
var/list/trait_list = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_BOMBIMMUNE)
|
||||
|
||||
/datum/eldritch_knowledge/final/ash_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the blaze, for Ashbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big)
|
||||
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/fire_sworn)
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.physiology.brute_mod *= 0.5
|
||||
H.physiology.burn_mod *= 0.5
|
||||
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
for(var/X in trait_list)
|
||||
ADD_TRAIT(user,X,MAGIC_TRAIT)
|
||||
return ..()
|
||||
252
code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
Normal file
252
code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm
Normal file
@@ -0,0 +1,252 @@
|
||||
/datum/eldritch_knowledge/base_flesh
|
||||
name = "Principle of Hunger"
|
||||
desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with your eldritch blade into a Blade of Flesh."
|
||||
gain_text = "Hundred's of us starved, but I.. I found the strength in my greed."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_grasp)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/effect/decal/cleanable/blood)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/flesh)
|
||||
cost = 1
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul
|
||||
name = "Imperfect Ritual"
|
||||
desc = "Allows you to resurrect the dead as voiceless dead by sacrificing them on the transmutation rune with a poppy. Voiceless dead are mute and have 50 HP. You can only have 2 at a time."
|
||||
gain_text = "I found notes... notes of a ritual, scraps, unfinished, and yet... I still did it."
|
||||
cost = 1
|
||||
required_atoms = list(/mob/living/carbon/human,/obj/item/reagent_containers/food/snacks/grown/poppy)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/ashen_eyes)
|
||||
route = PATH_FLESH
|
||||
var/max_amt = 2
|
||||
var/current_amt = 0
|
||||
var/list/ghouls = list()
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul/on_finished_recipe(mob/living/user,list/atoms,loc)
|
||||
var/mob/living/carbon/human/humie = locate() in atoms
|
||||
if(QDELETED(humie) || humie.stat != DEAD)
|
||||
return
|
||||
|
||||
if(length(ghouls) >= max_amt)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(humie,TRAIT_HUSK))
|
||||
return
|
||||
|
||||
humie.grab_ghost()
|
||||
|
||||
if(!humie.mind || !humie.client)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [humie.real_name], a voiceless dead.", ROLE_HERETIC, null, ROLE_HERETIC, 50,humie)
|
||||
if(!LAZYLEN(candidates))
|
||||
return
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(humie)]) to replace an AFK player.")
|
||||
humie.ghostize(0)
|
||||
humie.key = C.key
|
||||
|
||||
ADD_TRAIT(humie,TRAIT_MUTE,MAGIC_TRAIT)
|
||||
log_game("[key_name_admin(humie)] has become a voiceless dead, their master is [user.real_name]")
|
||||
humie.revive(full_heal = TRUE, admin_revive = TRUE)
|
||||
humie.setMaxHealth(75)
|
||||
humie.health = 75 // Voiceless dead are much tougher than ghouls
|
||||
humie.become_husk()
|
||||
humie.faction |= "heretics"
|
||||
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = humie.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
atoms -= humie
|
||||
RegisterSignal(humie,COMSIG_MOB_DEATH,.proc/remove_ghoul)
|
||||
ghouls += humie
|
||||
|
||||
/datum/eldritch_knowledge/flesh_ghoul/proc/remove_ghoul(datum/source)
|
||||
var/mob/living/carbon/human/humie = source
|
||||
ghouls -= humie
|
||||
humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
|
||||
UnregisterSignal(source,COMSIG_MOB_DEATH)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp
|
||||
name = "Grasp of Flesh"
|
||||
gain_text = "'My newfound desire, it drove me to do great things,' The Priest said."
|
||||
desc = "Empowers your Mansus Grasp to be able to create a single ghoul out of a dead player. You cannot raise the same person twice. Ghouls have only 50 HP and look like husks."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul)
|
||||
var/ghoul_amt = 6
|
||||
var/list/spooky_scaries
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!ishuman(target) || target == user)
|
||||
return
|
||||
var/mob/living/carbon/human/human_target = target
|
||||
var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(eldritch_effect)
|
||||
. = TRUE
|
||||
eldritch_effect.on_effect()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
|
||||
var/datum/wound/slash/severe/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
|
||||
if(QDELETED(human_target) || human_target.stat != DEAD)
|
||||
return
|
||||
|
||||
human_target.grab_ghost()
|
||||
|
||||
if(!human_target.mind || !human_target.client)
|
||||
to_chat(user, "<span class='warning'>There is no soul connected to this body...</span>")
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(human_target, TRAIT_HUSK))
|
||||
to_chat(user, "<span class='warning'>You cannot revive a dead ghoul!</span>")
|
||||
return
|
||||
|
||||
if(LAZYLEN(spooky_scaries) >= ghoul_amt)
|
||||
to_chat(user, "<span class='warning'>Your patron cannot support more ghouls on this plane!</span>")
|
||||
return
|
||||
|
||||
LAZYADD(spooky_scaries, human_target)
|
||||
log_game("[key_name_admin(human_target)] has become a ghoul, their master is [user.real_name]")
|
||||
//we change it to true only after we know they passed all the checks
|
||||
. = TRUE
|
||||
RegisterSignal(human_target,COMSIG_MOB_DEATH,.proc/remove_ghoul)
|
||||
human_target.revive(full_heal = TRUE, admin_revive = TRUE)
|
||||
human_target.setMaxHealth(40)
|
||||
human_target.health = 40
|
||||
human_target.become_husk()
|
||||
human_target.faction |= "heretics"
|
||||
var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
heretic_monster.set_owner(master)
|
||||
return
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/flesh_grasp/proc/remove_ghoul(datum/source)
|
||||
var/mob/living/carbon/human/humie = source
|
||||
spooky_scaries -= humie
|
||||
humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster)
|
||||
UnregisterSignal(source, COMSIG_MOB_DEATH)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_mark
|
||||
name = "Mark of Flesh"
|
||||
gain_text = "I saw them, the marked ones. The screams... the silence."
|
||||
desc = "Your sickly blade now applies a mark of flesh to those cut by it. Once marked, using your Mansus Grasp upon them will cause additional bleeding from the target."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
|
||||
/datum/eldritch_knowledge/flesh_blade_upgrade
|
||||
name = "Bleeding Steel"
|
||||
gain_text = "It rained blood, that's when I understood the gravekeeper's advice."
|
||||
desc = "Your blade will now cause additional bleeding to those hit by it."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/flesh_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts)
|
||||
var/datum/wound/slash/severe/crit_wound = new
|
||||
crit_wound.apply_wound(bodypart)
|
||||
|
||||
/datum/eldritch_knowledge/summon/raw_prophet
|
||||
name = "Raw Ritual"
|
||||
gain_text = "The uncanny man walks alone in the valley, I was able to call his aid."
|
||||
desc = "You can now summon a Raw Prophet using eyes, a left arm, right arm and a pool of blood using a transmutation circle. Raw prophets have increased seeing range, and can see through walls. They can jaunt long distances, though they are fragile."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm,/obj/effect/decal/cleanable/blood)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/raw_prophet
|
||||
next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/curse/paralysis)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/summon/stalker
|
||||
name = "Lonely Ritual"
|
||||
gain_text = "I was able to combine my greed and desires to summon an eldritch beast I have not seen before."
|
||||
desc = "You can now summon a Stalker using a knife, a flower, a pen and a piece of paper using a transmutation circle. Stalkers possess the ability to shapeshift into various forms while assuming the vigor and powers of that form."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/item/kitchen/knife,/obj/item/reagent_containers/food/snacks/grown/poppy,/obj/item/pen,/obj/item/paper)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/summon/rusty,/datum/eldritch_knowledge/final/flesh_final)
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/summon/ashy
|
||||
name = "Ashen Ritual"
|
||||
gain_text = "I combined principle of hunger with desire of destruction. The eyeful lords have noticed me."
|
||||
desc = "You can now summon an Ashen One by transmuting a pile of ash, a head and a book using a transmutation circle. They possess the ability to jaunt short distances and create a cascade of flames."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/effect/decal/cleanable/ash,/obj/item/bodypart/head,/obj/item/book)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/ash_spirit
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/flame_birth)
|
||||
|
||||
/datum/eldritch_knowledge/summon/rusty
|
||||
name = "Rusted Ritual"
|
||||
gain_text = "I combined principle of hunger with desire of corruption. The rusted hills call my name."
|
||||
desc = "You can now summon a Rust Walker transmuting a vomit pool, a head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area."
|
||||
cost = 1
|
||||
required_atoms = list(/obj/effect/decal/cleanable/vomit,/obj/item/bodypart/head,/obj/item/book)
|
||||
mob_to_summon = /mob/living/simple_animal/hostile/eldritch/rust_spirit
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/entropic_plume)
|
||||
|
||||
/datum/eldritch_knowledge/spell/blood_siphon
|
||||
name = "Blood Siphon"
|
||||
gain_text = "Our blood is all the same after all, the owl told me."
|
||||
desc = "You are granted a spell that drains some of the targets health, and returns it to you. It also has a chance to transfer any wounds you possess onto the target."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/blood_siphon
|
||||
next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet,/datum/eldritch_knowledge/spell/area_conversion)
|
||||
|
||||
/datum/eldritch_knowledge/final/flesh_final
|
||||
name = "Priest's Final Hymn"
|
||||
gain_text = "Man of this world. Hear me! For the time of the lord of arms has come!"
|
||||
desc = "Bring three corpses to a transmutation rune to either ascend as The Lord of the Night or summon a single Terror of the Night, however you cannot ascend more than once."
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
cost = 5
|
||||
route = PATH_FLESH
|
||||
|
||||
/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
var/alert_ = alert(user,"Do you want to ascend as the lord of the night or just summon a terror of the night?","...","Yes","No")
|
||||
user.SetImmobilized(10 HOURS) // no way someone will stand 10 hours in a spot, just so he can move while the alert is still showing.
|
||||
switch(alert_)
|
||||
if("No")
|
||||
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy(loc)
|
||||
message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]")
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [summoned.real_name]", ROLE_HERETIC, null, ROLE_HERETIC, 100,summoned)
|
||||
user.SetImmobilized(0)
|
||||
if(LAZYLEN(candidates) == 0)
|
||||
to_chat(user,"<span class='warning'>No ghost could be found...</span>")
|
||||
qdel(summoned)
|
||||
return FALSE
|
||||
var/mob/dead/observer/ghost_candidate = pick(candidates)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for vassal of arms has ascended! Terror of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
log_game("[key_name_admin(ghost_candidate)] has taken control of ([key_name_admin(summoned)]).")
|
||||
summoned.ghostize(FALSE)
|
||||
summoned.key = ghost_candidate.key
|
||||
summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster)
|
||||
var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
monster.set_owner(master)
|
||||
master.ascended = TRUE
|
||||
if("Yes")
|
||||
var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10)
|
||||
summoned.ghostize(0)
|
||||
user.SetImmobilized(0)
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
log_game("[user.real_name] ascended as [summoned.real_name]")
|
||||
var/mob/living/carbon/carbon_user = user
|
||||
var/datum/antagonist/heretic/ascension = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
carbon_user.mind.transfer_to(summoned, TRUE)
|
||||
carbon_user.gib()
|
||||
|
||||
return ..()
|
||||
209
code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
Normal file
209
code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm
Normal file
@@ -0,0 +1,209 @@
|
||||
/datum/eldritch_knowledge/base_rust
|
||||
name = "Blacksmith's Tale"
|
||||
desc = "Inducts you into the Path of Rust. Allows you to transmute an eldritch blade with any trash item into a Blade of Rust."
|
||||
gain_text = "'Let me tell you a story,' The Blacksmith said as he gazed into his rusty blade."
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final)
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_fist)
|
||||
required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/trash)
|
||||
result_atoms = list(/obj/item/melee/sickly_blade/rust)
|
||||
cost = 1
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_fist
|
||||
name = "Grasp of Rust"
|
||||
desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any structure it touches. Destroys already rusted structures."
|
||||
gain_text = "Rust grows on the ceiling of the mansus."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen)
|
||||
var/rust_force = 500
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava,/turf/open/chasm,/turf/open/floor/plating/rust))
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_fist/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh)
|
||||
if(E)
|
||||
E.on_effect()
|
||||
H.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_EARS,ORGAN_SLOT_EYES,ORGAN_SLOT_LIVER,ORGAN_SLOT_LUNGS,ORGAN_SLOT_STOMACH,ORGAN_SLOT_HEART),25)
|
||||
target.rust_heretic_act()
|
||||
target.emp_act(EMP_HEAVY)
|
||||
return TRUE
|
||||
|
||||
/datum/eldritch_knowledge/spell/area_conversion
|
||||
name = "Aggressive Spread"
|
||||
desc = "Spreads rust to nearby turfs. Destroys already rusted walls."
|
||||
gain_text = "All wise men know not to touch the bound king."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/rust_conversion
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/spell/rust_wave)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/spell/rust_wave
|
||||
name = "Patron's Reach"
|
||||
desc = "You can now send a bolt of rust that corrupts the immediate area, and poisons the first target hit."
|
||||
gain_text = "Messengers of hope fear the rustbringer."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/aimed/rust_wave
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_regen
|
||||
name = "Leeching Walk"
|
||||
desc = "Passively heals you when you are on rusted tiles."
|
||||
gain_text = "'The strength was unparalleled, unnatural.' The Blacksmith was smiling."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/essence)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_regen/on_life(mob/user)
|
||||
. = ..()
|
||||
var/turf/user_loc_turf = get_turf(user)
|
||||
if(!istype(user_loc_turf, /turf/open/floor/plating/rust) || !isliving(user))
|
||||
return
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBruteLoss(-3, FALSE)
|
||||
living_user.adjustFireLoss(-3, FALSE)
|
||||
living_user.adjustToxLoss(-3, FALSE)
|
||||
living_user.adjustOxyLoss(-1, FALSE)
|
||||
living_user.adjustStaminaLoss(-6)
|
||||
|
||||
/datum/eldritch_knowledge/rust_mark
|
||||
name = "Mark of Rust"
|
||||
desc = "Your eldritch blade now applies a rust mark. Rust marks have a chance to deal between 0 to 200 damage to 75% of enemies items. To activate the mark use your Mansus Grasp on it."
|
||||
gain_text = "Lords of the depths help those in dire need at a cost."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/area_conversion)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_status_effect(/datum/status_effect/eldritch/rust)
|
||||
|
||||
/datum/eldritch_knowledge/rust_blade_upgrade
|
||||
name = "Toxic Steel"
|
||||
gain_text = "Let the blade guide you through the flesh."
|
||||
desc = "Your blade of choice will now add toxin to enemies bloodstream."
|
||||
cost = 2
|
||||
next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume)
|
||||
banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/rust_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/carbon_target = target
|
||||
carbon_target.reagents.add_reagent(/datum/reagent/eldritch, 5)
|
||||
|
||||
/datum/eldritch_knowledge/spell/entropic_plume
|
||||
name = "Entropic Plume"
|
||||
desc = "You can now send a befuddling plume that blinds, poisons and makes enemies strike each other, while also converting the immediate area into rust."
|
||||
gain_text = "Messengers of hope fear the rustbringer."
|
||||
cost = 1
|
||||
spell_to_add = /obj/effect/proc_holder/spell/cone/staggered/entropic_plume
|
||||
next_knowledge = list(/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/rusty)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/armor
|
||||
name = "Armorer's Ritual"
|
||||
desc = "You can now create eldritch armor using a built table and a gas mask on top of a transmutation rune."
|
||||
gain_text = "For I am the heir to the throne of doom."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/flesh_ghoul)
|
||||
required_atoms = list(/obj/structure/table,/obj/item/clothing/mask/gas)
|
||||
result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch)
|
||||
|
||||
/datum/eldritch_knowledge/essence
|
||||
name = "Priest's Ritual"
|
||||
desc = "You can now transmute a tank of water into a bottle of eldritch fluid."
|
||||
gain_text = "This is an old recipe, i got it from an owl."
|
||||
cost = 1
|
||||
next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/spell/ashen_shift)
|
||||
required_atoms = list(/obj/structure/reagent_dispensers/watertank)
|
||||
result_atoms = list(/obj/item/reagent_containers/glass/beaker/eldritch)
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final
|
||||
name = "Rustbringer's Oath"
|
||||
desc = "Bring three corpses onto a transmutation rune. After you finish the ritual, rust will now automatically spread from the rune. Your healing on rust is also tripled, while you become more resilient overall."
|
||||
gain_text = "Champion of rust. Corruptor of steel. Fear the dark for Rustbringer has come!"
|
||||
cost = 5
|
||||
required_atoms = list(/mob/living/carbon/human)
|
||||
route = PATH_RUST
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final/on_finished_recipe(mob/living/user, list/atoms, loc)
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.physiology.brute_mod *= 0.5
|
||||
H.physiology.burn_mod *= 0.5
|
||||
priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the decay, for Rustbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg')
|
||||
new /datum/rust_spread(loc)
|
||||
var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic)
|
||||
ascension.ascended = TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/eldritch_knowledge/final/rust_final/on_life(mob/user)
|
||||
. = ..()
|
||||
if(!finished)
|
||||
return
|
||||
var/mob/living/carbon/human/human_user = user
|
||||
human_user.adjustBruteLoss(-6, FALSE)
|
||||
human_user.adjustFireLoss(-6, FALSE)
|
||||
human_user.adjustToxLoss(-6, FALSE)
|
||||
human_user.adjustOxyLoss(-6, FALSE)
|
||||
human_user.adjustStaminaLoss(-20)
|
||||
|
||||
|
||||
/**
|
||||
* #Rust spread datum
|
||||
*
|
||||
* Simple datum that automatically spreads rust around it
|
||||
*
|
||||
* Simple implementation of automatically growing entity
|
||||
*/
|
||||
/datum/rust_spread
|
||||
var/list/edge_turfs = list()
|
||||
var/list/turfs = list()
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/open/indestructible,/turf/closed/indestructible,/turf/open/space,/turf/open/lava,/turf/open/chasm))
|
||||
var/spread_per_tick = 6
|
||||
|
||||
|
||||
/datum/rust_spread/New(loc)
|
||||
. = ..()
|
||||
var/turf/turf_loc = get_turf(loc)
|
||||
turf_loc.rust_heretic_act()
|
||||
turfs += turf_loc
|
||||
START_PROCESSING(SSprocessing,src)
|
||||
|
||||
|
||||
/datum/rust_spread/Destroy(force, ...)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
return ..()
|
||||
|
||||
/datum/rust_spread/process()
|
||||
compile_turfs()
|
||||
var/turf/T
|
||||
for(var/i in 0 to spread_per_tick)
|
||||
T = pick(edge_turfs)
|
||||
T.rust_heretic_act()
|
||||
turfs += get_turf(T)
|
||||
|
||||
/**
|
||||
* Compile turfs
|
||||
*
|
||||
* Recreates all edge_turfs as well as normal turfs.
|
||||
*/
|
||||
/datum/rust_spread/proc/compile_turfs()
|
||||
edge_turfs = list()
|
||||
for(var/X in turfs)
|
||||
if(!istype(X,/turf/closed/wall/rust) && !istype(X,/turf/closed/wall/r_wall/rust) && !istype(X,/turf/open/floor/plating/rust))
|
||||
turfs -=X
|
||||
continue
|
||||
for(var/turf/T in range(1,X))
|
||||
if(T in turfs)
|
||||
continue
|
||||
if(is_type_in_typecache(T,blacklisted_turfs))
|
||||
continue
|
||||
edge_turfs += T
|
||||
@@ -161,12 +161,12 @@
|
||||
|
||||
/datum/spellbook_entry/blind
|
||||
name = "Blind"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind
|
||||
cost = 1
|
||||
|
||||
/datum/spellbook_entry/mindswap
|
||||
name = "Mindswap"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
category = "Mobility"
|
||||
|
||||
/datum/spellbook_entry/forcewall
|
||||
@@ -246,7 +246,7 @@
|
||||
|
||||
/datum/spellbook_entry/barnyard
|
||||
name = "Barnyard Curse"
|
||||
spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse
|
||||
spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse
|
||||
|
||||
/datum/spellbook_entry/charge
|
||||
name = "Charge"
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
|
||||
if(APPRENTICE_ROBELESS)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
|
||||
if(APPRENTICE_MARTIAL)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null))
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
shuffle_inplace(mobs)
|
||||
|
||||
var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new /obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new /obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
while(mobs.len > 1)
|
||||
var/mob/living/carbon/human/H = pick(mobs)
|
||||
mobs -= H
|
||||
|
||||
@@ -476,5 +476,19 @@
|
||||
hand_bodyparts[i] = BP
|
||||
..() //Don't redraw hands until we have organs for them
|
||||
|
||||
|
||||
//GetAllContents that is reasonable and not stupid
|
||||
/mob/living/carbon/proc/get_all_gear()
|
||||
var/list/processing_list = get_equipped_items(include_pockets = TRUE) + held_items
|
||||
listclearnulls(processing_list) // handles empty hands
|
||||
var/i = 0
|
||||
while(i < length(processing_list) )
|
||||
var/atom/A = processing_list[++i]
|
||||
if(SEND_SIGNAL(A, COMSIG_CONTAINS_STORAGE))
|
||||
var/list/item_stuff = list()
|
||||
SEND_SIGNAL(A, COMSIG_TRY_STORAGE_RETURN_INVENTORY, item_stuff)
|
||||
processing_list += item_stuff
|
||||
return processing_list
|
||||
|
||||
/mob/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
|
||||
return ..() && (user == src)
|
||||
|
||||
@@ -299,10 +299,10 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/ex_act(severity, target, origin)
|
||||
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
|
||||
if(TRAIT_BOMBIMMUNE in dna.species.species_traits)
|
||||
return
|
||||
..()
|
||||
if (!severity)
|
||||
if (!severity || QDELETED(src))
|
||||
return
|
||||
var/brute_loss = 0
|
||||
var/burn_loss = 0
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
/mob/living/Bump(atom/A)
|
||||
if(..()) //we are thrown onto something
|
||||
return
|
||||
if (buckled || now_pushing)
|
||||
if(buckled || now_pushing)
|
||||
return
|
||||
if(ismob(A))
|
||||
var/mob/M = A
|
||||
|
||||
@@ -430,3 +430,6 @@
|
||||
|
||||
/mob/living/silicon/handle_high_gravity(gravity)
|
||||
return
|
||||
|
||||
/mob/living/silicon/rust_heretic_act()
|
||||
adjustBruteLoss(500)
|
||||
|
||||
@@ -1058,3 +1058,6 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
if(I)
|
||||
I.icon_state = null
|
||||
path.Cut(1, 2)
|
||||
|
||||
/mob/living/silicon/rust_heretic_act()
|
||||
adjustBruteLoss(500)
|
||||
|
||||
386
code/modules/mob/living/simple_animal/eldritch_demons.dm
Normal file
386
code/modules/mob/living/simple_animal/eldritch_demons.dm
Normal file
@@ -0,0 +1,386 @@
|
||||
/mob/living/simple_animal/hostile/eldritch
|
||||
name = "Demon"
|
||||
real_name = "Demon"
|
||||
desc = ""
|
||||
gender = NEUTER
|
||||
mob_biotypes = NONE
|
||||
speak_emote = list("screams")
|
||||
response_help_continuous = "thinks better of touching"
|
||||
response_help_simple = "think better of touching"
|
||||
response_disarm_continuous = "flails at"
|
||||
response_disarm_simple = "flail at"
|
||||
response_harm_continuous = "reaps"
|
||||
response_harm_simple = "tears"
|
||||
speak_chance = 1
|
||||
icon = 'icons/mob/eldritch_mobs.dmi'
|
||||
speed = 0
|
||||
a_intent = INTENT_HARM
|
||||
stop_automated_movement = 1
|
||||
AIStatus = AI_OFF
|
||||
attack_sound = 'sound/weapons/punch1.ogg'
|
||||
see_in_dark = 7
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
healable = 0
|
||||
movement_type = GROUND
|
||||
pressure_resistance = 100
|
||||
del_on_death = TRUE
|
||||
deathmessage = "implodes into itself"
|
||||
faction = list("heretics")
|
||||
simple_mob_flags = SILENCE_RANGED_MESSAGE
|
||||
///Innate spells that are supposed to be added when a beast is created
|
||||
var/list/spells_to_add
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/Initialize()
|
||||
. = ..()
|
||||
add_spells()
|
||||
|
||||
/**
|
||||
* Add_spells
|
||||
*
|
||||
* Goes through spells_to_add and adds each spell to the mind.
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/eldritch/proc/add_spells()
|
||||
for(var/spell in spells_to_add)
|
||||
AddSpell(new spell())
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet
|
||||
name = "Raw Prophet"
|
||||
real_name = "Raw Prophet"
|
||||
desc = "Abomination made from severed limbs."
|
||||
icon_state = "raw_prophet"
|
||||
status_flags = CANPUSH
|
||||
icon_living = "raw_prophet"
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
sight = SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long,/obj/effect/proc_holder/spell/pointed/manse_link,/obj/effect/proc_holder/spell/targeted/telepathy/eldritch,/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch)
|
||||
|
||||
var/list/linked_mobs = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet/Initialize()
|
||||
. = ..()
|
||||
link_mob(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet/Login()
|
||||
. = ..()
|
||||
client.change_view(10)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/link_mob(mob/living/mob_linked)
|
||||
if(QDELETED(mob_linked) || mob_linked.stat == DEAD)
|
||||
return FALSE
|
||||
if(HAS_TRAIT(mob_linked, TRAIT_MINDSHIELD)) //mindshield implant, no dice
|
||||
return FALSE
|
||||
if(mob_linked.anti_magic_check(FALSE, FALSE, TRUE, 0))
|
||||
return FALSE
|
||||
if(linked_mobs[mob_linked])
|
||||
return FALSE
|
||||
|
||||
to_chat(mob_linked, "<span class='notice'>You feel something new enter your sphere of mind, you hear whispers of people far away, screeches of horror and a humming of welcome to [src]'s Mansus Link.</span>")
|
||||
var/datum/action/innate/mansus_speech/action = new(src)
|
||||
linked_mobs[mob_linked] = action
|
||||
action.Grant(mob_linked)
|
||||
RegisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING) , .proc/unlink_mob)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/unlink_mob(mob/living/mob_linked)
|
||||
if(!linked_mobs[mob_linked])
|
||||
return
|
||||
UnregisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING))
|
||||
var/datum/action/innate/mansus_speech/action = linked_mobs[mob_linked]
|
||||
action.Remove(mob_linked)
|
||||
qdel(action)
|
||||
to_chat(mob_linked, "<span class='notice'>Your mind shatters as the [src]'s Mansus Link leaves your mind.</span>")
|
||||
mob_linked.emote("Scream")
|
||||
//micro stun
|
||||
mob_linked.AdjustParalyzed(0.5 SECONDS)
|
||||
linked_mobs -= mob_linked
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/raw_prophet/death(gibbed)
|
||||
for(var/linked_mob in linked_mobs)
|
||||
unlink_mob(linked_mob)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy
|
||||
name = "Terror of the Night"
|
||||
real_name = "Armsy"
|
||||
desc = "Abomination made from severed limbs."
|
||||
icon_state = "armsy_start"
|
||||
icon_living = "armsy_start"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
obj_damage = 80
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
move_resist = MOVE_FORCE_OVERPOWERING+1
|
||||
movement_type = GROUND
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
sight = SEE_MOBS
|
||||
spells_to_add = list(/obj/effect/proc_holder/spell/targeted/worm_contract)
|
||||
ranged = TRUE
|
||||
///Previous segment in the chain
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/back
|
||||
///Next segment in the chain
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/front
|
||||
///Your old location
|
||||
var/oldloc
|
||||
///Allow / disallow pulling
|
||||
var/allow_pulling = FALSE
|
||||
///How many arms do we have to eat to expand?
|
||||
var/stacks_to_grow = 2
|
||||
///Currently eaten arms
|
||||
var/current_stacks = 0
|
||||
|
||||
//I tried Initalize but it didnt work, like at all. This proc just wouldnt fire if it was Initalize instead of New
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/Initialize(mapload,spawn_more = TRUE,len = 6)
|
||||
. = ..()
|
||||
if(len < 3)
|
||||
stack_trace("Eldritch Armsy created with invalid len ([len]). Reverting to 3.")
|
||||
len = 3 //code breaks below 3, let's just not allow it.
|
||||
oldloc = loc
|
||||
RegisterSignal(src,COMSIG_MOVABLE_MOVED,.proc/update_chain_links)
|
||||
if(!spawn_more)
|
||||
return
|
||||
allow_pulling = TRUE
|
||||
///next link
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/next
|
||||
///previous link
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/prev
|
||||
///current link
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/current
|
||||
for(var/i in 0 to len)
|
||||
prev = current
|
||||
//i tried using switch, but byond is really fucky and it didnt work as intended. Im sorry
|
||||
if(i == 0)
|
||||
current = new type(drop_location(),FALSE)
|
||||
current.icon_state = "armsy_mid"
|
||||
current.icon_living = "armsy_mid"
|
||||
current.front = src
|
||||
current.AIStatus = AI_OFF
|
||||
back = current
|
||||
else if(i < len)
|
||||
current = new type(drop_location(),FALSE)
|
||||
prev.back = current
|
||||
prev.icon_state = "armsy_mid"
|
||||
prev.icon_living = "armsy_mid"
|
||||
prev.front = next
|
||||
prev.AIStatus = AI_OFF
|
||||
else
|
||||
prev.icon_state = "armsy_end"
|
||||
prev.icon_living = "armsy_end"
|
||||
prev.front = next
|
||||
prev.AIStatus = AI_OFF
|
||||
next = prev
|
||||
|
||||
//we are literally a vessel of otherworldly destruction, we bring our own gravity unto this plane
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/has_gravity(turf/T)
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/can_be_pulled()
|
||||
return FALSE
|
||||
|
||||
///Updates chain links to force move onto a single tile
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/proc/contract_next_chain_into_single_tile()
|
||||
if(back)
|
||||
back.forceMove(loc)
|
||||
back.contract_next_chain_into_single_tile()
|
||||
return
|
||||
|
||||
///Updates the next mob in the chain to move to our last location, fixed the worm if somehow broken.
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/proc/update_chain_links()
|
||||
gib_trail()
|
||||
if(back && back.loc != oldloc)
|
||||
back.Move(oldloc)
|
||||
// self fixing properties if somehow broken
|
||||
if(front && loc != front.oldloc)
|
||||
forceMove(front.oldloc)
|
||||
oldloc = loc
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/proc/gib_trail()
|
||||
if(front) // head makes gibs
|
||||
return
|
||||
var/chosen_decal = pick(typesof(/obj/effect/decal/cleanable/blood/tracks))
|
||||
var/obj/effect/decal/cleanable/blood/gibs/decal = new chosen_decal(drop_location())
|
||||
decal.setDir(dir)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/Destroy()
|
||||
if(front)
|
||||
front.icon_state = "armsy_end"
|
||||
front.icon_living = "armsy_end"
|
||||
front.back = null
|
||||
if(back)
|
||||
QDEL_NULL(back) // chain destruction baby
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/BiologicalLife(seconds, times_fired)
|
||||
adjustBruteLoss(-2)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/proc/heal()
|
||||
if(health == maxHealth)
|
||||
if(back)
|
||||
back.heal()
|
||||
return
|
||||
else
|
||||
current_stacks++
|
||||
if(current_stacks >= stacks_to_grow)
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE)
|
||||
icon_state = "armsy_mid"
|
||||
icon_living = "armsy_mid"
|
||||
back = prev
|
||||
prev.icon_state = "armsy_end"
|
||||
prev.icon_living = "armsy_end"
|
||||
prev.front = src
|
||||
prev.AIStatus = AI_OFF
|
||||
current_stacks = 0
|
||||
|
||||
adjustBruteLoss(-maxHealth * 0.5, FALSE)
|
||||
adjustFireLoss(-maxHealth * 0.5 ,FALSE)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/Shoot(atom/targeted_atom)
|
||||
target = targeted_atom
|
||||
AttackingTarget()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/AttackingTarget()
|
||||
if(istype(target,/obj/item/bodypart/r_arm) || istype(target,/obj/item/bodypart/l_arm))
|
||||
qdel(target)
|
||||
heal()
|
||||
return
|
||||
if(target == back || target == front)
|
||||
return
|
||||
if(back)
|
||||
back.target = target
|
||||
back.AttackingTarget()
|
||||
if(!Adjacent(target))
|
||||
return
|
||||
do_attack_animation(target)
|
||||
//have fun
|
||||
//if(istype(target,/turf/closed/wall))
|
||||
//var/turf/closed/wall = target
|
||||
//wall.ScrapeAway()
|
||||
|
||||
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(HAS_TRAIT(C, TRAIT_NODISMEMBER))
|
||||
return
|
||||
var/list/parts = list()
|
||||
for(var/X in C.bodyparts)
|
||||
var/obj/item/bodypart/bodypart = X
|
||||
if(bodypart.body_part != HEAD && bodypart.body_part != CHEST)
|
||||
if(bodypart.dismemberable)
|
||||
parts += bodypart
|
||||
if(length(parts) && prob(10))
|
||||
var/obj/item/bodypart/bodypart = pick(parts)
|
||||
bodypart.dismember()
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/prime
|
||||
name = "Lord of the Night"
|
||||
real_name = "Master of Decay"
|
||||
maxHealth = 400
|
||||
health = 400
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 25
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/prime/Initialize(mapload,spawn_more = TRUE,len = 9)
|
||||
. = ..()
|
||||
var/matrix/matrix_transformation = matrix()
|
||||
matrix_transformation.Scale(1.4,1.4)
|
||||
transform = matrix_transformation
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/armsy/primeproc/heal()
|
||||
if(health == maxHealth)
|
||||
if(back)
|
||||
back.heal()
|
||||
return
|
||||
else
|
||||
current_stacks++
|
||||
if(current_stacks >= stacks_to_grow)
|
||||
var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE)
|
||||
icon_state = "armsy_mid"
|
||||
icon_living = "armsy_mid"
|
||||
back = prev
|
||||
prev.icon_state = "armsy_end"
|
||||
prev.icon_living = "armsy_end"
|
||||
prev.front = src
|
||||
prev.AIStatus = AI_OFF
|
||||
current_stacks = 0
|
||||
var/matrix/matrix_transformation = matrix()
|
||||
matrix_transformation.Scale(1.4,1.4)
|
||||
transform = matrix_transformation
|
||||
|
||||
adjustBruteLoss(-maxHealth * 0.5, FALSE)
|
||||
adjustFireLoss(-maxHealth * 0.5 ,FALSE)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/rust_spirit
|
||||
name = "Rust Walker"
|
||||
real_name = "Rusty"
|
||||
desc = "Incomprehensible abomination actively seeping life out of it's surrounding."
|
||||
icon_state = "rust_walker_s"
|
||||
status_flags = CANPUSH
|
||||
icon_living = "rust_walker_s"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
sight = SEE_TURFS
|
||||
spells_to_add = list(/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small,/obj/effect/proc_holder/spell/aimed/rust_wave/short)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/rust_spirit/setDir(newdir, ismousemovement)
|
||||
. = ..()
|
||||
if(newdir == NORTH)
|
||||
icon_state = "rust_walker_n"
|
||||
else if(newdir == SOUTH)
|
||||
icon_state = "rust_walker_s"
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/rust_spirit/Moved()
|
||||
. = ..()
|
||||
playsound(src, 'sound/effects/footstep/rustystep1.ogg', 100, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/rust_spirit/Life()
|
||||
if(stat == DEAD)
|
||||
return ..()
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T,/turf/open/floor/plating/rust))
|
||||
adjustBruteLoss(-3, FALSE)
|
||||
adjustFireLoss(-3, FALSE)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/ash_spirit
|
||||
name = "Ash Man"
|
||||
real_name = "Ashy"
|
||||
desc = "Incomprehensible abomination actively seeping life out of it's surrounding."
|
||||
icon_state = "ash_walker"
|
||||
status_flags = CANPUSH
|
||||
icon_living = "ash_walker"
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
sight = SEE_TURFS
|
||||
spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/pointed/cleave/long,/obj/effect/proc_holder/spell/aoe_turf/fire_cascade)
|
||||
|
||||
/mob/living/simple_animal/hostile/eldritch/stalker
|
||||
name = "Flesh Stalker"
|
||||
real_name = "Flesh Stalker"
|
||||
desc = "Abomination made from severed limbs."
|
||||
icon_state = "stalker"
|
||||
status_flags = CANPUSH
|
||||
icon_living = "stalker"
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
sight = SEE_MOBS
|
||||
spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch,/obj/effect/proc_holder/spell/targeted/emplosion/eldritch)
|
||||
@@ -146,6 +146,8 @@
|
||||
var/bare_wound_bonus = 0
|
||||
//If the attacks from this are sharp
|
||||
var/sharpness = SHARP_NONE
|
||||
//Generic flags
|
||||
var/simple_mob_flags = NONE
|
||||
|
||||
/mob/living/simple_animal/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -2301,6 +2301,32 @@
|
||||
M.adjustStaminaLoss(-0.25*REM) // the more wounds, the more stamina regen
|
||||
..()
|
||||
|
||||
datum/reagent/eldritch
|
||||
name = "Eldritch Essence"
|
||||
description = "Strange liquid that defies the laws of physics"
|
||||
taste_description = "Ag'hsj'saje'sh"
|
||||
color = "#1f8016"
|
||||
|
||||
/datum/reagent/eldritch/on_mob_life(mob/living/carbon/M)
|
||||
if(IS_HERETIC(M))
|
||||
M.drowsyness = max(M.drowsyness-5, 0)
|
||||
M.AdjustAllImmobility(-40, FALSE)
|
||||
M.adjustStaminaLoss(-15, FALSE)
|
||||
M.adjustToxLoss(-3, FALSE)
|
||||
M.adjustOxyLoss(-3, FALSE)
|
||||
M.adjustBruteLoss(-3, FALSE)
|
||||
M.adjustFireLoss(-3, FALSE)
|
||||
if(ishuman(M) && M.blood_volume < BLOOD_VOLUME_NORMAL)
|
||||
M.blood_volume += 3
|
||||
else
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150)
|
||||
M.adjustToxLoss(2, FALSE)
|
||||
M.adjustFireLoss(2, FALSE)
|
||||
M.adjustOxyLoss(2, FALSE)
|
||||
M.adjustBruteLoss(2, FALSE)
|
||||
holder.remove_reagent(type, 1)
|
||||
return TRUE
|
||||
|
||||
/datum/reagent/cellulose
|
||||
name = "Cellulose Fibers"
|
||||
description = "A crystaline polydextrose polymer, plants swear by this stuff."
|
||||
|
||||
@@ -224,7 +224,15 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
/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/can_target(mob/living/target)
|
||||
/**
|
||||
* can_target: Checks if we are allowed to cast the spell on a target.
|
||||
*
|
||||
* Arguments:
|
||||
* * target The atom that is being targeted by the spell.
|
||||
* * user The mob using the spell.
|
||||
* * silent If the checks should not give any feedback messages.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/proc/can_target(atom/target, mob/user, silent = FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/start_recharge()
|
||||
@@ -296,6 +304,13 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
/obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr)
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/view_or_range(distance = world.view, center=usr, type="view")
|
||||
switch(type)
|
||||
if("view")
|
||||
. = view(distance,center)
|
||||
if("range")
|
||||
. = range(distance,center)
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
@@ -345,7 +360,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
switch(max_targets)
|
||||
if(0) //unlimited
|
||||
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
||||
if(!can_target(target))
|
||||
if(!can_target(target, user, TRUE))
|
||||
continue
|
||||
targets += target
|
||||
if(1) //single target can be picked
|
||||
@@ -357,7 +372,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
for(var/mob/living/M in view_or_range(range, user, selection_type))
|
||||
if(!include_user && user == M)
|
||||
continue
|
||||
if(!can_target(M))
|
||||
if(!can_target(M, user, TRUE))
|
||||
continue
|
||||
possible_targets += M
|
||||
|
||||
@@ -365,7 +380,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
//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 null|mob in possible_targets
|
||||
M = input("Choose the target for the spell.", "Targeting") as null|mob in sortNames(possible_targets)
|
||||
else
|
||||
switch(random_target_priority)
|
||||
if(TARGET_RANDOM)
|
||||
@@ -385,7 +400,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
else
|
||||
var/list/possible_targets = list()
|
||||
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
||||
if(!can_target(target))
|
||||
if(!can_target(target, user, TRUE))
|
||||
continue
|
||||
possible_targets += target
|
||||
for(var/i=1,i<=max_targets,i++)
|
||||
@@ -411,7 +426,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
var/list/targets = list()
|
||||
|
||||
for(var/turf/target in view_or_range(range,user,selection_type))
|
||||
if(!can_target(target))
|
||||
if(!can_target(target, user, TRUE))
|
||||
continue
|
||||
if(!(target in view_or_range(inner_radius,user,selection_type)))
|
||||
targets += target
|
||||
|
||||
117
code/modules/spells/spell_types/cone_spells.dm
Normal file
117
code/modules/spells/spell_types/cone_spells.dm
Normal file
@@ -0,0 +1,117 @@
|
||||
/obj/effect/proc_holder/spell/cone
|
||||
name = "Cone of Nothing"
|
||||
desc = "Does nothing in a cone! Wow!"
|
||||
school = "evocation"
|
||||
charge_max = 100
|
||||
clothes_req = FALSE
|
||||
invocation = "FUKAN NOTHAN"
|
||||
invocation_type = "shout"
|
||||
sound = 'sound/magic/forcewall.ogg'
|
||||
action_icon_state = "shield"
|
||||
range = -1
|
||||
cooldown_min = 0.5 SECONDS
|
||||
///This controls how many levels the cone has, increase this value to make a bigger cone.
|
||||
var/cone_levels = 3
|
||||
///This value determines if the cone penetrates walls.
|
||||
var/respect_density = FALSE
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/choose_targets(mob/user = usr)
|
||||
perform(null, user=user)
|
||||
|
||||
///This proc creates a list of turfs that are hit by the cone
|
||||
/obj/effect/proc_holder/spell/cone/proc/cone_helper(var/turf/starter_turf, var/dir_to_use, var/cone_levels = 3)
|
||||
var/list/turfs_to_return = list()
|
||||
var/turf/turf_to_use = starter_turf
|
||||
var/turf/left_turf
|
||||
var/turf/right_turf
|
||||
var/right_dir
|
||||
var/left_dir
|
||||
switch(dir_to_use)
|
||||
if(NORTH)
|
||||
left_dir = WEST
|
||||
right_dir = EAST
|
||||
if(SOUTH)
|
||||
left_dir = EAST
|
||||
right_dir = WEST
|
||||
if(EAST)
|
||||
left_dir = NORTH
|
||||
right_dir = SOUTH
|
||||
if(WEST)
|
||||
left_dir = SOUTH
|
||||
right_dir = NORTH
|
||||
|
||||
|
||||
for(var/i in 1 to cone_levels)
|
||||
var/list/level_turfs = list()
|
||||
turf_to_use = get_step(turf_to_use, dir_to_use)
|
||||
level_turfs += turf_to_use
|
||||
if(i != 1)
|
||||
left_turf = get_step(turf_to_use, left_dir)
|
||||
level_turfs += left_turf
|
||||
right_turf = get_step(turf_to_use, right_dir)
|
||||
level_turfs += right_turf
|
||||
for(var/left_i in 1 to i -calculate_cone_shape(i))
|
||||
if(left_turf.density && respect_density)
|
||||
break
|
||||
left_turf = get_step(left_turf, left_dir)
|
||||
level_turfs += left_turf
|
||||
for(var/right_i in 1 to i -calculate_cone_shape(i))
|
||||
if(right_turf.density && respect_density)
|
||||
break
|
||||
right_turf = get_step(right_turf, right_dir)
|
||||
level_turfs += right_turf
|
||||
turfs_to_return += list(level_turfs)
|
||||
if(i == cone_levels)
|
||||
continue
|
||||
if(turf_to_use.density && respect_density)
|
||||
break
|
||||
return turfs_to_return
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/cast(list/targets,mob/user = usr)
|
||||
var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels)
|
||||
for(var/list/turf_list in cone_turfs)
|
||||
do_cone_effects(turf_list)
|
||||
|
||||
///This proc does obj, mob and turf cone effects on all targets in a list
|
||||
/obj/effect/proc_holder/spell/cone/proc/do_cone_effects(list/target_turf_list, level)
|
||||
for(var/target_turf in target_turf_list)
|
||||
if(!target_turf) //if turf is no longer there
|
||||
continue
|
||||
do_turf_cone_effect(target_turf, level)
|
||||
if(isopenturf(target_turf))
|
||||
var/turf/open/open_turf = target_turf
|
||||
for(var/movable_content in open_turf)
|
||||
if(isobj(movable_content))
|
||||
do_obj_cone_effect(movable_content, level)
|
||||
else if(isliving(movable_content))
|
||||
do_mob_cone_effect(movable_content, level)
|
||||
|
||||
///This proc deterimines how the spell will affect turfs.
|
||||
/obj/effect/proc_holder/spell/cone/proc/do_turf_cone_effect(turf/target_turf, level)
|
||||
return
|
||||
|
||||
///This proc deterimines how the spell will affect objects.
|
||||
/obj/effect/proc_holder/spell/cone/proc/do_obj_cone_effect(obj/target_obj, level)
|
||||
return
|
||||
|
||||
///This proc deterimines how the spell will affect mobs.
|
||||
/obj/effect/proc_holder/spell/cone/proc/do_mob_cone_effect(mob/living/target_mob, level)
|
||||
return
|
||||
|
||||
///This proc adjusts the cones width depending on the level.
|
||||
/obj/effect/proc_holder/spell/cone/proc/calculate_cone_shape(current_level)
|
||||
var/end_taper_start = round(cone_levels * 0.8)
|
||||
if(current_level > end_taper_start)
|
||||
return (current_level % end_taper_start) * 2 //someone more talented and probably come up with a better formula.
|
||||
else
|
||||
return 2
|
||||
|
||||
///This type of cone gradually affects each level of the cone instead of affecting the entire area at once.
|
||||
/obj/effect/proc_holder/spell/cone/staggered
|
||||
|
||||
/obj/effect/proc_holder/spell/cone/staggered/cast(list/targets,mob/user = usr)
|
||||
var/level_counter = 0
|
||||
var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels)
|
||||
for(var/list/turf_list in cone_turfs)
|
||||
level_counter++
|
||||
addtimer(CALLBACK(src, .proc/do_cone_effects, turf_list, level_counter), 2 * level_counter)
|
||||
@@ -49,8 +49,8 @@
|
||||
var/projectile_type = text2path(proj_type)
|
||||
projectile = new projectile_type(user)
|
||||
else if(istype(proj_type, /obj/effect/proc_holder/spell))
|
||||
projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
|
||||
var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile
|
||||
projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user)
|
||||
var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile
|
||||
T.linked_spells += proj_type
|
||||
else
|
||||
projectile = new proj_type(user)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
action_icon_state = "jaunt"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded
|
||||
playsound(get_turf(user), 'sound/magic/ethereal_enter.ogg', 50, 1, -1)
|
||||
play_sound("enter",user)
|
||||
for(var/mob/living/target in targets)
|
||||
INVOKE_ASYNC(src, .proc/do_jaunt, target)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
ADD_TRAIT(target, TRAIT_MOBILITY_NOMOVE, src)
|
||||
target.update_mobility()
|
||||
holder.reappearing = 1
|
||||
playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, 1, -1)
|
||||
play_sound("exit",target)
|
||||
sleep(25 - jaunt_in_time)
|
||||
new jaunt_in_type(mobloc, holder.dir)
|
||||
target.setDir(holder.dir)
|
||||
@@ -63,6 +63,13 @@
|
||||
steam.set_up(10, 0, mobloc)
|
||||
steam.start()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/play_sound(type,mob/living/target)
|
||||
switch(type)
|
||||
if("enter")
|
||||
playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 50, TRUE, -1)
|
||||
if("exit")
|
||||
playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1)
|
||||
|
||||
/obj/effect/dummy/phased_mob/spell_jaunt
|
||||
name = "water"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
clothes_req = NONE
|
||||
invocation = "GIN'YU CAPAN"
|
||||
invocation_type = "whisper"
|
||||
range = 1
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell
|
||||
var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell
|
||||
|
||||
action_icon_state = "mindswap"
|
||||
|
||||
/*
|
||||
Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
|
||||
Make sure spells that are removed from spell_list are actually removed and deleted when mind transferring.
|
||||
Also, you never added distance checking after target is selected. I've went ahead and did that.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride, silent = FALSE)
|
||||
if(!targets.len)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>No mind found!</span>")
|
||||
return
|
||||
|
||||
if(targets.len > 1)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Too many minds! You're not a hive damnit!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
|
||||
var/t_He = target.p_they(TRUE)
|
||||
var/t_is = target.p_are()
|
||||
|
||||
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[t_He] [t_is] too far away!</span>")
|
||||
return
|
||||
|
||||
if(ismegafauna(target))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>This creature is too powerful to control!</span>")
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You don't particularly want to be dead!</span>")
|
||||
return
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.</span>")
|
||||
return
|
||||
|
||||
if(user.suiciding)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>")
|
||||
return
|
||||
|
||||
var/datum/mind/TM = target.mind
|
||||
if(target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev) || target.key[1] == "@")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[target.p_their(TRUE)] mind is resisting your spell!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/victim = target//The target of the spell whos body will be transferred to.
|
||||
var/mob/living/caster = user//The wizard/whomever doing the body transferring.
|
||||
|
||||
//MIND TRANSFER BEGIN
|
||||
var/mob/dead/observer/ghost = victim.ghostize(FALSE, TRUE)
|
||||
caster.mind.transfer_to(victim)
|
||||
|
||||
ghost.mind.transfer_to(caster)
|
||||
if(ghost.key)
|
||||
ghost.transfer_ckey(caster) //have to transfer the key since the mind was not active
|
||||
qdel(ghost)
|
||||
|
||||
//MIND TRANSFER END
|
||||
|
||||
//Here we knock both mobs out for a time.
|
||||
caster.Unconscious(unconscious_amount_caster)
|
||||
victim.Unconscious(unconscious_amount_victim)
|
||||
SEND_SOUND(caster, sound('sound/magic/mandswap.ogg'))
|
||||
SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
|
||||
return TRUE
|
||||
@@ -1,51 +1,54 @@
|
||||
/obj/effect/proc_holder/spell/targeted/barnyardcurse
|
||||
/obj/effect/proc_holder/spell/pointed/barnyardcurse
|
||||
name = "Curse of the Barnyard"
|
||||
desc = "This spell dooms an unlucky soul to possess the speech and facial attributes of a barnyard animal."
|
||||
school = "transmutation"
|
||||
charge_type = "recharge"
|
||||
charge_max = 150
|
||||
charge_counter = 0
|
||||
clothes_req = NONE
|
||||
stat_allowed = 0
|
||||
clothes_req = FALSE
|
||||
stat_allowed = FALSE
|
||||
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
|
||||
invocation_type = "shout"
|
||||
range = 7
|
||||
cooldown_min = 30
|
||||
selection_type = "range"
|
||||
var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
|
||||
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/barn_target.dmi'
|
||||
action_icon_state = "barn"
|
||||
active_msg = "You prepare to curse a target..."
|
||||
deactive_msg = "You dispel the curse..."
|
||||
/// List of mobs which are allowed to be a target of the spell
|
||||
var/static/list/compatible_mobs_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/carbon/monkey))
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/barnyardcurse/cast(list/targets, mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/pointed/barnyardcurse/cast(list/targets, mob/user)
|
||||
if(!targets.len)
|
||||
to_chat(user, "<span class='notice'>No target found in range.</span>")
|
||||
return
|
||||
to_chat(user, "<span class='warning'>No target found in range!</span>")
|
||||
return FALSE
|
||||
if(!can_target(targets[1], user))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/target = targets[1]
|
||||
|
||||
if(!(target.type in compatible_mobs))
|
||||
to_chat(user, "<span class='notice'>You are unable to curse [target]'s head!</span>")
|
||||
return
|
||||
|
||||
if(!(target in oview(range)))
|
||||
to_chat(user, "<span class='notice'>[target.p_theyre(TRUE)] too far away!</span>")
|
||||
return
|
||||
|
||||
if(target.anti_magic_check())
|
||||
to_chat(user, "<span class='warning'>The spell had no effect!</span>")
|
||||
target.visible_message("<span class='danger'>[target]'s face bursts into flames, which instantly burst outward, leaving [target] unharmed!</span>", \
|
||||
"<span class='danger'>Your face starts burning up, but the flames are repulsed by your anti-magic protection!</span>")
|
||||
return
|
||||
"<span class='danger'>Your face starts burning up, but the flames are repulsed by your anti-magic protection!</span>")
|
||||
return FALSE
|
||||
|
||||
var/list/masks = list(/obj/item/clothing/mask/pig/cursed, /obj/item/clothing/mask/cowmask/cursed, /obj/item/clothing/mask/horsehead/cursed)
|
||||
|
||||
var/choice = pick(masks)
|
||||
var/obj/item/clothing/mask/magichead = new choice(get_turf(target))
|
||||
magichead.flags_inv = null
|
||||
|
||||
target.visible_message("<span class='danger'>[target]'s face bursts into flames, and a barnyard animal's head takes its place!</span>", \
|
||||
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a barnyard animal!</span>")
|
||||
if(!target.dropItemToGround(target.wear_mask))
|
||||
qdel(target.wear_mask)
|
||||
target.equip_to_slot_if_possible(magichead, SLOT_WEAR_MASK, 1, 1)
|
||||
|
||||
target.equip_to_slot_if_possible(magichead, ITEM_SLOT_MASK, 1, 1)
|
||||
target.flash_act()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/barnyardcurse/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!is_type_in_typecache(target, compatible_mobs_typecache))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You are unable to curse [target]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
35
code/modules/spells/spell_types/pointed/blind.dm
Normal file
35
code/modules/spells/spell_types/pointed/blind.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind
|
||||
name = "Blind"
|
||||
desc = "This spell temporarily blinds a single target."
|
||||
school = "transmutation"
|
||||
charge_max = 300
|
||||
clothes_req = FALSE
|
||||
invocation = "STI KALY"
|
||||
invocation_type = "whisper"
|
||||
message = "<span class='notice'>Your eyes cry out in pain!</span>"
|
||||
cooldown_min = 50 //12 deciseconds reduction per rank
|
||||
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind", "/obj/effect/proc_holder/spell/targeted/genetic/blind")
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/blind_target.dmi'
|
||||
action_icon_state = "blind"
|
||||
active_msg = "You prepare to blind a target..."
|
||||
|
||||
/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
|
||||
mutations = list(BLINDMUT)
|
||||
duration = 300
|
||||
charge_max = 400 // needs to be higher than the duration or it'll be permanent
|
||||
sound = 'sound/magic/blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/blind/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!isliving(target))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can only blind living beings!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
103
code/modules/spells/spell_types/pointed/mind_transfer.dm
Normal file
103
code/modules/spells/spell_types/pointed/mind_transfer.dm
Normal file
@@ -0,0 +1,103 @@
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target next to him."
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
clothes_req = FALSE
|
||||
invocation = "GIN'YU CAPAN"
|
||||
invocation_type = "whisper"
|
||||
range = 1
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/mindswap_target.dmi'
|
||||
action_icon_state = "mindswap"
|
||||
active_msg = "You prepare to swap minds with a target..."
|
||||
/// For how long is the caster stunned for after the spell
|
||||
var/unconscious_amount_caster = 40 SECONDS
|
||||
/// For how long is the victim stunned for after the spell
|
||||
var/unconscious_amount_victim = 40 SECONDS
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer/cast(list/targets, mob/living/user, silent = FALSE)
|
||||
if(!targets.len)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>No mind found!</span>")
|
||||
return FALSE
|
||||
if(targets.len > 1)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Too many minds! You're not a hive damnit!</span>")
|
||||
return FALSE
|
||||
if(!can_target(targets[1], user, silent))
|
||||
return FALSE
|
||||
|
||||
var/mob/living/victim = targets[1] //The target of the spell whos body will be transferred to.
|
||||
var/datum/mind/VM = victim.mind
|
||||
if(victim.anti_magic_check(TRUE, FALSE) || VM.has_antag_datum(/datum/antagonist/wizard) || VM.has_antag_datum(/datum/antagonist/cult) || VM.has_antag_datum(/datum/antagonist/changeling) || VM.has_antag_datum(/datum/antagonist/rev) || victim.key[1] == "@")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[victim.p_their(TRUE)] mind is resisting your spell!</span>")
|
||||
return FALSE
|
||||
if(istype(victim, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/stand = victim
|
||||
if(stand.summoner)
|
||||
victim = stand.summoner
|
||||
|
||||
//You should not be able to enter one of the most powerful side-antags as a fucking wizard.
|
||||
if(istype(victim,/mob/living/simple_animal/slaughter))
|
||||
to_chat(user, "<span class='warning'>The devilish contract doesn't include the 'mind swappable' package, please try again another lifetime.</span>")
|
||||
return
|
||||
|
||||
//MIND TRANSFER BEGIN
|
||||
var/mob/dead/observer/ghost = victim.ghostize()
|
||||
user.mind.transfer_to(victim)
|
||||
|
||||
ghost.mind.transfer_to(user)
|
||||
if(ghost.key)
|
||||
user.key = ghost.key //have to transfer the key since the mind was not active
|
||||
qdel(ghost)
|
||||
//MIND TRANSFER END
|
||||
|
||||
//Here we knock both mobs out for a time.
|
||||
user.Unconscious(unconscious_amount_caster)
|
||||
victim.Unconscious(unconscious_amount_victim)
|
||||
SEND_SOUND(user, sound('sound/magic/mandswap.ogg'))
|
||||
SEND_SOUND(victim, sound('sound/magic/mandswap.ogg')) // only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/mind_transfer/can_target(atom/target, mob/user, silent)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(!isliving(target))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can only swap minds with living beings!</span>")
|
||||
return FALSE
|
||||
if(user == target)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can't swap minds with yourself!</span>")
|
||||
return FALSE
|
||||
|
||||
var/mob/living/victim = target
|
||||
var/t_He = victim.p_they(TRUE)
|
||||
|
||||
if(ismegafauna(victim))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>This creature is too powerful to control!</span>")
|
||||
return FALSE
|
||||
if(victim.stat == DEAD)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You don't particularly want to be dead!</span>")
|
||||
return FALSE
|
||||
if(!victim.key || !victim.mind)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[t_He] appear[victim.p_s()] to be catatonic! Not even magic can affect [victim.p_their()] vacant mind.</span>")
|
||||
return FALSE
|
||||
if(user.suiciding)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>")
|
||||
return FALSE
|
||||
if(istype(victim, /mob/living/simple_animal/hostile/guardian))
|
||||
var/mob/living/simple_animal/hostile/guardian/stand = victim
|
||||
if(stand.summoner)
|
||||
if(stand.summoner == user)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>Swapping minds with your own guardian would just put you back into your own head!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
105
code/modules/spells/spell_types/pointed/pointed.dm
Normal file
105
code/modules/spells/spell_types/pointed/pointed.dm
Normal file
@@ -0,0 +1,105 @@
|
||||
/obj/effect/proc_holder/spell/pointed
|
||||
name = "pointed spell"
|
||||
ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi'
|
||||
action_icon_state = "projectile"
|
||||
/// Message showing to the spell owner upon deactivating pointed spell.
|
||||
var/deactive_msg = "You dispel the magic..."
|
||||
/// Message showing to the spell owner upon activating pointed spell.
|
||||
var/active_msg = "You prepare to use the spell on a target..."
|
||||
/// Variable dictating if the user is allowed to cast a spell on himself.
|
||||
var/self_castable = FALSE
|
||||
/// Variable dictating if the spell will use turf based aim assist
|
||||
var/aim_assist = TRUE
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/Trigger(mob/user, skip_can_cast = TRUE)
|
||||
if(!istype(user))
|
||||
return
|
||||
var/msg
|
||||
if(!can_cast(user))
|
||||
msg = "<span class='warning'>You can no longer cast [name]!</span>"
|
||||
remove_ranged_ability(msg)
|
||||
return
|
||||
if(active)
|
||||
msg = "<span class='notice'>[deactive_msg]</span>"
|
||||
remove_ranged_ability(msg)
|
||||
else
|
||||
msg = "<span class='notice'>[active_msg] <B>Left-click to activate spell on a target!</B></span>"
|
||||
add_ranged_ability(user, msg, TRUE)
|
||||
on_activation(user)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/on_lose(mob/living/user)
|
||||
remove_ranged_ability()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/remove_ranged_ability(msg)
|
||||
. = ..()
|
||||
on_deactivation(ranged_ability_user)
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/add_ranged_ability(mob/living/user, msg, forced)
|
||||
. = ..()
|
||||
on_activation(user)
|
||||
|
||||
/**
|
||||
* on_activation: What happens upon pointed spell activation.
|
||||
*
|
||||
* Arguments:
|
||||
* * user The mob interacting owning the spell.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/on_activation(mob/user)
|
||||
return
|
||||
|
||||
/**
|
||||
* on_activation: What happens upon pointed spell deactivation.
|
||||
*
|
||||
* Arguments:
|
||||
* * user The mob interacting owning the spell.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/on_deactivation(mob/user)
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/update_icon()
|
||||
if(!action)
|
||||
return
|
||||
if(active)
|
||||
action.button_icon_state = "[action_icon_state]1"
|
||||
else
|
||||
action.button_icon_state = "[action_icon_state]"
|
||||
action.UpdateButtonIcon()
|
||||
|
||||
/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
return TRUE
|
||||
if(aim_assist && isturf(target))
|
||||
var/list/possible_targets = list()
|
||||
for(var/A in target)
|
||||
if(intercept_check(caller, A, TRUE))
|
||||
possible_targets += A
|
||||
if(possible_targets.len == 1)
|
||||
target = possible_targets[1]
|
||||
if(!intercept_check(caller, target))
|
||||
return TRUE
|
||||
if(!cast_check(FALSE, caller))
|
||||
return TRUE
|
||||
perform(list(target), user = caller)
|
||||
remove_ranged_ability()
|
||||
return TRUE // Do not do any underlying actions after the spell cast
|
||||
|
||||
/**
|
||||
* intercept_check: Specific spell checks for InterceptClickOn() targets.
|
||||
*
|
||||
* Arguments:
|
||||
* * user The mob using the ranged spell via intercept.
|
||||
* * target The atom that is being targeted by the spell via intercept.
|
||||
* * silent If the checks should produce not any feedback messages for the user.
|
||||
*/
|
||||
/obj/effect/proc_holder/spell/pointed/proc/intercept_check(mob/user, atom/target, silent = FALSE)
|
||||
if(!self_castable && target == user)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You cannot cast the spell on yourself!</span>")
|
||||
return FALSE
|
||||
if(!(target in view_or_range(range, user, selection_type)))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>[target.p_theyre(TRUE)] too far away!</span>")
|
||||
return FALSE
|
||||
if(!can_target(target, user, silent))
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -37,8 +37,8 @@
|
||||
var/projectile_type = text2path(proj_type)
|
||||
projectile = new projectile_type(user)
|
||||
if(istype(proj_type, /obj/effect/proc_holder/spell))
|
||||
projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
|
||||
var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile
|
||||
projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user)
|
||||
var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile
|
||||
T.linked_spells += proj_type
|
||||
projectile.icon = proj_icon
|
||||
projectile.icon_state = proj_icon_state
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
/obj/effect/proc_holder/spell/targeted/trigger
|
||||
/obj/effect/proc_holder/spell/pointed/trigger
|
||||
name = "Trigger"
|
||||
desc = "This spell triggers another spell or a few."
|
||||
|
||||
var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly
|
||||
var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/Initialize()
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/Initialize()
|
||||
. = ..()
|
||||
|
||||
for(var/spell in starting_spells)
|
||||
var/spell_to_add = text2path(spell)
|
||||
new spell_to_add(src) //should result in adding to contents, needs testing
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/Destroy()
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/Destroy()
|
||||
for(var/spell in contents)
|
||||
qdel(spell)
|
||||
linked_spells = null
|
||||
starting_spells = null
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets,mob/user = usr)
|
||||
/obj/effect/proc_holder/spell/pointed/trigger/cast(list/targets,mob/user = usr)
|
||||
playMagSound()
|
||||
for(var/mob/living/target in targets)
|
||||
for(var/obj/effect/proc_holder/spell/spell in contents)
|
||||
spell.perform(list(target),0)
|
||||
for(var/obj/effect/proc_holder/spell/spell in linked_spells)
|
||||
spell.perform(list(target),0)
|
||||
|
||||
return
|
||||
@@ -207,40 +207,12 @@
|
||||
summon_type = list(/mob/living/simple_animal/hostile/netherworld)
|
||||
cast_sound = 'sound/magic/summonitems_generic.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/blind
|
||||
name = "Blind"
|
||||
desc = "This spell temporarily blinds a single person and does not require wizard garb."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 300
|
||||
clothes_req = NONE
|
||||
invocation = "STI KALY"
|
||||
invocation_type = "whisper"
|
||||
message = "<span class='notice'>Your eyes cry out in pain!</span>"
|
||||
cooldown_min = 50 //12 deciseconds reduction per rank
|
||||
|
||||
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind")
|
||||
|
||||
action_icon_state = "blind"
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature/cult
|
||||
name = "Summon Creatures (DANGEROUS)"
|
||||
clothes_req = SPELL_CULT_GARB
|
||||
charge_max = 5000
|
||||
summon_amt = 2
|
||||
|
||||
|
||||
|
||||
/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
|
||||
mutations = list(BLINDMUT)
|
||||
duration = 300
|
||||
sound = 'sound/magic/blind.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/repulse
|
||||
name = "Repulse"
|
||||
desc = "This spell throws everything around the user away."
|
||||
|
||||
Reference in New Issue
Block a user