Merge branch 'master' into upstream-merge-33634

This commit is contained in:
LetterJay
2017-12-24 02:39:35 -06:00
committed by GitHub
384 changed files with 3361 additions and 3068 deletions
+31 -29
View File
@@ -194,27 +194,22 @@
set waitfor = FALSE
return
// Convenience proc to see if a container is open for chemistry handling
// returns true if open
// false if closed
// Convenience procs to see if a container is open for chemistry handling
/atom/proc/is_open_container()
return container_type & OPENCONTAINER_1
/atom/proc/is_transparent()
return container_type & TRANSPARENT_1
return is_refillable() && is_drainable()
/atom/proc/is_injectable(allowmobs = TRUE)
if(isliving(src) && allowmobs)
var/mob/living/L = src
return L.can_inject()
if(container_type & OPENCONTAINER_1)
return TRUE
return container_type & INJECTABLE_1
return reagents && (container_type & (INJECTABLE | REFILLABLE))
/atom/proc/is_drawable(allowmobs = TRUE)
if(is_injectable(allowmobs)) //Everything that can be injected can also be drawn from, but not vice versa
return TRUE
return container_type & DRAWABLE_1
return reagents && (container_type & (DRAWABLE | DRAINABLE))
/atom/proc/is_refillable()
return reagents && (container_type & REFILLABLE)
/atom/proc/is_drainable()
return reagents && (container_type & DRAINABLE)
/atom/proc/AllowDrop()
return FALSE
@@ -256,19 +251,26 @@
if(desc)
to_chat(user, desc)
if(reagents && (is_open_container() || is_transparent())) //is_open_container() isn't really the right proc for this, but w/e
to_chat(user, "It contains:")
if(reagents.reagent_list.len)
if(user.can_see_reagents()) //Show each individual reagent
for(var/datum/reagent/R in reagents.reagent_list)
to_chat(user, "[R.volume] units of [R.name]")
else //Otherwise, just show the total volume
var/total_volume = 0
for(var/datum/reagent/R in reagents.reagent_list)
total_volume += R.volume
to_chat(user, "[total_volume] units of various reagents")
else
to_chat(user, "Nothing.")
if(reagents)
if(container_type & TRANSPARENT)
to_chat(user, "It contains:")
if(reagents.reagent_list.len)
if(user.can_see_reagents()) //Show each individual reagent
for(var/datum/reagent/R in reagents.reagent_list)
to_chat(user, "[R.volume] units of [R.name]")
else //Otherwise, just show the total volume
var/total_volume = 0
for(var/datum/reagent/R in reagents.reagent_list)
total_volume += R.volume
to_chat(user, "[total_volume] units of various reagents")
else
to_chat(user, "Nothing.")
else if(container_type & AMOUNT_VISIBLE)
if(reagents.total_volume)
to_chat(user, "<span class='notice'>It has [reagents.total_volume] unit\s left.</span>")
else
to_chat(user, "<span class='danger'>It's empty.</span>")
SendSignal(COMSIG_PARENT_EXAMINE, user)
/atom/proc/relaymove(mob/user)
+4 -3
View File
@@ -73,7 +73,7 @@
C.prefs.copy_to(M)
M.key = C.key
var/datum/mind/app_mind = M.mind
var/datum/antagonist/wizard/apprentice/app = new(app_mind)
app.master = user
app.school = kind
@@ -165,7 +165,7 @@
var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE)
if(!creator_op)
return
switch(borg_to_spawn)
if("Medical")
R = new /mob/living/silicon/robot/modules/syndicate/medical(T)
@@ -187,7 +187,7 @@
R.real_name = R.name
R.key = C.key
var/datum/antagonist/nukeop/new_borg = new(R.mind)
new_borg.send_to_spawnpoint = FALSE
R.mind.add_antag_datum(new_borg,creator_op.nuke_team)
@@ -247,6 +247,7 @@
new_objective2.owner = S.mind
new_objective2.explanation_text = "[objective_verb] everyone[usr ? " else while you're at it":""]."
S.mind.objectives += new_objective2
S.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(S, S.playstyle_string)
to_chat(S, "<B>You are currently not currently in the same plane of existence as the station. \
Ctrl+Click a blood pool to manifest.</B>")
+34
View File
@@ -0,0 +1,34 @@
//A barebones antagonist team.
/datum/team
var/list/datum/mind/members = list()
var/name = "team"
var/member_name = "member"
var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
/datum/team/New(starting_members)
. = ..()
if(starting_members)
if(islist(starting_members))
for(var/datum/mind/M in starting_members)
add_member(M)
else
add_member(starting_members)
/datum/team/proc/is_solo()
return members.len == 1
/datum/team/proc/add_member(datum/mind/new_member)
members |= new_member
/datum/team/proc/remove_member(datum/mind/member)
members -= member
//Display members/victory/failure/objectives for the team
/datum/team/proc/roundend_report()
var/list/report = list()
report += "<b>[name]:</b>"
report += "The [member_name]s were:"
report += printplayerlist(members)
return report.Join("<br>")
+6 -74
View File
@@ -1,44 +1,6 @@
/datum/objective_team/brother_team
name = "brotherhood"
member_name = "blood brother"
var/list/objectives = list()
var/meeting_area
/datum/objective_team/brother_team/is_solo()
return FALSE
/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE)
O.team = src
if(needs_target)
O.find_target()
O.update_explanation_text()
objectives += O
/datum/objective_team/brother_team/proc/forge_brother_objectives()
objectives = list()
var/is_hijacker = prob(10)
for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
forge_single_objective()
if(is_hijacker)
if(!locate(/datum/objective/hijack) in objectives)
add_objective(new/datum/objective/hijack)
else if(!locate(/datum/objective/escape) in objectives)
add_objective(new/datum/objective/escape)
/datum/objective_team/brother_team/proc/forge_single_objective()
if(prob(50))
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
add_objective(new/datum/objective/destroy, TRUE)
else if(prob(30))
add_objective(new/datum/objective/maroon, TRUE)
else
add_objective(new/datum/objective/assassinate, TRUE)
else
add_objective(new/datum/objective/steal, TRUE)
/datum/game_mode
var/list/datum/mind/brothers = list()
var/list/datum/objective_team/brother_team/brother_teams = list()
var/list/datum/team/brother_team/brother_teams = list()
/datum/game_mode/traitor/bros
name = "traitor+brothers"
@@ -51,9 +13,10 @@
<span class='danger'>Blood Brothers</span>: Accomplish your objectives.\n\
<span class='notice'>Crew</span>: Do not let the traitors or brothers succeed!"
var/list/datum/objective_team/brother_team/pre_brother_teams = list()
var/list/datum/team/brother_team/pre_brother_teams = list()
var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off
var/const/min_team_size = 2
traitors_required = FALSE //Only teams are possible
var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library")
@@ -73,7 +36,7 @@
for(var/j = 1 to num_teams)
if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies)
break
var/datum/objective_team/brother_team/team = new
var/datum/team/brother_team/team = new
var/team_size = prob(10) ? min(3, possible_brothers.len) : 2
for(var/k = 1 to team_size)
var/datum/mind/bro = pick(possible_brothers)
@@ -86,50 +49,19 @@
return ..()
/datum/game_mode/traitor/bros/post_setup()
for(var/datum/objective_team/brother_team/team in pre_brother_teams)
for(var/datum/team/brother_team/team in pre_brother_teams)
team.meeting_area = pick(meeting_areas)
meeting_areas -= team.meeting_area
team.forge_brother_objectives()
for(var/datum/mind/M in team.members)
M.add_antag_datum(ANTAG_DATUM_BROTHER, team)
team.update_name()
brother_teams += pre_brother_teams
return ..()
/datum/game_mode/traitor/bros/generate_report()
return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust."
/datum/game_mode/proc/auto_declare_completion_brother()
if(!LAZYLEN(brother_teams))
return
var/text = "<br><font size=4><b>The blood brothers were:</b></font>"
var/teamnumber = 1
for(var/datum/objective_team/brother_team/team in brother_teams)
if(!team.members.len)
continue
text += "<br><font size=3><b>Team #[teamnumber++]</b></font>"
for(var/datum/mind/M in team.members)
text += printplayer(M)
var/win = TRUE
var/objective_count = 1
for(var/datum/objective/objective in team.objectives)
if(objective.check_completion())
text += "<br><B>Objective #[objective_count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS"))
else
text += "<br><B>Objective #[objective_count]</B>: [objective.explanation_text] <font color='red'>Fail.</font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL"))
if(!(istype(objective, /datum/objective/crew)))
win = FALSE
objective_count++
if(win)
text += "<br><font color='green'><B>The blood brothers were successful!</B></font>"
SSblackbox.record_feedback("tally", "brother_success", 1, "SUCCESS")
else
text += "<br><font color='red'><B>The blood brothers have failed!</B></font>"
SSblackbox.record_feedback("tally", "brother_success", 1, "FAIL")
text += "<br>"
to_chat(world, text)
/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind)
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
brotherhud.join_hud(brother_mind.current)
@@ -94,47 +94,6 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \
as paranoia may spread and inhibit workplace efficiency."
/datum/game_mode/proc/auto_declare_completion_changeling()
var/list/changelings = get_antagonists(/datum/antagonist/changeling,TRUE) //Only real lings get a mention
if(changelings.len)
var/text = "<br><font size=3><b>The changelings were:</b></font>"
for(var/datum/mind/changeling in changelings)
var/datum/antagonist/changeling/ling = changeling.has_antag_datum(/datum/antagonist/changeling)
var/changelingwin = 1
if(!changeling.current)
changelingwin = 0
text += printplayer(changeling)
//Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
text += "<br><b>Changeling ID:</b> [ling.changelingID]."
text += "<br><b>Genomes Extracted:</b> [ling.absorbedcount]"
if(changeling.objectives.len)
var/count = 1
for(var/datum/objective/objective in changeling.objectives)
if(objective.check_completion())
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <font color='green'><b>Success!</b></font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "SUCCESS"))
else
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <span class='danger'>Fail.</span> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "FAIL"))
if(!(istype(objective, /datum/objective/crew)))
changelingwin = 0
count++
if(changelingwin)
text += "<br><font color='green'><b>The changeling was successful!</b></font>"
SSblackbox.record_feedback("tally", "changeling_success", 1, "SUCCESS")
else
text += "<br><span class='boldannounce'>The changeling has failed.</span>"
SSblackbox.record_feedback("tally", "changeling_success", 1, "FAIL")
text += "<br>"
to_chat(world, text)
return 1
/proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof)
var/datum/dna/chosen_dna = chosen_prof.dna
user.real_name = chosen_prof.name
+15 -36
View File
@@ -65,13 +65,16 @@ Credit where due:
return TRUE
return FALSE
/proc/add_servant_of_ratvar(mob/L, silent = FALSE)
/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE)
if(!L || !L.mind)
return
var/update_type = ANTAG_DATUM_CLOCKCULT
if(silent)
update_type = ANTAG_DATUM_CLOCKCULT_SILENT
. = L.mind.add_antag_datum(update_type)
var/datum/antagonist/clockcult/C = new update_type(L.mind)
C.make_team = create_team
C.show_in_roundend = create_team //tutorial scarabs begone
. = L.mind.add_antag_datum(C)
/proc/remove_servant_of_ratvar(mob/L, silent = FALSE)
if(!L || !L.mind)
@@ -88,7 +91,6 @@ Credit where due:
///////////////
/datum/game_mode
var/datum/mind/eminence //The clockwork Eminence
var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar
var/clockwork_explanation = "Defend the Ark of the Clockwork Justiciar and free Ratvar." //The description of the current objective
@@ -111,6 +113,8 @@ Credit where due:
var/roundstart_player_count
var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.)
var/datum/team/clockcult/main_clockcult
/datum/game_mode/clockwork_cult/pre_setup()
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
@@ -185,22 +189,21 @@ Credit where due:
return FALSE
/datum/game_mode/clockwork_cult/check_finished()
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
if(G && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed
if(GLOB.ark_of_the_clockwork_justiciar && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed
return FALSE
. = ..()
return ..()
/datum/game_mode/clockwork_cult/proc/check_clockwork_victory()
return main_clockcult.check_clockwork_victory()
/datum/game_mode/clock_cult/set_round_result()
..()
if(GLOB.clockwork_gateway_activated)
SSticker.news_report = CLOCK_SUMMON
return TRUE
SSticker.mode_result = "win - servants completed their objective (summon ratvar)"
else
SSticker.news_report = CULT_FAILURE
return FALSE
/datum/game_mode/clockwork_cult/declare_completion()
..()
return //Doesn't end until the round does
SSticker.mode_result = "loss - servants failed their objective (summon ratvar)"
/datum/game_mode/clockwork_cult/generate_report()
return "Bluespace monitors near your sector have detected a continuous stream of patterned fluctuations since the station was completed. It is most probable that a powerful entity \
@@ -210,30 +213,6 @@ Credit where due:
working for this entity and utilizing highly-advanced technology to cross the great distance at will. If they should turn out to be a credible threat, the task falls on you and \
your crew to dispatch it in a timely manner."
/datum/game_mode/proc/auto_declare_completion_clockwork_cult()
var/text = ""
if(istype(SSticker.mode, /datum/game_mode/clockwork_cult)) //Possibly hacky?
var/datum/game_mode/clockwork_cult/C = SSticker.mode
if(C.check_clockwork_victory())
text += "<span class='bold large_brass'>Ratvar's servants defended the Ark until its activation!</span>"
SSticker.mode_result = "win - servants completed their objective (summon ratvar)"
else
text += "<span class='userdanger'>The Ark was destroyed! Ratvar will rust away for all eternity!</span>"
SSticker.mode_result = "loss - servants failed their objective (summon ratvar)"
text += "<br><b>The servants' objective was:</b> [CLOCKCULT_OBJECTIVE]."
text += "<br>Ratvar's servants had <b>[GLOB.clockwork_caches]</b> Tinkerer's Caches."
text += "<br><b>Construction Value(CV)</b> was: <b>[GLOB.clockwork_construction_value]</b>"
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER)
text += "<br><b>[i] scripture</b> was: <b>[SSticker.scripture_states[i] ? "UN":""]LOCKED</b>"
if(SSticker.mode.eminence)
text += "<br><b>The Eminence was:</b> [printplayer(SSticker.mode.eminence)]"
if(servants_of_ratvar.len)
text += "<br><b>Ratvar's servants were:</b>"
for(var/datum/mind/M in servants_of_ratvar - SSticker.mode.eminence)
text += printplayer(M)
to_chat(world, text)
/datum/game_mode/proc/update_servant_icons_added(datum/mind/M)
var/datum/atom_hud/antag/A = GLOB.huds[ANTAG_HUD_CLOCKWORK]
A.join_hud(M.current)
@@ -275,7 +275,6 @@
/obj/effect/clockwork/sigil/vitality/sigil_effects(mob/living/L)
if((is_servant_of_ratvar(L) && L.suiciding) || sigil_active)
return
visible_message("<span class='warning'>[src] begins to glow bright blue!</span>")
animate(src, alpha = 255, time = 10, flags = ANIMATION_END_NOW) //we may have a previous animation going. finish it first, then do this one without delay.
sleep(10)
//as long as they're still on the sigil and are either not a servant or they're a servant AND it has remaining vitality
@@ -355,5 +354,4 @@
if(sigil_active)
animation_number = initial(animation_number)
sigil_active = FALSE
visible_message("<span class='warning'>[src] slowly stops glowing!</span>")
animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW)
@@ -91,7 +91,8 @@
/obj/item/clockwork/construct_chassis/cogscarab/pre_spawn()
if(infinite_resources)
construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar //During rounds where they can't interact with the station, let them experiment with builds
//During rounds where they can't interact with the station, let them experiment with builds
construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar
/obj/item/clockwork/construct_chassis/cogscarab/post_spawn(mob/living/construct)
if(infinite_resources) //Allow them to build stuff and recite scripture
@@ -18,16 +18,6 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/static/superheated_walls = 0
/mob/camera/eminence/Initialize()
if(SSticker.mode.eminence)
return INITIALIZE_HINT_QDEL
. = ..()
/mob/camera/eminence/Destroy(force)
if(!force && mind && SSticker.mode.eminence == mind)
return QDEL_HINT_LETMELIVE
return ..()
/mob/camera/eminence/CanPass(atom/movable/mover, turf/target)
return TRUE
@@ -46,20 +36,20 @@
/mob/camera/eminence/Login()
..()
add_servant_of_ratvar(src, TRUE)
var/datum/antagonist/clockcult/C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
if(C && C.clock_team)
if(C.clock_team.eminence)
remove_servant_of_ratvar(src,TRUE)
qdel(src)
return
else
C.clock_team.eminence = src
if(!C)
add_servant_of_ratvar(src, TRUE)
C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
if(C && C.clock_team)
if(C.clock_team.eminence)
remove_servant_of_ratvar(src,TRUE)
qdel(src)
else
C.clock_team.eminence = src
to_chat(src, "<span class='bold large_brass'>You have been selected as the Eminence!</span>")
to_chat(src, "<span class='brass'>As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.</span>")
to_chat(src, "<span class='brass'>Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.</span>")
to_chat(src, "<span class='brass'>Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.</span>")
SSticker.mode.eminence = mind
eminence_help()
for(var/V in actions)
var/datum/action/A = V
@@ -17,7 +17,11 @@
return
if(kingmaking)
return
if(SSticker.mode.eminence)
var/datum/antagonist/clockcult/C = user.mind.has_antag_datum(/datum/antagonist/clockcult)
if(!C || !C.clock_team)
return
if(C.clock_team.eminence)
to_chat(user, "<span class='warning'>There's already an Eminence!</span>")
return
if(!GLOB.servants_active)
+25 -183
View File
@@ -2,24 +2,23 @@
/datum/game_mode
var/list/datum/mind/cult = list()
var/list/cult_objectives = list()
var/eldergod = 1 //for the summon god objective
/proc/iscultist(mob/living/M)
return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT)
/proc/is_sacrifice_target(datum/mind/mind)
if(mind == GLOB.sac_mind)
return TRUE
/datum/team/cult/proc/is_sacrifice_target(datum/mind/mind)
for(var/datum/objective/sacrifice/sac_objective in objectives)
if(mind == sac_objective.target)
return TRUE
return FALSE
/proc/is_convertable_to_cult(mob/living/M)
/proc/is_convertable_to_cult(mob/living/M,datum/team/cult/specific_cult)
if(!istype(M))
return FALSE
if(M.mind)
if(ishuman(M) && (M.mind.assigned_role in list("Captain", "Chaplain")))
return FALSE
if(is_sacrifice_target(M.mind))
if(specific_cult && specific_cult.is_sacrifice_target(M.mind))
return FALSE
if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to))
return FALSE
@@ -55,10 +54,10 @@
var/list/cultists_to_cult = list() //the cultists we'll convert
var/datum/team/cult/main_cult
/datum/game_mode/cult/pre_setup()
cult_objectives += "sacrifice"
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
@@ -86,82 +85,19 @@
/datum/game_mode/cult/post_setup()
if("sacrifice" in cult_objectives)
var/list/possible_targets = get_unconvertables()
if(!possible_targets.len)
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !(player.mind in cultists_to_cult))
possible_targets += player.mind
if(possible_targets.len > 0)
GLOB.sac_mind = pick(possible_targets)
if(!GLOB.sac_mind)
message_admins("Cult Sacrifice: ERROR - Null target chosen!")
else
var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role)
var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs
var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
reshape.Shift(SOUTH, 4)
reshape.Shift(EAST, 1)
reshape.Crop(7,4,26,31)
reshape.Crop(-5,-3,26,30)
GLOB.sac_image = reshape
else
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
if(!GLOB.summon_spots.len)
while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
if((summon.z in GLOB.station_z_levels) && summon.valid_territory)
GLOB.summon_spots += summon
cult_objectives += "eldergod"
for(var/datum/mind/cult_mind in cultists_to_cult)
equip_cultist(cult_mind.current)
update_cult_icons_added(cult_mind)
to_chat(cult_mind.current, "<span class='userdanger'>You are a member of the cult!</span>")
cult_mind.current.playsound_local(get_turf(cult_mind.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
add_cultist(cult_mind, 0)
add_cultist(cult_mind, 0, equip=TRUE)
..()
/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob,tome = 0)
if(!istype(mob))
return
if (mob.mind)
if (mob.mind.assigned_role == "Clown")
to_chat(mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
mob.dna.remove_mutation(CLOWNMUT)
if(tome)
. += cult_give_item(/obj/item/tome, mob)
else
. += cult_give_item(/obj/item/paper/talisman/supply, mob)
to_chat(mob, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.</span>")
/datum/game_mode/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob)
var/list/slots = list(
"backpack" = slot_in_backpack,
"left pocket" = slot_l_store,
"right pocket" = slot_r_store
)
var/T = new item_path(mob)
var/item_name = initial(item_path.name)
var/where = mob.equip_in_one_of_slots(T, slots)
if(!where)
to_chat(mob, "<span class='userdanger'>Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).</span>")
return 0
else
to_chat(mob, "<span class='danger'>You have a [item_name] in your [where].</span>")
if(where == "backpack")
var/obj/item/storage/B = mob.back
B.orient2hud(mob)
B.show_to(mob)
return 1
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun) //BASE
/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun , equip = FALSE) //BASE
if (!istype(cult_mind))
return 0
if(cult_mind.add_antag_datum(ANTAG_DATUM_CULT))
var/datum/antagonist/cult/new_cultist = new(cult_mind)
new_cultist.give_equipment = equip
if(cult_mind.add_antag_datum(new_cultist))
if(stun)
cult_mind.current.Unconscious(100)
return 1
@@ -187,25 +123,19 @@
culthud.leave_hud(cult_mind.current)
set_antag_hud(cult_mind.current, null)
/datum/game_mode/cult/proc/get_unconvertables()
var/list/ucs = list()
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(player.mind && !is_convertable_to_cult(player) && !(player.mind in cultists_to_cult))
ucs += player.mind
return ucs
/datum/game_mode/cult/proc/check_cult_victory()
var/cult_fail = 0
if(cult_objectives.Find("survive"))
cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise
if(cult_objectives.Find("eldergod"))
cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once
if(cult_objectives.Find("sacrifice"))
if(GLOB.sac_mind && !GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail
cult_fail++
return cult_fail //if any objectives aren't met, failure
return main_cult.check_cult_victory()
/datum/game_mode/cult/set_round_result()
..()
if(check_cult_victory())
SSticker.mode_result = "win - cult win"
SSticker.news_report = CULT_SUMMON
else
SSticker.mode_result = "loss - staff stopped the cult"
SSticker.news_report = CULT_FAILURE
/datum/game_mode/cult/proc/check_survive()
var/acolytes_survived = 0
for(var/datum/mind/cult_mind in cult)
@@ -218,57 +148,6 @@
return 1
/datum/game_mode/cult/declare_completion()
if(!check_cult_victory())
SSticker.mode_result = "win - cult win"
to_chat(world, "<span class='greentext'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>")
else
SSticker.mode_result = "loss - staff stopped the cult"
to_chat(world, "<span class='redtext'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>")
var/text = ""
if(cult_objectives.len)
text += "<br><b>The cultists' objectives were:</b>"
for(var/obj_count=1, obj_count <= cult_objectives.len, obj_count++)
var/explanation
switch(cult_objectives[obj_count])
if("survive")
if(!check_survive())
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) <span class='greenannounce'>Success!</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "SUCCESS"))
SSticker.news_report = CULT_ESCAPE
else
explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) <span class='boldannounce'>Fail.</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "FAIL"))
SSticker.news_report = CULT_FAILURE
if("sacrifice")
if(GLOB.sac_complete)
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='greenannounce'>Success!</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS"))
else
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='boldannounce'>Fail.</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL"))
if("eldergod")
if(!eldergod)
explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)].<span class='greenannounce'>Success!</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS"))
SSticker.news_report = CULT_SUMMON
else
explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)]<span class='boldannounce'>Fail.</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL"))
SSticker.news_report = CULT_FAILURE
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
if(cult.len)
text += "<br><b>The cultists were:</b>"
for(var/datum/mind/M in cult)
text += printplayer(M)
to_chat(world, text)
..()
return 1
/datum/game_mode/cult/generate_report()
return "Some stations in your sector have reported evidence of blood sacrifice and strange magic. Ties to the Wizards' Federation have been proven not to exist, and many employees \
have disappeared; even Central Command employees light-years away have felt strange presences and at times hysterical compulsions. Interrogations point towards this being the work of \
@@ -276,41 +155,4 @@
devoted to stopping this cult. Note that holy water seems to weaken and eventually return the minds of cultists that ingest it, and mindshield implants will prevent conversion \
altogether."
/datum/game_mode/proc/datum_cult_completion()
var/text = ""
var/cult_fail = 0
cult_fail += eldergod
if(!GLOB.sac_complete)
cult_fail++
if(!cult_fail)
SSticker.mode_result = "win - cult win"
to_chat(world, "<span class='greentext'>The cult has succeeded! Nar-sie has snuffed out another torch in the void!</span>")
else
SSticker.mode_result = "loss - staff stopped the cult"
to_chat(world, "<span class='redtext'>The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!</span>")
if(cult_objectives.len)
text += "<br><b>The cultists' objectives were:</b>"
for(var/obj_count in 1 to 2)
var/explanation
switch(cult_objectives[obj_count])
if("sacrifice")
if(GLOB.sac_mind)
if(GLOB.sac_complete)
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='greenannounce'>Success!</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS"))
else
explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. <span class='boldannounce'>Fail.</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL"))
if("eldergod")
if(!eldergod)
explanation = "Summon Nar-Sie. <span class='greenannounce'>Success!</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS"))
SSticker.news_report = CULT_SUMMON
else
explanation = "Summon Nar-Sie. <span class='boldannounce'>Fail.</span>"
SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL"))
SSticker.news_report = CULT_FAILURE
text += "<br><B>Objective #[obj_count]</B>: [explanation]"
to_chat(world, text)
#undef CULT_SCALING_COEFFICIENT
+39 -31
View File
@@ -30,7 +30,7 @@
user.whisper("O bidai nabora se[pick("'","`")]sma!", language = /datum/language/common)
user.whisper(html_decode(message))
var/title = "Acolyte"
var/span = "cultitalic"
var/span = "cult italic"
if(user.mind && user.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
span = "cultlarge"
if(ishuman(user))
@@ -88,19 +88,21 @@
button_icon_state = "cultvote"
/datum/action/innate/cult/mastervote/IsAvailable()
if(GLOB.cult_vote_called || !ishuman(owner))
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C || C.cult_team.cult_vote_called || !ishuman(owner))
return FALSE
return ..()
/datum/action/innate/cult/mastervote/Activate()
pollCultists(owner)
var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
pollCultists(owner,C.cult_team)
/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll
/proc/pollCultists(var/mob/living/Nominee,datum/team/cult/team) //Cult Master Poll
if(world.time < CULT_POLL_WAIT)
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].")
return
GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try
for(var/datum/mind/B in SSticker.mode.cult)
team.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_action_buttons_icon()
if(!B.current.incapacitated())
@@ -108,39 +110,39 @@
to_chat(B.current, "<span class='cultlarge'>Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.</span>")
sleep(100)
var/list/asked_cultists = list()
for(var/datum/mind/B in SSticker.mode.cult)
for(var/datum/mind/B in team.members)
if(B.current && B.current != Nominee && !B.current.incapacitated())
SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg')
asked_cultists += B.current
var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists)
if(QDELETED(Nominee) || Nominee.incapacitated())
GLOB.cult_vote_called = FALSE
for(var/datum/mind/B in SSticker.mode.cult)
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_action_buttons_icon()
if(!B.current.incapacitated())
to_chat(B.current,"<span class='cultlarge'>[Nominee] has died in the process of attempting to win the cult's support!</span>")
return FALSE
if(!Nominee.mind)
GLOB.cult_vote_called = FALSE
for(var/datum/mind/B in SSticker.mode.cult)
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_action_buttons_icon()
if(!B.current.incapacitated())
to_chat(B.current,"<span class='cultlarge'>[Nominee] has gone catatonic in the process of attempting to win the cult's support!</span>")
return FALSE
if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5)
GLOB.cult_vote_called = FALSE
for(var/datum/mind/B in SSticker.mode.cult)
team.cult_vote_called = FALSE
for(var/datum/mind/B in team.members)
if(B.current)
B.current.update_action_buttons_icon()
if(!B.current.incapacitated())
to_chat(B.current, "<span class='cultlarge'>[Nominee] could not win the cult's support and shall continue to serve as an acolyte.</span>")
return FALSE
GLOB.cult_mastered = TRUE
team.cult_mastered = TRUE
SSticker.mode.remove_cultist(Nominee.mind, TRUE)
Nominee.mind.add_antag_datum(ANTAG_DATUM_CULT_MASTER)
for(var/datum/mind/B in SSticker.mode.cult)
for(var/datum/mind/B in team.members)
if(B.current)
for(var/datum/action/innate/cult/mastervote/vote in B.current.actions)
vote.Remove(B.current)
@@ -159,6 +161,9 @@
button_icon_state = "sintouch"
/datum/action/innate/cult/master/finalreck/Activate()
var/datum/antagonist/cult/antag = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!antag)
return
for(var/i in 1 to 4)
chant(i)
var/list/destinations = list()
@@ -169,7 +174,7 @@
to_chat(owner, "<span class='warning'>You need more space to summon the cult!</span>")
return
if(do_after(owner, 30, target = owner))
for(var/datum/mind/B in SSticker.mode.cult)
for(var/datum/mind/B in antag.cult_team.members)
if(B.current && B.current.stat != DEAD)
var/turf/mobloc = get_turf(B.current)
switch(i)
@@ -194,7 +199,7 @@
addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10)
else
return
GLOB.reckoning_complete = TRUE
antag.cult_team.reckoning_complete = TRUE
Remove(owner)
/mob/proc/reckon(turf/final)
@@ -269,34 +274,37 @@
var/turf/T = get_turf(ranged_ability_user)
if(!isturf(T))
return FALSE
var/datum/antagonist/cult/C = caller.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(target in view(7, get_turf(ranged_ability_user)))
GLOB.blood_target = target
C.cult_team.blood_target = target
var/area/A = get_area(target)
attached_action.cooldown = world.time + attached_action.base_cooldown
addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER)
GLOB.blood_target_image.appearance_flags = RESET_COLOR
GLOB.blood_target_image.pixel_x = -target.pixel_x
GLOB.blood_target_image.pixel_y = -target.pixel_y
C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER)
C.cult_team.blood_target_image.appearance_flags = RESET_COLOR
C.cult_team.blood_target_image.pixel_x = -target.pixel_x
C.cult_team.blood_target_image.pixel_y = -target.pixel_y
for(var/datum/mind/B in SSticker.mode.cult)
if(B.current && B.current.stat != DEAD && B.current.client)
to_chat(B.current, "<span class='cultlarge'><b>Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!</b></span>")
to_chat(B.current, "<span class='cultlarge'><b>Master [ranged_ability_user] has marked [C.cult_team.blood_target] in the [A.name] as the cult's top priority, get there immediately!</b></span>")
SEND_SOUND(B.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75))
B.current.client.images += GLOB.blood_target_image
B.current.client.images += C.cult_team.blood_target_image
attached_action.owner.update_action_buttons_icon()
remove_ranged_ability("<span class='cult'>The marking rite is complete! It will last for 90 seconds.</span>")
GLOB.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_STOPPABLE)
C.cult_team.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target,C.cult_team), 900, TIMER_STOPPABLE)
return TRUE
return FALSE
/proc/reset_blood_target()
for(var/datum/mind/B in SSticker.mode.cult)
/proc/reset_blood_target(datum/team/cult/team)
for(var/datum/mind/B in team.members)
if(B.current && B.current.stat != DEAD && B.current.client)
if(GLOB.blood_target)
if(team.blood_target)
to_chat(B.current,"<span class='cultlarge'><b>The blood mark has expired!</b></span>")
B.current.client.images -= GLOB.blood_target_image
QDEL_NULL(GLOB.blood_target_image)
GLOB.blood_target = null
B.current.client.images -= team.blood_target_image
QDEL_NULL(team.blood_target_image)
team.blood_target = null
+16 -7
View File
@@ -179,6 +179,13 @@ This file contains the arcane tome files.
var/list/shields = list()
var/area/A = get_area(src)
var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!user_antag)
return
var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives
var/datum/objective/sacrifice/sac_objective = locate() in user_antag.cult_team.objectives
if(!check_rune_turf(Turf, user))
return
entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in GLOB.rune_types
@@ -196,18 +203,20 @@ This file contains the arcane tome files.
A = get_area(src)
if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user))
return
//AAAAAAAAAAAAAAAH, i'm rewriting enough for now so TODO: remove this shit
if(ispath(rune_to_scribe, /obj/effect/rune/narsie))
if(!("eldergod" in SSticker.mode.cult_objectives))
if(!summon_objective)
to_chat(user, "<span class='warning'>Nar-Sie does not wish to be summoned!</span>")
return
if(!GLOB.sac_complete)
if(sac_objective && !sac_objective.check_completion())
to_chat(user, "<span class='warning'>The sacrifice is not complete. The portal would lack the power to open if you tried!</span>")
return
if(!SSticker.mode.eldergod)
if(summon_objective.check_completion())
to_chat(user, "<span class='cultlarge'>\"I am already here. There is no need to try to summon me now.\"</span>")
return
if(!(A in GLOB.summon_spots))
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!</span>")
if(!(A in summon_objective.summon_spots))
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!</span>")
return
var/confirm_final = alert(user, "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?", "My life for Nar-Sie!", "No")
if(confirm_final == "No")
@@ -215,8 +224,8 @@ This file contains the arcane tome files.
return
Turf = get_turf(user)
A = get_area(src)
if(!(A in GLOB.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!</span>")
if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!</span>")
return
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg')
for(var/B in spiral_range_turfs(1, user, 1))
+32 -30
View File
@@ -349,7 +349,11 @@ structure_check() searches for nearby cultist structures required for the invoca
color = RUNE_COLOR_DARKRED
var/mob/living/L = pick(myriad_targets)
var/is_clock = is_servant_of_ratvar(L)
var/is_convertable = is_convertable_to_cult(L)
var/mob/living/F = invokers[1]
var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
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!"
..()
@@ -397,17 +401,27 @@ structure_check() searches for nearby cultist structures required for the invoca
return 1
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers)
var/mob/living/first_invoker = invokers[1]
if(!first_invoker)
return FALSE
var/datum/antagonist/cult/C = first_invoker.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(!C)
return
var/big_sac = FALSE
if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3)
for(var/M in invokers)
to_chat(M, "<span class='cultitalic'>[sacrificial] is too greatly linked to the world! You need three acolytes!</span>")
log_game("Offer rune failed - not enough acolytes and target is living or sac target")
return FALSE
if(sacrificial.mind)
GLOB.sacrificed += sacrificial.mind
if(is_sacrifice_target(sacrificial.mind))
GLOB.sac_complete = TRUE
big_sac = TRUE
for(var/datum/objective/sacrifice/sac_objective in C.cult_team.objectives)
if(sac_objective.target == sacrificial.mind)
sac_objective.sacced = TRUE
sac_objective.update_explanation_text()
big_sac = TRUE
else
GLOB.sacrificed += sacrificial
@@ -481,7 +495,6 @@ structure_check() searches for nearby cultist structures required for the invoca
sleep(40)
if(src)
color = RUNE_COLOR_RED
SSticker.mode.eldergod = FALSE
new /obj/singularity/narsie/large/cult(T) //Causes Nar-Sie to spawn even if the rune has been removed
/obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal.
@@ -497,10 +510,10 @@ structure_check() searches for nearby cultist structures required for the invoca
message_admins("[key_name_admin(user)] erased a Narsie rune with a null rod")
..()
//Rite of Resurrection: Requires a dead or inactive cultist. When reviving the dead, you can only perform one revival for every sacrifice your cult has carried out.
//Rite of Resurrection: Requires the corpse of a cultist and that there have been less revives than the number of people GLOB.sacrificed
/obj/effect/rune/raise_dead
cultist_name = "Revive Cultist"
cultist_desc = "requires a dead, mindless, or inactive cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be given a new life."
cultist_name = "Resurrect Cultist"
cultist_desc = "requires the corpse of a cultist placed upon the rune. Provided there have been sufficient sacrifices, they will be revived."
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
@@ -521,11 +534,16 @@ structure_check() searches for nearby cultist structures required for the invoca
return
rune_in_use = TRUE
for(var/mob/living/M in T.contents)
if(iscultist(M) && (M.stat == DEAD || !M.client || M.client.is_afk()))
if(iscultist(M) && M.stat == DEAD)
potential_revive_mobs |= M
if(!potential_revive_mobs.len)
to_chat(user, "<span class='cultitalic'>There are no dead cultists on the rune!</span>")
log_game("Raise Dead rune failed - no cultists to revive")
log_game("Raise Dead rune failed - no corpses to revive")
fail_invoke()
rune_in_use = FALSE
return
if(LAZYLEN(GLOB.sacrificed) <= revives_used)
to_chat(user, "<span class='warning'>You have sacrificed too few people to revive a cultist!</span>")
fail_invoke()
rune_in_use = FALSE
return
@@ -541,25 +559,9 @@ structure_check() searches for nearby cultist structures required for the invoca
else
invocation = initial(invocation)
..()
if(mob_to_revive.stat == DEAD)
if(LAZYLEN(GLOB.sacrificed) <= revives_used)
to_chat(user, "<span class='warning'>Your cult must carry out another sacrifice before it can revive a cultist!</span>")
fail_invoke()
rune_in_use = FALSE
return
revives_used++
mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it!
mob_to_revive.grab_ghost()
else if(!mob_to_revive.client || mob_to_revive.client.is_afk())
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", "[name]", null, "Blood Cultist", 50, mob_to_revive)
var/mob/dead/observer/theghost = null
if(candidates.len)
theghost = pick(candidates)
to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.")
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
mob_to_revive.ghostize(0)
mob_to_revive.key = theghost.key
revives_used++
mob_to_revive.revive(1, 1) //This does remove disabilities and such, but the rune might actually see some use because of it!
mob_to_revive.grab_ghost()
to_chat(mob_to_revive, "<span class='cultlarge'>\"PASNAR SAVRAE YAM'TOTH. Arise.\"</span>")
mob_to_revive.visible_message("<span class='warning'>[mob_to_revive] draws in a huge breath, red light shining from [mob_to_revive.p_their()] eyes.</span>", \
"<span class='cultlarge'>You awaken suddenly from the void. You're alive!</span>")
-38
View File
@@ -3,32 +3,6 @@
var/list/datum/mind/devils = list()
var/devil_ascended = 0 // Number of arch devils on station
/datum/game_mode/proc/auto_declare_completion_sintouched()
var/text = ""
if(sintouched.len)
text += "<br><span class='big'><b>The sintouched were:</b></span>"
var/list/sintouchedUnique = uniqueList(sintouched)
for(var/S in sintouchedUnique)
var/datum/mind/sintouched_mind = S
text += printplayer(sintouched_mind)
text += printobjectives(sintouched_mind)
text += "<br>"
text += "<br>"
to_chat(world, text)
/datum/game_mode/proc/auto_declare_completion_devils()
/var/text = ""
if(devils.len)
text += "<br><span class='big'><b>The devils were:</b></span>"
for(var/D in devils)
var/datum/mind/devil = D
text += printplayer(devil)
text += printdevilinfo(devil.current)
text += printobjectives(devil)
text += "<br>"
text += "<br>"
to_chat(world, text)
/datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity)
var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target)
for(var/i = 1 to quantity)
@@ -41,18 +15,6 @@
else
objective.find_target()
/datum/game_mode/proc/printdevilinfo(mob/living/ply)
var/datum/antagonist/devil/devilinfo = is_devil(ply)
if(!devilinfo)
return "Target is not a devil."
var/text = "</br>The devil's true name is: [devilinfo.truename]</br>"
text += "The devil's bans were:</br>"
text += " [GLOB.lawlorify[LORE][devilinfo.ban]]</br>"
text += " [GLOB.lawlorify[LORE][devilinfo.bane]]</br>"
text += " [GLOB.lawlorify[LORE][devilinfo.obligation]]</br>"
text += " [GLOB.lawlorify[LORE][devilinfo.banish]]</br></br>"
return text
/datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind)
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_DEVIL]
hud.join_hud(devil_mind.current)
+14 -80
View File
@@ -74,7 +74,6 @@
/datum/game_mode/proc/pre_setup()
return 1
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report.
if(!report)
@@ -242,55 +241,9 @@
return 0
/datum/game_mode/proc/declare_completion()
var/clients = 0
var/surviving_humans = 0
var/surviving_total = 0
var/ghosts = 0
var/escaped_humans = 0
var/escaped_total = 0
for(var/mob/M in GLOB.player_list)
if(M.client)
clients++
if(ishuman(M))
if(!M.stat)
surviving_humans++
if(M.z == ZLEVEL_CENTCOM)
escaped_humans++
if(!M.stat)
surviving_total++
if(M.z == ZLEVEL_CENTCOM)
escaped_total++
if(isobserver(M))
ghosts++
if(clients)
SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
if(ghosts)
SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts"))
if(surviving_humans)
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human"))
if(surviving_total)
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total"))
if(escaped_humans)
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human"))
if(escaped_total)
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total"))
send2irc("Server", "Round just ended.")
if(cult.len && !istype(SSticker.mode, /datum/game_mode/cult))
datum_cult_completion()
return 0
/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere.
return 0
/datum/game_mode/proc/send_intercept()
var/intercepttext = "<b><i>Central Command Status Summary</i></b><hr>"
intercepttext += "<b>Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \
@@ -452,34 +405,6 @@
for (var/C in GLOB.admins)
to_chat(C, msg)
/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck)
var/text = "<br><b>[ply.key]</b> was <b>[ply.name]</b> the <b>[ply.assigned_role]</b> and"
if(ply.current)
if(ply.current.stat == DEAD)
text += " <span class='boldannounce'>died</span>"
else
text += " <span class='greenannounce'>survived</span>"
if(fleecheck)
var/turf/T = get_turf(ply.current)
if(!T || !(T.z in GLOB.station_z_levels))
text += " while <span class='boldannounce'>fleeing the station</span>"
if(ply.current.real_name != ply.name)
text += " as <b>[ply.current.real_name]</b>"
else
text += " <span class='boldannounce'>had their body destroyed</span>"
return text
/datum/game_mode/proc/printobjectives(datum/mind/ply)
var/text = ""
var/count = 1
for(var/datum/objective/objective in ply.objectives)
if(objective.check_completion())
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <span class='greenannounce'>Success!</span>"
else
text += "<br><b>Objective #[count]</b>: [objective.explanation_text] <span class='boldannounce'>Fail.</span>"
count++
return text
//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1
/datum/game_mode/proc/age_check(client/C)
if(get_remaining_days(C) == 0)
@@ -519,11 +444,6 @@
station_goals += new picked
/datum/game_mode/proc/declare_station_goal_completion()
for(var/V in station_goals)
var/datum/station_goal/G = V
G.print_result()
/datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report
return "Gamemode report for [name] not set. Contact a coder."
@@ -532,3 +452,17 @@
nuke_off_station = off_station
if(off_station < 2)
station_was_nuked = TRUE //Will end the round on next check.
//Additional report section in roundend report
/datum/game_mode/proc/special_report()
return
//Set result and news report here
/datum/game_mode/proc/set_round_result()
SSticker.mode_result = "undefined"
if(station_was_nuked)
SSticker.news_report = STATION_DESTROYED_NUKE
if(EMERGENCY_ESCAPED_OR_ENDGAMED)
SSticker.news_report = STATION_EVACUATED
if(SSshuttle.emergency.is_hijacked())
SSticker.news_report = SHUTTLE_HIJACK
+9 -10
View File
@@ -30,30 +30,29 @@
spawn_meteors(ramp_up_final, wavetype)
/datum/game_mode/meteor/declare_completion()
var/text
/datum/game_mode/meteor/special_report()
var/survivors = 0
var/list/survivor_list = list()
for(var/mob/living/player in GLOB.player_list)
if(player.stat != DEAD)
++survivors
if(player.onCentCom())
text += "<br><b><font size=2>[player.real_name] escaped to the safety of CentCom.</font></b>"
survivor_list += "<span class='greentext'>[player.real_name] escaped to the safety of CentCom.</span>"
else if(player.onSyndieBase())
text += "<br><b><font size=2>[player.real_name] escaped to the (relative) safety of Syndicate Space.</font></b>"
survivor_list += "<span class='greentext'>[player.real_name] escaped to the (relative) safety of Syndicate Space.</span>"
else
text += "<br><font size=1>[player.real_name] survived but is stranded without any hope of rescue.</font>"
survivor_list += "<span class='neutraltext'>[player.real_name] survived but is stranded without any hope of rescue.</span>"
if(survivors)
to_chat(world, "<span class='boldnotice'>The following survived the meteor storm</span>:[text]")
return "<span class='header'>The following survived the meteor storm:</span><br>[survivor_list.Join("<br>")]"
else
to_chat(world, "<span class='boldnotice'>Nobody survived the meteor storm!</span>")
return "<span class='redtext big'>Nobody survived the meteor storm!</span>"
SSticker.mode_result = "end - evacuation"
/datum/game_mode/meteor/set_round_result()
..()
return 1
SSticker.mode_result = "end - evacuation"
/datum/game_mode/meteor/generate_report()
return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \
@@ -1,19 +1,5 @@
/datum/objective_team/abductor_team
member_name = "abductor"
var/list/objectives = list()
var/team_number
/datum/objective_team/abductor_team/is_solo()
return FALSE
/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O)
O.team = src
O.update_explanation_text()
objectives += O
/datum/game_mode
var/list/datum/mind/abductors = list()
var/list/datum/mind/abductees = list()
/datum/game_mode/abduction
name = "abduction"
@@ -24,7 +10,7 @@
required_players = 15
maximum_players = 50
var/max_teams = 4
var/list/datum/objective_team/abductor_team/abductor_teams = list()
var/list/datum/team/abductor_team/abductor_teams = list()
var/finished = FALSE
var/static/team_count = 0
@@ -51,7 +37,7 @@
if(team_number > max_teams)
return //or should it try to stuff them in anway ?
var/datum/objective_team/abductor_team/team = new
var/datum/team/abductor_team/team = new
team.team_number = team_number
team.name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
team.add_objective(new/datum/objective/experiment)
@@ -64,6 +50,7 @@
antag_candidates -= scientist
team.members |= scientist
scientist.assigned_role = "Abductor Scientist"
scientist.special_role = "Abductor Scientist"
log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.")
if(!agent)
@@ -71,18 +58,19 @@
antag_candidates -= agent
team.members |= agent
agent.assigned_role = "Abductor Agent"
agent.special_role = "Abductor Agent"
log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.")
abductor_teams += team
return team
/datum/game_mode/abduction/post_setup()
for(var/datum/objective_team/abductor_team/team in abductor_teams)
for(var/datum/team/abductor_team/team in abductor_teams)
post_setup_team(team)
return ..()
//Used for create antag buttons
/datum/game_mode/abduction/proc/post_setup_team(datum/objective_team/abductor_team/team)
/datum/game_mode/abduction/proc/post_setup_team(datum/team/abductor_team/team)
for(var/datum/mind/M in team.members)
if(M.assigned_role == "Abductor Scientist")
M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, team)
@@ -91,7 +79,7 @@
/datum/game_mode/abduction/check_finished()
if(!finished)
for(var/datum/objective_team/abductor_team/team in abductor_teams)
for(var/datum/team/abductor_team/team in abductor_teams)
for(var/datum/objective/O in team.objectives)
if(O.check_completion())
SSshuttle.emergency.request(null, set_coefficient = 0.5)
@@ -99,35 +87,6 @@
return ..()
return ..()
/datum/game_mode/abduction/declare_completion()
for(var/datum/objective_team/abductor_team/team in abductor_teams)
var/won = TRUE
for(var/datum/objective/O in team.objectives)
if(!O.check_completion())
won = FALSE
if(won)
to_chat(world, "<span class='greenannounce'>[team.name] team fulfilled its mission!</span>")
else
to_chat(world, "<span class='boldannounce'>[team.name] team failed its mission.</span>")
..()
return TRUE
/datum/game_mode/proc/auto_declare_completion_abduction()
var/text = ""
if(abductors.len)
text += "<br><span class='big'><b>The abductors were:</b></span>"
for(var/datum/mind/abductor_mind in abductors)
text += printplayer(abductor_mind)
text += printobjectives(abductor_mind)
text += "<br>"
if(abductees.len)
text += "<br><span class='big'><b>The abductees were:</b></span>"
for(var/datum/mind/abductee_mind in abductees)
text += printplayer(abductee_mind)
text += printobjectives(abductee_mind)
text += "<br>"
to_chat(world, text)
// LANDMARKS
/obj/effect/landmark/abductor
var/team_number = 1
@@ -144,9 +103,9 @@
/datum/objective/experiment/check_completion()
for(var/obj/machinery/abductor/experiment/E in GLOB.machines)
if(!istype(team, /datum/objective_team/abductor_team))
if(!istype(team, /datum/team/abductor_team))
return FALSE
var/datum/objective_team/abductor_team/T = team
var/datum/team/abductor_team/T = team
if(E.team_number == T.team_number)
return E.points >= target_amount
return FALSE
@@ -151,13 +151,18 @@
var/mob/living/mob_occupant = occupant
if(mob_occupant.stat != DEAD)
if(href_list["experiment"])
flash = Experiment(occupant,href_list["experiment"])
flash = Experiment(occupant,href_list["experiment"],usr)
updateUsrDialog()
add_fingerprint(usr)
/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type)
/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type,mob/user)
LAZYINITLIST(history)
var/mob/living/carbon/human/H = occupant
var/datum/antagonist/abductor/user_abductor = user.mind.has_antag_datum(/datum/antagonist/abductor)
if(!user_abductor)
return "<span class='bad'>Authorization failure. Contact mothership immidiately.</span>"
var/point_reward = 0
if(H in history)
return "<span class='bad'>Specimen already in database.</span>"
@@ -182,15 +187,8 @@
if(3)
to_chat(H, "<span class='warning'>You feel intensely watched.</span>")
sleep(5)
to_chat(H, "<span class='warning'><b>Your mind snaps!</b></span>")
H.gain_trauma_type(BRAIN_TRAUMA_MILD)
to_chat(H, "<big><span class='warning'><b>You can't remember how you got here...</b></span></big>")
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
SSticker.mode.abductees += H.mind
H.mind.objectives += O
H.mind.announce_objectives()
SSticker.mode.update_abductor_icons_added(H.mind)
user_abductor.team.abductees += H.mind
H.mind.add_antag_datum(/datum/antagonist/abductee)
for(var/obj/item/organ/heart/gland/G in H.internal_organs)
G.Start()
@@ -105,13 +105,18 @@
monkey_mind.special_role = null
/datum/game_mode/monkey/declare_completion()
/datum/game_mode/monkey/set_round_result()
..()
if(check_monkey_victory())
SSticker.mode_result = "win - monkey win"
to_chat(world, "<span class='userdanger'>The monkeys have overthrown their captors! Eeek eeeek!!</span>")
else
SSticker.mode_result = "loss - staff stopped the monkeys"
to_chat(world, "<span class='userdanger'>The staff managed to contain the monkey infestation!</span>")
/datum/game_mode/monkey/special_report()
if(check_monkey_victory())
return "<span class='redtext big'>The monkeys have overthrown their captors! Eeek eeeek!!</span>"
else
return "<span class='redtext big'>The staff managed to contain the monkey infestation!</span>"
/datum/game_mode/monkey/generate_report()
return "Reports of an ancient [pick("retrovirus", "flesh eating bacteria", "disease", "magical curse blamed on viruses", "banana blight")] outbreak that turn humans into monkeys has been reported in your quadrant. Any such infections may be treated with banana juice. If an outbreak occurs, ensure the station is quarantined to prevent a largescale outbreak at CentCom."
@@ -227,6 +227,7 @@
player_mind.assigned_role = "Morph"
player_mind.special_role = "Morph"
SSticker.mode.traitors |= player_mind
player_mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(S, S.playstyle_string)
SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
message_admins("[key_name_admin(S)] has been made into a morph by an event.")
@@ -87,6 +87,7 @@
mind.assigned_role = "revenant"
mind.special_role = "Revenant"
SSticker.mode.traitors |= mind //Necessary for announcing
mind.add_antag_datum(/datum/antagonist/auto_custom)
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
@@ -38,6 +38,7 @@
player_mind.assigned_role = "Slaughter Demon"
player_mind.special_role = "Slaughter Demon"
SSticker.mode.traitors |= player_mind
player_mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(S, S.playstyle_string)
to_chat(S, "<B>You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.</B>")
SEND_SOUND(S, 'sound/magic/demon_dies.ogg')
+7 -14
View File
@@ -17,7 +17,7 @@
var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer!
var/list/pre_nukeops = list()
var/datum/objective_team/nuclear/nuke_team
var/datum/team/nuclear/nuke_team
/datum/game_mode/nuclear/pre_setup()
var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible)
@@ -69,7 +69,8 @@
return FALSE //its a static var btw
..()
/datum/game_mode/nuclear/declare_completion()
/datum/game_mode/nuclear/set_round_result()
..()
var result = nuke_team.get_result()
switch(result)
if(NUKE_RESULT_FLUKE)
@@ -102,22 +103,12 @@
else
SSticker.mode_result = "halfwin - interrupted"
SSticker.news_report = OPERATIVE_SKIRMISH
return ..()
/datum/game_mode/nuclear/generate_report()
return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \
transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \
can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders."
/datum/game_mode/proc/auto_declare_completion_nuclear()
var/list/nuke_teams = list()
for(var/datum/antagonist/nukeop/N in GLOB.antagonists) //collect all nuke teams
nuke_teams |= N.nuke_team
for(var/datum/objective_team/nuclear/nuke_team in nuke_teams)
nuke_team.roundend_display()
return TRUE
/proc/is_nuclear_operative(mob/M)
return M && istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/nukeop)
@@ -132,7 +123,8 @@
l_pocket = /obj/item/pinpointer/nuke/syndicate
id = /obj/item/card/id/syndicate
belt = /obj/item/gun/ballistic/automatic/pistol
backpack_contents = list(/obj/item/storage/box/syndie=1)
backpack_contents = list(/obj/item/storage/box/syndie=1,\
/obj/item/kitchen/knife/combat/survival)
var/tc = 25
var/command_radio = FALSE
@@ -177,4 +169,5 @@
r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog
backpack_contents = list(/obj/item/storage/box/syndie=1,\
/obj/item/tank/jetpack/oxygen/harness=1,\
/obj/item/gun/ballistic/automatic/pistol=1)
/obj/item/gun/ballistic/automatic/pistol=1,\
/obj/item/kitchen/knife/combat/survival)
+12 -2
View File
@@ -3,6 +3,7 @@
var/list/datum/mind/members = list()
var/name = "team"
var/member_name = "member"
var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
/datum/objective_team/New(starting_members)
. = ..()
@@ -12,7 +13,6 @@
add_member(M)
else
add_member(starting_members)
members += starting_members
/datum/objective_team/proc/is_solo()
return members.len == 1
@@ -21,4 +21,14 @@
members |= new_member
/datum/objective_team/proc/remove_member(datum/mind/member)
members -= member
members -= member
//Display members/victory/failure/objectives for the team
/datum/objective_team/proc/roundend_report()
var/list/report = list()
report += "<b>[name]:</b>"
report += "The [member_name]s were:"
report += printplayerlist(members)
return report.Join("<br>")
+10 -50
View File
@@ -26,7 +26,7 @@
var/finished = 0
var/check_counter = 0
var/max_headrevs = 3
var/datum/objective_team/revolution/revolution
var/datum/team/revolution/revolution
var/list/datum/mind/headrev_candidates = list()
///////////////////////////
@@ -169,62 +169,22 @@
return FALSE
return TRUE
//////////////////////////////////////////////////////////////////////
//Announces the end of the game with all relavent information stated//
//////////////////////////////////////////////////////////////////////
/datum/game_mode/revolution/declare_completion()
/datum/game_mode/revolution/set_round_result()
..()
if(finished == 1)
SSticker.mode_result = "win - heads killed"
to_chat(world, "<span class='redtext'>The heads of staff were killed or exiled! The revolutionaries win!</span>")
SSticker.news_report = REVS_WIN
else if(finished == 2)
SSticker.mode_result = "loss - rev heads killed"
to_chat(world, "<span class='redtext'>The heads of staff managed to stop the revolution!</span>")
SSticker.news_report = REVS_LOSE
..()
return TRUE
/datum/game_mode/proc/auto_declare_completion_revolution()
var/list/targets = list()
var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head)
var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE)
if(headrevs.len)
var/num_revs = 0
var/num_survivors = 0
for(var/mob/living/carbon/survivor in GLOB.alive_mob_list)
if(survivor.ckey)
num_survivors++
if(survivor.mind)
if(is_revolutionary(survivor))
num_revs++
if(num_survivors)
to_chat(world, "[GLOB.TAB]Command's Approval Rating: <B>[100 - round((num_revs/num_survivors)*100, 0.1)]%</B>" )
var/text = "<br><font size=3><b>The head revolutionaries were:</b></font>"
for(var/datum/mind/headrev in headrevs)
text += printplayer(headrev, 1)
text += "<br>"
to_chat(world, text)
if(revs.len)
var/text = "<br><font size=3><b>The revolutionaries were:</b></font>"
for(var/datum/mind/rev in revs)
text += printplayer(rev, 1)
text += "<br>"
to_chat(world, text)
if(revs.len || headrevs.len)
var/text = "<br><font size=3><b>The heads of staff were:</b></font>"
var/list/heads = SSjob.get_all_heads()
for(var/datum/mind/head in heads)
var/target = (head in targets)
if(target)
text += "<span class='boldannounce'>Target</span>"
text += printplayer(head, 1)
text += "<br>"
to_chat(world, text)
//TODO What should be displayed for revs in non-rev rounds
/datum/game_mode/revolution/special_report()
if(finished == 1)
return "<span class='redtext big'>The heads of staff were killed or exiled! The revolutionaries win!</span>"
else if(finished == 2)
return "<span class='redtext big'>The heads of staff managed to stop the revolution!</span>"
/datum/game_mode/revolution/generate_report()
return "Employee unrest has spiked in recent weeks, with several attempted mutinies on heads of staff. Some crew have been observed using flashbulb devices to blind their colleagues, \
+2 -71
View File
@@ -27,6 +27,7 @@
var/traitors_possible = 4 //hard limit on traitors if scaling is turned off
var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual.
var/antag_datum = ANTAG_DATUM_TRAITOR //what type of antag to create
var/traitors_required = TRUE //Will allow no traitors
/datum/game_mode/traitor/pre_setup()
@@ -55,7 +56,7 @@
log_game("[traitor.key] (ckey) has been selected as a [traitor_name]")
antag_candidates.Remove(traitor)
return pre_traitors.len > 0
return !traitors_required || pre_traitors.len > 0
/datum/game_mode/traitor/post_setup()
@@ -85,80 +86,10 @@
new_antag.should_specialise = TRUE
character.add_antag_datum(new_antag)
/datum/game_mode/traitor/declare_completion()
..()
return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder.
/datum/game_mode/proc/auto_declare_completion_traitor()
if(traitors.len)
var/text = "<br><font size=3><b>The [traitor_name]s were:</b></font>"
for(var/datum/mind/traitor in traitors)
var/traitorwin = TRUE
text += printplayer(traitor)
var/TC_uses = 0
var/uplink_true = FALSE
var/purchases = ""
for(var/datum/component/uplink/H in GLOB.uplinks)
if(H && H.owner && H.owner == traitor.key)
TC_uses += H.spent_telecrystals
uplink_true = TRUE
purchases += H.purchase_log.generate_render(FALSE)
var/objectives = ""
if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this.
var/count = 1
for(var/datum/objective/objective in traitor.objectives)
if(objective.check_completion())
objectives += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS"))
else
objectives += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='red'>Fail.</font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL"))
if(!(istype(objective, /datum/objective/crew)))
traitorwin = FALSE
count++
if(uplink_true)
text += " (used [TC_uses] TC) [purchases]"
if(TC_uses==0 && traitorwin)
var/static/icon/badass = icon('icons/badass.dmi', "badass")
text += "<BIG>[icon2html(badass, world)]</BIG>"
text += objectives
var/special_role_text
if(traitor.special_role)
special_role_text = lowertext(traitor.special_role)
else
special_role_text = "antagonist"
if(traitorwin)
text += "<br><font color='green'><B>The [special_role_text] was successful!</B></font>"
SSblackbox.record_feedback("tally", "traitor_success", 1, "SUCCESS")
else
text += "<br><font color='red'><B>The [special_role_text] has failed!</B></font>"
SSblackbox.record_feedback("tally", "traitor_success", 1, "FAIL")
SEND_SOUND(traitor.current, 'sound/ambience/ambifailure.ogg')
text += "<br>"
text += "<br><b>The code phrases were:</b> <font color='red'>[GLOB.syndicate_code_phrase]</font><br>\
<b>The code responses were:</b> <font color='red'>[GLOB.syndicate_code_response]</font><br>"
to_chat(world, text)
return TRUE
/datum/game_mode/traitor/generate_report()
return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \
Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions."
/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind)
var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR]
traitorhud.join_hud(traitor_mind.current)
+2 -2
View File
@@ -64,7 +64,6 @@
to_chat(user, "<span class='cultlarge'>\"Come now, do not capture your bretheren's soul.\"</span>")
return
add_logs(user, M, "captured [M.name]'s soul", src)
transfer_soul("VICTIM", M, user)
///////////////////Options for using captured souls///////////////////////////////////////
@@ -142,7 +141,8 @@
if("VICTIM")
var/mob/living/carbon/human/T = target
if(is_sacrifice_target(T.mind))
var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
if(C && C.cult_team.is_sacrifice_target(T.mind))
if(iscultist(user))
to_chat(user, "<span class='cult'><b>\"This soul is mine.</b></span> <span class='cultlarge'>SACRIFICE THEM!\"</span>")
else
+5 -54
View File
@@ -58,65 +58,16 @@
return TRUE
/datum/game_mode/wizard/declare_completion()
/datum/game_mode/wizard/set_round_result()
..()
if(finished)
SSticker.mode_result = "loss - wizard killed"
to_chat(world, "<span class='userdanger'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>")
SSticker.news_report = WIZARD_KILLED
..()
return 1
/datum/game_mode/wizard/special_report()
if(finished)
return "<span class='redtext big'>The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!</span>"
/datum/game_mode/proc/auto_declare_completion_wizard()
if(wizards.len)
var/text = "<br><font size=3><b>the wizards/witches were:</b></font>"
for(var/datum/mind/wizard in wizards)
text += "<br><b>[wizard.key]</b> was <b>[wizard.name]</b> ("
if(wizard.current)
if(wizard.current.stat == DEAD)
text += "died"
else
text += "survived"
if(wizard.current.real_name != wizard.name)
text += " as <b>[wizard.current.real_name]</b>"
else
text += "body destroyed"
text += ")"
var/count = 1
var/wizardwin = 1
for(var/datum/objective/objective in wizard.objectives)
if(objective.check_completion())
text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "SUCCESS"))
else
text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <font color='red'>Fail.</font> [istype(objective, /datum/objective/crew) ? "<font color='grey'>(Optional)</font>" : ""]"
SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "FAIL"))
if(!(istype(objective, /datum/objective/crew)))
wizardwin = 0
count++
if(wizard.current && wizardwin)
text += "<br><font color='green'><B>The wizard was successful!</B></font>"
SSblackbox.record_feedback("tally", "wizard_success", 1, "SUCCESS")
else
text += "<br><font color='red'><B>The wizard has failed!</B></font>"
SSblackbox.record_feedback("tally", "wizard_success", 1, "FAIL")
if(wizard.spell_list.len>0)
text += "<br><B>[wizard.name] used the following spells: </B>"
var/i = 1
for(var/obj/effect/proc_holder/spell/S in wizard.spell_list)
text += "[S.name]"
if(wizard.spell_list.len > i)
text += ", "
i++
text += "<br>"
to_chat(world, text)
return 1
//returns whether the mob is a wizard (or apprentice)
/proc/iswizard(mob/living/M)
return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE)
+1 -1
View File
@@ -10,7 +10,7 @@
icon = 'icons/obj/machines/limbgrower.dmi'
icon_state = "limbgrower_idleoff"
density = TRUE
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 10
+1
View File
@@ -45,6 +45,7 @@
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
user.mind.objectives += hijack
user.mind.add_antag_datum(/datum/antagonist/auto_custom)
user.mind.announce_objectives()
+2 -2
View File
@@ -571,9 +571,9 @@
if(bumpsmash && occupant) //Need a pilot to push the PUNCH button.
if(nextsmash < world.time)
obstacle.mech_melee_attack(src)
if(!obstacle || !obstacle.density)
step(src,dir)
nextsmash = world.time + smashcooldown
if(!obstacle || obstacle.CanPass(src,get_step(src,dir)))
step(src,dir)
if(isobj(obstacle))
var/obj/O = obstacle
if(!O.anchored)
@@ -47,10 +47,8 @@
return
else
var/hotness = W.is_hot()
var/added_heat = (hotness / 100)
src.reagents.chem_temp = min(src.reagents.chem_temp + added_heat, hotness)
src.reagents.handle_reactions()
to_chat(user, "<span class='notice'>You heat [src] with [W]!</span>")
reagents.expose_temperature(hotness)
to_chat(user, "<span class='notice'>You heat [name] with [W]!</span>")
else
return ..()
@@ -62,8 +60,7 @@
/obj/effect/decal/cleanable/fire_act(exposed_temperature, exposed_volume)
if(reagents)
reagents.chem_temp += 30
reagents.handle_reactions()
reagents.expose_temperature(exposed_temperature)
..()
+2 -2
View File
@@ -102,7 +102,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
icon_state = "cigoff"
throw_speed = 0.5
item_state = "cigoff"
container_type = INJECTABLE_1
container_type = INJECTABLE
w_class = WEIGHT_CLASS_TINY
body_parts_covered = null
grind_results = list()
@@ -660,7 +660,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
item_state = "[param_color]_vape"
/obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/reagent_containers) && (O.container_type & OPENCONTAINER_1))
if(O.is_drainable())
if(reagents.total_volume < chem_volume)
if(O.reagents.total_volume > 0)
O.reagents.trans_to(src,25)
+3 -4
View File
@@ -16,6 +16,7 @@
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
dog_fashion = /datum/dog_fashion/back
resistance_flags = FIRE_PROOF
container_type = AMOUNT_VISIBLE
var/max_water = 50
var/last_use = 1
var/safety = TRUE
@@ -48,7 +49,6 @@
/obj/item/extinguisher/attack_self(mob/user)
safety = !safety
src.icon_state = "[sprite_name][!safety]"
src.desc = "The safety is [safety ? "on" : "off"]."
to_chat(user, "The safety is [safety ? "on" : "off"].")
return
@@ -67,11 +67,10 @@
/obj/item/extinguisher/examine(mob/user)
..()
to_chat(user, "The safety is [safety ? "on" : "off"].")
if(reagents.total_volume)
to_chat(user, "It contains [round(reagents.total_volume)] unit\s.")
to_chat(user, "<span class='notice'>Alt-click to empty it.</span>")
else
to_chat(user, "It is empty.")
/obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user)
if(istype(target, /obj/structure/reagent_dispensers/watertank) && target.Adjacent(user))
+28 -6
View File
@@ -7,6 +7,9 @@
/*
* Gifts
*/
GLOBAL_LIST_EMPTY(possible_gifts)
/obj/item/a_gift
name = "gift"
desc = "PRESENTS!!!! eek!"
@@ -30,6 +33,14 @@
to_chat(M, "<span class='warning'>You're supposed to be spreading gifts, not opening them yourself!</span>")
return
var/gift_type = get_gift_type()
qdel(src)
var/obj/item/I = new gift_type(M)
M.put_in_hands(I)
I.add_fingerprint(M)
/obj/item/a_gift/proc/get_gift_type()
var/gift_type_list = list(/obj/item/sord,
/obj/item/storage/wallet,
/obj/item/storage/photo_album,
@@ -72,10 +83,21 @@
var/gift_type = pick(gift_type_list)
if(!ispath(gift_type, /obj/item))
return
return gift_type
qdel(src)
var/obj/item/I = new gift_type(M)
M.put_in_hands(I)
I.add_fingerprint(M)
/obj/item/a_gift/anything
name = "christmas gift"
desc = "It could be anything!"
/obj/item/a_gift/anything/get_gift_type()
if(!GLOB.possible_gifts.len)
var/list/gift_types_list = subtypesof(/obj/item)
for(var/V in gift_types_list)
var/obj/item/I = V
if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.flags_1) & ABSTRACT_1))
gift_types_list -= V
GLOB.possible_gifts = gift_types_list
var/gift_type = pick(GLOB.possible_gifts)
return gift_type
@@ -2,7 +2,7 @@
name = "chem implant"
desc = "Injects things."
icon_state = "reagents"
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
/obj/item/implant/chem/get_data()
var/dat = {"<b>Implant Specifications:</b><BR>
+1 -1
View File
@@ -419,7 +419,7 @@
name = "suspicious looking duffel bag"
desc = "A large duffel bag for holding extra tactical supplies."
icon_state = "duffel-syndie"
item_state = "duffel-syndie"
item_state = "duffel-syndieammo"
silent = 1
slowdown = 0
+2 -2
View File
@@ -114,7 +114,7 @@
possible_transfer_amounts = list(25,50,100)
volume = 500
flags_1 = NOBLUDGEON_1
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
slot_flags = 0
var/obj/item/watertank/tank
@@ -351,7 +351,7 @@
var/usage_ratio = 5 //5 unit added per 1 removed
var/injection_amount = 1
amount_per_transfer_from_this = 5
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
spillable = FALSE
possible_transfer_amounts = list(5,10,15)
+2 -2
View File
@@ -120,7 +120,7 @@
/obj/item/weldingtool/afterattack(atom/O, mob/user, proximity)
if(!proximity)
return
if(!status && istype(O, /obj/item/reagent_containers) && O.is_open_container())
if(!status && O.is_refillable())
reagents.trans_to(O, reagents.total_volume)
to_chat(user, "<span class='notice'>You empty [src]'s fuel tank into [O].</span>")
update_icon()
@@ -241,7 +241,7 @@
container_type = NONE
else
to_chat(user, "<span class='notice'>[src] can now be attached, modified, and refuelled.</span>")
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
add_fingerprint(user)
/obj/item/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user)
+15 -3
View File
@@ -36,9 +36,6 @@
else
return ..()
/obj/structure/flora/tree/pine
name = "pine tree"
desc = "A coniferous pine tree."
@@ -53,6 +50,21 @@
name = "xmas tree"
desc = "A wondrous decorated Christmas tree."
icon_state = "pine_c"
var/gifts_under_tree = FALSE
var/list/ckeys_that_took = list()
/obj/structure/flora/tree/pine/xmas/attack_hand(mob/living/user)
if(!gifts_under_tree)
return
if(!user.ckey)
return
if(ckeys_that_took[user.ckey])
to_chat(user, "<span class='warning'>You already took your gift.</span>")
return
to_chat(user, "<span class='warning'>After a bit of rummaging, you locate a gift with your name on it!</span>")
ckeys_that_took[user.ckey] = TRUE
var/obj/item/a_gift/anything/A = new
user.put_in_hands(A)
/obj/structure/flora/tree/pine/xmas/Initialize()
. = ..()
+1 -1
View File
@@ -5,7 +5,7 @@
icon_state = "cart"
anchored = FALSE
density = TRUE
container_type = OPENCONTAINER_1
container_type = OPENCONTAINER
//copypaste sorry
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
var/obj/item/storage/bag/trash/mybag = null
+1 -1
View File
@@ -89,7 +89,7 @@
name = "magic mirror"
desc = "Turn and face the strange... face."
icon_state = "magic_mirror"
var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombie")
var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombies")
var/list/choosable_races = list()
/obj/structure/mirror/magic/New()
+23 -23
View File
@@ -1,24 +1,24 @@
/obj/structure/mopbucket
name = "mop bucket"
desc = "Fill it with water, but don't forget a mop!"
icon = 'icons/obj/janitor.dmi'
icon_state = "mopbucket"
/obj/structure/mopbucket
name = "mop bucket"
desc = "Fill it with water, but don't forget a mop!"
icon = 'icons/obj/janitor.dmi'
icon_state = "mopbucket"
density = TRUE
container_type = OPENCONTAINER_1
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
/obj/structure/mopbucket/New()
create_reagents(100)
..()
/obj/structure/mopbucket/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/mop))
if(reagents.total_volume < 1)
to_chat(user, "[src] is out of water!</span>")
else
reagents.trans_to(I, 5)
to_chat(user, "<span class='notice'>You wet [I] in [src].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
else
return ..()
container_type = OPENCONTAINER
var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
/obj/structure/mopbucket/New()
create_reagents(100)
..()
/obj/structure/mopbucket/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/mop))
if(reagents.total_volume < 1)
to_chat(user, "[src] is out of water!</span>")
else
reagents.trans_to(I, 5)
to_chat(user, "<span class='notice'>You wet [I] in [src].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
else
return ..()
+3 -3
View File
@@ -483,9 +483,9 @@
if(istype(O, /obj/item/reagent_containers))
var/obj/item/reagent_containers/RG = O
if(RG.container_type & OPENCONTAINER_1)
if(RG.is_refillable())
if(!RG.reagents.holder_full())
RG.reagents.add_reagent("[dispensedreagent]", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this))
to_chat(user, "<span class='notice'>You fill [RG] from [src].</span>")
return TRUE
to_chat(user, "<span class='notice'>\The [RG] is full.</span>")
@@ -533,7 +533,7 @@
O.clean_blood()
O.acid_level = 0
create_reagents(5)
reagents.add_reagent("[dispensedreagent]", 5)
reagents.add_reagent(dispensedreagent, 5)
reagents.reaction(O, TOUCH)
user.visible_message("<span class='notice'>[user] washes [O] using [src].</span>", \
"<span class='notice'>You wash [O] using [src].</span>")
+4 -2
View File
@@ -139,9 +139,11 @@
if(isliving(A))
var/mob/living/L = A
if(L.pulling)
var/atom/movable/AM = L.pulling
if(AM)
var/turf/T = get_step(L.loc,turn(A.dir, 180))
L.pulling.forceMove(T)
AM.forceMove(T)
L.start_pulling(AM)
//now we're on the new z_level, proceed the space drifting
stoplag()//Let a diagonal move finish, if necessary