code folder. 221 files changed wew
This commit is contained in:
@@ -73,19 +73,18 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/is_banned(mob/M)
|
||||
if(!M)
|
||||
return FALSE
|
||||
. = (jobban_isbanned(M,"Syndicate") || (job_rank && jobban_isbanned(M,job_rank)))
|
||||
. = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M,job_rank)))
|
||||
|
||||
/datum/antagonist/proc/replace_banned_player()
|
||||
set waitfor = FALSE
|
||||
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
|
||||
var/mob/dead/observer/theghost = null
|
||||
if(candidates.len)
|
||||
theghost = pick(candidates)
|
||||
if(LAZYLEN(candidates))
|
||||
var/client/C = pick(candidates)
|
||||
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
||||
owner.current.ghostize(0)
|
||||
owner.current.key = theghost.key
|
||||
owner.current.key = C.key
|
||||
|
||||
/datum/antagonist/proc/on_removal()
|
||||
remove_innate_effects()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/used = 0
|
||||
var/used = FALSE
|
||||
|
||||
/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, kind = "", datum/mind/user)
|
||||
return
|
||||
@@ -57,13 +57,13 @@
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src)
|
||||
if(candidates.len)
|
||||
if(LAZYLEN(candidates))
|
||||
if(used)
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
used = 1
|
||||
var/mob/dead/observer/theghost = pick(candidates)
|
||||
spawn_antag(theghost.client, get_turf(src), href_list["school"],H.mind)
|
||||
used = TRUE
|
||||
var/client/C = pick(candidates)
|
||||
spawn_antag(C, get_turf(src), href_list["school"],H.mind)
|
||||
else
|
||||
to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.")
|
||||
|
||||
@@ -120,12 +120,12 @@
|
||||
|
||||
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
||||
var/list/nuke_candidates = pollGhostCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE)
|
||||
if(nuke_candidates.len)
|
||||
if(LAZYLEN(nuke_candidates))
|
||||
if(!(check_usability(user)))
|
||||
return
|
||||
used = TRUE
|
||||
var/mob/dead/observer/theghost = pick(nuke_candidates)
|
||||
spawn_antag(theghost.client, get_turf(src), "syndieborg", user.mind)
|
||||
var/client/C = pick(nuke_candidates)
|
||||
spawn_antag(C, get_turf(src), "syndieborg", user.mind)
|
||||
do_sparks(4, TRUE, src)
|
||||
qdel(src)
|
||||
else
|
||||
@@ -213,13 +213,13 @@
|
||||
return
|
||||
if(used)
|
||||
return
|
||||
var/list/demon_candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", null, null, ROLE_ALIEN, 50, src)
|
||||
if(demon_candidates.len)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
|
||||
if(LAZYLEN(candidates))
|
||||
if(used)
|
||||
return
|
||||
used = 1
|
||||
var/mob/dead/observer/theghost = pick(demon_candidates)
|
||||
spawn_antag(theghost.client, get_turf(src), initial(demon_type.name),user.mind)
|
||||
used = TRUE
|
||||
var/client/C = pick(candidates)
|
||||
spawn_antag(C, get_turf(src), initial(demon_type.name),user.mind)
|
||||
to_chat(user, shatter_msg)
|
||||
to_chat(user, veil_msg)
|
||||
playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1)
|
||||
|
||||
@@ -682,8 +682,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
/obj/structure/table_frame/abductor/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/wrench))
|
||||
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
|
||||
playsound(src.loc, I.usesound, 50, 1)
|
||||
if(do_after(user, 30*I.toolspeed, target = src))
|
||||
I.play_tool_sound(src)
|
||||
if(I.use_tool(src, user, 30))
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
for(var/i = 1, i <= framestackamount, i++)
|
||||
new framestack(get_turf(src))
|
||||
|
||||
@@ -262,10 +262,9 @@
|
||||
mind_control_duration = 1800
|
||||
|
||||
/obj/item/organ/heart/gland/egg/activate()
|
||||
to_chat(owner, "<span class='boldannounce'>You lay an egg!</span>")
|
||||
var/obj/item/reagent_containers/food/snacks/egg/egg = new(owner.drop_location())
|
||||
egg.reagents.add_reagent(get_random_reagent_id(), 15)
|
||||
egg.desc += " It looks weird..."
|
||||
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
|
||||
var/turf/T = owner.drop_location()
|
||||
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
|
||||
|
||||
/obj/item/organ/heart/gland/electric
|
||||
cooldown_low = 800
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "Brother"
|
||||
antagpanel_category = "Brother"
|
||||
job_rank = ROLE_BROTHER
|
||||
var/special_role = "blood brother"
|
||||
var/special_role = ROLE_BROTHER
|
||||
var/datum/team/brother_team/team
|
||||
|
||||
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
|
||||
|
||||
@@ -76,6 +76,13 @@
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/changeling/on_removal()
|
||||
//We'll be using this from now on
|
||||
var/mob/living/carbon/C = owner.current
|
||||
if(istype(C))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(B && (B.decoy_override != initial(B.decoy_override)))
|
||||
B.vital = TRUE
|
||||
B.decoy_override = FALSE
|
||||
remove_changeling_powers()
|
||||
owner.objectives -= objectives
|
||||
. = ..()
|
||||
@@ -389,7 +396,7 @@
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = owner
|
||||
if(team_mode) //No backstabbing while in a team
|
||||
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
kill_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
|
||||
else
|
||||
kill_objective.find_target()
|
||||
objectives += kill_objective
|
||||
@@ -397,7 +404,7 @@
|
||||
var/datum/objective/maroon/maroon_objective = new
|
||||
maroon_objective.owner = owner
|
||||
if(team_mode)
|
||||
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
maroon_objective.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
|
||||
else
|
||||
maroon_objective.find_target()
|
||||
objectives += maroon_objective
|
||||
@@ -419,7 +426,7 @@
|
||||
var/datum/objective/escape/escape_with_identity/identity_theft = new
|
||||
identity_theft.owner = owner
|
||||
if(team_mode)
|
||||
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
|
||||
identity_theft.find_target_by_role(role = ROLE_CHANGELING, role_type = 1, invert = 1)
|
||||
else
|
||||
identity_theft.find_target()
|
||||
objectives += identity_theft
|
||||
|
||||
@@ -34,4 +34,4 @@
|
||||
else
|
||||
adjust_clockwork_power(1) //Continue generating power when the cell has run dry; 5 W/second
|
||||
|
||||
#undef COG_MAX_SIPHON_THRESHOLD
|
||||
#undef COG_MAX_SIPHON_THRESHOLD
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
var/distance = get_dist(src, O)
|
||||
to_chat(user, "[O] ([distance == 0 ? "same tile" : "[distance] tiles [dir2text(get_dir(src, O))]"])")
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/wrench)
|
||||
/obj/structure/destructible/clockwork/trap/wrench_act(mob/living/user, obj/item/I)
|
||||
if(!is_servant_of_ratvar(user))
|
||||
return ..()
|
||||
to_chat(user, "<span class='notice'>You break down the delicate components of [src] into brass.</span>")
|
||||
playsound(src, wrench.usesound, 50, TRUE)
|
||||
I.play_tool_sound(src)
|
||||
new/obj/item/stack/tile/brass(get_turf(src))
|
||||
qdel(src)
|
||||
return TRUE
|
||||
@@ -56,14 +56,14 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/wirecutters)
|
||||
/obj/structure/destructible/clockwork/trap/wirecutter_act(mob/living/user, obj/item/I)
|
||||
if(!is_servant_of_ratvar(user))
|
||||
return
|
||||
if(!wired_to.len)
|
||||
to_chat(user, "<span class='warning'>[src] has no connections!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You sever all connections to [src].</span>")
|
||||
playsound(src, wirecutters.usesound, 50, TRUE)
|
||||
I.play_tool_sound(src)
|
||||
for(var/V in wired_to)
|
||||
var/obj/structure/destructible/clockwork/trap/T = V
|
||||
T.wired_to -= src
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
if(anchored)
|
||||
to_chat(user, "<span class='warning'>[src] needs to be unsecured to disassemble it!</span>")
|
||||
else
|
||||
playsound(src, I.usesound, 100, 1)
|
||||
user.visible_message("<span class='warning'>[user] starts to disassemble [src].</span>", "<span class='notice'>You start to disassemble [src]...</span>")
|
||||
if(do_after(user, 30*I.toolspeed, target = src) && !anchored)
|
||||
if(I.use_tool(src, user, 30, volume=100) && !anchored)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
|
||||
deconstruct(TRUE)
|
||||
return 1
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
var/mob/living/current = owner.current
|
||||
SSticker.mode.servants_of_ratvar += owner
|
||||
SSticker.mode.update_servant_icons_added(owner)
|
||||
owner.special_role = "Servant of Ratvar"
|
||||
owner.special_role = ROLE_SERVANT_OF_RATVAR
|
||||
owner.current.log_message("<font color=#BE8700>Has been converted to the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(issilicon(current))
|
||||
if(iscyborg(current) && !silent)
|
||||
|
||||
@@ -0,0 +1,775 @@
|
||||
/datum/action/innate/cult/blood_magic //Blood magic handles the creation of blood spells (formerly talismans)
|
||||
name = "Prepare Blood Magic"
|
||||
button_icon_state = "carve"
|
||||
desc = "Prepare blood magic by carving runes into your flesh. This rite is most effective with an <b>empowering rune</b>"
|
||||
var/list/spells = list()
|
||||
var/channeling = FALSE
|
||||
|
||||
/datum/action/innate/cult/blood_magic/Grant()
|
||||
..()
|
||||
button.screen_loc = "6:-29,4:-2"
|
||||
button.moved = "6:-29,4:-2"
|
||||
|
||||
/datum/action/innate/cult/blood_magic/Remove()
|
||||
for(var/X in spells)
|
||||
qdel(X)
|
||||
..()
|
||||
|
||||
/datum/action/innate/cult/blood_magic/IsAvailable()
|
||||
if(!iscultist(owner))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cult/blood_magic/proc/Positioning()
|
||||
var/list/screen_loc_split = splittext(button.screen_loc,",")
|
||||
var/list/screen_loc_X = splittext(screen_loc_split[1],":")
|
||||
var/list/screen_loc_Y = splittext(screen_loc_split[2],":")
|
||||
var/pix_X = text2num(screen_loc_X[2])
|
||||
for(var/datum/action/innate/cult/blood_spell/B in spells)
|
||||
if(B.button.locked)
|
||||
var/order = pix_X+spells.Find(B)*31
|
||||
B.button.screen_loc = "[screen_loc_X[1]]:[order],[screen_loc_Y[1]]:[screen_loc_Y[2]]"
|
||||
B.button.moved = B.button.screen_loc
|
||||
|
||||
/datum/action/innate/cult/blood_magic/Activate()
|
||||
var/rune = FALSE
|
||||
var/limit = RUNELESS_MAX_BLOODCHARGE
|
||||
for(var/obj/effect/rune/empower/R in range(1, owner))
|
||||
rune = TRUE
|
||||
break
|
||||
if(rune)
|
||||
limit = MAX_BLOODCHARGE
|
||||
if(spells.len >= limit)
|
||||
if(rune)
|
||||
to_chat(owner, "<span class='cultitalic'>Your body has reached its limit, you cannot store more than [MAX_BLOODCHARGE] spells at once. <b>Pick a spell to nullify.</b></span>")
|
||||
else
|
||||
to_chat(owner, "<span class='cultitalic'>Your body has reached its limit, <b><u>you cannot have more than [RUNELESS_MAX_BLOODCHARGE] spells at once without an empowering rune! Pick a spell to nullify.</b></u></span>")
|
||||
var/nullify_spell = input(owner, "Choose a spell to remove.", "Current Spells") as null|anything in spells
|
||||
if(nullify_spell)
|
||||
qdel(nullify_spell)
|
||||
return
|
||||
var/entered_spell_name
|
||||
var/datum/action/innate/cult/blood_spell/BS
|
||||
var/list/possible_spells = list()
|
||||
for(var/I in subtypesof(/datum/action/innate/cult/blood_spell))
|
||||
var/datum/action/innate/cult/blood_spell/J = I
|
||||
var/cult_name = initial(J.name)
|
||||
possible_spells[cult_name] = J
|
||||
possible_spells += "(REMOVE SPELL)"
|
||||
entered_spell_name = input(owner, "Pick a blood spell to prepare...", "Spell Choices") as null|anything in possible_spells
|
||||
if(entered_spell_name == "(REMOVE SPELL)")
|
||||
var/nullify_spell = input(owner, "Choose a spell to remove.", "Current Spells") as null|anything in spells
|
||||
if(nullify_spell)
|
||||
qdel(nullify_spell)
|
||||
return
|
||||
BS = possible_spells[entered_spell_name]
|
||||
if(QDELETED(src) || owner.incapacitated() || !BS)
|
||||
return
|
||||
to_chat(owner,"<span class='warning'>You begin to carve unnatural symbols into your flesh!</span>")
|
||||
SEND_SOUND(owner, sound('sound/weapons/slice.ogg',0,1,10))
|
||||
if(!channeling)
|
||||
channeling = TRUE
|
||||
else
|
||||
to_chat(owner, "<span class='cultitalic'>You are already invoking blood magic!")
|
||||
return
|
||||
if(do_after(owner, 100 - rune*65, target = owner))
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.bleed(30 - rune*25)
|
||||
var/datum/action/innate/cult/blood_spell/new_spell = new BS(owner)
|
||||
new_spell.Grant(owner, src)
|
||||
spells += new_spell
|
||||
Positioning()
|
||||
to_chat(owner, "<span class='warning'>Your wounds glows with power, you have prepared a [new_spell.name] invocation!</span>")
|
||||
channeling = FALSE
|
||||
|
||||
/datum/action/innate/cult/blood_spell //The next generation of talismans
|
||||
name = "Blood Magic"
|
||||
button_icon_state = "telerune"
|
||||
desc = "Fear the Old Blood."
|
||||
var/charges = 1
|
||||
var/magic_path = null
|
||||
var/obj/item/melee/blood_magic/hand_magic
|
||||
var/datum/action/innate/cult/blood_magic/all_magic
|
||||
var/base_desc //To allow for updating tooltips
|
||||
var/invocation
|
||||
var/health_cost = 0
|
||||
|
||||
/datum/action/innate/cult/blood_spell/Grant(mob/living/owner, datum/action/innate/cult/blood_magic/BM)
|
||||
if(health_cost)
|
||||
desc += "<br>Deals <u>[health_cost] damage</u> to your arm per use."
|
||||
base_desc = desc
|
||||
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
|
||||
all_magic = BM
|
||||
..()
|
||||
button.locked = TRUE
|
||||
|
||||
/datum/action/innate/cult/blood_spell/Remove()
|
||||
if(all_magic)
|
||||
all_magic.spells -= src
|
||||
if(hand_magic)
|
||||
qdel(hand_magic)
|
||||
hand_magic = null
|
||||
..()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/IsAvailable()
|
||||
if(!iscultist(owner) || owner.incapacitated() || !charges)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/Activate()
|
||||
if(magic_path) //If this spell flows from the hand
|
||||
if(!hand_magic)
|
||||
hand_magic = new magic_path(owner, src)
|
||||
if(!owner.put_in_hands(hand_magic))
|
||||
qdel(hand_magic)
|
||||
hand_magic = null
|
||||
to_chat(owner, "<span class='warning'>You have no empty hand for invoking blood magic!</span>")
|
||||
return
|
||||
to_chat(owner, "<span class='notice'>Your old wounds glow again as you invoke the [name].</span>")
|
||||
return
|
||||
if(hand_magic)
|
||||
qdel(hand_magic)
|
||||
hand_magic = null
|
||||
to_chat(owner, "<span class='warning'>You snuff out the spell with your hand, saving its power for another time.</span>")
|
||||
|
||||
|
||||
//Cult Blood Spells
|
||||
/datum/action/innate/cult/blood_spell/stun
|
||||
name = "Stun"
|
||||
desc = "A potent spell that will stun and mute victims upon contact."
|
||||
button_icon_state = "hand"
|
||||
magic_path = "/obj/item/melee/blood_magic/stun"
|
||||
health_cost = 10
|
||||
|
||||
/datum/action/innate/cult/blood_spell/teleport
|
||||
name = "Teleport"
|
||||
desc = "A useful spell that teleport cultists to a chosen destination on contact."
|
||||
button_icon_state = "tele"
|
||||
magic_path = "/obj/item/melee/blood_magic/teleport"
|
||||
health_cost = 7
|
||||
|
||||
/datum/action/innate/cult/blood_spell/emp
|
||||
name = "Electromagnetic Pulse"
|
||||
desc = "A large spell that immediately disables all electronics in the area."
|
||||
button_icon_state = "emp"
|
||||
health_cost = 10
|
||||
invocation = "Ta'gh fara'qha fel d'amar det!"
|
||||
|
||||
/datum/action/innate/cult/blood_spell/emp/Activate()
|
||||
owner.visible_message("<span class='warning'>[owner]'s hand flashes a bright blue!</span>", \
|
||||
"<span class='cultitalic'>You speak the cursed words, emitting an EMP blast from your hand.</span>")
|
||||
empulse(owner, 3, 6)
|
||||
owner.whisper(invocation, language = /datum/language/common)
|
||||
charges--
|
||||
if(charges<=0)
|
||||
qdel(src)
|
||||
|
||||
/datum/action/innate/cult/blood_spell/shackles
|
||||
name = "Shadow Shackles"
|
||||
desc = "A stealthy spell that will handcuff and temporarily silence your victim."
|
||||
button_icon_state = "cuff"
|
||||
charges = 4
|
||||
magic_path = "/obj/item/melee/blood_magic/shackles"
|
||||
|
||||
/datum/action/innate/cult/blood_spell/construction
|
||||
name = "Twisted Construction"
|
||||
desc = "<u>A sinister spell used to convert:</u><br>Plasteel into runed metal<br>25 metal into a construct shell<br>Cyborgs directly into constructs<br>Cyborg shells into construct shells<br>Airlocks into runed airlocks (harm intent)"
|
||||
button_icon_state = "transmute"
|
||||
magic_path = "/obj/item/melee/blood_magic/construction"
|
||||
|
||||
/datum/action/innate/cult/blood_spell/equipment
|
||||
name = "Summon Equipment"
|
||||
desc = "A crucial spell that enables you to summon either a ritual dagger or combat gear including armored robes, the nar'sien bola, and an eldritch longsword."
|
||||
button_icon_state = "equip"
|
||||
magic_path = "/obj/item/melee/blood_magic/armor"
|
||||
|
||||
/datum/action/innate/cult/blood_spell/equipment/Activate()
|
||||
var/choice = alert(owner,"Choose your equipment type",,"Combat Equipment","Ritual Dagger","Cancel")
|
||||
if(choice == "Ritual Dagger")
|
||||
var/turf/T = get_turf(owner)
|
||||
owner.visible_message("<span class='warning'>[owner]'s hand glows red for a moment.</span>", \
|
||||
"<span class='cultitalic'>Red light begins to shimmer and take form within your hand!</span>")
|
||||
var/obj/O = new /obj/item/melee/cultblade/dagger(T)
|
||||
if(owner.put_in_hands(O))
|
||||
to_chat(owner, "<span class='warning'>A ritual dagger appears in your hand!</span>")
|
||||
else
|
||||
owner.visible_message("<span class='warning'>A ritual dagger appears at [owner]'s feet!</span>", \
|
||||
"<span class='cultitalic'>A ritual dagger materializes at your feet.</span>")
|
||||
SEND_SOUND(owner, sound('sound/effects/magic.ogg',0,1,25))
|
||||
charges--
|
||||
desc = base_desc
|
||||
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
|
||||
if(charges<=0)
|
||||
qdel(src)
|
||||
else if(choice == "Combat Equipment")
|
||||
..()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/horror
|
||||
name = "Hallucinations"
|
||||
desc = "A <u>ranged yet stealthy</u> spell that will break the mind of the victim with nightmarish hallucinations."
|
||||
button_icon_state = "horror"
|
||||
var/obj/effect/proc_holder/horror/PH
|
||||
charges = 4
|
||||
|
||||
/datum/action/innate/cult/blood_spell/horror/New()
|
||||
PH = new()
|
||||
PH.attached_action = src
|
||||
..()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/horror/Destroy()
|
||||
var/obj/effect/proc_holder/horror/destroy = PH
|
||||
. = ..()
|
||||
if(destroy && !QDELETED(destroy))
|
||||
QDEL_NULL(destroy)
|
||||
|
||||
/datum/action/innate/cult/blood_spell/horror/Activate()
|
||||
PH.toggle(owner) //the important bit
|
||||
return TRUE
|
||||
|
||||
/obj/effect/proc_holder/horror
|
||||
active = FALSE
|
||||
ranged_mousepointer = 'icons/effects/cult_target.dmi'
|
||||
var/datum/action/innate/cult/blood_spell/attached_action
|
||||
|
||||
/obj/effect/proc_holder/horror/Destroy()
|
||||
var/datum/action/innate/cult/blood_spell/AA = attached_action
|
||||
. = ..()
|
||||
if(AA && !QDELETED(AA))
|
||||
QDEL_NULL(AA)
|
||||
|
||||
/obj/effect/proc_holder/horror/proc/toggle(mob/user)
|
||||
if(active)
|
||||
remove_ranged_ability("<span class='cult'>You dispel the magic...</span>")
|
||||
else
|
||||
add_ranged_ability(user, "<span class='cult'>You prepare to horrify a target...</span>")
|
||||
|
||||
/obj/effect/proc_holder/horror/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(..())
|
||||
return
|
||||
if(ranged_ability_user.incapacitated() || !iscultist(caller))
|
||||
remove_ranged_ability()
|
||||
return
|
||||
var/turf/T = get_turf(ranged_ability_user)
|
||||
if(!isturf(T))
|
||||
return FALSE
|
||||
if(target in view(7, get_turf(ranged_ability_user)))
|
||||
if(!ishuman(target) || iscultist(target))
|
||||
return
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.hallucination = max(H.hallucination, 240)
|
||||
SEND_SOUND(ranged_ability_user, sound('sound/effects/ghost.ogg',0,1,50))
|
||||
var/image/C = image('icons/effects/cult_effects.dmi',H,"bloodsparkles", ABOVE_MOB_LAYER)
|
||||
add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/cult, "cult_apoc", C, FALSE)
|
||||
addtimer(CALLBACK(H,/atom/.proc/remove_alt_appearance,"cult_apoc",TRUE), 2400, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
to_chat(ranged_ability_user,"<span class='cult'><b>[H] has been cursed with living nightmares!</b></span>")
|
||||
attached_action.charges--
|
||||
attached_action.desc = attached_action.base_desc
|
||||
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
|
||||
attached_action.UpdateButtonIcon()
|
||||
if(attached_action.charges <= 0)
|
||||
remove_mousepointer(ranged_ability_user.client)
|
||||
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
|
||||
qdel(src)
|
||||
|
||||
/datum/action/innate/cult/blood_spell/veiling
|
||||
name = "Conceal Presence"
|
||||
desc = "A multi-function spell that alternates between hiding and revealing nearby cult runes, structures, turf, and airlocks."
|
||||
invocation = "Kla'atu barada nikt'o!"
|
||||
button_icon_state = "gone"
|
||||
charges = 10
|
||||
var/revealing = FALSE //if it reveals or not
|
||||
|
||||
/datum/action/innate/cult/blood_spell/veiling/Activate()
|
||||
if(!revealing)
|
||||
owner.visible_message("<span class='warning'>Thin grey dust falls from [owner]'s hand!</span>", \
|
||||
"<span class='cultitalic'>You invoke the veiling spell, hiding nearby runes.</span>")
|
||||
charges--
|
||||
SEND_SOUND(owner, sound('sound/magic/smoke.ogg',0,1,25))
|
||||
owner.whisper(invocation, language = /datum/language/common)
|
||||
for(var/obj/effect/rune/R in range(5,owner))
|
||||
R.conceal()
|
||||
for(var/obj/structure/destructible/cult/S in range(5,owner))
|
||||
S.conceal()
|
||||
for(var/turf/open/floor/engine/cult/T in range(5,owner))
|
||||
T.realappearance.alpha = 0
|
||||
for(var/obj/machinery/door/airlock/cult/AL in range(5, owner))
|
||||
AL.conceal()
|
||||
revealing = TRUE
|
||||
name = "Reveal Runes"
|
||||
button_icon_state = "back"
|
||||
else
|
||||
owner.visible_message("<span class='warning'>A flash of light shines from [owner]'s hand!</span>", \
|
||||
"<span class='cultitalic'>You invoke the counterspell, revealing nearby runes.</span>")
|
||||
charges--
|
||||
owner.whisper(invocation, language = /datum/language/common)
|
||||
SEND_SOUND(owner, sound('sound/magic/enter_blood.ogg',0,1,25))
|
||||
for(var/obj/effect/rune/R in range(7,owner)) //More range in case you weren't standing in exactly the same spot
|
||||
R.reveal()
|
||||
for(var/obj/structure/destructible/cult/S in range(6,owner))
|
||||
S.reveal()
|
||||
for(var/turf/open/floor/engine/cult/T in range(6,owner))
|
||||
T.realappearance.alpha = initial(T.realappearance.alpha)
|
||||
for(var/obj/machinery/door/airlock/cult/AL in range(6, owner))
|
||||
AL.reveal()
|
||||
revealing = FALSE
|
||||
name = "Conceal Runes"
|
||||
button_icon_state = "gone"
|
||||
if(charges<= 0)
|
||||
qdel(src)
|
||||
desc = base_desc
|
||||
desc += "<br><b><u>Has [charges] use\s remaining</u></b>."
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/innate/cult/blood_spell/manipulation
|
||||
name = "Blood Rites"
|
||||
desc = "A complex spell that allows you to gather blood and use it for healing or other powerful spells."
|
||||
invocation = "Fel'th Dol Ab'orod!"
|
||||
button_icon_state = "manip"
|
||||
charges = 5
|
||||
magic_path = "/obj/item/melee/blood_magic/manipulator"
|
||||
|
||||
|
||||
// The "magic hand" items
|
||||
/obj/item/melee/blood_magic
|
||||
name = "\improper magical aura"
|
||||
desc = "Sinister looking aura that distorts the flow of reality around it."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "disintegrate"
|
||||
item_state = null
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
throwforce = 0
|
||||
throw_range = 0
|
||||
throw_speed = 0
|
||||
var/invocation
|
||||
var/uses = 1
|
||||
var/health_cost = 0 //The amount of health taken from the user when invoking the spell
|
||||
var/datum/action/innate/cult/blood_spell/source
|
||||
|
||||
/obj/item/melee/blood_magic/New(loc, spell)
|
||||
source = spell
|
||||
uses = source.charges
|
||||
health_cost = source.health_cost
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/Destroy()
|
||||
if(!QDELETED(source))
|
||||
if(uses <= 0)
|
||||
source.hand_magic = null
|
||||
qdel(source)
|
||||
source = null
|
||||
else
|
||||
source.hand_magic = null
|
||||
source.charges = uses
|
||||
source.desc = source.base_desc
|
||||
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
|
||||
source.UpdateButtonIcon()
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/attack_self(mob/living/user)
|
||||
afterattack(user, user, TRUE)
|
||||
|
||||
/obj/item/melee/blood_magic/attack(mob/living/M, mob/living/carbon/user)
|
||||
if(!iscarbon(user) || !iscultist(user))
|
||||
uses = 0
|
||||
qdel(src)
|
||||
return
|
||||
add_logs(user, M, "used a cult spell on", source.name, "")
|
||||
M.lastattacker = user.real_name
|
||||
M.lastattackerckey = user.ckey
|
||||
|
||||
/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(invocation)
|
||||
user.whisper(invocation, language = /datum/language/common)
|
||||
if(health_cost)
|
||||
if(user.active_hand_index == 1)
|
||||
user.apply_damage(health_cost, BRUTE, "l_arm")
|
||||
else
|
||||
user.apply_damage(health_cost, BRUTE, "r_arm")
|
||||
if(uses <= 0)
|
||||
qdel(src)
|
||||
else if(source)
|
||||
source.desc = source.base_desc
|
||||
source.desc += "<br><b><u>Has [uses] use\s remaining</u></b>."
|
||||
source.UpdateButtonIcon()
|
||||
|
||||
//Stun
|
||||
/obj/item/melee/blood_magic/stun
|
||||
name = "Stunning Aura "
|
||||
color = "#ff0000" // red
|
||||
invocation = "Fuu ma'jin!"
|
||||
|
||||
/obj/item/melee/blood_magic/stun/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(!isliving(target) || !proximity)
|
||||
return
|
||||
var/mob/living/L = target
|
||||
if(iscultist(target))
|
||||
return
|
||||
if(iscultist(user))
|
||||
user.visible_message("<span class='warning'>[user] holds up their hand, which explodes in a flash of red light!</span>", \
|
||||
"<span class='cultitalic'>You stun [L] with the spell!</span>")
|
||||
var/obj/item/nullrod/N = locate() in L
|
||||
if(N)
|
||||
target.visible_message("<span class='warning'>[L]'s holy weapon absorbs the light!</span>", \
|
||||
"<span class='userdanger'>Your holy weapon absorbs the blinding light!</span>")
|
||||
else
|
||||
L.Knockdown(180)
|
||||
L.flash_act(1,1)
|
||||
if(issilicon(target))
|
||||
var/mob/living/silicon/S = L
|
||||
S.emp_act(EMP_HEAVY)
|
||||
else if(iscarbon(target))
|
||||
var/mob/living/carbon/C = L
|
||||
C.silent += 6
|
||||
C.stuttering += 15
|
||||
C.cultslurring += 15
|
||||
C.Jitter(15)
|
||||
if(is_servant_of_ratvar(L))
|
||||
L.adjustBruteLoss(15)
|
||||
uses--
|
||||
..()
|
||||
|
||||
//Teleportation
|
||||
/obj/item/melee/blood_magic/teleport
|
||||
name = "Shifting Aura"
|
||||
color = RUNE_COLOR_TELEPORT
|
||||
desc = "A potent spell that teleport cultists on contact."
|
||||
invocation = "Sas'so c'arta forbici!"
|
||||
|
||||
/obj/item/melee/blood_magic/teleport/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(!iscultist(target) || !proximity)
|
||||
to_chat(user, "<span class='warning'>You can only teleport adjacent cultists with this spell!</span>")
|
||||
return
|
||||
if(iscultist(user))
|
||||
var/list/potential_runes = list()
|
||||
var/list/teleportnames = list()
|
||||
for(var/R in GLOB.teleport_runes)
|
||||
var/obj/effect/rune/teleport/T = R
|
||||
potential_runes[avoid_assoc_duplicate_keys(T.listkey, teleportnames)] = T
|
||||
|
||||
if(!potential_runes.len)
|
||||
to_chat(user, "<span class='warning'>There are no valid runes to teleport to!</span>")
|
||||
log_game("Teleport talisman failed - no other teleport runes")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(is_away_level(T.z))
|
||||
to_chat(user, "<span class='cultitalic'>You are not in the right dimension!</span>")
|
||||
log_game("Teleport spell failed - user in away mission")
|
||||
return
|
||||
|
||||
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
|
||||
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
|
||||
if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity)
|
||||
return
|
||||
var/turf/dest = get_turf(actual_selected_rune)
|
||||
if(is_blocked_turf(dest, TRUE))
|
||||
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
|
||||
return
|
||||
uses--
|
||||
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!</span>", \
|
||||
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
|
||||
var/mob/living/L = target
|
||||
L.forceMove(dest)
|
||||
dest.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
|
||||
..()
|
||||
|
||||
//Shackles
|
||||
/obj/item/melee/blood_magic/shackles
|
||||
name = "Binding Aura"
|
||||
desc = "Allows you to bind a victim and temporarily silence them."
|
||||
invocation = "In'totum Lig'abis!"
|
||||
color = "#000000" // black
|
||||
|
||||
/obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(iscultist(user) && iscarbon(target) && proximity)
|
||||
var/mob/living/carbon/C = target
|
||||
if(C.get_num_arms() >= 2 || C.get_arm_ignore())
|
||||
CuffAttack(C, user)
|
||||
else
|
||||
user.visible_message("<span class='cultitalic'>This victim doesn't have enough arms to complete the restraint!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user)
|
||||
if(!C.handcuffed)
|
||||
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
|
||||
C.visible_message("<span class='danger'>[user] begins restraining [C] with dark magic!</span>", \
|
||||
"<span class='userdanger'>[user] begins shaping a dark magic around your wrists!</span>")
|
||||
if(do_mob(user, C, 30))
|
||||
if(!C.handcuffed)
|
||||
C.handcuffed = new /obj/item/restraints/handcuffs/energy/cult/used(C)
|
||||
C.update_handcuffed()
|
||||
C.silent += 5
|
||||
to_chat(user, "<span class='notice'>You shackle [C].</span>")
|
||||
add_logs(user, C, "shackled")
|
||||
uses--
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[C] is already bound.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You fail to shackle [C].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[C] is already bound.</span>")
|
||||
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/cult //For the shackling spell
|
||||
name = "shadow shackles"
|
||||
desc = "Shackles that bind the wrists with sinister magic."
|
||||
trashtype = /obj/item/restraints/handcuffs/energy/used
|
||||
flags_1 = DROPDEL_1
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/cult/used/dropped(mob/user)
|
||||
user.visible_message("<span class='danger'>[user]'s shackles shatter in a discharge of dark magic!</span>", \
|
||||
"<span class='userdanger'>Your [src] shatters in a discharge of dark magic!</span>")
|
||||
. = ..()
|
||||
|
||||
|
||||
//Construction: Creates a construct shell out of 25 metal sheets, or converts plasteel into runed metal
|
||||
/obj/item/melee/blood_magic/construction
|
||||
name = "Corrupting Aura"
|
||||
desc = "Corrupts metal and plasteel into more sinister forms."
|
||||
invocation = "Ethra p'ni dedol!"
|
||||
color = "#000000" // black
|
||||
|
||||
/obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(proximity_flag && iscultist(user))
|
||||
var/turf/T = get_turf(target)
|
||||
if(istype(target, /obj/item/stack/sheet/metal))
|
||||
var/obj/item/stack/sheet/candidate = target
|
||||
if(candidate.use(50))
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need 50 metal to produce a construct shell!</span>")
|
||||
else if(istype(target, /obj/item/stack/sheet/plasteel))
|
||||
var/obj/item/stack/sheet/plasteel/candidate = target
|
||||
var/quantity = min(candidate.amount, uses)
|
||||
uses -= quantity
|
||||
new /obj/item/stack/sheet/runed_metal(T,quantity)
|
||||
candidate.use(quantity)
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(candidate.mmi)
|
||||
user.visible_message("<span class='danger'>A dark cloud eminates from [user]'s hand and swirls around [candidate]!</span>")
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
if(do_after(user, 90, target = candidate))
|
||||
candidate.emp_act(EMP_HEAVY)
|
||||
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
|
||||
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
|
||||
switch(construct_class)
|
||||
if("Juggernaut")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/armored, candidate, user, 0, T)
|
||||
if("Wraith")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, candidate, user, 0, T)
|
||||
if("Artificer")
|
||||
makeNewConstruct(/mob/living/simple_animal/hostile/construct/builder, candidate, user, 0, T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
uses--
|
||||
candidate.mmi = null
|
||||
qdel(candidate)
|
||||
else
|
||||
candidate.color = prev_color
|
||||
else
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else if(istype(target,/obj/machinery/door/airlock))
|
||||
target.narsie_act()
|
||||
uses--
|
||||
user.visible_message("<span class='warning'>Black ribbons suddenly eminate from [user]'s hand and cling to the airlock - twisting and corrupting it!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The spell will not work on [target]!</span>")
|
||||
..()
|
||||
|
||||
//Armor: Gives the target a basic cultist combat loadout
|
||||
/obj/item/melee/blood_magic/armor
|
||||
name = "Bladed Aura"
|
||||
desc = "A spell that will equip the target with cultist equipment if there is a slot to equip it to."
|
||||
color = "#33cc33" // green
|
||||
|
||||
/obj/item/melee/blood_magic/armor/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
if(iscarbon(target) && proximity)
|
||||
uses--
|
||||
var/mob/living/carbon/C = target
|
||||
C.visible_message("<span class='warning'>Otherworldly armor suddenly appears on [C]!</span>")
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,slot_w_uniform)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit)
|
||||
C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes)
|
||||
C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back)
|
||||
if(C == user)
|
||||
qdel(src) //Clears the hands
|
||||
C.put_in_hands(new /obj/item/melee/cultblade(user))
|
||||
C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user))
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator
|
||||
name = "Ritual Aura"
|
||||
desc = "A spell that will absorb blood from anything you touch.<br>Touching cultists and constructs can heal them.<br><b>Clicking the hand will potentially let you focus the spell into something stronger.</b>"
|
||||
color = "#7D1717"
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity)
|
||||
if(proximity)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(NOBLOOD in H.dna.species.species_traits)
|
||||
to_chat(user,"<span class='warning'>Blood rites do not work on species with no blood!</span>")
|
||||
return
|
||||
if(iscultist(H))
|
||||
if(H.stat == DEAD)
|
||||
to_chat(user,"<span class='warning'>Only a revive rune can bring back the dead!</span>")
|
||||
return
|
||||
if(H.blood_volume < BLOOD_VOLUME_SAFE)
|
||||
var/restore_blood = BLOOD_VOLUME_SAFE - H.blood_volume
|
||||
if(uses*2 < restore_blood)
|
||||
H.blood_volume += uses*2
|
||||
to_chat(user,"<span class='danger'>You use the last of your blood rites to restore what blood you could!</span>")
|
||||
uses = 0
|
||||
return ..()
|
||||
else
|
||||
H.blood_volume = BLOOD_VOLUME_SAFE
|
||||
uses -= round(restore_blood/2)
|
||||
to_chat(user,"<span class='warning'>Your blood rites have restored [H == user ? "your" : "their"] blood to safe levels!</span>")
|
||||
var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
|
||||
if(overall_damage == 0)
|
||||
to_chat(user,"<span class='cult'>That cultist doesn't require healing!</span>")
|
||||
else
|
||||
var/ratio = uses/overall_damage
|
||||
if(H == user)
|
||||
to_chat(user,"<span class='cult'><b>Your blood healing is far less efficient when used on yourself!</b></span>")
|
||||
ratio *= 0.35 // Healing is half as effective if you can't perform a full heal
|
||||
uses -= round(overall_damage) // Healing is 65% more "expensive" even if you can still perform the full heal
|
||||
if(ratio>1)
|
||||
ratio = 1
|
||||
uses -= round(overall_damage)
|
||||
H.visible_message("<span class='warning'>[H] is fully healed by [H==user ? "their":"[H]'s"]'s blood magic!</span>")
|
||||
else
|
||||
H.visible_message("<span class='warning'>[H] is partially healed by [H==user ? "their":"[H]'s"] blood magic.</span>")
|
||||
uses = 0
|
||||
ratio *= -1
|
||||
H.adjustOxyLoss((overall_damage*ratio) * (H.getOxyLoss() / overall_damage), 0)
|
||||
H.adjustToxLoss((overall_damage*ratio) * (H.getToxLoss() / overall_damage), 0)
|
||||
H.adjustFireLoss((overall_damage*ratio) * (H.getFireLoss() / overall_damage), 0)
|
||||
H.adjustBruteLoss((overall_damage*ratio) * (H.getBruteLoss() / overall_damage), 0)
|
||||
H.updatehealth()
|
||||
playsound(get_turf(H), 'sound/magic/staff_healing.ogg', 25)
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(H))
|
||||
user.Beam(H,icon_state="sendbeam",time=15)
|
||||
else
|
||||
if(H.stat == DEAD)
|
||||
to_chat(user,"<span class='warning'>Their blood has stopped flowing, you'll have to find another way to extract it.</span>")
|
||||
return
|
||||
if(H.cultslurring)
|
||||
to_chat(user,"<span class='danger'>Their blood has been tainted by an even stronger form of blood magic, it's no use to us like this!</span>")
|
||||
return
|
||||
if(H.blood_volume > BLOOD_VOLUME_SAFE)
|
||||
H.blood_volume -= 100
|
||||
uses += 50
|
||||
user.Beam(H,icon_state="drainbeam",time=10)
|
||||
playsound(get_turf(H), 'sound/magic/enter_blood.ogg', 50)
|
||||
H.visible_message("<span class='danger'>[user] has drained some of [H]'s blood!</span>")
|
||||
to_chat(user,"<span class='cultitalic'>Your blood rite gains 50 charges from draining [H]'s blood.</span>")
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(H))
|
||||
else
|
||||
to_chat(user,"<span class='danger'>They're missing too much blood - you cannot drain them further!</span>")
|
||||
return
|
||||
if(isconstruct(target))
|
||||
var/mob/living/simple_animal/M = target
|
||||
var/missing = M.maxHealth - M.health
|
||||
if(missing)
|
||||
if(uses > missing)
|
||||
M.adjustHealth(-missing)
|
||||
M.visible_message("<span class='warning'>[M] is fully healed by [user]'s blood magic!</span>")
|
||||
uses -= missing
|
||||
else
|
||||
M.adjustHealth(-uses)
|
||||
M.visible_message("<span class='warning'>[M] is partially healed by [user]'s blood magic!</span>")
|
||||
uses = 0
|
||||
playsound(get_turf(M), 'sound/magic/staff_healing.ogg', 25)
|
||||
user.Beam(M,icon_state="sendbeam",time=10)
|
||||
if(istype(target, /obj/effect/decal/cleanable/blood))
|
||||
blood_draw(target, user)
|
||||
..()
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator/proc/blood_draw(atom/target, mob/living/carbon/human/user)
|
||||
var/temp = 0
|
||||
var/turf/T = get_turf(target)
|
||||
if(T)
|
||||
for(var/obj/effect/decal/cleanable/blood/B in view(T, 2))
|
||||
if(B.blood_state == "blood")
|
||||
if(B.bloodiness == 100) //Bonus for "pristine" bloodpools, also to prevent cheese with footprint spam
|
||||
temp += 30
|
||||
else
|
||||
temp += max((B.bloodiness**2)/800,1)
|
||||
new /obj/effect/temp_visual/cult/turf/floor(get_turf(B))
|
||||
qdel(B)
|
||||
for(var/obj/effect/decal/cleanable/trail_holder/TH in view(T, 2))
|
||||
qdel(TH)
|
||||
var/obj/item/clothing/shoes/shoecheck = user.shoes
|
||||
if(shoecheck && shoecheck.bloody_shoes["blood"])
|
||||
temp += shoecheck.bloody_shoes["blood"]/20
|
||||
shoecheck.bloody_shoes["blood"] = 0
|
||||
if(temp)
|
||||
user.Beam(T,icon_state="drainbeam",time=15)
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(user))
|
||||
playsound(T, 'sound/magic/enter_blood.ogg', 50)
|
||||
to_chat(user, "<span class='cultitalic'>Your blood rite has gained [round(temp)] charge\s from blood sources around you!</span>")
|
||||
uses += max(1, round(temp))
|
||||
|
||||
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
|
||||
if(iscultist(user))
|
||||
var/list/options = list("Blood Spear (200)", "Blood Bolt Barrage (400)", "Blood Beam (600)")
|
||||
var/choice = input(user, "Choose a greater blood rite...", "Greater Blood Rites") as null|anything in options
|
||||
if(!choice)
|
||||
to_chat(user, "<span class='cultitalic'>You decide against conducting a greater blood rite.</span>")
|
||||
return
|
||||
switch(choice)
|
||||
if("Blood Spear (200)")
|
||||
if(uses < 200)
|
||||
to_chat(user, "<span class='cultitalic'>You need 200 charges to perform this rite.</span>")
|
||||
else
|
||||
uses -= 200
|
||||
var/turf/T = get_turf(user)
|
||||
qdel(src)
|
||||
var/datum/action/innate/cult/spear/S = new(user)
|
||||
var/obj/item/twohanded/cult_spear/rite = new(T)
|
||||
S.Grant(user, rite)
|
||||
rite.spear_act = S
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cultitalic'>A [rite.name] appears in your hand!</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>A [rite.name] appears at [user]'s feet!</span>", \
|
||||
"<span class='cultitalic'>A [rite.name] materializes at your feet.</span>")
|
||||
if("Blood Bolt Barrage (400)")
|
||||
if(uses < 400)
|
||||
to_chat(user, "<span class='cultitalic'>You need 400 charges to perform this rite.</span>")
|
||||
else
|
||||
var/obj/rite = new /obj/item/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/blood()
|
||||
uses -= 400
|
||||
qdel(src)
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cult'><b>Your hands glow with power!</b></span>")
|
||||
else
|
||||
to_chat(user, "<span class='cultitalic'>You need a free hand for this rite!</span>")
|
||||
qdel(rite)
|
||||
if("Blood Beam (600)")
|
||||
if(uses < 600)
|
||||
to_chat(user, "<span class='cultitalic'>You need 600 charges to perform this rite.</span>")
|
||||
else
|
||||
var/obj/rite = new /obj/item/blood_beam()
|
||||
uses -= 600
|
||||
qdel(src)
|
||||
if(user.put_in_hands(rite))
|
||||
to_chat(user, "<span class='cultlarge'><b>Your hands glow with POWER OVERWHELMING!!!</b></span>")
|
||||
else
|
||||
to_chat(user, "<span class='cultitalic'>You need a free hand for this rite!</span>")
|
||||
qdel(rite)
|
||||
@@ -123,9 +123,11 @@
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cult italic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
|
||||
var/choice
|
||||
if(user.mind.has_antag_datum(/datum/antagonist/cult/master))
|
||||
choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword")
|
||||
else
|
||||
choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
|
||||
var/list/pickedtype = list()
|
||||
switch(choice)
|
||||
if("Shielded Robe")
|
||||
|
||||
@@ -125,16 +125,15 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(L.stat)
|
||||
continue
|
||||
invokers += L
|
||||
if(invokers.len >= req_cultists)
|
||||
invokers -= user
|
||||
if(allow_excess_invokers)
|
||||
chanters += invokers
|
||||
else
|
||||
shuffle_inplace(invokers)
|
||||
for(var/i in 1 to req_cultists)
|
||||
var/L = pick_n_take(invokers)
|
||||
if(L)
|
||||
chanters += L
|
||||
var/C = pick_n_take(invokers)
|
||||
if(!C)
|
||||
break
|
||||
chanters += C
|
||||
return chanters
|
||||
|
||||
/obj/effect/rune/proc/invoke(var/list/invokers)
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
adj = "objectiveless"
|
||||
else
|
||||
return
|
||||
new_owner.assigned_role = "Space Ninja"
|
||||
new_owner.special_role = "Space Ninja"
|
||||
new_owner.assigned_role = ROLE_NINJA
|
||||
new_owner.special_role = ROLE_NINJA
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has [adj] ninja'ed [new_owner.current].")
|
||||
log_admin("[key_name(admin)] has [adj] ninja'ed [new_owner.current].")
|
||||
|
||||
@@ -115,9 +115,8 @@
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_INTACT)
|
||||
if(istype(I, /obj/item/screwdriver/nuke))
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
to_chat(user, "<span class='notice'>You start removing [src]'s front panel's screws...</span>")
|
||||
if(do_after(user, 60*I.toolspeed,target=src))
|
||||
if(I.use_tool(src, user, 60, volume=100))
|
||||
deconstruction_state = NUKESTATE_UNSCREWED
|
||||
to_chat(user, "<span class='notice'>You remove the screws from [src]'s front panel.</span>")
|
||||
update_icon()
|
||||
@@ -125,14 +124,13 @@
|
||||
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
if(istype(I, /obj/item/weldingtool))
|
||||
var/obj/item/weldingtool/welder = I
|
||||
playsound(loc, I.usesound, 100, 1)
|
||||
if(!I.tool_start_check(user, amount=1))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start cutting [src]'s inner plate...</span>")
|
||||
if(welder.remove_fuel(1,user))
|
||||
if(do_after(user,80*I.toolspeed,target=src))
|
||||
to_chat(user, "<span class='notice'>You cut [src]'s inner plate.</span>")
|
||||
deconstruction_state = NUKESTATE_WELDED
|
||||
update_icon()
|
||||
if(I.use_tool(src, user, 80, volume=100, amount=1))
|
||||
to_chat(user, "<span class='notice'>You cut [src]'s inner plate.</span>")
|
||||
deconstruction_state = NUKESTATE_WELDED
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
if(istype(I, /obj/item/nuke_core_container))
|
||||
@@ -148,19 +146,15 @@
|
||||
to_chat(user, "<span class='warning'>You fail to load the plutonium core into [core_box]. [core_box] has already been used!</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/stack/sheet/metal))
|
||||
var/obj/item/stack/sheet/metal/M = I
|
||||
if(M.amount >= 20)
|
||||
to_chat(user, "<span class='notice'>You begin repairing [src]'s inner metal plate...</span>")
|
||||
if(do_after(user, 100, target=src))
|
||||
if(M.use(20))
|
||||
to_chat(user, "<span class='notice'>You repair [src]'s inner metal plate. The radiation is contained.</span>")
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need more metal to do that!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need more metal to do that!</span>")
|
||||
if(!I.tool_start_check(user, amount=20))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin repairing [src]'s inner metal plate...</span>")
|
||||
if(I.use_tool(src, user, 100, amount=20))
|
||||
to_chat(user, "<span class='notice'>You repair [src]'s inner metal plate. The radiation is contained.</span>")
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_icon()
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -169,16 +163,14 @@
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
to_chat(user, "<span class='notice'>You start removing [src]'s front panel...</span>")
|
||||
playsound(loc, tool.usesound, 100, 1)
|
||||
if(do_after(user, 30 * tool.toolspeed, target = src))
|
||||
if(tool.use_tool(src, user, 30, volume=100))
|
||||
to_chat(user, "<span class='notice'>You remove [src]'s front panel.</span>")
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
update_icon()
|
||||
return TRUE
|
||||
if(NUKESTATE_WELDED)
|
||||
to_chat(user, "<span class='notice'>You start prying off [src]'s inner plate...</span>")
|
||||
playsound(loc, tool.usesound, 100, 1)
|
||||
if(do_after(user, 50 * tool.toolspeed, target = src))
|
||||
if(tool.use_tool(src, user, 30, volume=100))
|
||||
to_chat(user, "<span class='notice'>You pry off [src]'s inner plate. You can see the core's green glow!</span>")
|
||||
deconstruction_state = NUKESTATE_CORE_EXPOSED
|
||||
update_icon()
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
nuke_team = new_team
|
||||
|
||||
/datum/antagonist/nukeop/admin_add(datum/mind/new_owner,mob/admin)
|
||||
new_owner.assigned_role = "Syndicate"
|
||||
new_owner.assigned_role = ROLE_SYNDICATE
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has nuke op'ed [new_owner.current].")
|
||||
log_admin("[key_name(admin)] has nuke op'ed [new_owner.current].")
|
||||
|
||||
@@ -224,7 +224,6 @@
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
revealed = FALSE
|
||||
ghostize(0)//Don't re-enter invisible corpse
|
||||
SSshuttle.shuttle_purchase_requirements_met |= "revenant"
|
||||
|
||||
|
||||
//reveal, stun, icon updates, cast checks, and essence changing
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
carbon_mob.flash_act(1, 1)
|
||||
rev_mind.current.Stun(100)
|
||||
rev_mind.add_antag_datum(/datum/antagonist/rev,rev_team)
|
||||
rev_mind.special_role = "Revolutionary"
|
||||
rev_mind.special_role = ROLE_REV
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/rev/head/proc/demote()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
var/should_specialise = TRUE //do we split into AI and human, set to true on inital assignment only
|
||||
var/ai_datum = /datum/antagonist/traitor/AI
|
||||
var/human_datum = /datum/antagonist/traitor/human
|
||||
var/special_role = "traitor"
|
||||
var/special_role = ROLE_TRAITOR
|
||||
var/employer = "The Syndicate"
|
||||
var/give_objectives = TRUE
|
||||
var/should_give_codewords = TRUE
|
||||
@@ -85,7 +85,9 @@
|
||||
return
|
||||
|
||||
/datum/antagonist/traitor/human/forge_traitor_objectives()
|
||||
var/is_hijacker = prob(10)
|
||||
var/is_hijacker = FALSE
|
||||
if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
|
||||
is_hijacker = prob(10)
|
||||
var/martyr_chance = prob(20)
|
||||
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
|
||||
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
//Apprenticeship contract - moved to antag_spawner.dm
|
||||
|
||||
///////////////////////////Veil Render//////////////////////
|
||||
|
||||
@@ -156,12 +156,12 @@
|
||||
/datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard
|
||||
M.faction |= "wizard"
|
||||
M.faction |= ROLE_WIZARD
|
||||
|
||||
/datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_wiz_icons_removed(M)
|
||||
M.faction -= "wizard"
|
||||
M.faction -= ROLE_WIZARD
|
||||
|
||||
|
||||
/datum/antagonist/wizard/get_admin_commands()
|
||||
|
||||
Reference in New Issue
Block a user