[MIRROR] Cultist pets (#26983)

* Cultist pets (#80595)

## About The Pull Request
cultists can now convert pets on their side. when you convert a pet, it
will become much more dangerous and obedient to you, it will also gain a
new dangerous AI. cultist pets will look for fellow dead cultists, and
revive them by dragging them to nearby revival runes and activating it.
if there is no revival runes around them then they will create their own
and drag u to it. u can give them commands to follow, attack, or to
create revival runes. they will also go around to crit non cultists so
cultists can convert them

![pughealed](https://github.com/tgstation/tgstation/assets/138636438/8cd10a4f-2a30-40d9-b4fb-c9ff70bdcddd)

they will also now feed on organs and blood for healing

## Why It's Good For The Game
adds a extra layer to cult, u can now command non-sentient pets to aid
you

## Changelog
🆑
add: cultists can now convert pets to their side
/🆑

---------

Co-authored-by: san7890 <the@san7890.com>

* Yeah...

---------

Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: Useroth <37159550+Useroth@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-04-03 23:44:23 +02:00
committed by GitHub
co-authored by san7890 Ben10Omintrix Useroth
parent e1c64ec3e7
commit 4fa0479c83
42 changed files with 604 additions and 179 deletions
+14
View File
@@ -51,6 +51,20 @@
/// key that holds items we arent interested in hoarding
#define BB_IGNORE_ITEMS "ignore_items"
// Cultist pet keys
///our ability to summon runes
#define BB_RUNE_ABILITY "rune_ability"
///the cult team we serve
#define BB_CULT_TEAM "cult_team"
///our dead cultist we revive
#define BB_DEAD_CULTIST "dead_cultist"
///nearby runes
#define BB_NEARBY_RUNE "nearby_rune"
///occupied runes
#define BB_OCCUPIED_RUNE "occupied_rune"
///friendly cultists we befriend
#define BB_FRIENDLY_CULTIST "friendly_cultist"
//virtual pet keys
///the last PDA message we must relay
#define BB_LAST_RECIEVED_MESSAGE "last_recieved_message"
+2
View File
@@ -219,6 +219,8 @@ GLOBAL_LIST_INIT(ai_employers, list(
/// Checks if the given mob is a blood cultist
#define IS_CULTIST(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/cult))
/// Checks if the mob is a sentient or non-sentient cultist
#define IS_CULTIST_OR_CULTIST_MOB(mob) ((IS_CULTIST(mob)) || (mob.faction.Find(FACTION_CULT)))
/// Checks if the given mob is a changeling
#define IS_CHANGELING(mob) (mob?.mind?.has_antag_datum(/datum/antagonist/changeling))
+6
View File
@@ -36,6 +36,12 @@
/// The global Nar'sie that the cult's summoned
GLOBAL_DATUM(cult_narsie, /obj/narsie)
///how many sacrifices we have used, cultists get 1 free revive at the start
GLOBAL_VAR_INIT(sacrifices_used, -SOULS_TO_REVIVE)
/// list of weakrefs to mobs OR minds that have been sacrificed
GLOBAL_LIST(sacrificed)
// Used in determining which cinematic to play when cult ends
#define CULT_VICTORY_MASS_CONVERSION 2
#define CULT_FAILURE_NARSIE_KILLED 1
+4 -4
View File
@@ -38,10 +38,10 @@
#define span_command_headset(str) ("<span class='command_headset'>" + str + "</span>")
#define span_comradio(str) ("<span class='comradio'>" + str + "</span>")
#define span_cult(str) ("<span class='cult'>" + str + "</span>")
#define span_cultbold(str) ("<span class='cultbold'>" + str + "</span>")
#define span_cultboldtalic(str) ("<span class='cultboldtalic'>" + str + "</span>")
#define span_cultitalic(str) ("<span class='cultitalic'>" + str + "</span>")
#define span_cultlarge(str) ("<span class='cultlarge'>" + str + "</span>")
#define span_cult_bold(str) ("<span class='cult_bold'>" + str + "</span>")
#define span_cult_bold_italic(str) ("<span class='cult_bold_italic'>" + str + "</span>")
#define span_cult_italic(str) ("<span class='cult_italic'>" + str + "</span>")
#define span_cult_large(str) ("<span class='cult_large'>" + str + "</span>")
#define span_danger(str) ("<span class='danger'>" + str + "</span>")
#define span_deadsay(str) ("<span class='deadsay'>" + str + "</span>")
#define span_deconversion_message(str) ("<span class='deconversion_message'>" + str + "</span>")
+2
View File
@@ -1090,6 +1090,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait which self-identifies as an enemy of the law
#define TRAIT_ALWAYS_WANTED "always_wanted"
/// Trait given to mobs that have the basic eating element
#define TRAIT_MOB_EATER "mob_eater"
/// Trait which means whatever has this is dancing by a dance machine
#define TRAIT_DISCO_DANCER "disco_dancer"
+1
View File
@@ -295,6 +295,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_MINDSHIELD" = TRAIT_MINDSHIELD,
"TRAIT_MIND_TEMPORARILY_GONE" = TRAIT_MIND_TEMPORARILY_GONE,
"TRAIT_MOB_BREEDER" = TRAIT_MOB_BREEDER,
"TRAIT_MOB_EATER" = TRAIT_MOB_EATER,
"TRAIT_MOB_TIPPED" = TRAIT_MOB_TIPPED,
"TRAIT_MORBID" = TRAIT_MORBID,
"TRAIT_MULTIZ_SUIT_SENSORS" = TRAIT_MULTIZ_SUIT_SENSORS,
@@ -0,0 +1,25 @@
/datum/ai_behavior/pull_target
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION | AI_BEHAVIOR_REQUIRE_REACH
/datum/ai_behavior/pull_target/setup(datum/ai_controller/controller, target_key)
. = ..()
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return FALSE
set_movement_target(controller, target)
/datum/ai_behavior/pull_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/atom/movable/target = controller.blackboard[target_key]
if(QDELETED(target) || target.anchored || target.pulledby)
finish_action(controller, FALSE, target_key)
return
var/mob/living/our_mob = controller.pawn
our_mob.start_pulling(target)
finish_action(controller, TRUE, target_key)
/datum/ai_behavior/pull_target/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
if(!succeeded)
controller.clear_blackboard_key(target_key)
+3 -3
View File
@@ -283,13 +283,13 @@
return FALSE
if(ispath(rune_to_scribe, /obj/effect/rune/summon) && (!is_station_level(our_turf.z) || istype(get_area(cultist), /area/space)))
to_chat(cultist, span_cultitalic("The veil is not weak enough here to summon a cultist, you must be on station!"))
to_chat(cultist, span_cult_italic("The veil is not weak enough here to summon a cultist, you must be on station!"))
return
if(ispath(rune_to_scribe, /obj/effect/rune/apocalypse))
if((world.time - SSticker.round_start_time) <= 6000)
var/wait = 6000 - (world.time - SSticker.round_start_time)
to_chat(cultist, span_cultitalic("The veil is not yet weak enough for this rune - it will be available in [DisplayTimeText(wait)]."))
to_chat(cultist, span_cult_italic("The veil is not yet weak enough for this rune - it will be available in [DisplayTimeText(wait)]."))
return
if(!check_if_in_ritual_site(cultist, user_team, TRUE))
return
@@ -359,7 +359,7 @@
to_chat(cultist, span_warning("The sacrifice is not complete. The portal would lack the power to open if you tried!"))
return FALSE
if(summon_objective.check_completion())
to_chat(cultist, span_cultlarge("\"I am already here. There is no need to try to summon me now.\""))
to_chat(cultist, span_cult_large("\"I am already here. There is no need to try to summon me now.\""))
return FALSE
var/confirm_final = tgui_alert(cultist, "This is the FINAL step to summon Nar'Sie; it is a long, painful ritual and the crew will be alerted to your presence.", "Are you prepared for the final battle?", list("My life for Nar'Sie!", "No"))
if(confirm_final == "No")
+2
View File
@@ -23,6 +23,7 @@
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
ADD_TRAIT(target, TRAIT_MOB_EATER, REF(src))
src.heal_amt = heal_amt
src.damage_amount = damage_amount
src.damage_type = damage_type
@@ -35,6 +36,7 @@
RegisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attackingtarget))
/datum/element/basic_eating/Detach(datum/target)
REMOVE_TRAIT(target, TRAIT_MOB_EATER, REF(src))
UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET))
return ..()
@@ -8,7 +8,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 4 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Pylon: Heals and regenerates the blood of nearby blood cultists and constructs, and also \
desc = span_cult_bold("Pylon: Heals and regenerates the blood of nearby blood cultists and constructs, and also \
converts nearby floor tiles into engraved flooring, which allows blood cultists to scribe runes faster."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
@@ -20,7 +20,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 4 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Altar: Can make Eldritch Whetstones, Construct Shells, and Flasks of Unholy Water."), \
desc = span_cult_bold("Altar: Can make Eldritch Whetstones, Construct Shells, and Flasks of Unholy Water."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
), \
@@ -31,7 +31,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 4 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Archives: Can make Zealot's Blindfolds, Shuttle Curse Orbs, \
desc = span_cult_bold("Archives: Can make Zealot's Blindfolds, Shuttle Curse Orbs, \
and Veil Walker equipment. Emits Light."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
@@ -43,7 +43,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 4 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Daemon Forge: Can make Nar'Sien Hardened Armor, Flagellant's Robes, \
desc = span_cult_bold("Daemon Forge: Can make Nar'Sien Hardened Armor, Flagellant's Robes, \
and Eldritch Longswords. Emits Light."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
@@ -54,7 +54,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 5 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Runed Door: A weak door which stuns non-blood cultists who touch it."), \
desc = span_cult_bold("Runed Door: A weak door which stuns non-blood cultists who touch it."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
), \
@@ -64,7 +64,7 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list( \
time = 5 SECONDS, \
one_per_turf = TRUE, \
on_solid_ground = TRUE, \
desc = span_cultbold("Runed Girder: A weak girder that can be instantly destroyed by ritual daggers. Not a recommended usage of runed metal."), \
desc = span_cult_bold("Runed Girder: A weak girder that can be instantly destroyed by ritual daggers. Not a recommended usage of runed metal."), \
required_noun = "runed metal sheet", \
category = CAT_CULT, \
), \
+26 -26
View File
@@ -46,9 +46,9 @@
limit = MAX_BLOODCHARGE
if(length(spells) >= limit)
if(rune)
to_chat(owner, span_cultitalic("You cannot store more than [MAX_BLOODCHARGE] spells. <b>Pick a spell to remove.</b>"))
to_chat(owner, span_cult_italic("You cannot store more than [MAX_BLOODCHARGE] spells. <b>Pick a spell to remove.</b>"))
else
to_chat(owner, span_cultitalic("<b><u>You cannot store more than [RUNELESS_MAX_BLOODCHARGE] spells without an empowering rune! Pick a spell to remove.</b></u>"))
to_chat(owner, span_cult_bold_italic("<u>You cannot store more than [RUNELESS_MAX_BLOODCHARGE] spells without an empowering rune! Pick a spell to remove.</u>"))
var/nullify_spell = tgui_input_list(owner, "Spell to remove", "Current Spells", spells)
if(isnull(nullify_spell))
return
@@ -77,7 +77,7 @@
if(!channeling)
channeling = TRUE
else
to_chat(owner, span_cultitalic("You are already invoking blood magic!"))
to_chat(owner, span_cult_italic("You are already invoking blood magic!"))
return
if(do_after(owner, 100 - rune*60, target = owner))
if(ishuman(owner))
@@ -167,7 +167,7 @@
/datum/action/innate/cult/blood_spell/emp/Activate()
owner.whisper(invocation, language = /datum/language/common)
owner.visible_message(span_warning("[owner]'s hand flashes a bright blue!"), \
span_cultitalic("You speak the cursed words, emitting an EMP blast from your hand."))
span_cult_italic("You speak the cursed words, emitting an EMP blast from your hand."))
empulse(owner, 2, 5)
charges--
if(charges <= 0)
@@ -205,13 +205,13 @@
var/turf/owner_turf = get_turf(owner)
owner.whisper(invocation, language = /datum/language/common)
owner.visible_message(span_warning("[owner]'s hand glows red for a moment."), \
span_cultitalic("Your plea for aid is answered, and light begins to shimmer and take form within your hand!"))
span_cult_italic("Your plea for aid is answered, and light begins to shimmer and take form within your hand!"))
var/obj/item/summoned_blade = new summoned_type(owner_turf)
if(owner.put_in_hands(summoned_blade))
to_chat(owner, span_warning("A [summoned_blade] appears in your hand!"))
else
owner.visible_message(span_warning("A [summoned_blade] appears at [owner]'s feet!"), \
span_cultitalic("A [summoned_blade] materializes at your feet."))
span_cult_italic("A [summoned_blade] materializes at your feet."))
SEND_SOUND(owner, sound('sound/effects/magic.ogg', FALSE, 0, 25))
charges--
if(charges <= 0)
@@ -249,7 +249,7 @@
clicked_on.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/cult, "cult_apoc", sparkle_image, NONE)
addtimer(CALLBACK(clicked_on, TYPE_PROC_REF(/atom/, remove_alt_appearance), "cult_apoc", TRUE), 4 MINUTES, TIMER_OVERRIDE|TIMER_UNIQUE)
to_chat(caller, span_cultbold("[clicked_on] has been cursed with living nightmares!"))
to_chat(caller, span_cult_bold("[clicked_on] has been cursed with living nightmares!"))
charges--
desc = base_desc
@@ -272,7 +272,7 @@
/datum/action/innate/cult/blood_spell/veiling/Activate()
if(!revealing)
owner.visible_message(span_warning("Thin grey dust falls from [owner]'s hand!"), \
span_cultitalic("You invoke the veiling spell, hiding nearby runes."))
span_cult_italic("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)
@@ -291,7 +291,7 @@
button_icon_state = "back"
else
owner.visible_message(span_warning("A flash of light shines from [owner]'s hand!"), \
span_cultitalic("You invoke the counterspell, revealing nearby runes."))
span_cult_italic("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))
@@ -404,7 +404,7 @@
return
if(IS_CULTIST(user))
user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \
span_cultitalic("You attempt to stun [target] with the spell!"))
span_cult_italic("You attempt to stun [target] with the spell!"))
user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS)
if(IS_HERETIC(target))
to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!"))
@@ -425,7 +425,7 @@
else if(target.can_block_magic())
to_chat(user, span_warning("The spell had no effect!"))
else
to_chat(user, span_cultitalic("In a brilliant flash of red, [target] falls to the ground!"))
to_chat(user, span_cult_italic("In a brilliant flash of red, [target] falls to the ground!"))
target.Paralyze(16 SECONDS)
target.flash_act(1, TRUE)
if(issilicon(target))
@@ -464,7 +464,7 @@
var/turf/T = get_turf(src)
if(is_away_level(T.z))
to_chat(user, span_cultitalic("You are not in the right dimension!"))
to_chat(user, span_cult_italic("You are not in the right dimension!"))
return
var/input_rune_key = tgui_input_list(user, "Rune to teleport to", "Teleportation Target", potential_runes) //we know what key they picked
@@ -485,7 +485,7 @@
var/mob/living/L = target
if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT))
origin.visible_message(span_warning("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!"), \
span_cultitalic("You speak the words of the talisman and find yourself somewhere else!"), "<i>You hear a sharp crack.</i>")
span_cult_italic("You speak the words of the talisman and find yourself somewhere else!"), "<i>You hear a sharp crack.</i>")
dest.visible_message(span_warning("There is a boom of outrushing air as something appears above the rune!"), null, "<i>You hear a boom.</i>")
..()
@@ -502,7 +502,7 @@
if(C.canBeHandcuffed())
CuffAttack(C, user)
else
user.visible_message(span_cultitalic("This victim doesn't have enough arms to complete the restraint!"))
user.visible_message(span_cult_italic("This victim doesn't have enough arms to complete the restraint!"))
return
..()
@@ -560,7 +560,7 @@
/obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(proximity_flag && IS_CULTIST(user))
if(channeling)
to_chat(user, span_cultitalic("You are already invoking twisted construction!"))
to_chat(user, span_cult_italic("You are already invoking twisted construction!"))
return
. |= AFTERATTACK_PROCESSED_ITEM
var/turf/T = get_turf(target)
@@ -743,7 +743,7 @@
user.Beam(human_bloodbag, icon_state="drainbeam", time = 1 SECONDS)
playsound(get_turf(human_bloodbag), 'sound/magic/enter_blood.ogg', 50)
human_bloodbag.visible_message(span_danger("[user] drains some of [human_bloodbag]'s blood!"))
to_chat(user,span_cultitalic("Your blood rite gains 50 charges from draining [human_bloodbag]'s blood."))
to_chat(user,span_cult_italic("Your blood rite gains 50 charges from draining [human_bloodbag]'s blood."))
new /obj/effect/temp_visual/cult/sparks(get_turf(human_bloodbag))
else
to_chat(user,span_warning("[human_bloodbag.p_Theyre()] missing too much blood - you cannot drain [human_bloodbag.p_them()] further!"))
@@ -787,7 +787,7 @@
user.Beam(our_turf,icon_state="drainbeam", time = 15)
new /obj/effect/temp_visual/cult/sparks(get_turf(user))
playsound(our_turf, 'sound/magic/enter_blood.ogg', 50)
to_chat(user, span_cultitalic("Your blood rite has gained [round(blood_to_gain)] charge\s from blood sources around you!"))
to_chat(user, span_cult_italic("Your blood rite has gained [round(blood_to_gain)] charge\s from blood sources around you!"))
uses += max(1, round(blood_to_gain))
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
@@ -799,12 +799,12 @@
)
var/choice = show_radial_menu(user, src, spells, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE)
if(!check_menu(user))
to_chat(user, span_cultitalic("You decide against conducting a greater blood rite."))
to_chat(user, span_cult_italic("You decide against conducting a greater blood rite."))
return
switch(choice)
if("Bloody Halberd (150)")
if(uses < BLOOD_HALBERD_COST)
to_chat(user, span_cultitalic("You need [BLOOD_HALBERD_COST] charges to perform this rite."))
to_chat(user, span_cult_italic("You need [BLOOD_HALBERD_COST] charges to perform this rite."))
else
uses -= BLOOD_HALBERD_COST
var/turf/current_position = get_turf(user)
@@ -814,13 +814,13 @@
halberd_act_granted.Grant(user, rite)
rite.halberd_act = halberd_act_granted
if(user.put_in_hands(rite))
to_chat(user, span_cultitalic("A [rite.name] appears in your hand!"))
to_chat(user, span_cult_italic("A [rite.name] appears in your hand!"))
else
user.visible_message(span_warning("A [rite.name] appears at [user]'s feet!"), \
span_cultitalic("A [rite.name] materializes at your feet."))
span_cult_italic("A [rite.name] materializes at your feet."))
if("Blood Bolt Barrage (300)")
if(uses < BLOOD_BARRAGE_COST)
to_chat(user, span_cultitalic("You need [BLOOD_BARRAGE_COST] charges to perform this rite."))
to_chat(user, span_cult_italic("You need [BLOOD_BARRAGE_COST] charges to perform this rite."))
else
var/obj/rite = new /obj/item/gun/magic/wand/arcane_barrage/blood()
uses -= BLOOD_BARRAGE_COST
@@ -828,19 +828,19 @@
if(user.put_in_hands(rite))
to_chat(user, span_cult("<b>Your hands glow with power!</b>"))
else
to_chat(user, span_cultitalic("You need a free hand for this rite!"))
to_chat(user, span_cult_italic("You need a free hand for this rite!"))
qdel(rite)
if("Blood Beam (500)")
if(uses < BLOOD_BEAM_COST)
to_chat(user, span_cultitalic("You need [BLOOD_BEAM_COST] charges to perform this rite."))
to_chat(user, span_cult_italic("You need [BLOOD_BEAM_COST] charges to perform this rite."))
else
var/obj/rite = new /obj/item/blood_beam()
uses -= BLOOD_BEAM_COST
qdel(src)
if(user.put_in_hands(rite))
to_chat(user, span_cultlarge("<b>Your hands glow with POWER OVERWHELMING!!!</b>"))
to_chat(user, span_cult_large("<b>Your hands glow with POWER OVERWHELMING!!!</b>"))
else
to_chat(user, span_cultitalic("You need a free hand for this rite!"))
to_chat(user, span_cult_italic("You need a free hand for this rite!"))
qdel(rite)
/obj/item/melee/blood_magic/manipulator/proc/check_menu(mob/living/user)
+4 -4
View File
@@ -202,10 +202,10 @@
for(var/datum/mind/cult_mind as anything in cult_team.members)
var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(/datum/antagonist/cult)
cult_datum.vote_ability.Remove(cult_mind.current)
to_chat(cult_mind.current, span_cultlarge("[owner.current] has won the cult's support and is now their master. \
to_chat(cult_mind.current, span_cult_large("[owner.current] has won the cult's support and is now their master. \
Follow [owner.current.p_their()] orders to the best of your ability!"))
to_chat(owner.current, span_cultlarge("<span class='warningplain'>You are the cult's Master</span>. \
to_chat(owner.current, span_cult_large("<span class='warningplain'>You are the cult's Master</span>. \
As the cult's Master, you have a unique title and loud voice when communicating, are capable of marking \
targets, such as a location or a noncultist, to direct the cult to them, and, finally, you are capable of \
summoning the entire living cult to your location <b><i>once</i></b>. Use these abilities to direct the cult \
@@ -238,7 +238,7 @@
var/datum/antagonist/cult/cult_datum = cult_mind.has_antag_datum(/datum/antagonist/cult)
cult_datum.vote_ability.Grant(cult_mind.current)
to_chat(owner.current, span_cultlarge("You have been demoted from being the cult's Master, you are now an acolyte once more!"))
to_chat(owner.current, span_cult_large("You have been demoted from being the cult's Master, you are now an acolyte once more!"))
return TRUE
@@ -256,7 +256,7 @@
var/area/current_area = get_area(owner.current)
for(var/datum/mind/cult_mind as anything in cult_team.members)
SEND_SOUND(cult_mind, sound('sound/hallucinations/veryfar_noise.ogg'))
to_chat(cult_mind, span_cultlarge("The Cult's Master, [owner.current.name], has fallen in \the [current_area]!"))
to_chat(cult_mind, span_cult_large("The Cult's Master, [owner.current.name], has fallen in \the [current_area]!"))
/datum/antagonist/cult/get_preview_icon()
var/icon/icon = render_preview_outfit(preview_outfit)
@@ -77,7 +77,7 @@
force = 5
return
else
to_chat(user, span_cultlarge("\"You cling to the Forgotten Gods, as if you're more than their pawn.\""))
to_chat(user, span_cult_large("\"You cling to the Forgotten Gods, as if you're more than their pawn.\""))
to_chat(user, span_userdanger("A horrible force yanks at your arm!"))
user.emote("scream")
user.apply_damage(30, BRUTE, pick(GLOB.arm_zones))
+14 -14
View File
@@ -81,7 +81,7 @@
var/my_message
if(!message)
return
my_message = span_cultboldtalic("The [user.name]: [message]")
my_message = span_cult_bold_italic("The [user.name]: [message]")
for(var/mob/player_list as anything in GLOB.player_list)
if(IS_CULTIST(player_list))
to_chat(player_list, my_message)
@@ -123,7 +123,7 @@
if(team_member.current.incapacitated())
continue
SEND_SOUND(team_member.current, 'sound/hallucinations/im_here1.ogg')
to_chat(team_member.current, span_cultlarge("Acolyte [nominee] has asserted that [nominee.p_theyre()] worthy of leading the cult. A vote will be called shortly."))
to_chat(team_member.current, span_cult_large("Acolyte [nominee] has asserted that [nominee.p_theyre()] worthy of leading the cult. A vote will be called shortly."))
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(poll_cultists_for_leader), nominee, team), 10 SECONDS)
@@ -137,7 +137,7 @@
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has died in the process of attempting to start a vote!"))
to_chat(team_member.current,span_cult_large("[nominee] has died in the process of attempting to start a vote!"))
return FALSE
var/list/mob/living/asked_cultists = list()
for(var/datum/mind/team_member as anything in team.members)
@@ -169,7 +169,7 @@
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has died in the process of attempting to win the cult's support!"))
to_chat(team_member.current,span_cult_large("[nominee] has died in the process of attempting to win the cult's support!"))
return FALSE
if(!nominee.mind)
team.cult_vote_called = FALSE
@@ -179,7 +179,7 @@
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current,span_cultlarge("[nominee] has gone catatonic in the process of attempting to win the cult's support!"))
to_chat(team_member.current,span_cult_large("[nominee] has gone catatonic in the process of attempting to win the cult's support!"))
return FALSE
if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5)
team.cult_vote_called = FALSE
@@ -189,7 +189,7 @@
team_member.current.update_mob_action_buttons()
if(team_member.current.incapacitated())
continue
to_chat(team_member.current, span_cultlarge("[nominee] could not win the cult's support and shall continue to serve as an acolyte."))
to_chat(team_member.current, span_cult_large("[nominee] could not win the cult's support and shall continue to serve as an acolyte."))
return FALSE
team.cult_vote_called = FALSE
@@ -218,7 +218,7 @@
var/place = get_area(owner)
var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives
if(place in summon_objective.summon_spots)//cant do final reckoning in the summon area to prevent abuse, you'll need to get everyone to stand on the circle!
to_chat(owner, span_cultlarge("The veil is too weak here! Move to an area where it is strong enough to support this magic."))
to_chat(owner, span_cult_large("The veil is too weak here! Move to an area where it is strong enough to support this magic."))
return
for(var/i in 1 to 4)
chant(i)
@@ -353,14 +353,14 @@
if(cult_team.blood_target)
if(!COOLDOWN_FINISHED(src, cult_mark_cooldown))
cult_team.unset_blood_target_and_timer()
to_chat(owner, span_cultbold("You have cleared the cult's blood target!"))
to_chat(owner, span_cult_bold("You have cleared the cult's blood target!"))
return TRUE
to_chat(owner, span_cultbold("The cult has already designated a target!"))
to_chat(owner, span_cult_bold("The cult has already designated a target!"))
return FALSE
if(!COOLDOWN_FINISHED(src, cult_mark_cooldown))
to_chat(owner, span_cultbold("You aren't ready to place another blood mark yet!"))
to_chat(owner, span_cult_bold("You aren't ready to place another blood mark yet!"))
return FALSE
var/atom/mark_target = owner.orbiting?.parent || get_turf(owner)
@@ -368,7 +368,7 @@
return FALSE
if(cult_team.set_blood_target(mark_target, owner, 60 SECONDS))
to_chat(owner, span_cultbold("You have marked [mark_target] for the cult! It will last for [DisplayTimeText(cult_mark_duration)]."))
to_chat(owner, span_cult_bold("You have marked [mark_target] for the cult! It will last for [DisplayTimeText(cult_mark_duration)]."))
COOLDOWN_START(src, cult_mark_cooldown, cult_mark_cooldown_duration)
build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON)
addtimer(CALLBACK(src, PROC_REF(reset_button)), cult_mark_cooldown_duration + 1)
@@ -400,7 +400,7 @@
return
SEND_SOUND(owner, 'sound/magic/enter_blood.ogg')
to_chat(owner, span_cultbold("Your previous mark is gone - you are now ready to create a new blood mark."))
to_chat(owner, span_cult_bold("Your previous mark is gone - you are now ready to create a new blood mark."))
build_all_button_icons(UPDATE_BUTTON_NAME|UPDATE_BUTTON_ICON)
//////// ELDRITCH PULSE /////////
@@ -489,12 +489,12 @@
if(!IS_CULTIST(living_clicked))
return FALSE
SEND_SOUND(caller, sound('sound/weapons/thudswoosh.ogg'))
to_chat(caller, span_cultbold("You reach through the veil with your mind's eye and seize [clicked_on]! <b>Click anywhere nearby to teleport [clicked_on.p_them()]!</b>"))
to_chat(caller, span_cult_bold("You reach through the veil with your mind's eye and seize [clicked_on]! <b>Click anywhere nearby to teleport [clicked_on.p_them()]!</b>"))
throwee_ref = WEAKREF(clicked_on)
return TRUE
if(istype(clicked_on, /obj/structure/destructible/cult))
to_chat(caller, span_cultbold("You reach through the veil with your mind's eye and lift [clicked_on]! <b>Click anywhere nearby to teleport it!</b>"))
to_chat(caller, span_cult_bold("You reach through the veil with your mind's eye and lift [clicked_on]! <b>Click anywhere nearby to teleport it!</b>"))
throwee_ref = WEAKREF(clicked_on)
return TRUE
+6 -6
View File
@@ -97,7 +97,7 @@ Striking a noncultist, however, will tear their flesh."}
user.Paralyze(100)
user.dropItemToGround(src, TRUE)
user.visible_message(span_warning("A powerful force shoves [user] away from [target]!"), \
span_cultlarge("\"You shouldn't play with sharp things. You'll poke someone's eye out.\""))
span_cult_large("\"You shouldn't play with sharp things. You'll poke someone's eye out.\""))
if(ishuman(user))
var/mob/living/carbon/human/miscreant = user
miscreant.apply_damage(rand(force/2, force), BRUTE, pick(GLOB.arm_zones))
@@ -121,7 +121,7 @@ Striking a noncultist, however, will tear their flesh."}
/obj/item/melee/cultblade/pickup(mob/living/user)
..()
if(!IS_CULTIST(user))
to_chat(user, span_cultlarge("\"I wouldn't advise that.\""))
to_chat(user, span_cult_large("\"I wouldn't advise that.\""))
/datum/action/innate/dash/cult
name = "Rend the Veil"
@@ -156,7 +156,7 @@ Striking a noncultist, however, will tear their flesh."}
return
var/mob/living/carbon/carbon_user = user
if(user.num_legs < 2 || carbon_user.legcuffed) //if they can't be ensnared, stun for the same time as it takes to breakout of bola
to_chat(user, span_cultlarge("\"I wouldn't advise that.\""))
to_chat(user, span_cult_large("\"I wouldn't advise that.\""))
user.dropItemToGround(src, TRUE)
user.Paralyze(CULT_BOLA_PICKUP_STUN)
else
@@ -413,7 +413,7 @@ Striking a noncultist, however, will tear their flesh."}
/obj/item/clothing/suit/hooded/cultrobes/cult_shield/equipped(mob/living/user, slot)
..()
if(!IS_CULTIST(user))
to_chat(user, span_cultlarge("\"I wouldn't advise that.\""))
to_chat(user, span_cult_large("\"I wouldn't advise that.\""))
to_chat(user, span_warning("An overwhelming sense of nausea overpowers you!"))
user.dropItemToGround(src, TRUE)
user.set_dizzy_if_lower(1 MINUTES)
@@ -450,7 +450,7 @@ Striking a noncultist, however, will tear their flesh."}
/obj/item/clothing/suit/hooded/cultrobes/berserker/equipped(mob/living/user, slot)
..()
if(!IS_CULTIST(user))
to_chat(user, span_cultlarge("\"I wouldn't advise that.\""))
to_chat(user, span_cult_large("\"I wouldn't advise that.\""))
to_chat(user, span_warning("An overwhelming sense of nausea overpowers you!"))
user.dropItemToGround(src, TRUE)
user.set_dizzy_if_lower(1 MINUTES)
@@ -467,7 +467,7 @@ Striking a noncultist, however, will tear their flesh."}
/obj/item/clothing/glasses/hud/health/night/cultblind/equipped(mob/living/user, slot)
..()
if(user.stat != DEAD && !IS_CULTIST(user) && (slot & ITEM_SLOT_EYES))
to_chat(user, span_cultlarge("\"You want to be blind, do you?\""))
to_chat(user, span_cult_large("\"You want to be blind, do you?\""))
user.dropItemToGround(src, TRUE)
user.set_dizzy_if_lower(1 MINUTES)
user.Paralyze(100)
@@ -30,7 +30,7 @@
options = altar_items
/obj/structure/destructible/cult/item_dispenser/altar/succcess_message(mob/living/user, obj/item/spawned_item)
to_chat(user, span_cultitalic("You kneel before [src] and your faith is rewarded with [spawned_item]!"))
to_chat(user, span_cult_italic("You kneel before [src] and your faith is rewarded with [spawned_item]!"))
#undef ELDRITCH_WHETSTONE
#undef CONSTRUCT_SHELL
@@ -32,7 +32,7 @@
options = archive_items
/obj/structure/destructible/cult/item_dispenser/archives/succcess_message(mob/living/user, obj/item/spawned_item)
to_chat(user, span_cultitalic("You summon [spawned_item] from [src]!"))
to_chat(user, span_cult_italic("You summon [spawned_item] from [src]!"))
// Preset for the library that doesn't spawn runed metal on destruction.
/obj/structure/destructible/cult/item_dispenser/archives/library
@@ -32,7 +32,7 @@
options = forge_items
/obj/structure/destructible/cult/item_dispenser/forge/succcess_message(mob/living/user, obj/item/spawned_item)
to_chat(user, span_cultitalic("You work [src] as dark knowledge guides your hands, creating [spawned_item]!"))
to_chat(user, span_cult_italic("You work [src] as dark knowledge guides your hands, creating [spawned_item]!"))
/obj/structure/destructible/cult/item_dispenser/forge/engine
name = "magma engine"
@@ -25,7 +25,7 @@
if(cult_examine_tip)
. += span_cult(cult_examine_tip)
if(!COOLDOWN_FINISHED(src, use_cooldown_duration))
. += span_cultitalic("The magic in [src] is too weak, it will be ready to use again in <b>[DisplayTimeText(COOLDOWN_TIMELEFT(src, use_cooldown_duration))]</b>.")
. += span_cult_italic("The magic in [src] is too weak, it will be ready to use again in <b>[DisplayTimeText(COOLDOWN_TIMELEFT(src, use_cooldown_duration))]</b>.")
/obj/structure/destructible/cult/set_anchored(anchorvalue)
. = ..()
@@ -78,10 +78,10 @@
to_chat(user, span_warning("You're pretty sure you know exactly what this is used for and you can't seem to touch it."))
return
if(!anchored)
to_chat(user, span_cultitalic("You need to anchor [src] to the floor first."))
to_chat(user, span_cult_italic("You need to anchor [src] to the floor first."))
return
if(!COOLDOWN_FINISHED(src, use_cooldown))
to_chat(user, span_cultitalic("The magic in [src] is too weak, it will be ready to use again in <b>[DisplayTimeText(COOLDOWN_TIMELEFT(src, use_cooldown))]</b>."))
to_chat(user, span_cult_italic("The magic in [src] is too weak, it will be ready to use again in <b>[DisplayTimeText(COOLDOWN_TIMELEFT(src, use_cooldown))]</b>."))
return
var/list/spawned_items = get_items_to_spawn(user)
@@ -142,7 +142,7 @@
* Override for unique feedback messages on item spawn.
*/
/obj/structure/destructible/cult/item_dispenser/proc/succcess_message(mob/living/user, obj/item/spawned_item)
to_chat(user, span_cultitalic("[src] produces a [spawned_item.name]."))
to_chat(user, span_cult_italic("[src] produces a [spawned_item.name]."))
/*
* Simple proc intended for use in callbacks to determine if [user] can continue to use a radial menu.
+5 -5
View File
@@ -49,7 +49,7 @@
for(var/datum/mind/mind as anything in members)
if(mind.current)
SEND_SOUND(mind.current, 'sound/ambience/antag/bloodcult/bloodcult_eyes.ogg')
to_chat(mind.current, span_cultlarge(span_warning("The veil weakens as your cult grows, your eyes begin to glow...")))
to_chat(mind.current, span_cult_large(span_warning("The veil weakens as your cult grows, your eyes begin to glow...")))
mind.current.AddElement(/datum/element/cult_eyes)
cult_risen = TRUE
log_game("The blood cult has risen with [cultplayers] players.")
@@ -58,7 +58,7 @@
for(var/datum/mind/mind as anything in members)
if(mind.current)
SEND_SOUND(mind.current, 'sound/ambience/antag/bloodcult/bloodcult_halos.ogg')
to_chat(mind.current, span_cultlarge(span_warning("Your cult is ascendent and the red harvest approaches - you cannot hide your true nature for much longer!!")))
to_chat(mind.current, span_cult_large(span_warning("Your cult is ascendent and the red harvest approaches - you cannot hide your true nature for much longer!!")))
mind.current.AddElement(/datum/element/cult_halo)
cult_ascendent = TRUE
log_game("The blood cult has ascended with [cultplayers] players.")
@@ -156,7 +156,7 @@
if(cultist.current.stat == DEAD || !cultist.current.client)
continue
to_chat(cultist.current, span_bold(span_cultlarge("[marker] has marked [blood_target] in the [target_area.name] as the cult's top priority, get there immediately!")))
to_chat(cultist.current, span_bold(span_cult_large("[marker] has marked [blood_target] in the [target_area.name] as the cult's top priority, get there immediately!")))
SEND_SOUND(cultist.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'), 0, 1, 75))
cultist.current.client.images += blood_target_image
@@ -175,9 +175,9 @@
continue
if(QDELETED(blood_target))
to_chat(cultist.current, span_bold(span_cultlarge("The blood mark's target is lost!")))
to_chat(cultist.current, span_bold(span_cult_large("The blood mark's target is lost!")))
else
to_chat(cultist.current, span_bold(span_cultlarge("The blood mark has expired!")))
to_chat(cultist.current, span_bold(span_cult_large("The blood mark has expired!")))
cultist.current.client.images -= blood_target_image
UnregisterSignal(blood_target, COMSIG_QDELETING)
+75 -74
View File
@@ -1,6 +1,4 @@
/// list of weakrefs to mobs OR minds that have been sacrificed
GLOBAL_LIST(sacrificed)
/// List of all teleport runes
GLOBAL_LIST(teleport_runes)
/// Assoc list of every rune that can be drawn by ritual daggers. [rune_name] = [typepath]
@@ -100,7 +98,7 @@ Runes can either be invoked by one's self or with many different cultists. Each
. = ..()
if(.)
return
if(!IS_CULTIST(user))
if(!IS_CULTIST_OR_CULTIST_MOB(user))
to_chat(user, span_warning("You aren't able to understand the words of [src]."))
return
var/list/invokers = can_invoke(user)
@@ -110,15 +108,16 @@ Runes can either be invoked by one's self or with many different cultists. Each
to_chat(user, span_danger("You need [req_cultists - length(invokers)] more adjacent cultists to use this rune in such a manner."))
fail_invoke()
/obj/effect/rune/attack_animal(mob/living/simple_animal/user, list/modifiers)
if(isshade(user) || isconstruct(user))
if(HAS_TRAIT(user, TRAIT_ANGELIC))
to_chat(user, span_warning("You purge the rune!"))
qdel(src)
else if(construct_invoke || !IS_CULTIST(user)) //if you're not a cult construct we want the normal fail message
attack_hand(user)
else
to_chat(user, span_warning("You are unable to invoke the rune!"))
/obj/effect/rune/attack_animal(mob/living/user, list/modifiers)
if(!isshade(user) && !isconstruct(user))
return
if(HAS_TRAIT(user, TRAIT_ANGELIC))
to_chat(user, span_warning("You purge the rune!"))
qdel(src)
else if(construct_invoke || !IS_CULTIST(user)) //if you're not a cult construct we want the normal fail message
attack_hand(user)
else
to_chat(user, span_warning("You are unable to invoke the rune!"))
/obj/effect/rune/proc/conceal() //for talisman of revealing/hiding
visible_message(span_danger("[src] fades away."))
@@ -161,17 +160,19 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/proc/invoke(list/invokers)
//This proc contains the effects of the rune as well as things that happen afterwards. If you want it to spawn an object and then delete itself, have both here.
for(var/M in invokers)
if(isliving(M))
var/mob/living/L = M
if(invocation)
L.say(invocation, language = /datum/language/common, ignore_spam = TRUE, forced = "cult invocation")
if(invoke_damage)
L.apply_damage(invoke_damage, BRUTE)
to_chat(L, "<span class='cult italic'>[src] saps your strength!</span>")
else if(istype(M, /obj/item/toy/plush/narplush))
var/obj/item/toy/plush/narplush/P = M
P.visible_message("<span class='cult italic'>[P] squeaks loudly!</span>")
for(var/atom/invoker in invokers)
if(istype(invoker, /obj/item/toy/plush/narplush))
invoker.visible_message(span_cult_italic("[src] squeaks_loudly!"))
continue
if(!isliving(invoker))
continue
var/mob/living/living_invoker = invoker
if(invocation)
living_invoker.say(invocation, language = /datum/language/common, ignore_spam = TRUE, forced = "cult invocation")
if(invoke_damage)
living_invoker.apply_damage(invoke_damage, BRUTE)
to_chat(living_invoker, span_cult_italic("[src] saps your strength!"))
do_invoke_glow()
/obj/effect/rune/proc/do_invoke_glow()
@@ -234,7 +235,6 @@ structure_check() searches for nearby cultist structures required for the invoca
rune_in_use = TRUE
visible_message(span_warning("[src] pulses blood red!"))
var/oldcolor = color
color = RUNE_COLOR_DARKRED
if(length(myriad_targets))
@@ -259,9 +259,10 @@ structure_check() searches for nearby cultist structures required for the invoca
else
do_invoke_glow()
animate(src, color = oldcolor, time = 0.5 SECONDS)
animate(src, color = initial(color), time = 0.5 SECONDS)
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_atom_colour)), 0.5 SECONDS)
rune_in_use = FALSE
return ..()
/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers, datum/team/cult/cult_team)
ASSERT(convertee.mind)
@@ -286,7 +287,7 @@ structure_check() searches for nearby cultist structures required for the invoca
span_warning("[convertee] writhes in pain [(brutedamage || burndamage) \
? "even as [convertee.p_their()] wounds heal and close" \
: "as the markings below [convertee.p_them()] glow a bloody red"]!"),
span_cultlarge("<i>AAAAAAAAAAAAAA-</i>"),
span_cult_large("<i>AAAAAAAAAAAAAA-</i>"),
)
// We're not guaranteed to be a human but we'll cast here since we use it in a few branches
@@ -305,11 +306,11 @@ structure_check() searches for nearby cultist structures required for the invoca
convertee.mind.special_role = ROLE_CULTIST
convertee.mind.add_antag_datum(/datum/antagonist/cult, cult_team)
to_chat(convertee, span_cultitalic("<b>Your blood pulses. Your head throbs. The world goes red. \
to_chat(convertee, span_cult_bold_italic("Your blood pulses. Your head throbs. The world goes red. \
All at once you are aware of a horrible, horrible, truth. The veil of reality has been ripped away \
and something evil takes root.</b>"))
to_chat(convertee, span_cultitalic("<b>Assist your new compatriots in their dark dealings. \
Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back.</b>"))
and something evil takes root."))
to_chat(convertee, span_cult_bold_italic("Assist your new compatriots in their dark dealings. \
Your goal is theirs, and theirs is yours. You serve the Geometer above all else. Bring it back."))
if(istype(human_convertee))
human_convertee.uncuff()
@@ -324,10 +325,10 @@ structure_check() searches for nearby cultist structures required for the invoca
var/big_sac = FALSE
if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || cult_team.is_sacrifice_target(sacrificial.mind)) && length(invokers) < 3)
for(var/invoker in invokers)
to_chat(invoker, span_cultitalic("[sacrificial] is too greatly linked to the world! You need three acolytes!"))
to_chat(invoker, span_cult_italic("[sacrificial] is too greatly linked to the world! You need three acolytes!"))
return FALSE
var/signal_result = SEND_SIGNAL(sacrificial, COMSIG_LIVING_CULT_SACRIFICED, invokers)
var/signal_result = SEND_SIGNAL(sacrificial, COMSIG_LIVING_CULT_SACRIFICED, invokers, cult_team)
if(signal_result & STOP_SACRIFICE)
return FALSE
@@ -347,12 +348,12 @@ structure_check() searches for nearby cultist structures required for the invoca
if(!(signal_result & SILENCE_SACRIFICE_MESSAGE))
for(var/invoker in invokers)
if(big_sac)
to_chat(invoker, span_cultlarge("\"Yes! This is the one I desire! You have done well.\""))
to_chat(invoker, span_cult_large("\"Yes! This is the one I desire! You have done well.\""))
continue
if(ishuman(sacrificial) || iscyborg(sacrificial))
to_chat(invoker, span_cultlarge("\"I accept this sacrifice.\""))
to_chat(invoker, span_cult_large("\"I accept this sacrifice.\""))
else
to_chat(invoker, span_cultlarge("\"I accept this meager sacrifice.\""))
to_chat(invoker, span_cult_large("\"I accept this meager sacrifice.\""))
if(iscyborg(sacrificial))
var/construct_class = show_radial_menu(invokers[1], sacrificial, GLOB.construct_radial_images, require_near = TRUE, tooltips = TRUE)
@@ -389,7 +390,7 @@ structure_check() searches for nearby cultist structures required for the invoca
if(GET_ATOM_BLOOD_DNA_LENGTH(rod))
displayed_message += " The blood of [num_slain] fallen cultist[num_slain == 1 ? "":"s"] is absorbed into [rod]!"
rod.visible_message(span_cultitalic(displayed_message))
rod.visible_message(span_cult_italic(displayed_message))
switch(num_slain)
if(0, 1)
animate_spawn_sword(rod, /obj/item/melee/cultblade/dagger)
@@ -653,7 +654,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives
var/area/place = get_area(src)
if(!(place in summon_objective.summon_spots))
to_chat(user, span_cultlarge("The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!"))
to_chat(user, span_cult_large("The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!"))
return
if(locate(/obj/narsie) in SSpoints_of_interest.narsies)
for(var/invoker in invokers)
@@ -689,50 +690,50 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
invocation = "Pasnar val'keriam usinar. Savrae ines amutan. Yam'toth remium il'tarat!" //Depends on the name of the user - see below
icon_state = "1"
color = RUNE_COLOR_MEDIUMRED
var/static/sacrifices_used = -SOULS_TO_REVIVE // Cultists get one "free" revive
/obj/effect/rune/raise_dead/examine(mob/user)
. = ..()
if(IS_CULTIST(user) || user.stat == DEAD)
. += "<b>Sacrifices unrewarded:</b> [LAZYLEN(GLOB.sacrificed) - sacrifices_used]"
. += "<b>Sacrifices unrewarded:</b> [LAZYLEN(GLOB.sacrificed) - GLOB.sacrifices_used]"
/obj/effect/rune/raise_dead/invoke(list/invokers)
var/turf/T = get_turf(src)
var/mob/living/mob_to_revive
var/list/potential_revive_mobs = list()
var/mob/living/user = invokers[1]
if(rune_in_use)
return
rune_in_use = TRUE
for(var/mob/living/M in T.contents)
if(IS_CULTIST(M) && (M.stat == DEAD || !M.client || M.client.is_afk()))
potential_revive_mobs |= M
var/mob/living/mob_to_revive
var/list/potential_revive_mobs = list()
var/mob/living/user = invokers[1]
for(var/mob/living/target in loc)
if(IS_CULTIST(target) && (target.stat == DEAD || isnull(target.client) || target.client.is_afk()))
potential_revive_mobs += target
if(!length(potential_revive_mobs))
to_chat(user, "<span class='cult italic'>There are no dead cultists on the rune!</span>")
to_chat(user, span_cult_italic("There are no dead cultists on the rune!"))
log_game("Raise Dead rune activated by [user] at [COORD(src)] failed - no cultists to revive.")
fail_invoke()
return
if(length(potential_revive_mobs) > 1)
if(length(potential_revive_mobs) > 1 && user.mind)
mob_to_revive = tgui_input_list(user, "Cultist to revive", "Revive Cultist", potential_revive_mobs)
if(isnull(mob_to_revive))
return
else
mob_to_revive = potential_revive_mobs[1]
if(QDELETED(src) || !validness_checks(mob_to_revive, user))
fail_invoke()
return
if(user.name == "Herbert West")
invocation = "To life, to life, I bring them!"
else
invocation = initial(invocation)
..()
invocation = (user.name == "Herbert West") ? "To life, to life, I bring them!" : initial(invocation)
if(mob_to_revive.stat == DEAD)
var/diff = LAZYLEN(GLOB.sacrificed) - SOULS_TO_REVIVE - sacrifices_used
var/diff = LAZYLEN(GLOB.sacrificed) - SOULS_TO_REVIVE - GLOB.sacrifices_used
if(diff < 0)
to_chat(user, span_warning("Your cult must carry out [abs(diff)] more sacrifice\s before it can revive another cultist!"))
fail_invoke()
return
sacrifices_used += SOULS_TO_REVIVE
GLOB.sacrifices_used += SOULS_TO_REVIVE
mob_to_revive.revive(ADMIN_HEAL_ALL) //This does remove traits and such, but the rune might actually see some use because of it! //Why did you think this was a good idea
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
@@ -747,21 +748,21 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
fail_invoke()
return
SEND_SOUND(mob_to_revive, 'sound/ambience/antag/bloodcult/bloodcult_gain.ogg')
to_chat(mob_to_revive, span_cultlarge("\"PASNAR SAVRAE YAM'TOTH. Arise.\""))
to_chat(mob_to_revive, span_cult_large("\"PASNAR SAVRAE YAM'TOTH. Arise.\""))
mob_to_revive.visible_message(span_warning("[mob_to_revive] draws in a huge breath, red light shining from [mob_to_revive.p_their()] eyes."), \
span_cultlarge("You awaken suddenly from the void. You're alive!"))
span_cult_large("You awaken suddenly from the void. You're alive!"))
rune_in_use = FALSE
return ..()
/obj/effect/rune/raise_dead/proc/validness_checks(mob/living/target_mob, mob/living/user)
var/turf/T = get_turf(src)
if(QDELETED(user))
return FALSE
if(!Adjacent(user) || user.incapacitated())
return FALSE
if(QDELETED(target_mob))
return FALSE
if(!(target_mob in T.contents))
to_chat(user, "<span class='cult italic'>The cultist to revive has been moved!</span>")
if(!(target_mob in loc))
to_chat(user, span_cult_italic("The cultist to revive has been moved!"))
log_game("Raise Dead rune activated by [user] at [COORD(src)] failed - revival target moved.")
return FALSE
return TRUE
@@ -769,9 +770,9 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
/obj/effect/rune/raise_dead/fail_invoke()
..()
rune_in_use = FALSE
for(var/mob/living/M in range(1,src))
if(IS_CULTIST(M) && M.stat == DEAD)
M.visible_message(span_warning("[M] twitches."))
for(var/mob/living/cultist in loc)
if(IS_CULTIST(cultist) && cultist.stat == DEAD)
cultist.visible_message(span_warning("[cultist] twitches."))
//Rite of the Corporeal Shield: When invoked, becomes solid and cannot be passed. Invoke again to undo.
/obj/effect/rune/wall
@@ -895,7 +896,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
if(!IS_CULTIST(target) && target.blood_volume)
if(target.can_block_magic(charge_cost = 0))
continue
to_chat(target, span_cultlarge("Your blood boils in your veins!"))
to_chat(target, span_cult_large("Your blood boils in your veins!"))
animate(src, color = "#FCB56D", time = 4)
sleep(0.4 SECONDS)
if(QDELETED(src))
@@ -959,10 +960,10 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
var/choice = tgui_alert(user, "You tear open a connection to the spirit realm...", "Spirit Realm", list("Summon a Cult Ghost", "Ascend as a Dark Spirit"))
if(choice == "Summon a Cult Ghost")
if(!is_station_level(T.z))
to_chat(user, span_cultitalic("<b>The veil is not weak enough here to manifest spirits, you must be on station!</b>"))
to_chat(user, span_cult_italic("<b>The veil is not weak enough here to manifest spirits, you must be on station!</b>"))
return
if(ghosts >= ghost_limit)
to_chat(user, span_cultitalic("You are sustaining too many ghosts to summon more!"))
to_chat(user, span_cult_italic("You are sustaining too many ghosts to summon more!"))
fail_invoke()
log_game("Manifest rune failed - too many summoned ghosts")
return list()
@@ -977,7 +978,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
if(O.client && !is_banned_from(O.ckey, ROLE_CULTIST) && !QDELETED(src) && !(isAdminObserver(O) && (O.client.prefs.toggles & ADMIN_IGNORE_CULT_GHOST)) && !QDELETED(O))
ghosts_on_rune += O
if(!length(ghosts_on_rune))
to_chat(user, span_cultitalic("There are no spirits near [src]!"))
to_chat(user, span_cult_italic("There are no spirits near [src]!"))
fail_invoke()
log_game("Manifest rune failed - no nearby ghosts")
return list()
@@ -995,7 +996,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
ghosts++
playsound(src, 'sound/magic/exit_blood.ogg', 50, TRUE)
visible_message(span_warning("A cloud of red mist forms above [src], and from within steps... a [new_human.gender == FEMALE ? "wo":""]man."))
to_chat(user, span_cultitalic("Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely..."))
to_chat(user, span_cult_italic("Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely..."))
var/obj/structure/emergency_shield/cult/weak/N = new(T)
if(ghost_to_spawn.mind && ghost_to_spawn.mind.current)
new_human.AddComponent( \
@@ -1006,7 +1007,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
new_human.key = ghost_to_spawn.key
var/datum/antagonist/cult/created_cultist = new_human.mind?.add_antag_datum(/datum/antagonist/cult)
created_cultist?.silent = TRUE
to_chat(new_human, span_cultitalic("<b>You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.</b>"))
to_chat(new_human, span_cult_italic("<b>You are a servant of the Geometer. You have been made semi-corporeal by the cult of Nar'Sie, and you are to serve them at all costs.</b>"))
while(!QDELETED(src) && !QDELETED(user) && !QDELETED(new_human) && (user in T))
if(user.stat != CONSCIOUS || HAS_TRAIT(new_human, TRAIT_CRITICAL_CONDITION))
@@ -1018,7 +1019,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
ghosts--
if(new_human)
new_human.visible_message(span_warning("[new_human] suddenly dissolves into bones and ashes."), \
span_cultlarge("Your link to the world fades. Your form breaks apart."))
span_cult_large("Your link to the world fades. Your form breaks apart."))
for(var/obj/I in new_human)
new_human.dropItemToGround(I, TRUE)
new_human.mind?.remove_antag_datum(/datum/antagonist/cult)
@@ -1047,7 +1048,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
affecting.Paralyze(40)
break
if(affecting.health <= 10)
to_chat(G, span_cultitalic("Your body can no longer sustain the connection!"))
to_chat(G, span_cult_italic("Your body can no longer sustain the connection!"))
break
sleep(0.5 SECONDS)
CM.Remove(G)
@@ -1090,10 +1091,10 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives
if(length(summon_objective.summon_spots) <= 1)
to_chat(user, span_cultlarge("Only one ritual site remains - it must be reserved for the final summoning!"))
to_chat(user, span_cult_large("Only one ritual site remains - it must be reserved for the final summoning!"))
return
if(!(place in summon_objective.summon_spots))
to_chat(user, span_cultlarge("The Apocalypse rune will remove a ritual site, where Nar'Sie can be summoned, it can only be scribed in [english_list(summon_objective.summon_spots)]!"))
to_chat(user, span_cult_large("The Apocalypse rune will remove a ritual site, where Nar'Sie can be summoned, it can only be scribed in [english_list(summon_objective.summon_spots)]!"))
return
summon_objective.summon_spots -= place
@@ -1144,7 +1145,7 @@ GLOBAL_VAR_INIT(narsie_summon_count, 0)
addtimer(CALLBACK(M, TYPE_PROC_REF(/atom/, remove_alt_appearance),"cult_apoc",TRUE), duration)
images += C
else
to_chat(M, span_cultlarge("An Apocalypse Rune was invoked in the [place.name], it is no longer available as a summoning site!"))
to_chat(M, span_cult_large("An Apocalypse Rune was invoked in the [place.name], it is no longer available as a summoning site!"))
SEND_SOUND(M, 'sound/effects/pope_entry.ogg')
image_handler(images, duration)
if(intensity >= 285) // Based on the prior formula, this means the cult makes up <15% of current players
@@ -180,7 +180,7 @@
if(M == user)
return
if(IS_CULTIST(M) && IS_CULTIST(user))
to_chat(user, span_cultlarge("\"Come now, do not capture your bretheren's soul.\""))
to_chat(user, span_cult_large("\"Come now, do not capture your bretheren's soul.\""))
return
if(theme == THEME_HOLY && IS_CULTIST(user))
hot_potato(user)
@@ -508,7 +508,7 @@
if(newstruct.mind && !IS_CULTIST(newstruct) && ((stoner && IS_CULTIST(stoner)) || cultoverride) && SSticker.HasRoundStarted())
newstruct.mind.add_antag_datum(/datum/antagonist/cult/construct)
if(IS_CULTIST(stoner) || cultoverride)
to_chat(newstruct, span_cultbold("You are still bound to serve the cult[stoner ? " and [stoner]" : ""], follow [stoner?.p_their() || "their"] orders and help [stoner?.p_them() || "them"] complete [stoner?.p_their() || "their"] goals at all costs."))
to_chat(newstruct, span_cult_bold("You are still bound to serve the cult[stoner ? " and [stoner]" : ""], follow [stoner?.p_their() || "their"] orders and help [stoner?.p_them() || "them"] complete [stoner?.p_their() || "their"] goals at all costs."))
else if(stoner)
to_chat(newstruct, span_boldwarning("You are still bound to serve your creator, [stoner], follow [stoner.p_their()] orders and help [stoner.p_them()] complete [stoner.p_their()] goals at all costs."))
newstruct.clear_alert("bloodsense")
@@ -86,7 +86,7 @@
return
var/num_slain = LAZYLEN(cultists_slain)
. += span_cultitalic("It has the blood of [num_slain] fallen cultist[num_slain == 1 ? "" : "s"] on it. \
. += span_cult_italic("It has the blood of [num_slain] fallen cultist[num_slain == 1 ? "" : "s"] on it. \
<b>Offering</b> it to Nar'sie will transform it into a [num_slain >= 3 ? "powerful" : "standard"] cult weapon.")
/obj/item/nullrod/godhand
@@ -86,7 +86,7 @@
health = maxHealth / 2 // Start out injured to encourage not beelining away from the blob
SEND_SOUND(src, sound('sound/effects/blobattack.ogg'))
SEND_SOUND(src, sound('sound/effects/attackblob.ogg'))
to_chat(src, span_infoplain("You are powerful, hard to kill, and slowly regenerate near nodes and cores, [span_cultlarge("but will slowly die if not near the blob")] or if the factory that made you is killed."))
to_chat(src, span_infoplain("You are powerful, hard to kill, and slowly regenerate near nodes and cores, [span_cult_large("but will slowly die if not near the blob")] or if the factory that made you is killed."))
to_chat(src, span_infoplain("You can communicate with other blobbernauts and overminds <b>telepathically</b> by attempting to speak normally"))
to_chat(src, span_infoplain("Your overmind's blob reagent is: <b><font color=\"[blobstrain.color]\">[blobstrain.name]</b></font>!"))
to_chat(src, span_infoplain("The <b><font color=\"[blobstrain.color]\">[blobstrain.name]</b></font> reagent [blobstrain.shortdesc ? "[blobstrain.shortdesc]" : "[blobstrain.description]"]"))
@@ -50,7 +50,7 @@
carbon_target.Paralyze(6 SECONDS)
visible_message(span_danger("[src] knocks [carbon_target] down!"))
to_chat(src, span_cultlarge("\"Bring [carbon_target.p_them()] to me.\""))
to_chat(src, span_cult_large("\"Bring [carbon_target.p_them()] to me.\""))
/datum/action/innate/seek_master
name = "Seek your Master"
@@ -80,18 +80,18 @@
the_construct.master = cult_status.cult_team.blood_target
if(!the_construct.master)
to_chat(the_construct, span_cultitalic("You have no master to seek!"))
to_chat(the_construct, span_cult_italic("You have no master to seek!"))
the_construct.seeking = FALSE
return
if(tracking)
tracking = FALSE
the_construct.seeking = FALSE
to_chat(the_construct, span_cultitalic("You are no longer tracking your master."))
to_chat(the_construct, span_cult_italic("You are no longer tracking your master."))
return
else
tracking = TRUE
the_construct.seeking = TRUE
to_chat(the_construct, span_cultitalic("You are now tracking your master."))
to_chat(the_construct, span_cult_italic("You are now tracking your master."))
/datum/action/innate/seek_prey
@@ -113,16 +113,16 @@
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
button_icon_state = "cult_mark"
the_construct.seeking = FALSE
to_chat(the_construct, span_cultitalic("You are now tracking Nar'Sie, return to reap the harvest!"))
to_chat(the_construct, span_cult_italic("You are now tracking Nar'Sie, return to reap the harvest!"))
return
if(!LAZYLEN(GLOB.cult_narsie.souls_needed))
to_chat(the_construct, span_cultitalic("Nar'Sie has completed her harvest!"))
to_chat(the_construct, span_cult_italic("Nar'Sie has completed her harvest!"))
return
the_construct.master = pick(GLOB.cult_narsie.souls_needed)
var/mob/living/real_target = the_construct.master //We can typecast this way because Narsie only allows /mob/living into the souls list
to_chat(the_construct, span_cultitalic("You are now tracking your prey, [real_target.real_name] - harvest [real_target.p_them()]!"))
to_chat(the_construct, span_cult_italic("You are now tracking your prey, [real_target.real_name] - harvest [real_target.p_them()]!"))
desc = "Activate to track Nar'Sie!"
button_icon_state = "sintouch"
the_construct.seeking = TRUE
@@ -58,11 +58,11 @@
if(cult_converted)
for(var/mob/living/cultist as anything in invokers)
to_chat(cultist, span_cultitalic("[src] has already been sacrificed!"))
to_chat(cultist, span_cult_italic("[src] has already been sacrificed!"))
return STOP_SACRIFICE
for(var/mob/living/cultist as anything in invokers)
to_chat(cultist, span_cultitalic("This feels a bit too cliché, don't you think?"))
to_chat(cultist, span_cult_italic("This feels a bit too cliché, don't you think?"))
cult_converted = TRUE
INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, say), "BAAAAAAAAH!")
@@ -33,6 +33,7 @@
attack_verb_simple = "claw"
attack_sound = 'sound/weapons/slash.ogg'
attack_vis_effect = ATTACK_EFFECT_CLAW
cult_icon_state = "cat_cult"
///can this cat breed?
var/can_breed = TRUE
///can hold items?
@@ -11,6 +11,7 @@
butcher_results = list(/obj/item/food/meat/slab/corgi = 3, /obj/item/stack/sheet/animalhide/corgi = 1)
gold_core_spawnable = FRIENDLY_SPAWN
collar_icon_state = "corgi"
cult_icon_state = "narsian"
ai_controller = /datum/ai_controller/basic_controller/dog/corgi
///Access card for the corgi.
var/obj/item/card/id/access_card = null
@@ -507,7 +508,7 @@
/mob/living/basic/pet/dog/corgi/narsie/narsie_act()
if(stat == DEAD) //Nar'Sie loves her doggy
visible_message(span_warning("[src] arises again, revived by the dark magicks!"), \
span_cultlarge("RISE"))
span_cult_large("RISE"))
revive(ADMIN_HEAL_ALL) //also means that a dead Nars-Ian can consume a pet and revive
adjustBruteLoss(-maxHealth)
@@ -9,6 +9,7 @@
icon_living = "pug"
icon_dead = "pug_dead"
butcher_results = list(/obj/item/food/meat/slab/pug = 3)
cult_icon_state = "pug_cult"
gold_core_spawnable = FRIENDLY_SPAWN
collar_icon_state = "pug"
held_state = "pug"
+16 -1
View File
@@ -10,9 +10,12 @@
var/collar_icon_state = null
/// We have a seperate _rest collar icon state when the pet is resting.
var/has_collar_resting_icon_state = FALSE
/// Our collar
var/obj/item/clothing/neck/petcollar/collar
///can we become cultists?
var/can_cult_convert = TRUE
///whether we have a custom icon state when we get culted
var/cult_icon_state
/mob/living/basic/pet/Initialize(mapload)
. = ..()
@@ -22,6 +25,8 @@
collar = new(src)
update_icon(UPDATE_OVERLAYS)
if(can_cult_convert)
RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(become_cultist))
/mob/living/basic/pet/Destroy()
. = ..()
@@ -43,6 +48,10 @@
/mob/living/basic/pet/update_overlays()
. = ..()
if(isnull(mind) && (FACTION_CULT in faction))
var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE)
. += cult_indicator
if(!collar || !collar_icon_state)
return
@@ -54,6 +63,12 @@
. += mutable_appearance(icon, "[collar_icon_state][stat_tag]collar")
. += mutable_appearance(icon, "[collar_icon_state][stat_tag]tag")
/mob/living/basic/pet/update_icon_state()
if(cult_icon_state && (FACTION_CULT in faction))
icon_state = cult_icon_state
icon_living = cult_icon_state
return ..()
/mob/living/basic/pet/gib()
remove_collar(drop_location(), update_visuals = FALSE)
return ..()
@@ -0,0 +1,85 @@
#define PET_CULT_ATTACK 10
#define PET_CULT_HEALTH 50
///turn into terrifying beasts
/mob/living/basic/pet/proc/become_cultist(datum/source, list/invokers, datum/team)
SIGNAL_HANDLER
if(stat == DEAD || !can_cult_convert)
return
if(FACTION_CULT in faction)
return STOP_SACRIFICE
mind?.add_antag_datum(/datum/antagonist/cult, team)
qdel(GetComponent(/datum/component/obeys_commands))
melee_damage_lower = max(PET_CULT_ATTACK, initial(melee_damage_lower))
melee_damage_upper = max(PET_CULT_ATTACK + 5, initial(melee_damage_upper))
maxHealth = max(PET_CULT_HEALTH, initial(maxHealth))
fully_heal()
faction = list(FACTION_CULT) //we only serve the cult
if(isnull(cult_icon_state))
add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY)
var/static/list/cult_appetite = list(
/obj/item/organ,
/obj/effect/decal/cleanable/blood,
)
var/static/list/death_loot = list(
/obj/effect/gibspawner/generic,
/obj/item/soulstone,
)
AddElement(/datum/element/basic_eating, heal_amt = 15, food_types = cult_appetite)
AddElement(/datum/element/death_drops, death_loot)
basic_mob_flags &= DEL_ON_DEATH
qdel(ai_controller)
ai_controller = new /datum/ai_controller/basic_controller/pet_cult(src)
var/datum/action/cooldown/spell/conjure/revive_rune/rune_ability = new(src)
rune_ability.Grant(src)
ai_controller.set_blackboard_key(BB_RUNE_ABILITY, rune_ability)
ai_controller.set_blackboard_key(BB_CULT_TEAM, team)
var/static/list/new_pet_commands = list(
/datum/pet_command/point_targeting/attack,
/datum/pet_command/follow,
/datum/pet_command/free,
/datum/pet_command/idle,
/datum/pet_command/untargeted_ability/draw_rune,
)
AddComponent(/datum/component/obeys_commands, new_pet_commands)
RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(activate_rune), override = TRUE)
update_appearance()
return STOP_SACRIFICE
/mob/living/basic/pet/proc/activate_rune(datum/source, atom/target)
SIGNAL_HANDLER
if(!istype(target, /obj/effect/rune/raise_dead))
return NONE
target.attack_hand(src)
return COMPONENT_CANCEL_ATTACK_CHAIN
/mob/living/basic/pet/Login()
. = ..()
if(!. || !client)
return FALSE
if(!(FACTION_CULT in faction))
return
var/datum/team/cult_team = locate(/datum/team/cult) in GLOB.antagonist_teams
if(isnull(cult_team))
return
mind.add_antag_datum(/datum/antagonist/cult, cult_team)
update_appearance(UPDATE_OVERLAYS)
#undef PET_CULT_ATTACK
#undef PET_CULT_HEALTH
@@ -0,0 +1,14 @@
/datum/action/cooldown/spell/conjure/revive_rune
name = "Create Revival Rune"
button_icon = 'icons/obj/antags/cult/rune.dmi'
button_icon_state = "1"
background_icon_state = "bg_cult"
overlay_icon_state = "bg_cult_border"
spell_requirements = NONE
cooldown_time = 30 SECONDS
summon_type = list(
/obj/effect/rune/raise_dead,
)
summon_radius = 0
create_summon_timer = 5 SECONDS
sound = 'sound/magic/exit_blood.ogg'
@@ -0,0 +1,246 @@
/datum/ai_controller/basic_controller/pet_cult
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/cultist,
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/cultist,
BB_FRIENDLY_MESSAGE = "eagerly awaits your command...",
)
ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/befriend_cultists,
/datum/ai_planning_subtree/find_occupied_rune,
/datum/ai_planning_subtree/find_dead_cultist,
/datum/ai_planning_subtree/drag_target_to_rune,
/datum/ai_planning_subtree/pet_planning,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
)
ai_traits = PAUSE_DURING_DO_AFTER
///if target gets pulled away, unset him
/datum/ai_controller/basic_controller/pet_cult/proc/delete_pull_target(datum/source, atom/movable/was_pulling)
SIGNAL_HANDLER
UnregisterSignal(src, COMSIG_ATOM_NO_LONGER_PULLING)
if(was_pulling == blackboard[BB_DEAD_CULTIST])
clear_blackboard_key(BB_DEAD_CULTIST)
///targeting strat to attack non cultists
/datum/targeting_strategy/basic/cultist
/datum/targeting_strategy/basic/cultist/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target)
return IS_CULTIST_OR_CULTIST_MOB(the_target)
///befriend all cultists around us!
/datum/ai_planning_subtree/befriend_cultists
/datum/ai_planning_subtree/befriend_cultists/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
if(controller.blackboard_key_exists(BB_FRIENDLY_CULTIST))
controller.queue_behavior(/datum/ai_behavior/befriend_target, BB_FRIENDLY_CULTIST)
return
controller.queue_behavior(/datum/ai_behavior/find_and_set/friendly_cultist, BB_FRIENDLY_CULTIST, /mob/living/carbon)
///behavior to find cultists that we befriend
/datum/ai_behavior/find_and_set/friendly_cultist
action_cooldown = 5 SECONDS
behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION
/datum/ai_behavior/find_and_set/friendly_cultist/search_tactic(datum/ai_controller/controller, locate_path, search_range)
var/mob/living/living_pawn = controller.pawn
for(var/mob/living/carbon/possible_cultist in oview(search_range, controller.pawn))
if(IS_CULTIST(possible_cultist) && !(living_pawn.faction.Find(REF(possible_cultist))))
return possible_cultist
return null
///subtree to find a rune with a viable target on it, so we can go activate it
/datum/ai_planning_subtree/find_occupied_rune
/datum/ai_planning_subtree/find_occupied_rune/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
if((LAZYLEN(GLOB.sacrificed) - SOULS_TO_REVIVE - GLOB.sacrifices_used) < 0)
controller.clear_blackboard_key(BB_OCCUPIED_RUNE)
return
if(controller.blackboard_key_exists(BB_OCCUPIED_RUNE))
controller.queue_behavior(/datum/ai_behavior/activate_rune, BB_OCCUPIED_RUNE)
return SUBTREE_RETURN_FINISH_PLANNING
controller.queue_behavior(/datum/ai_behavior/find_and_set/occupied_rune, BB_OCCUPIED_RUNE, /obj/effect/rune/raise_dead)
/datum/ai_behavior/find_and_set/occupied_rune
/datum/ai_behavior/find_and_set/occupied_rune/search_tactic(datum/ai_controller/controller, locate_path, search_range)
var/datum/team/cult/cult_team = controller.blackboard[BB_CULT_TEAM]
if(isnull(cult_team))
return null
for(var/obj/effect/rune/raise_dead/target_rune in oview(search_range, controller.pawn))
controller.set_blackboard_key(BB_NEARBY_RUNE, target_rune)
var/mob/living/occupant = locate(/mob/living/carbon/human) in get_turf(target_rune)
if(isnull(occupant))
continue
if(occupant.stat != DEAD || !IS_CULTIST(occupant))
continue
return target_rune
return null
/datum/ai_behavior/activate_rune
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION | AI_BEHAVIOR_REQUIRE_REACH
action_cooldown = 3 SECONDS
/datum/ai_behavior/activate_rune/setup(datum/ai_controller/controller, target_key)
. = ..()
var/turf/target = controller.blackboard[target_key]
if(isnull(target))
return FALSE
set_movement_target(controller, target)
/datum/ai_behavior/activate_rune/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
. = ..()
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
finish_action(controller, FALSE, target_key)
return
var/datum/team/cult/cult_team = controller.blackboard[BB_CULT_TEAM]
var/mob/living/revive_mob = locate(/mob/living) in get_turf(target)
if(isnull(revive_mob) || revive_mob.stat != DEAD || !(revive_mob.mind in cult_team.members))
finish_action(controller, FALSE, target_key)
return
var/mob/living/basic/living_pawn = controller.pawn
living_pawn.melee_attack(target)
finish_action(controller, TRUE, target_key)
return
/datum/ai_behavior/activate_rune/finish_action(datum/ai_controller/controller, success, target_key)
. = ..()
controller.clear_blackboard_key(target_key)
///find targets that we can revive
/datum/ai_planning_subtree/find_dead_cultist
/datum/ai_planning_subtree/find_dead_cultist/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
if((LAZYLEN(GLOB.sacrificed) - SOULS_TO_REVIVE - GLOB.sacrifices_used) < 0)
controller.clear_blackboard_key(BB_DEAD_CULTIST)
return
var/mob/living/living_pawn = controller.pawn
if(!isnull(living_pawn.pulling))
return
if(controller.blackboard_key_exists(BB_DEAD_CULTIST))
controller.queue_behavior(/datum/ai_behavior/pull_target/cult_revive, BB_DEAD_CULTIST)
return SUBTREE_RETURN_FINISH_PLANNING
controller.queue_behavior(/datum/ai_behavior/find_and_set/dead_cultist, BB_DEAD_CULTIST, /mob/living/carbon/human)
/datum/ai_behavior/find_and_set/dead_cultist
/datum/ai_behavior/find_and_set/dead_cultist/search_tactic(datum/ai_controller/controller, locate_path, search_range)
var/datum/team/cult/cult_team = controller.blackboard[BB_CULT_TEAM]
if(isnull(cult_team))
return null
var/mob/living/living_pawn = controller.pawn
for(var/mob/living/carbon/human/target in oview(search_range, controller.pawn))
if(target.stat != DEAD)
continue
if(!IS_CULTIST(target))
continue
if(target.buckled || target.move_resist > living_pawn.move_force || target.pulledby)
continue
if(locate(/obj/effect/rune/raise_dead) in target.loc)
continue
return target
return null
/datum/ai_behavior/pull_target/cult_revive
/datum/ai_behavior/pull_target/cult_revive/finish_action(datum/ai_controller/basic_controller/controller, succeeded, target_key)
. = ..()
if(!succeeded)
return
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return
controller.RegisterSignal(controller.pawn, COMSIG_ATOM_NO_LONGER_PULLING, TYPE_PROC_REF(/datum/ai_controller/basic_controller/pet_cult, delete_pull_target), override = TRUE)
/datum/ai_planning_subtree/drag_target_to_rune
/datum/ai_planning_subtree/drag_target_to_rune/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
if(!controller.blackboard_key_exists(BB_DEAD_CULTIST)) //no target, we dont need to do anything
return
var/mob/living/our_pawn = controller.pawn
if(isnull(our_pawn.pulling))
return
var/atom/target_rune = controller.blackboard[BB_NEARBY_RUNE]
if(QDELETED(target_rune))
controller.queue_behavior(/datum/ai_behavior/use_mob_ability, BB_RUNE_ABILITY)
return SUBTREE_RETURN_FINISH_PLANNING
if(!can_see(our_pawn, target_rune, 9))
controller.clear_blackboard_key(BB_NEARBY_RUNE)
return
controller.queue_behavior(/datum/ai_behavior/drag_target_to_rune, BB_NEARBY_RUNE, BB_DEAD_CULTIST)
///behavior to drag the target onto the rune
/datum/ai_behavior/drag_target_to_rune
required_distance = 0
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
/datum/ai_behavior/drag_target_to_rune/setup(datum/ai_controller/controller, target_key, cultist_key)
. = ..()
var/turf/target = controller.blackboard[target_key]
if(isnull(target))
return FALSE
set_movement_target(controller, target)
/datum/ai_behavior/drag_target_to_rune/perform(seconds_per_tick, datum/ai_controller/controller, target_key, cultist_key)
. = ..()
var/mob/living/our_pawn = controller.pawn
var/atom/cultist_target = controller.blackboard[cultist_key]
if(isnull(cultist_target))
finish_action(controller, FALSE, target_key, cultist_key)
return
var/list/possible_dirs = GLOB.alldirs.Copy()
possible_dirs -= get_dir(our_pawn, cultist_target)
for(var/direction in possible_dirs)
var/turf/possible_turf = get_step(our_pawn, direction)
if(possible_turf.is_blocked_turf(source_atom = our_pawn))
possible_dirs -= direction
step(our_pawn, pick(possible_dirs))
our_pawn.stop_pulling()
finish_action(controller, TRUE, target_key, cultist_key)
/datum/ai_behavior/drag_target_to_rune/finish_action(datum/ai_controller/controller, success, target_key, cultist_key)
. = ..()
if(success)
var/atom/revival_rune = controller.blackboard[target_key]
controller.set_blackboard_key(BB_OCCUPIED_RUNE, revival_rune)
controller.clear_blackboard_key(cultist_key)
controller.clear_blackboard_key(target_key)
///command ability to draw runes
/datum/pet_command/untargeted_ability/draw_rune
command_name = "Draw Rune"
command_desc = "Draw a revival rune."
radial_icon = 'icons/obj/antags/cult/rune.dmi'
radial_icon_state = "1"
speech_commands = list("rune", "revival")
ability_key = BB_RUNE_ABILITY
+1 -1
View File
@@ -458,7 +458,7 @@
SIGNAL_HANDLER
for(var/mob/living/cultist as anything in invokers)
to_chat(cultist, span_cultitalic("You don't think this is what Nar'Sie had in mind when She asked for blood sacrifices..."))
to_chat(cultist, span_cult_italic("You don't think this is what Nar'Sie had in mind when She asked for blood sacrifices..."))
return STOP_SACRIFICE
/// Updates the distance we can be from our pai card
@@ -407,7 +407,7 @@
removed_any = TRUE
qdel(BS)
if(removed_any)
to_chat(affected_mob, span_cultlarge("Your blood rites falter as holy water scours your body!"))
to_chat(affected_mob, span_cult_large("Your blood rites falter as holy water scours your body!"))
if(data["deciseconds_metabolized"] >= (25 SECONDS)) // 10 units
affected_mob.adjust_stutter_up_to(4 SECONDS * REM * seconds_per_tick, 20 SECONDS)
@@ -417,7 +417,7 @@
if(prob(10))
affected_mob.visible_message(span_danger("[affected_mob] starts having a seizure!"), span_userdanger("You have a seizure!"))
affected_mob.Unconscious(12 SECONDS)
to_chat(affected_mob, span_cultlarge("[pick("Your blood is your bond - you are nothing without it", "Do not forget your place", \
to_chat(affected_mob, span_cult_large("[pick("Your blood is your bond - you are nothing without it", "Do not forget your place", \
"All that power, and you still fail?", "If you cannot scour this poison, I shall scour your meager life!")]."))
if(data["deciseconds_metabolized"] >= (1 MINUTES)) // 24 units
@@ -15,12 +15,17 @@
var/summon_respects_density = FALSE
/// If TRUE, no two summons can be spawned in the same turf.
var/summon_respects_prev_spawn_points = TRUE
/// for how long must we stay still when summoning
var/create_summon_timer
/datum/action/cooldown/spell/conjure/is_valid_target(atom/cast_on)
return isturf(cast_on.loc)
/datum/action/cooldown/spell/conjure/cast(atom/cast_on)
. = ..()
if(create_summon_timer && !do_after(owner, create_summon_timer, target = cast_on.loc))
owner?.balloon_alert(owner, "need to stay still!")
return
var/list/to_summon_in = list()
for(var/turf/summon_turf in range(summon_radius, cast_on))
if(summon_respects_density && summon_turf.density)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 85 KiB

@@ -79,7 +79,7 @@
/obj/item/nullrod/cultdagger/attack_self(mob/user)
if(narsian)
else if(user.mind && (user.mind.holy_role))
to_chat(user, span_cultlarge("\"Partake in the language of blood..\""))
to_chat(user, span_cult_large("\"Partake in the language of blood..\""))
user.grant_language(/datum/language/narsie, source = LANGUAGE_MIND)
special_desc_requirement = NONE // No point in keeping something that can't no longer be used
narsian = TRUE
@@ -93,7 +93,7 @@
/obj/item/nullrod/claymore/darkblade/attack_self(mob/user)
if(narsian)
else if(user.mind && (user.mind.holy_role))
to_chat(user, span_cultlarge("\"Partake in the language of blood..\""))
to_chat(user, span_cult_large("\"Partake in the language of blood..\""))
user.grant_language(/datum/language/narsie, source = LANGUAGE_MIND)
special_desc_requirement = NONE // No point in keeping something that can't no longer be used
narsian = TRUE
@@ -108,7 +108,7 @@
if(host.stat != DEAD)
return
if(!ismutant(host))
to_chat(host, span_cultlarge("You can feel your heart stopping, but something isn't right... \
to_chat(host, span_cult_large("You can feel your heart stopping, but something isn't right... \
life has not abandoned your broken form. You can only feel a deep and immutable hunger that \
not even death can stop, you will rise again!"))
var/revive_time = rand(REVIVE_TIME_LOWER, REVIVE_TIME_UPPER)
@@ -151,7 +151,7 @@
/datum/component/mutant_infection/proc/mutant_death()
SIGNAL_HANDLER
var/revive_time = rand(REVIVE_TIME_LOWER, REVIVE_TIME_UPPER)
to_chat(host, span_cultlarge("You can feel your heart stopping, but something isn't right... you will rise again!"))
to_chat(host, span_cult_large("You can feel your heart stopping, but something isn't right... you will rise again!"))
timer_id = addtimer(CALLBACK(src, PROC_REF(regenerate)), revive_time, TIMER_STOPPABLE)
/datum/component/mutant_infection/proc/regenerate()
+4
View File
@@ -966,6 +966,7 @@
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\find_parent.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\nearest_targeting.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\pick_up_item.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\pull_target.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\run_away_from_target.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\set_travel_destination.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\step_towards_turf.dm"
@@ -4820,6 +4821,9 @@
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_hoarding.dm"
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_perching.dm"
#include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parroting_action.dm"
#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult.dm"
#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_abilities.dm"
#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_ai.dm"
#include "code\modules\mob\living\basic\ruin_defender\flesh.dm"
#include "code\modules\mob\living\basic\ruin_defender\living_floor.dm"
#include "code\modules\mob\living\basic\ruin_defender\skeleton.dm"
@@ -579,24 +579,24 @@ em {
color: #973e3b;
}
.cultitalic {
.cult_italic {
color: #973e3b;
font-style: italic;
}
.cultbold {
.cult_bold {
color: #973e3b;
font-style: italic;
font-weight: bold;
}
.cultboldtalic {
.cult_bold_italic {
color: #973e3b;
font-weight: bold;
font-size: 185%;
}
.cultlarge {
.cult_large {
color: #973e3b;
font-weight: bold;
font-size: 185%;
@@ -601,19 +601,19 @@ h2.alert {
font-style: italic;
}
.cultbold {
.cult_bold {
color: #973e3b;
font-style: italic;
font-weight: bold;
}
.cultboldtalic {
.cult_bold_italic {
color: #973e3b;
font-weight: bold;
font-size: 185%;
}
.cultlarge {
.cult_large {
color: #973e3b;
font-weight: bold;
font-size: 185%;