diff --git a/code/__DEFINES/cult.dm b/code/__DEFINES/cult.dm
index 73ec1bc8d7c..198291f0ae7 100644
--- a/code/__DEFINES/cult.dm
+++ b/code/__DEFINES/cult.dm
@@ -10,5 +10,14 @@
#define RUNE_COLOR_SUMMON "#00FF00"
//blood magic
-#define MAX_BLOODCHARGE 5
-#define RUNELESS_MAX_BLOODCHARGE 2
\ No newline at end of file
+#define MAX_BLOODCHARGE 4
+#define RUNELESS_MAX_BLOODCHARGE 1
+#define CULT_RISEN 0.2 //percent before rise
+#define CULT_ASCENDENT 0.4 //percent before ascend
+//screen locations
+#define DEFAULT_BLOODSPELLS "6:-29,4:-2"
+#define DEFAULT_BLOODTIP "14:6,14:27"
+#define DEFAULT_TOOLTIP "6:-29,5:-2"
+//misc
+#define SOULS_TO_REVIVE 3
+#define BLOODCULT_EYE "f00"
\ No newline at end of file
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index d20399c9e1c..2455d373ab2 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -90,3 +90,4 @@
#define STASIS_MUTE "stasis"
#define GENETICS_SPELL "genetics_spell"
#define EYES_COVERED "eyes_covered"
+#define CULT_EYES "cult_eyes"
\ No newline at end of file
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 9431b18df45..1ab313d3e6d 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -190,6 +190,20 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
user.visible_message("[user] has purified the [sword]!!")
qdel(sword)
+ else if(istype(A, /obj/item/soulstone) && !iscultist(user))
+ var/obj/item/soulstone/SS = A
+ to_chat(user, "You begin to exorcise [SS].")
+ playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1)
+ if(do_after(user, 40, user = SS))
+ playsound(src,'sound/effects/pray_chaplain.ogg',60,1)
+ SS.usability = TRUE
+ for(var/mob/living/simple_animal/shade/EX in SS)
+ SSticker.mode.remove_cultist(EX.mind, 1, 0)
+ EX.icon_state = "ghost1"
+ EX.name = "Purified [EX.name]"
+ SS.release_shades(user)
+ user.visible_message("[user] has purified the [SS]!!")
+ qdel(SS)
/obj/item/storage/book/bible/booze
desc = "To be applied to the head repeatedly."
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 960bfcba1cd..328560d6838 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -7,8 +7,8 @@
/datum/action/innate/cult/blood_magic/Grant()
..()
- button.screen_loc = "6:-29,4:-2"
- button.moved = "6:-29,4:-2"
+ button.screen_loc = DEFAULT_BLOODSPELLS
+ button.moved = DEFAULT_BLOODSPELLS
button.ordered = FALSE
/datum/action/innate/cult/blood_magic/Remove()
@@ -84,7 +84,7 @@
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
+/datum/action/innate/cult/blood_spell //The next generation of talismans, handles storage/creation of blood magic
name = "Blood Magic"
button_icon_state = "telerune"
desc = "Fear the Old Blood."
@@ -161,7 +161,7 @@
/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)
+ empulse(owner, 2, 5)
owner.whisper(invocation, language = /datum/language/common)
charges--
if(charges<=0)
@@ -179,7 +179,7 @@
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"
magic_path = "/obj/item/melee/blood_magic/construction"
- health_cost = 10
+ health_cost = 12
/datum/action/innate/cult/blood_spell/equipment
name = "Summon Equipment"
@@ -401,7 +401,7 @@
//Stun
/obj/item/melee/blood_magic/stun
name = "Stunning Aura "
- color = "#ff0000" // red
+ color = RUNE_COLOR_RED
invocation = "Fuu ma'jin!"
/obj/item/melee/blood_magic/stun/afterattack(atom/target, mob/living/carbon/user, proximity)
@@ -586,10 +586,13 @@
new /obj/structure/constructshell(T)
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
else if(istype(target,/obj/machinery/door/airlock))
- target.narsie_act()
- uses--
- user.visible_message("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))
+ playsound(T, 'sound/machines/airlockforced.ogg', 50, 1)
+ do_sparks(5, TRUE, target)
+ if(do_after(user, 50, target = user))
+ target.narsie_act()
+ uses--
+ 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]!")
return
diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm
index c14cd9ecd93..0de096b5c5d 100644
--- a/code/modules/antagonists/cult/cult.dm
+++ b/code/modules/antagonists/cult/cult.dm
@@ -11,9 +11,9 @@
job_rank = ROLE_CULTIST
var/ignore_implant = FALSE
var/give_equipment = FALSE
-
var/datum/team/cult/cult_team
+
/datum/antagonist/cult/get_team()
return cult_team
@@ -111,7 +111,11 @@
if(ishuman(current))
magic.Grant(current)
current.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
-
+ if(cult_team.cult_risen)
+ cult_team.rise(current)
+ if(cult_team.cult_ascendent)
+ cult_team.ascend(current)
+
/datum/antagonist/cult/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/current = owner.current
@@ -123,7 +127,13 @@
communion.Remove(current)
magic.Remove(current)
current.clear_alert("bloodsense")
-
+ if(ishuman(current))
+ var/mob/living/carbon/human/H = current
+ H.eye_color = initial(H.eye_color)
+ H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.remove_trait(CULT_EYES)
+ H.cut_overlays()
+ H.regenerate_icons()
/datum/antagonist/cult/on_removal()
SSticker.mode.cult -= owner
SSticker.mode.update_cult_icons_removed(owner)
@@ -193,7 +203,10 @@
throwing.Grant(current)
current.update_action_buttons_icon()
current.apply_status_effect(/datum/status_effect/cult_master)
-
+ if(cult_team.cult_risen)
+ cult_team.rise(current)
+ if(cult_team.cult_ascendent)
+ cult_team.ascend(current)
/datum/antagonist/cult/master/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/current = owner.current
@@ -204,6 +217,14 @@
throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
+
+ if(ishuman(current))
+ var/mob/living/carbon/human/H = current
+ H.eye_color = initial(H.eye_color)
+ H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.remove_trait(CULT_EYES)
+ H.cut_overlays()
+ H.regenerate_icons()
/datum/team/cult
name = "Cult"
@@ -215,7 +236,53 @@
var/cult_vote_called = FALSE
var/mob/living/cult_master
var/reckoning_complete = FALSE
-
+ var/cult_risen = FALSE
+ var/cult_ascendent = FALSE
+
+/datum/team/cult/proc/check_size()
+ if(cult_ascendent)
+ return
+ var/alive = 0
+ var/cultplayers = 0
+ for(var/I in GLOB.player_list)
+ var/mob/M = I
+ if(M.stat != DEAD)
+ if(iscultist(M))
+ ++cultplayers
+ else
+ ++alive
+ var/ratio = cultplayers/alive
+ if(ratio > CULT_RISEN && !cult_risen)
+ for(var/datum/mind/B in members)
+ if(B.current)
+ SEND_SOUND(B.current, 'sound/hallucinations/i_see_you2.ogg')
+ to_chat(B.current, "The veil weakens as your cult grows, your eyes begin to glow...")
+ addtimer(CALLBACK(src, .proc/rise, B.current), 200)
+ cult_risen = TRUE
+
+ if(ratio > CULT_ASCENDENT && !cult_ascendent)
+ for(var/datum/mind/B in members)
+ if(B.current)
+ SEND_SOUND(B.current, 'sound/hallucinations/im_here1.ogg')
+ to_chat(B.current, "Your cult is ascendent and the red harvest approaches - you cannot hide your true nature for much longer!!")
+ addtimer(CALLBACK(src, .proc/ascend, B.current), 200)
+ cult_ascendent = TRUE
+
+
+/datum/team/cult/proc/rise(cultist)
+ if(ishuman(cultist))
+ var/mob/living/carbon/human/H = cultist
+ H.eye_color = "f00"
+ H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
+ H.add_trait(CULT_EYES)
+ H.update_body()
+
+/datum/team/cult/proc/ascend(cultist)
+ if(ishuman(cultist))
+ var/mob/living/carbon/human/H = cultist
+ new /obj/effect/temp_visual/cult/sparks(get_turf(H), H.dir)
+ var/istate = pick("halo1","halo2","halo3","halo4","halo5","halo6")
+ H.add_overlay(mutable_appearance('icons/effects/32x64.dmi', istate, -BODY_FRONT_LAYER))
/datum/team/cult/proc/setup_objectives()
//SAC OBJECTIVE , todo: move this to objective internals
@@ -257,6 +324,7 @@
summon_objective.team = src
objectives += summon_objective
+
/datum/objective/sacrifice
var/sacced = FALSE
var/sac_image
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index b5ccbae473d..1b211ab1021 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -906,22 +906,22 @@
force = 5
throwforce = 15
throw_speed = 1
- throw_range = 6
+ throw_range = 4
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("bumped", "prodded")
hitsound = 'sound/weapons/smash.ogg'
- var/illusions = 3
+ var/illusions = 2
/obj/item/shield/mirror/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(iscultist(owner))
if(istype(hitby, /obj/item/projectile))
var/obj/item/projectile/P = hitby
- if(P.damage >= 35)
+ if(P.damage >= 30)
var/turf/T = get_turf(owner)
T.visible_message("The sheer force from [P] shatters the mirror shield!")
new /obj/effect/temp_visual/cult/sparks(T)
playsound(T, 'sound/effects/glassbr3.ogg', 100)
- owner.Knockdown(20)
+ owner.Knockdown(25)
qdel(src)
return FALSE
if(P.is_reflectable)
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index fcd7216602f..6dc01ec54cb 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -131,7 +131,7 @@
return
var/choice
if(user.mind.has_antag_datum(/datum/antagonist/cult/master))
- choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword")
+ choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
else
choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Mirror Shield")
var/list/pickedtype = list()
@@ -140,14 +140,6 @@
pickedtype += /obj/item/clothing/suit/hooded/cultrobes/cult_shield
if("Flagellant's Robe")
pickedtype += /obj/item/clothing/suit/hooded/cultrobes/berserker
- if("Bastard Sword")
- if((world.time - SSticker.round_start_time) >= 12000)
- pickedtype += /obj/item/twohanded/required/cult_bastard
- else
- cooldowntime = 12000 - (world.time - SSticker.round_start_time)
- to_chat(user, "The forge fires are not yet hot enough for this weapon, give it another [DisplayTimeText(cooldowntime)].")
- cooldowntime = 0
- return
if("Mirror Shield")
pickedtype += /obj/item/shield/mirror
if(src && !QDELETED(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time)
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 7eb203c63f6..c7c00f448a3 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -211,7 +211,7 @@ structure_check() searches for nearby cultist structures required for the invoca
var/mob/living/F = invokers[1]
var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
-
+ var/datum/team/cult/Cult_team = C.cult_team
var/is_convertable = is_convertable_to_cult(L,C.cult_team)
if(L.stat != DEAD && (is_clock || is_convertable))
invocation = "Mah'weyh pleggh at e'ntrath!"
@@ -229,8 +229,8 @@ structure_check() searches for nearby cultist structures required for the invoca
do_sacrifice(L, invokers)
animate(src, color = oldcolor, time = 5)
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 5)
+ Cult_team.check_size() // Triggers the eye glow or aura effects if the cult has grown large enough relative to the crew
rune_in_use = FALSE
-
/obj/effect/rune/convert/proc/do_convert(mob/living/convertee, list/invokers)
if(invokers.len < 2)
for(var/M in invokers)
@@ -315,6 +315,7 @@ structure_check() searches for nearby cultist structures required for the invoca
return TRUE
+
/obj/effect/rune/empower
cultist_name = "Empower"
cultist_desc = "allows cultists to prepare greater amounts of blood magic at far less of a cost."
@@ -512,7 +513,7 @@ structure_check() searches for nearby cultist structures required for the invoca
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/revives_used = 0
+ var/static/revives_used = -SOULS_TO_REVIVE // Cultists get one "free" revive
/obj/effect/rune/raise_dead/examine(mob/user)
..()
@@ -549,11 +550,12 @@ structure_check() searches for nearby cultist structures required for the invoca
invocation = initial(invocation)
..()
if(mob_to_revive.stat == DEAD)
- if(LAZYLEN(GLOB.sacrificed) <= revives_used)
- to_chat(user, "Your cult must carry out another sacrifice before it can revive a cultist!")
+ var/diff = LAZYLEN(GLOB.sacrificed) - revives_used - SOULS_TO_REVIVE
+ if(diff < 0)
+ to_chat(user, "Your cult must carry out [abs(diff)] more sacrifice\s before it can revive another cultist!")
fail_invoke()
return
- revives_used++
+ revives_used += SOULS_TO_REVIVE
mob_to_revive.revive(1, 1) //This does remove traits and such, but the rune might actually see some use because of it!
mob_to_revive.grab_ghost()
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index a6f901e6956..7133d605be9 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/human/examine(mob/user)
+/mob/living/carbon/human/examine(mob/user) //User is the person being examined
//this is very slightly better than it was because you can use it more places. still can't do \his[src] though.
var/t_He = p_they(TRUE)
var/t_His = p_their(TRUE)
@@ -80,8 +80,11 @@
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
//eyes
- if(glasses && !(SLOT_GLASSES in obscured))
- msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n"
+ if(!(SLOT_GLASSES in obscured))
+ if(glasses)
+ msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n"
+ else if(eye_color == BLOODCULT_EYE && iscultist(src) && has_trait(CULT_EYES))
+ msg += "[t_His] eyes are glowing an unnatural red!\n"
//ears
if(ears && !(SLOT_EARS in obscured))
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 4272e45500f..4e1b26cfc45 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -122,8 +122,8 @@
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
icon_state = "behemoth"
icon_living = "behemoth"
- maxHealth = 200
- health = 200
+ maxHealth = 150
+ health = 150
response_harm = "harmlessly punches"
harm_intent_damage = 0
obj_damage = 90
@@ -148,7 +148,7 @@
/mob/living/simple_animal/hostile/construct/armored/bullet_act(obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
- var/reflectchance = 60 - round(P.damage/3)
+ var/reflectchance = 40 - round(P.damage/3)
if(prob(reflectchance))
apply_damage(P.damage * 0.5, P.damage_type)
visible_message("The [P.name] is reflected by [src]'s armored shell!", \
diff --git a/icons/effects/32x64.dmi b/icons/effects/32x64.dmi
new file mode 100644
index 00000000000..4d9f9911944
Binary files /dev/null and b/icons/effects/32x64.dmi differ