From aa04e62b29ded391048d23ddd454430548fd1de5 Mon Sep 17 00:00:00 2001 From: Poojawa Date: Wed, 31 Jan 2018 08:07:22 -0600 Subject: [PATCH] cult lol xd --- code/game/alternate_appearance.dm | 28 +- code/game/gamemodes/cult/blood_magic.dm | 767 ++++++++++++++++++++++ code/game/gamemodes/extended/extended.dm | 3 - code/game/gamemodes/game_mode.dm | 9 +- code/game/gamemodes/meteor/meteors.dm | 12 +- code/game/gamemodes/traitor/traitor.dm | 4 + code/modules/antagonists/cult/supply.dm | 123 ---- code/modules/antagonists/cult/talisman.dm | 346 ---------- tgstation.dme | 5 +- 9 files changed, 812 insertions(+), 485 deletions(-) create mode 100644 code/game/gamemodes/cult/blood_magic.dm delete mode 100644 code/modules/antagonists/cult/supply.dm delete mode 100644 code/modules/antagonists/cult/talisman.dm diff --git a/code/game/alternate_appearance.dm b/code/game/alternate_appearance.dm index 1a62a0fd5f..484f11fc09 100644 --- a/code/game/alternate_appearance.dm +++ b/code/game/alternate_appearance.dm @@ -125,6 +125,32 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) /datum/atom_hud/alternate_appearance/basic/observers/mobShouldSee(mob/M) return isobserver(M) +/datum/atom_hud/alternate_appearance/basic/noncult + +/datum/atom_hud/alternate_appearance/basic/noncult/New() + ..() + for(var/mob in GLOB.player_list) + if(mobShouldSee(mob)) + add_hud_to(mob) + +/datum/atom_hud/alternate_appearance/basic/noncult/mobShouldSee(mob/M) + if(!iscultist(M)) + return TRUE + return FALSE + +/datum/atom_hud/alternate_appearance/basic/cult + +/datum/atom_hud/alternate_appearance/basic/cult/New() + ..() + for(var/mob in GLOB.player_list) + if(mobShouldSee(mob)) + add_hud_to(mob) + +/datum/atom_hud/alternate_appearance/basic/cult/mobShouldSee(mob/M) + if(iscultist(M)) + return TRUE + return FALSE + /datum/atom_hud/alternate_appearance/basic/blessedAware /datum/atom_hud/alternate_appearance/basic/blessedAware/New() @@ -140,4 +166,4 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances) return TRUE if(isrevenant(M) || iseminence(M) || iswizard(M)) return TRUE - return FALSE \ No newline at end of file + return FALSE diff --git a/code/game/gamemodes/cult/blood_magic.dm b/code/game/gamemodes/cult/blood_magic.dm new file mode 100644 index 0000000000..04b56c9f7d --- /dev/null +++ b/code/game/gamemodes/cult/blood_magic.dm @@ -0,0 +1,767 @@ +/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 empowering rune" + 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" + button.locked = TRUE + +/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() + for(var/datum/action/innate/cult/blood_spell/B in spells) + var/pos = -29+spells.Find(B)*31 + B.button.screen_loc = "6:[pos],4:-2" + B.button.moved = B.button.screen_loc + B.button.locked = TRUE + +/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, "Your body has reached its limit, you cannot store more than [MAX_BLOODCHARGE] spells at once. Pick a spell to nullify.") + else + to_chat(owner, "Your body has reached its limit, you cannot have more than [RUNELESS_MAX_BLOODCHARGE] spells at once without an empowering rune! Pick a spell to nullify.") + 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,"You begin to carve unnatural symbols into your flesh!") + SEND_SOUND(owner, sound('sound/weapons/slice.ogg',0,1,10)) + if(!channeling) + channeling = TRUE + else + to_chat(owner, "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, "Your wounds glows with power, you have prepared a [new_spell.name] invocation!") + 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 += "
Deals [health_cost] damage to your arm per use." + base_desc = desc + desc += "
Has [charges] use\s remaining." + all_magic = BM + ..() + +/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, "You have no empty hand for invoking blood magic!") + return + to_chat(owner, "Your old wounds glow again as you invoke the [name].") + return + if(hand_magic) + qdel(hand_magic) + hand_magic = null + to_chat(owner, "You snuff out the spell with your hand, saving its power for another time.") + + +//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("[owner]'s hand flashes a bright blue!", \ + "You speak the cursed words, emitting an EMP blast from your hand.") + 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 = "A sinister spell used to convert:
Plasteel into runed metal
25 metal into a construct shell
Cyborgs directly into constructs
Cyborg shells into construct shells
Airlocks into runed airlocks (harm intent)" + button_icon_state = "transmute" + charges = 50 + 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" + charges = 1 + +/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("[owner]'s hand glows red for a moment.", \ + "Red light begins to shimmer and take form within your hand!") + var/obj/O = new /obj/item/melee/cultblade/dagger(T) + if(owner.put_in_hands(O)) + to_chat(owner, "A ritual dagger appears in your hand!") + else + owner.visible_message("A ritual dagger appears at [owner]'s feet!", \ + "A ritual dagger materializes at your feet.") + SEND_SOUND(owner, sound('sound/effects/magic.ogg',0,1,25)) + charges-- + desc = base_desc + desc += "
Has [charges] use\s remaining." + if(charges<=0) + qdel(src) + else if(choice == "Combat Equipment") + ..() + +/datum/action/innate/cult/blood_spell/horror + name = "Hallucinations" + desc = "A ranged yet stealthy 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("You dispel the magic...") + else + add_ranged_ability(user, "You prepare to horrify a target...") + +/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,"[H] has been cursed with living nightmares!") + attached_action.charges-- + attached_action.desc = attached_action.base_desc + attached_action.desc += "
Has [attached_action.charges] use\s remaining." + attached_action.UpdateButtonIcon() + if(attached_action.charges <= 0) + remove_mousepointer(ranged_ability_user.client) + remove_ranged_ability("You have exhausted the spell's power!") + qdel(src) + +/datum/action/innate/cult/blood_spell/veiling + name = "Conceal Runes" + desc = "A multi-function spell that alternates between hiding and revealing nearby runes." + 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("Thin grey dust falls from [owner]'s hand!", \ + "You invoke the veiling spell, hiding nearby runes.") + 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 + revealing = TRUE + name = "Reveal Runes" + button_icon_state = "back" + else + owner.visible_message("A flash of light shines from [owner]'s hand!", \ + "You invoke the counterspell, revealing nearby runes.") + 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(7,owner)) + S.reveal() + for(var/turf/open/floor/engine/cult/T in range(7,owner)) + T.realappearance.alpha = initial(T.realappearance.alpha) + revealing = FALSE + name = "Conceal Runes" + button_icon_state = "gone" + if(charges<= 0) + qdel(src) + desc = base_desc + desc += "
Has [charges] use\s remaining." + 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 += "
Has [uses] use\s remaining." + 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 += "
Has [uses] use\s remaining." + source.UpdateButtonIcon() + +//Stun +/obj/item/melee/blood_magic/stun + 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("[user] holds up their hand, which explodes in a flash of red light!", \ + "You stun [L] with the spell!") + var/obj/item/nullrod/N = locate() in L + if(N) + target.visible_message("[L]'s holy weapon absorbs the light!", \ + "Your holy weapon absorbs the blinding light!") + 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 + 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, "You can only teleport adjacent cultists with this spell!") + 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, "There are no valid runes to teleport to!") + 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, "You are not in the right dimension!") + 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, "The target rune is blocked. Attempting to teleport to it would be massively unwise.") + return + uses-- + user.visible_message("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!", \ + "You speak the words of the talisman and find yourself somewhere else!", "You hear a sharp crack.") + var/mob/living/L = target + L.forceMove(dest) + dest.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") + ..() + +//Shackles +/obj/item/melee/blood_magic/shackles + name = "Shadow Shackles" + 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("This victim doesn't have enough arms to complete the restraint!") + 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("[user] begins restraining [C] with dark magic!", \ + "[user] begins shaping a dark magic around your wrists!") + 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, "You shackle [C].") + add_logs(user, C, "shackled") + uses-- + else + to_chat(user, "[C] is already bound.") + else + to_chat(user, "You fail to shackle [C].") + else + to_chat(user, "[C] is already bound.") + + +/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("[user]'s shackles shatter in a discharge of dark magic!", \ + "Your [src] shatters in a discharge of dark magic!") + . = ..() + + +//Construction: Creates a construct shell out of 25 metal sheets, or converts plasteel into runed metal +/obj/item/melee/blood_magic/construction + name = "Twisted Construction" + 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(25)) + uses-=25 + to_chat(user, "A dark cloud eminates from your hand and swirls around the metal, twisting it into a construct shell!") + new /obj/structure/constructshell(T) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + else + to_chat(user, "You need more metal to produce a construct shell!") + 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, "A dark cloud eminates from you hand and swirls around the plasteel, transforming it into runed metal!") + 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("A dark cloud eminates from [user]'s hand and swirls around [candidate]!") + 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("The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!") + 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 -= 50 + candidate.mmi = null + qdel(candidate) + else + candidate.color = prev_color + else + uses -= 50 + to_chat(user, "A dark cloud eminates from you hand and swirls around [candidate] - twisting it into a construct shell!") + 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 -= 50 + user.visible_message("Black ribbons suddenly eminate from [user]'s hand and cling to the airlock - twisting and corrupting it!") + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + else + to_chat(user, "The spell will not work on [target]!") + ..() + +//Armor: Gives the target a basic cultist combat loadout +/obj/item/melee/blood_magic/armor + name = "Sinister Armaments" + 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("Otherworldly armor suddenly appears on [C]!") + 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 = "Blood Rite" + desc = "A spell that will absorb blood from anything you touch.
Touching cultists and constructs can heal them.
Clicking the hand will potentially let you focus the spell into something stronger." + 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,"Blood rites do not work on species with no blood!") + return + if(iscultist(H)) + if(H.stat == DEAD) + to_chat(user,"Only a revive rune can bring back the dead!") + 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,"You use the last of your blood rites to restore what blood you could!") + uses = 0 + return ..() + else + H.blood_volume = BLOOD_VOLUME_SAFE + uses -= round(restore_blood/2) + to_chat(user,"Your blood rites have restored [H == user ? "your" : "their"] blood to safe levels!") + var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss() + if(overall_damage == 0) + to_chat(user,"That cultist doesn't require healing!") + else + var/ratio = uses/overall_damage + if(H == user) + to_chat(user,"Your blood healing is far less efficient when used on yourself!") + 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("[H] is fully healed by [H==user ? "their":"[H]'s"]'s blood magic!") + else + H.visible_message("[H] is partially healed by [H==user ? "their":"[H]'s"] blood magic.") + 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,"Their blood has stopped flowing, you'll have to find another way to extract it.") + return + if(H.cultslurring) + to_chat(user,"Their blood has been tainted by an even stronger form of blood magic, it's no use to us like this!") + 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("[user] has drained some of [H]'s blood!") + to_chat(user,"Your blood rite gains 50 charges from draining [H]'s blood.") + new /obj/effect/temp_visual/cult/sparks(get_turf(H)) + else + to_chat(user,"They're missing too much blood - you cannot drain them further!") + 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("[M] is fully-healed by [user]'s blood magic!") + uses -= missing + else + M.adjustHealth(-uses) + M.visible_message("[M] is healed by [user]'sblood magic!") + 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,0.5) + 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, "Your blood rite has gained [round(temp)] charge\s from blood sources around you!") + uses += 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, "You decide against conducting a greater blood rite.") + return + switch(choice) + if("Blood Spear (200)") + if(uses < 200) + to_chat(user, "You need 200 charges to perform this rite.") + 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, "A [rite.name] appears in your hand!") + else + user.visible_message("A [rite.name] appears at [user]'s feet!", \ + "A [rite.name] materializes at your feet.") + if("Blood Bolt Barrage (400)") + if(uses < 400) + to_chat(user, "You need 400 charges to perform this rite.") + 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, "Your hands glow with power!") + else + to_chat(user, "You need a free hand for this rite!") + qdel(rite) + if("Blood Beam (600)") + if(uses < 600) + to_chat(user, "You need 600 charges to perform this rite.") + else + var/obj/rite = new /obj/item/blood_beam() + uses -= 600 + qdel(src) + if(user.put_in_hands(rite)) + to_chat(user, "Your hands glow with POWER OVERWHELMING!!!") + else + to_chat(user, "You need a free hand for this rite!") + qdel(rite) diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 72e8b472ed..ac55cb526d 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -10,9 +10,6 @@ /datum/game_mode/extended/pre_setup() return 1 -/datum/game_mode/extended/post_setup() - ..() - /datum/game_mode/extended/generate_report() return "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift." diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index a0e5a9f147..f708e3f4b1 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -46,6 +46,8 @@ var/allow_persistence_save = TRUE + var/gamemode_ready = FALSE //Is the gamemode all set up and ready to start checking for ending conditions. + /datum/game_mode/proc/announce() //Shows the gamemode's name and a fast description. to_chat(world, "The gamemode is: [name]!") to_chat(world, "[announce_text]") @@ -94,6 +96,7 @@ if(report) addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h)) generate_station_goals() + gamemode_ready = TRUE return 1 @@ -161,8 +164,10 @@ replacementmode.restricted_jobs += "Assistant" message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit stop the creation of antags or end the round now.") - + log_game("Roundtype converted to [replacementmode.name]") + . = 1 + sleep(rand(600,1800)) if(!SSticker.IsRoundInProgress()) message_admins("Roundtype conversion cancelled, the game appears to have finished!") @@ -189,7 +194,7 @@ /datum/game_mode/proc/check_finished(force_ending) //to be called by SSticker - if(!SSticker.setup_done) + if(!SSticker.setup_done || !gamemode_ready) return FALSE if(replacementmode && round_converted == 2) return replacementmode.check_finished() diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 13ab7a8bb1..d0c6cde8b9 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -284,7 +284,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event var/meteorgibs = /obj/effect/gibspawner/generic threat = 2 -/obj/effect/meteor/meaty/New() +/obj/effect/meteor/meaty/Initialize() for(var/path in meteordrop) if(path == /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant) meteordrop -= path @@ -294,7 +294,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event if(path == /obj/item/organ/tongue) meteordrop -= path meteordrop += pick(typesof(path)) - ..() + return ..() /obj/effect/meteor/meaty/make_debris() ..() @@ -315,9 +315,9 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event meteordrop = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno, /obj/item/organ/tongue/alien) meteorgibs = /obj/effect/gibspawner/xeno -/obj/effect/meteor/meaty/xeno/New() +/obj/effect/meteor/meaty/xeno/Initialize() meteordrop += subtypesof(/obj/item/organ/alien) - ..() + return ..() /obj/effect/meteor/meaty/xeno/ram_turf(turf/T) if(!isspaceturf(T)) @@ -366,8 +366,8 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin)) meteordrop = list(/obj/item/clothing/head/hardhat/pumpkinhead, /obj/item/reagent_containers/food/snacks/grown/pumpkin) threat = 100 -/obj/effect/meteor/pumpkin/New() - ..() +/obj/effect/meteor/pumpkin/Initialize() + . = ..() meteorsound = pick('sound/hallucinations/im_here1.ogg','sound/hallucinations/im_here2.ogg') ////////////////////////// #undef DEFAULT_METEOR_LIFETIME diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index ca2ce431b1..47c1b403bc 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -66,6 +66,10 @@ if(!exchange_blue) exchange_blue = -1 //Block latejoiners from getting exchange objectives ..() + + //We're not actually ready until all traitors are assigned. + gamemode_ready = FALSE + addtimer(VARSET_CALLBACK(src, gamemode_ready, TRUE), 101) return TRUE /datum/game_mode/traitor/make_antag_chance(mob/living/carbon/human/character) //Assigns traitor to latejoiners diff --git a/code/modules/antagonists/cult/supply.dm b/code/modules/antagonists/cult/supply.dm deleted file mode 100644 index 3720e496ea..0000000000 --- a/code/modules/antagonists/cult/supply.dm +++ /dev/null @@ -1,123 +0,0 @@ -//Supply Talisman: Has a few unique effects. Granted only to starter cultists. -/obj/item/paper/talisman/supply - cultist_name = "Supply Talisman" - cultist_desc = "A multi-use talisman that can create various objects. Intended to increase the cult's strength early on." - invocation = null - uses = 3 - var/list/possible_summons = list( - /datum/cult_supply/tome, - /datum/cult_supply/metal, - /datum/cult_supply/talisman/teleport, - /datum/cult_supply/talisman/emp, - /datum/cult_supply/talisman/stun, - /datum/cult_supply/talisman/veil, - /datum/cult_supply/soulstone, - /datum/cult_supply/construct_shell - ) - -/obj/item/paper/talisman/supply/invoke(mob/living/user, successfuluse = 1) - var/list/dat = list() - dat += "There are [uses] bloody runes on the parchment.
" - dat += "Please choose the chant to be imbued into the fabric of reality.
" - dat += "
" - for(var/s in possible_summons) - var/datum/cult_supply/S = s - dat += "[initial(S.invocation)] - [initial(S.desc)]
" - var/datum/browser/popup = new(user, "talisman", "", 400, 400) - popup.set_content(dat.Join("")) - popup.open() - return 0 - -/obj/item/paper/talisman/supply/Topic(href, href_list) - if(QDELETED(src) || usr.incapacitated() || !in_range(src, usr)) - return - - var/id = href_list["id"] - var/datum/cult_supply/match - - for(var/s in possible_summons) - var/datum/cult_supply/S = s - if(initial(S.id) == id) - match = S - break - - if(!match) - to_chat(usr, "The fabric of reality quivers in agony.") - return - - var/turf/T = get_turf(src) - var/summon_type = initial(match.summon_type) - - - var/atom/movable/AM = new summon_type(T) - if(istype(AM, /obj/item)) - usr.put_in_hands(AM) - - uses-- - if(uses <= 0) - to_chat(usr, "[src] crumbles to dust.") - burn() - -/obj/item/paper/talisman/supply/weak - cultist_name = "Lesser Supply Talisman" - uses = 2 - -/obj/item/paper/talisman/supply/weak/Initialize(mapload) - . = ..() - // no runed metal from lesser talismans. - possible_summons -= /datum/cult_supply/metal - -/datum/cult_supply - var/id = "used_popcorn" - var/invocation = "Pla'ceho'lder." - var/desc = "Summons a generic supply item, to aid the cult." - var/summon_type = /obj/item/trash/popcorn // wait this isn't useful - -/datum/cult_supply/tome - id = "arcane_tome" - invocation = "N'ath reth sh'yro eth d'raggathnor!" - desc = "Summons an arcane tome, used to scribe runes." - summon_type = /obj/item/tome - -/datum/cult_supply/metal - id = "runed_metal" - invocation = "Bar'tea eas!" - desc = "Provides 5 runed metal, which can build a variety of cult structures." - summon_type = /obj/item/stack/sheet/runed_metal/five - -/datum/cult_supply/talisman/teleport - id = "teleport_talisman" - invocation = "Sas'so c'arta forbici!" - desc = "Allows you to move to a selected teleportation rune." - summon_type = /obj/item/paper/talisman/teleport - -/datum/cult_supply/talisman/emp - id = "emp_talisman" - invocation = "Ta'gh fara'qha fel d'amar det!" - desc = "Allows you to destroy technology in a short range." - summon_type = /obj/item/paper/talisman/emp - -/datum/cult_supply/talisman/stun - id = "stun_talisman" - invocation = "Fuu ma'jin!" - desc = "Allows you to stun a person by attacking them with the talisman. Does not work on people holding a holy weapon!" - summon_type = /obj/item/paper/talisman/stun - -/datum/cult_supply/talisman/veil - id = "veil_talisman" - invocation = "Kla'atu barada nikt'o!" - desc = "Two use talisman, first use makes all nearby runes invisible, secnd use reveals nearby hidden runes." - summon_type = /obj/item/paper/talisman/true_sight - -/datum/cult_supply/soulstone - id = "soulstone" - invocation = "Kal'om neth!" - desc = "Summons a soul stone, used to capture the spirits of dead or dying humans." - summon_type = /obj/item/device/soulstone - -/datum/cult_supply/construct_shell - id = "construct_shell" - invocation = "Daa'ig osk!" - desc = "Summons a construct shell for use with soulstone-captured souls. It is too large to carry on your person." - summon_type = /obj/structure/constructshell - diff --git a/code/modules/antagonists/cult/talisman.dm b/code/modules/antagonists/cult/talisman.dm deleted file mode 100644 index 588b45d5f6..0000000000 --- a/code/modules/antagonists/cult/talisman.dm +++ /dev/null @@ -1,346 +0,0 @@ -/obj/item/paper/talisman - var/cultist_name = "talisman" - var/cultist_desc = "A basic talisman. It serves no purpose." - var/invocation = "Naise meam!" - var/uses = 1 - var/health_cost = 0 //The amount of health taken from the user when invoking the talisman - var/creation_time = 100 //how long it takes an imbue rune to make this type of talisman - -/obj/item/paper/talisman/examine(mob/user) - if(iscultist(user) || user.stat == DEAD) - to_chat(user, "Name: [cultist_name]") - to_chat(user, "Effect: [cultist_desc]") - to_chat(user, "Uses Remaining: [uses]") - else - to_chat(user, "There are indecipherable images scrawled on the paper in what looks to be... blood?") - -/obj/item/paper/talisman/attack_self(mob/living/user) - if(!iscultist(user)) - to_chat(user, "There are indecipherable images scrawled on the paper in what looks to be... blood?") - return - if(invoke(user)) - uses-- - if(uses <= 0) - qdel(src) - -/obj/item/paper/talisman/proc/invoke(mob/living/user, successfuluse = 1) - . = successfuluse - if(successfuluse) //if the calling whatever says we succeed, do the fancy stuff - if(invocation) - user.whisper(invocation, language = /datum/language/common) - if(health_cost && iscarbon(user)) - var/mob/living/carbon/C = user - C.apply_damage(health_cost, BRUTE, pick("l_arm", "r_arm")) - -//Malformed Talisman: If something goes wrong. -/obj/item/paper/talisman/malformed - cultist_name = "malformed talisman" - cultist_desc = "A talisman with gibberish scrawlings. No good can come from invoking this." - invocation = "Ra'sha yoka!" - -/obj/item/paper/talisman/malformed/invoke(mob/living/user, successfuluse = 1) - to_chat(user, "You feel a pain in your head. The Geometer is displeased.") - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.apply_damage(10, BRUTE, "head") - -//Rite of Translocation: Same as rune -/obj/item/paper/talisman/teleport - cultist_name = "Talisman of Teleportation" - cultist_desc = "A single-use talisman that will teleport a user to a random rune of the same keyword." - color = RUNE_COLOR_TELEPORT - invocation = "Sas'so c'arta forbici!" - health_cost = 5 - creation_time = 80 - -/obj/item/paper/talisman/teleport/invoke(mob/living/user, successfuluse = 1) - 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, "There are no valid runes to teleport to!") - log_game("Teleport talisman failed - no other teleport runes") - return ..(user, 0) - - if(is_away_level(user.z)) - to_chat(user, "You are not in the right dimension!") - log_game("Teleport talisman failed - user in away mission") - return ..(user, 0) - - 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(!src || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune) - return ..(user, 0) - var/turf/target = get_turf(actual_selected_rune) - if(is_blocked_turf(target, TRUE)) - to_chat(user, "The target rune is blocked. Attempting to teleport to it would be massively unwise.") - return ..(user, 0) - user.visible_message("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!", \ - "You speak the words of the talisman and find yourself somewhere else!", "You hear a sharp crack.") - user.forceMove(target) - target.visible_message("There is a boom of outrushing air as something appears above the rune!", null, "You hear a boom.") - return ..() - - -/obj/item/paper/talisman/summon_tome - cultist_name = "Talisman of Tome Summoning" - cultist_desc = "A one-use talisman that will call an untranslated tome from the archives of the Geometer." - color = "#512727" // red-black - invocation = "N'ath reth sh'yro eth d'raggathnor!" - health_cost = 1 - creation_time = 30 - -/obj/item/paper/talisman/summon_tome/invoke(mob/living/user, successfuluse = 1) - . = ..() - user.visible_message("[user]'s hand glows red for a moment.", \ - "You speak the words of the talisman!") - new /obj/item/tome(get_turf(user)) - user.visible_message("A tome appears at [user]'s feet!", \ - "An arcane tome materializes at your feet.") - -/obj/item/paper/talisman/true_sight - cultist_name = "Talisman of Veiling" - cultist_desc = "A multi-use talisman that hides nearby runes. On its second use, will reveal nearby runes." - color = "#9c9c9c" // grey - invocation = "Kla'atu barada nikt'o!" - health_cost = 1 - creation_time = 30 - uses = 6 - var/revealing = FALSE //if it reveals or not - -/obj/item/paper/talisman/true_sight/invoke(mob/living/user, successfuluse = 1) - . = ..() - if(!revealing) - user.visible_message("Thin grey dust falls from [user]'s hand!", \ - "You speak the words of the talisman, hiding nearby runes.") - invocation = "Nikt'o barada kla'atu!" - revealing = TRUE - for(var/obj/effect/rune/R in range(4,user)) - R.talismanhide() - else - user.visible_message("A flash of light shines from [user]'s hand!", \ - "You speak the words of the talisman, revealing nearby runes.") - for(var/obj/effect/rune/R in range(3,user)) - R.talismanreveal() - -//Rite of Disruption: Weaker than rune -/obj/item/paper/talisman/emp - cultist_name = "Talisman of Electromagnetic Pulse" - cultist_desc = "A talisman that will cause a moderately-sized electromagnetic pulse." - color = "#4d94ff" // light blue - invocation = "Ta'gh fara'qha fel d'amar det!" - health_cost = 5 - -/obj/item/paper/talisman/emp/invoke(mob/living/user, successfuluse = 1) - . = ..() - user.visible_message("[user]'s hand flashes a bright blue!", \ - "You speak the words of the talisman, emitting an EMP blast.") - empulse(src, 4, 8) - - -//Rite of Disorientation: Stuns and inhibit speech on a single target for quite some time -/obj/item/paper/talisman/stun - cultist_name = "Talisman of Stunning" - cultist_desc = "A talisman that will stun and inhibit speech on a single target. To use, attack target directly." - color = "#ff0000" // red - invocation = "Fuu ma'jin!" - health_cost = 10 - -/obj/item/paper/talisman/stun/invoke(mob/living/user, successfuluse = 0) - if(successfuluse) //if we're forced to be successful(we normally aren't) then do the normal stuff - return ..() - if(iscultist(user)) - to_chat(user, "To use this talisman, attack the target directly.") - else - to_chat(user, "There are indecipherable images scrawled on the paper in what looks to be... blood?") - return 0 - -/obj/item/paper/talisman/stun/attack(mob/living/target, mob/living/user, successfuluse = 1) - if(iscultist(user)) - invoke(user, 1) - user.visible_message("[user] holds up [src], which explodes in a flash of red light!", \ - "You stun [target] with the talisman!") - var/obj/item/nullrod/N = locate() in target - if(N) - target.visible_message("[target]'s holy weapon absorbs the talisman's light!", \ - "Your holy weapon absorbs the blinding light!") - else - target.Knockdown(200) - target.flash_act(1,1) - if(issilicon(target)) - var/mob/living/silicon/S = target - S.emp_act(EMP_HEAVY) - else if(iscarbon(target)) - var/mob/living/carbon/C = target - C.silent += 5 - C.stuttering += 15 - C.cultslurring += 15 - C.Jitter(15) - if(is_servant_of_ratvar(target)) - target.adjustBruteLoss(15) - qdel(src) - return - ..() - - -//Rite of Arming: Equips cultist armor on the user, where available -/obj/item/paper/talisman/armor - cultist_name = "Talisman of Arming" - cultist_desc = "A talisman that will equip the invoker with cultist equipment if there is a slot to equip it to." - color = "#33cc33" // green - invocation = "N'ath reth sh'yro eth draggathnor!" - creation_time = 80 - -/obj/item/paper/talisman/armor/invoke(mob/living/user, successfuluse = 1) - . = ..() - user.visible_message("Otherworldly armor suddenly appears on [user]!", \ - "You speak the words of the talisman, arming yourself!") - user.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(user), slot_head) - user.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(user), slot_wear_suit) - user.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), slot_shoes) - user.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), slot_back) - user.dropItemToGround(src) - user.put_in_hands(new /obj/item/melee/cultblade(user)) - user.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user)) - -/obj/item/paper/talisman/armor/attack(mob/living/target, mob/living/user) - if(iscultist(user) && iscultist(target)) - user.temporarilyRemoveItemFromInventory(src) - invoke(target) - qdel(src) - return - ..() - - -//Talisman of Horrors: Breaks the mind of the victim with nightmarish hallucinations -/obj/item/paper/talisman/horror - cultist_name = "Talisman of Horrors" - cultist_desc = "A talisman that will break the mind of the victim with nightmarish hallucinations." - color = "#ffb366" // light orange - invocation = "Lo'Nab Na'Dm!" - creation_time = 80 - -/obj/item/paper/talisman/horror/afterattack(mob/living/target, mob/living/user) - if(iscultist(user) && (get_dist(user, target) < 7)) - if(iscarbon(target)) - to_chat(user, "You disturb [target] with visions of madness!") - var/mob/living/carbon/H = target - H.reagents.add_reagent("mindbreaker", 12) - if(is_servant_of_ratvar(target)) - to_chat(target, "You see a brief but horrible vision of Ratvar, rusted and scrapped, being torn apart.") - target.emote("scream") - target.confused = max(0, target.confused + 3) - target.flash_act() - qdel(src) - -//Talisman of Fabrication: Creates a construct shell out of 25 metal sheets, or converts plasteel into runed metal up to 25 times -/obj/item/paper/talisman/construction - cultist_name = "Talisman of Construction" - cultist_desc = "Use this talisman on at least twenty-five metal sheets to create an empty construct shell" - invocation = "Ethra p'ni dedol!" - color = "#000000" // black - uses = 25 - creation_time = 80 - -/obj/item/paper/talisman/construction/attack_self(mob/living/user) - if(iscultist(user)) - to_chat(user, "To use this talisman, place it upon a stack of metal sheets.") - else - to_chat(user, "There are indecipherable images scrawled on the paper in what looks to be... blood?") - - -/obj/item/paper/talisman/construction/attack(obj/M,mob/living/user) - if(iscultist(user)) - to_chat(user, "This talisman will only work on a stack of metal or plasteel sheets!") - log_game("Construct talisman failed - not a valid target") - else - ..() - -/obj/item/paper/talisman/construction/afterattack(obj/item/stack/sheet/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)) - if(target.use(25)) - new /obj/structure/constructshell(T) - to_chat(user, "The talisman clings to the metal and twists it into a construct shell!") - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - invoke(user, 1) - qdel(src) - else - to_chat(user, "You need more metal to produce a construct shell!") - else if(istype(target, /obj/item/stack/sheet/plasteel)) - var/quantity = min(target.amount, uses) - uses -= quantity - new /obj/item/stack/sheet/runed_metal(T,quantity) - target.use(quantity) - to_chat(user, "The talisman clings to the plasteel, transforming it into runed metal!") - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - invoke(user, 1) - if(uses <= 0) - qdel(src) - else - to_chat(user, "The talisman must be used on metal or plasteel!") - - -//Talisman of Shackling: Applies special cuffs directly from the talisman -/obj/item/paper/talisman/shackle - cultist_name = "Talisman of Shackling" - cultist_desc = "Use this talisman on a victim to handcuff them with dark bindings." - invocation = "In'totum Lig'abis!" - color = "#B27300" // burnt-orange - uses = 6 - -/obj/item/paper/talisman/shackle/invoke(mob/living/user, successfuluse = 0) - if(successfuluse) //if we're forced to be successful(we normally aren't) then do the normal stuff - return ..() - if(iscultist(user)) - to_chat(user, "To use this talisman, attack the target directly.") - else - to_chat(user, "There are indecipherable images scrawled on the paper in what looks to be... blood?") - return 0 - -/obj/item/paper/talisman/shackle/attack(mob/living/carbon/target, mob/living/user) - if(iscultist(user) && istype(target)) - if(target.stat == DEAD) - user.visible_message("This talisman's magic does not affect the dead!") - return - CuffAttack(target, user) - return - ..() - -/obj/item/paper/talisman/shackle/proc/CuffAttack(mob/living/carbon/C, mob/living/user) - if(!C.handcuffed) - invoke(user, 1) - playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2) - C.visible_message("[user] begins restraining [C] with dark magic!", \ - "[user] begins shaping a dark magic around your wrists!") - if(do_mob(user, C, 30)) - if(!C.handcuffed) - C.handcuffed = new /obj/item/restraints/handcuffs/energy/cult/used(C) - C.update_handcuffed() - to_chat(user, "You shackle [C].") - add_logs(user, C, "handcuffed") - uses-- - else - to_chat(user, "[C] is already bound.") - else - to_chat(user, "You fail to shackle [C].") - else - to_chat(user, "[C] is already bound.") - if(uses <= 0) - qdel(src) - -/obj/item/restraints/handcuffs/energy/cult //For the talisman of shackling - name = "cult 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("[user]'s shackles shatter in a discharge of dark magic!", \ - "Your [src] shatters in a discharge of dark magic!") - . = ..() diff --git a/tgstation.dme b/tgstation.dme index 4bee6bf99f..0db2e71eef 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -487,8 +487,6 @@ #include "code\game\area\areas\ruins\lavaland.dm" #include "code\game\area\areas\ruins\space.dm" #include "code\game\area\areas\ruins\templates.dm" -#include "code\game\gamemodes\antag_spawner_cit.dm" -#include "code\game\gamemodes\cit_objectives.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\game_mode.dm" #include "code\game\gamemodes\objective.dm" @@ -497,6 +495,7 @@ #include "code\game\gamemodes\changeling\changeling.dm" #include "code\game\gamemodes\changeling\traitor_chan.dm" #include "code\game\gamemodes\clock_cult\clock_cult.dm" +#include "code\game\gamemodes\cult\blood_magic.dm" #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\devil\devil_game_mode.dm" #include "code\game\gamemodes\devil\game_mode.dm" @@ -1198,8 +1197,6 @@ #include "code\modules\antagonists\cult\ritual.dm" #include "code\modules\antagonists\cult\rune_spawn_action.dm" #include "code\modules\antagonists\cult\runes.dm" -#include "code\modules\antagonists\cult\supply.dm" -#include "code\modules\antagonists\cult\talisman.dm" #include "code\modules\antagonists\devil\devil.dm" #include "code\modules\antagonists\devil\devil_helpers.dm" #include "code\modules\antagonists\devil\imp\imp.dm"