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"