diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 6cadd480b3a..dcf966cabb0 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -55,6 +55,26 @@ var/global/list/all_cults = list()
var/const/max_cultists_to_start = 4
var/acolytes_survived = 0
+ var/narsie_condition_cleared = 0 //allows Nar-Sie to be summonned during cult rounds. set to 1 once the cult reaches the second phase.
+ var/current_objective = 1 //equals the number of cleared objectives + 1
+ var/prenarsie_objectives = 2 //how many objectives at most before the cult gets to summon narsie
+ var/list/bloody_floors = list()
+ var/spilltarget = 100 //how many floor tiles must be covered in blood to complete the bloodspill objective
+ var/convert_target = 0 //how many members the cult needs to reach to complete the convert objective
+ var/harvested = 0
+
+ var/list/sacrificed = list() //contains the mind of the sacrifice target ONCE the sacrifice objective has been completed
+ var/mass_convert = 0 //set to 1 if the convert objective has been accomplised once that round
+ var/spilled_blood = 0 //set to 1 if the bloodspill objective has been accomplised once that round
+ var/max_spilled_blood = 0 //highest quantity of blood covered tiles during the round
+ var/bonus = 0 //set to 1 if the cult has completed the bonus (third phase) objective (harvest, hijack, massacre)
+
+ var/harvest_target = 10
+ var/massacre_target = 5
+
+ var/escaped_shuttle = 0
+ var/escaped_pod = 0
+ var/survivors = 0
/datum/game_mode/cult/announce()
to_chat(world, "The current game mode is - Cult!")
@@ -62,13 +82,6 @@ var/global/list/all_cults = list()
/datum/game_mode/cult/pre_setup()
- if(prob(50))
- objectives += "survive"
- objectives += "sacrifice"
- else
- objectives += "eldergod"
- objectives += "sacrifice"
-
if(config.protect_roles_from_antagonist)
restricted_jobs += protected_jobs
@@ -101,7 +114,7 @@ var/global/list/all_cults = list()
equip_cultist(cult_mind.current)
update_cult_icons_added(cult_mind)
to_chat(cult_mind.current, "\blue You are a member of the cult!")
- memorize_cult_objectives(cult_mind)
+ first_phase()
..()
@@ -112,6 +125,10 @@ var/global/list/all_cults = list()
switch(objectives[obj_count])
if("survive")
explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station."
+ if("convert")
+ explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ if("bloodspill")
+ explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
if("sacrifice")
if(sacrifice_target)
explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune and three acolytes to do so."
@@ -217,6 +234,12 @@ var/global/list/all_cults = list()
if(objectives.Find("sacrifice"))
if(sacrifice_target && !(sacrifice_target in sacrificed)) //if the target has been sacrificed, ignore this step. otherwise, add 1 to cult_fail
cult_fail++
+ if(objectives.Find("convert"))
+ if(cult.len < convert_target)
+ cult_fail++
+ if(objectives.Find("bloodspill"))
+ if(max_spilled_blood < spilltarget)
+ cult_fail++
return cult_fail //if any objectives aren't met, failure
@@ -242,6 +265,7 @@ var/global/list/all_cults = list()
/datum/game_mode/cult/declare_completion()
+ bonus_check()
if(!check_cult_victory())
feedback_set_details("round_end_result","win - cult win")
@@ -284,6 +308,47 @@ var/global/list/all_cults = list()
else
explanation = "Summon [ticker.mode.cultdat.entity_name]. Fail."
feedback_add_details("cult_objective","cult_narsie|FAIL")
+
+ if("convert")//convert half the crew
+ if(obj_count < objectives.len)
+ explanation = "Convert [convert_target] crewmembers ([cult.len] cultists at round end). Success!"
+ feedback_add_details("cult_objective","cult_convertion|SUCCESS")
+ else
+ explanation = "Convert [convert_target] crewmembers ([cult.len] total cultists). Fail!"
+ feedback_add_details("cult_objective","cult_convertion|FAIL")
+
+ if("bloodspill")//cover a large portion of the station in blood
+ if(obj_count < objectives.len)
+ explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Success!"
+ feedback_add_details("cult_objective","cult_bloodspill|SUCCESS")
+ else
+ explanation = "Cover [spilltarget] tiles of the station in blood (The peak number of covered tiles was: [max_spilled_blood]). Fail!"
+ feedback_add_details("cult_objective","cult_bloodspill|FAIL")
+
+ if("harvest")
+ if(harvested > harvest_target)
+ explanation = "Offer [harvest_target] humans for [ticker.mode.cultdat.entity_name]'s first meal of the day. ([harvested] eaten) Success!"
+ feedback_add_details("cult_objective","cult_harvest|SUCCESS")
+ else
+ explanation = "Offer [harvest_target] humans for [ticker.mode.cultdat.entity_name]'s first meal of the day. ([harvested] eaten) Fail!"
+ feedback_add_details("cult_objective","cult_harvest|FAIL")
+
+ if("hijack")
+ if(!escaped_shuttle)
+ explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Success!"
+ feedback_add_details("cult_objective","cult_hijack|SUCCESS")
+ else
+ explanation = "Do not let a single non-cultist board the Escape Shuttle. ([escaped_shuttle] escaped on the shuttle) ([escaped_pod] escaped on pods) Fail!"
+ feedback_add_details("cult_objective","cult_hijack|FAIL")
+
+ if("massacre")
+ if(survivors < massacre_target)
+ explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humans left alive) Success!"
+ feedback_add_details("cult_objective","cult_massacre|SUCCESS")
+ else
+ explanation = "Massacre the crew until less than [massacre_target] people are left on the station. ([survivors] humans left alive) Fail!"
+ feedback_add_details("cult_objective","cult_massacre|FAIL")
+
text += "
Objective #[obj_count]: [explanation]"
to_chat(world, text)
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
new file mode 100644
index 00000000000..6b2dcd6edd0
--- /dev/null
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -0,0 +1,238 @@
+/datum/game_mode/cult/proc/blood_check()
+ max_spilled_blood = (max(bloody_floors.len,max_spilled_blood))
+ if((objectives[current_objective] == "bloodspill") && (bloody_floors.len >= spilltarget) && !spilled_blood)
+ spilled_blood = 1
+ additional_phase()
+
+/datum/game_mode/cult/proc/check_numbers()
+ if((objectives[current_objective] == "convert") && (cult.len >= convert_target) && !mass_convert)
+ mass_convert = 1
+ additional_phase()
+
+/datum/game_mode/cult/proc/first_phase()
+
+
+ var/new_objective = pick_objective()
+
+ objectives += new_objective
+
+ var/explanation
+
+ switch(new_objective)
+ if("convert")
+ explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name], Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ if("bloodspill")
+ spilltarget = 100 + rand(0,player_list.len * 3)
+ explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spill blood and gibs over [spilltarget] floor tiles."
+ if("sacrifice")
+ explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
+
+ for(var/datum/mind/cult_mind in cult)
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation]
"
+
+/datum/game_mode/cult/proc/bypass_phase()
+ switch(objectives[current_objective])
+ if("convert")
+ mass_convert = 1
+ if("bloodspill")
+ spilled_blood = 1
+ if("sacrifice")
+ sacrificed += sacrifice_target
+ additional_phase()
+
+/datum/game_mode/cult/proc/additional_phase()
+ current_objective++
+
+ message_admins("Picking a new Cult objective.")
+ var/new_objective = "eldergod"
+ //the idea here is that if the cult performs well, the should get more objectives before they can summon Nar-Sie.
+ if(cult.len >= 4)//if there are less than 4 remaining cultists, they get a free pass to the summon objective.
+ if(current_objective <= prenarsie_objectives)
+ var/list/unconvertables = get_unconvertables()
+ if(unconvertables.len <= (cult.len * 2))//if cultists are getting radically outnumbered, they get a free pass to the summon objective.
+ new_objective = pick_objective()
+ else
+ message_admins("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.")
+ log_admin("There are over twice more unconvertables than there are cultists ([cult.len] cultists for [unconvertables.len]) unconvertables! Nar-Sie objective unlocked.")
+ else
+ message_admins("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
+ log_admin("The Cult has already completed [prenarsie_objectives] objectives! Nar-Sie objective unlocked.")
+ else
+ message_admins("There are less than 4 cultists! [ticker.mode.cultdat.entity_name] objective unlocked.")
+ log_admin("There are less than 4 cultists! [ticker.mode.cultdat.entity_name] objective unlocked.")
+
+ if(!sacrificed.len && (new_objective != "sacrifice"))
+ sacrifice_target = null
+
+ if(new_objective == "eldergod")
+ second_phase()
+ return
+ else
+ objectives += new_objective
+
+ var/explanation
+
+ switch(new_objective)
+ if("convert")
+ explanation = "We must increase our influence before we can summon [ticker.mode.cultdat.entity_name]. Convert [convert_target] crew members. Take it slowly to avoid raising suspicions."
+ if("bloodspill")
+ spilltarget = 100 + rand(0,player_list.len * 3)
+ explanation = "We must prepare this place for [ticker.mode.cultdat.entity_title1]'s coming. Spread blood and gibs over [spilltarget] of the Station's floor tiles."
+ if("sacrifice")
+ explanation = "We need to sacrifice [sacrifice_target.name], the [sacrifice_target.assigned_role], for his blood is the key that will lead our master to this realm. You will need 3 cultists around a Sacrifice rune to perform the ritual."
+
+ for(var/datum/mind/cult_mind in cult)
+ to_chat(cult_mind.current, "You and your acolytes have completed your task, but this place requires yet more preparation!")
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation]
"
+
+ message_admins("New Cult Objective: [new_objective]")
+ log_admin("New Cult Objective: [new_objective]")
+
+ blood_check()//in case there are already enough blood covered tiles when the objective is given.
+
+/datum/game_mode/cult/proc/second_phase()
+ narsie_condition_cleared = 1
+
+ objectives += "eldergod"
+
+ var/explanation = "Summon [ticker.mode.cultdat.entity_name] on the Station via the use of the Tear Reality rune."
+ for(var/datum/mind/cult_mind in cult)
+ to_chat(cult_mind.current, "You and your acolytes have succeeded in preparing the station for the ultimate ritual!")
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation]
"
+
+/datum/game_mode/cult/proc/third_phase()
+ current_objective++
+
+ sleep(10)
+
+ var/last_objective = pick_bonus_objective()
+
+ objectives += last_objective
+
+ var/explanation
+
+ switch(last_objective)
+ if("harvest")
+ explanation = "[ticker.mode.cultdat.entity_title1] hungers for his first meal of this never-ending day. Offer him [harvest_target] humans in sacrifice."
+ if("hijack")
+ explanation = "[ticker.mode.cultdat.entity_name] wishes for his troops to start the assault on Centcom immediately. Hijack the escape shuttle and don't let a single non-cultist board it."
+ if("massacre")
+ explanation = "[ticker.mode.cultdat.entity_name] wants to watch you as you massacre the remaining humans on the station (until less than [massacre_target] humans are left alive)."
+
+ for(var/datum/mind/cult_mind in cult)
+ to_chat(cult_mind.current, "Objective #[current_objective]: [explanation]")
+ cult_mind.memory += "Objective #[current_objective]: [explanation]
"
+
+ message_admins("Last Cult Objective: [last_objective]")
+ log_admin("Last Cult Objective: [last_objective]")
+
+
+/datum/game_mode/cult/proc/pick_objective()
+ var/list/possible_objectives = list()
+
+ if(!spilled_blood && (bloody_floors.len < spilltarget))
+ possible_objectives |= "bloodspill"
+
+ if(!sacrificed.len)
+ var/list/possible_targets = list()
+ for(var/mob/living/carbon/human/player in player_list)
+ if(player.z == ZLEVEL_CENTCOMM) //We can't sacrifice people that are on the centcom z-level
+ continue
+ if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD))
+ possible_targets += player.mind
+
+ if(!possible_targets.len)
+ //There are no living Unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers
+ for(var/mob/living/carbon/human/player in player_list)
+ if(player.z == ZLEVEL_CENTCOMM) //We can't sacrifice people that are on the centcom z-level
+ continue
+ if(player.mind && !(player.mind in cult))
+ possible_targets += player.mind
+
+ if(possible_targets.len > 0)
+ sacrifice_target = pick(possible_targets)
+ possible_objectives |= "sacrifice"
+ else
+ message_admins("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.")
+ log_admin("Didn't find a suitable sacrifice target...what the hell? Shout at Deity.")
+
+ if(!mass_convert)
+ var/living_crew = 0
+ var/living_cultists = 0
+ for(var/mob/living/L in player_list)
+ if(L.stat != DEAD)
+ if(L.mind in cult)
+ living_cultists++
+ else
+ if(istype(L, /mob/living/carbon))
+ living_crew++
+
+ var/total = living_crew + living_cultists
+
+ if((living_cultists * 2) < total)
+ if (total < 15)
+ message_admins("There are [total] players, too little for the mass convert objective!")
+ log_admin("There are [total] players, too little for the mass convert objective!")
+ else if (total > 50)
+ message_admins("There are [total] players, too many for the mass convert objective!")
+ log_admin("There are [total] players, too many for the mass convert objective!")
+ else
+ possible_objectives |= "convert"
+ convert_target = round(total / 2)
+
+ if(!possible_objectives.len)//No more possible objectives, time to summon Nar-Sie
+ message_admins("No suitable objectives left! Nar-Sie objective unlocked.")
+ log_admin("No suitable objectives left! Nar-Sie objective unlocked.")
+ return "eldergod"
+ else
+ return pick(possible_objectives)
+
+/datum/game_mode/cult/proc/pick_bonus_objective()
+ var/list/possible_objectives = list()
+
+ var/living_crew = 0
+ for(var/mob/living/carbon/C in player_list)
+ if(C.stat != DEAD)
+ if(!(C.mind in cult))
+ var/turf/T = get_turf(C)
+ if(T.z == ZLEVEL_STATION) //we're only interested in the remaining humans on the station
+ living_crew++
+
+ if(living_crew > 5)
+ possible_objectives |= "massacre"
+
+ if(living_crew > 10)
+ possible_objectives |= "harvest"
+
+ possible_objectives |= "hijack" //we need at least one objective guarranted to fire
+
+ return pick(possible_objectives)
+
+/datum/game_mode/cult/proc/bonus_check()
+ switch(objectives[current_objective])
+ if("harvest")
+ if(harvested >= harvest_target)
+ bonus = 1
+
+ if("hijack")
+ for(var/mob/living/L in player_list)
+ if(L.stat != DEAD)
+ if(!(L.mind in cult))
+ var/area/A = get_area(L)
+ if(is_type_in_list(A.loc, centcom_areas))
+ escaped_shuttle++
+ if(!escaped_shuttle)
+ bonus = 1
+
+ if("massacre")
+ for(var/mob/living/carbon/C in player_list)
+ if(C.stat != DEAD)
+ if(!(C.mind in cult))
+ var/turf/T = get_turf(C)
+ if(T.z == ZLEVEL_STATION) //we're only interested in the remaining humans on the station
+ survivors++
+ if(survivors < massacre_target)
+ bonus = 1
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index b11ad6bf633..c5f8c7de727 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -24,6 +24,14 @@ var/global/list/image/splatter_cache=list()
/obj/effect/decal/cleanable/blood/New()
..()
update_icon()
+ if(ticker && ticker.mode && ticker.mode.name == "cult")
+ var/datum/game_mode/cult/mode_ticker = ticker.mode
+ var/turf/T = get_turf(src)
+ if(T && (T.z == ZLEVEL_STATION))//F I V E T I L E S
+ if(!(T in mode_ticker.bloody_floors))
+ mode_ticker.bloody_floors += T
+ mode_ticker.bloody_floors[T] = T
+ mode_ticker.blood_check()
if(istype(src, /obj/effect/decal/cleanable/blood/gibs))
return
if(src.type == /obj/effect/decal/cleanable/blood)
@@ -36,6 +44,17 @@ var/global/list/image/splatter_cache=list()
spawn(DRYING_TIME * (amount+1))
dry()
+/obj/effect/decal/cleanable/blood/Destroy()
+
+ if(ticker.mode && ticker.mode.name == "cult")
+ var/datum/game_mode/cult/mode_ticker = ticker.mode
+ var/turf/T = get_turf(src)
+ if(T && (T.z == ZLEVEL_STATION))
+ mode_ticker.bloody_floors -= T
+ mode_ticker.blood_check()
+ ..()
+
+
/obj/effect/decal/cleanable/blood/update_icon()
if(basecolor == "rainbow") basecolor = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]"
color = basecolor
diff --git a/paradise.dme b/paradise.dme
index c246eb45fa7..e4d760c05ea 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -396,6 +396,7 @@
#include "code\game\gamemodes\cult\cult_comms.dm"
#include "code\game\gamemodes\cult\cult_datums.dm"
#include "code\game\gamemodes\cult\cult_items.dm"
+#include "code\game\gamemodes\cult\cult_objectives.dm"
#include "code\game\gamemodes\cult\cult_structures.dm"
#include "code\game\gamemodes\cult\ritual.dm"
#include "code\game\gamemodes\cult\runes.dm"