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