Merge remote-tracking branch 'Citadel-Station-13/master' into Garlic
This commit is contained in:
@@ -269,7 +269,7 @@ Credit where due:
|
||||
//Servant of Ratvar outfit
|
||||
/datum/outfit/servant_of_ratvar
|
||||
name = "Servant of Ratvar"
|
||||
uniform = /obj/item/clothing/under/rank/engineer //no more chameleon suit for them, as requested
|
||||
uniform = /obj/item/clothing/under/rank/engineering/engineer //no more chameleon suit for them, as requested
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
back = /obj/item/storage/backpack
|
||||
ears = /obj/item/radio/headset
|
||||
|
||||
@@ -4,23 +4,17 @@
|
||||
icon = 'icons/obj/machines/nuke.dmi'
|
||||
icon_state = "bananiumbomb_base"
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon()
|
||||
if(deconstruction_state == NUKESTATE_INTACT)
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "bananiumbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
if(NUKE_ON_TIMING)
|
||||
cut_overlays()
|
||||
icon_state = "bananiumbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
cut_overlays()
|
||||
icon_state = "bananiumbomb_exploding"
|
||||
else
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon_state()
|
||||
if(deconstruction_state != NUKESTATE_INTACT)
|
||||
icon_state = "bananiumbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
return
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "bananiumbomb_base"
|
||||
if(NUKE_ON_TIMING)
|
||||
icon_state = "bananiumbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
icon_state = "bananiumbomb_exploding"
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/get_cinematic_type(off_station)
|
||||
switch(off_station)
|
||||
@@ -41,7 +35,7 @@
|
||||
H.Stun(10)
|
||||
var/obj/item/clothing/C
|
||||
if(!H.w_uniform || H.dropItemToGround(H.w_uniform))
|
||||
C = new /obj/item/clothing/under/rank/clown(H)
|
||||
C = new /obj/item/clothing/under/rank/civilian/clown(H)
|
||||
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
|
||||
H.equip_to_slot_or_del(C, SLOT_W_UNIFORM)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
ruletype = "Event"
|
||||
var/typepath // typepath of the event
|
||||
var/triggering
|
||||
var/earliest_start = 20 MINUTES
|
||||
|
||||
/datum/dynamic_ruleset/event/get_blackbox_info()
|
||||
var/list/ruleset_data = list()
|
||||
@@ -25,8 +26,10 @@
|
||||
|
||||
return E
|
||||
|
||||
/datum/dynamic_ruleset/event/ready(forced = FALSE) // same as midround cause we're still using enemy system
|
||||
/datum/dynamic_ruleset/event/ready(forced = FALSE)
|
||||
if (!forced)
|
||||
if(earliest_start >= world.time-SSticker.round_start_time)
|
||||
return FALSE
|
||||
var/job_check = 0
|
||||
if (enemy_roles.len > 0)
|
||||
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
@@ -56,6 +59,7 @@
|
||||
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
|
||||
weight = 5
|
||||
cost = 10
|
||||
earliest_start = 30 MINUTES
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
|
||||
requirements = list(70,60,50,50,40,40,40,30,20,15)
|
||||
property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1)
|
||||
@@ -157,17 +161,18 @@
|
||||
required_enemies = list(3,3,3,3,3,3,3,3,3,3)
|
||||
cost = 15
|
||||
weight = 3
|
||||
earliest_start = 25 MINUTES
|
||||
repeatable_weight_decrease = 2
|
||||
requirements = list(60,50,40,30,30,30,30,30,30,30)
|
||||
high_population_requirement = 30
|
||||
property_weights = list("extended" = -2)
|
||||
|
||||
/datum/dynamic_ruleset/event/meteor_wave/ready()
|
||||
if(mode.threat_level > 40 && mode.threat >= 25 && prob(20))
|
||||
if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30))
|
||||
name = "Meteor Wave: Threatening"
|
||||
cost = 25
|
||||
typepath = /datum/round_event/meteor_wave/threatening
|
||||
else if(mode.threat_level > 50 && mode.threat >= 40 && prob(30))
|
||||
else if(world.time-SSticker.round_start_time > 45 MINUTES && mode.threat_level > 50 && mode.threat >= 40 && prob(30))
|
||||
name = "Meteor Wave: Catastrophic"
|
||||
cost = 40
|
||||
typepath = /datum/round_event/meteor_wave/catastrophic
|
||||
@@ -280,6 +285,7 @@
|
||||
cost = 4
|
||||
requirements = list(10,10,10,10,10,10,10,10,10,10)
|
||||
high_population_requirement = 10
|
||||
earliest_start = 10 MINUTES
|
||||
repeatable = TRUE
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
@@ -324,6 +330,7 @@
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
repeatable = TRUE
|
||||
earliest_start = 0 MINUTES
|
||||
property_weights = list("extended" = 1)
|
||||
always_max_weight = TRUE
|
||||
|
||||
@@ -381,3 +388,67 @@
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = 1,"chaos" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/portal_storm_syndicate
|
||||
name = "Portal Storm"
|
||||
config_tag = "portal_storm"
|
||||
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
|
||||
cost = 10
|
||||
weight = 1
|
||||
enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(101,101,101,30,30,30,30,30,30,30)
|
||||
high_population_requirement = 30
|
||||
earliest_start = 30 MINUTES
|
||||
property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1)
|
||||
|
||||
/datum/dynamic_ruleset/event/wormholes
|
||||
name = "Wormholes"
|
||||
config_tag = "wormhole"
|
||||
typepath = /datum/round_event/wormholes
|
||||
cost = 3
|
||||
weight = 4
|
||||
enemy_roles = list("AI","Medical Doctor","Station Engineer","Head of Personnel","Captain")
|
||||
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
|
||||
requirements = list(5,5,5,5,5,5,5,5,5,5)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = 1)
|
||||
|
||||
/datum/dynamic_ruleset/event/swarmers
|
||||
name = "Swarmers"
|
||||
config_tag = "swarmer"
|
||||
typepath = /datum/round_event/spawn_swarmer
|
||||
cost = 10
|
||||
weight = 1
|
||||
earliest_start = 30 MINUTES
|
||||
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer")
|
||||
required_enemies = list(4,4,4,4,3,3,2,2,1,1)
|
||||
requirements = list(101,101,101,101,101,101,101,101,101,101)
|
||||
high_population_requirement = 5
|
||||
property_weights = list("extended" = -2)
|
||||
|
||||
/datum/dynamic_ruleset/event/sentient_disease
|
||||
name = "Sentient Disease"
|
||||
config_tag = "sentient_disease"
|
||||
typepath = /datum/round_event/ghost_role/sentient_disease
|
||||
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
|
||||
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
|
||||
high_population_requirement = 5
|
||||
|
||||
/datum/dynamic_ruleset/event/revenant
|
||||
name = "Revenant"
|
||||
config_tag = "revenant"
|
||||
typepath = /datum/round_event/ghost_role/revenant
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,30,30,20,15,15,15,15,15)
|
||||
high_population_requirement = 15
|
||||
property_weights = list("story_potential" = -2, "extended" = -1)
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
|
||||
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
|
||||
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
|
||||
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
|
||||
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
|
||||
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
|
||||
|
||||
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
|
||||
@@ -43,7 +43,7 @@
|
||||
if (!istype(M, required_type))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.GetComponent(/datum/component/virtual_reality))
|
||||
if (HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG))
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (!M.client) // Are they connected?
|
||||
@@ -273,10 +273,14 @@
|
||||
var/ion_announce = 33
|
||||
var/removeDontImproveChance = 10
|
||||
|
||||
/datum/dynamic_ruleset/midround/malf/ready()
|
||||
if(!candidates || !candidates.len)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/malf/trim_candidates()
|
||||
..()
|
||||
living_players = candidates[CURRENT_LIVING_PLAYERS]
|
||||
for(var/mob/living/player in candidates)
|
||||
for(var/mob/living/player in living_players)
|
||||
if(!isAI(player))
|
||||
candidates -= player
|
||||
continue
|
||||
@@ -287,8 +291,6 @@
|
||||
candidates -= player
|
||||
|
||||
/datum/dynamic_ruleset/midround/malf/execute()
|
||||
if(!candidates || !candidates.len)
|
||||
return FALSE
|
||||
var/mob/living/silicon/ai/M = pick_n_take(candidates)
|
||||
assigned += M.mind
|
||||
var/datum/antagonist/traitor/AI = new
|
||||
@@ -337,6 +339,7 @@
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/wizard/finish_setup(mob/new_character, index)
|
||||
..()
|
||||
new_character.forceMove(pick(GLOB.wizardstart))
|
||||
wizard = new_character.mind
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
|
||||
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
|
||||
@@ -447,9 +450,7 @@
|
||||
property_weights = list("story_potential" = -1, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
|
||||
var/list/vents = list()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
|
||||
// 50% chance of being incremented by one
|
||||
required_candidates += prob(50)
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines)
|
||||
if(QDELETED(temp_vent))
|
||||
continue
|
||||
@@ -463,6 +464,12 @@
|
||||
vents += temp_vent
|
||||
if(!vents.len)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
|
||||
// 50% chance of being incremented by one
|
||||
required_candidates += prob(50)
|
||||
. = ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant)
|
||||
@@ -497,7 +504,7 @@
|
||||
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 1)
|
||||
var/list/spawn_locs = list()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute()
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/ready()
|
||||
for(var/X in GLOB.xeno_spawn)
|
||||
var/turf/T = X
|
||||
var/light_amount = T.get_lumcount()
|
||||
@@ -505,7 +512,7 @@
|
||||
spawn_locs += T
|
||||
if(!spawn_locs.len)
|
||||
return FALSE
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/generate_ruleset_body(mob/applicant)
|
||||
var/datum/mind/player_mind = new /datum/mind(applicant.key)
|
||||
@@ -523,88 +530,6 @@
|
||||
log_game("DYNAMIC: [key_name(S)] was spawned as a Nightmare by the midround ruleset.")
|
||||
return S
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// SENTIENT DISEASE //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease
|
||||
name = "Sentient Disease"
|
||||
config_tag = "sentient_disease"
|
||||
antag_flag = ROLE_ALIEN
|
||||
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
|
||||
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
|
||||
high_population_requirement = 5
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/generate_ruleset_body(mob/applicant)
|
||||
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
|
||||
applicant.transfer_ckey(virus, FALSE)
|
||||
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
|
||||
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by the midround ruleset.")
|
||||
log_game("[key_name(virus)] was spawned as a sentient disease by the midround ruleset.")
|
||||
return virus
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// REVENANT //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/revenant
|
||||
name = "Revenant"
|
||||
config_tag = "revenant"
|
||||
antag_flag = ROLE_REVENANT
|
||||
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
|
||||
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
|
||||
required_candidates = 1
|
||||
weight = 4
|
||||
cost = 5
|
||||
requirements = list(30,30,30,30,20,15,15,15,15,15)
|
||||
high_population_requirement = 15
|
||||
property_weights = list("story_potential" = -2, "extended" = -1)
|
||||
var/list/spawn_locs = list()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population = 0,threat = 0)
|
||||
var/deadMobs = 0
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
deadMobs++
|
||||
if(deadMobs < REVENANT_SPAWN_THRESHOLD)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE)
|
||||
for(var/mob/living/L in GLOB.dead_mob_list) //look for any dead bodies
|
||||
var/turf/T = get_turf(L)
|
||||
if(T && is_station_level(T.z))
|
||||
spawn_locs += T
|
||||
if(!spawn_locs.len || spawn_locs.len < 15) //look for any morgue trays, crematoriums, ect if there weren't alot of dead bodies on the station to pick from
|
||||
for(var/obj/structure/bodycontainer/bc in GLOB.bodycontainers)
|
||||
var/turf/T = get_turf(bc)
|
||||
if(T && is_station_level(T.z))
|
||||
spawn_locs += T
|
||||
if(!spawn_locs.len) //If we can't find any valid spawnpoints, try the carp spawns
|
||||
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc))
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/revenant/generate_ruleset_body(mob/applicant)
|
||||
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
|
||||
applicant.transfer_ckey(revvie, FALSE)
|
||||
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by the midround ruleset.")
|
||||
log_game("[key_name(revvie)] was spawned as a revenant by the midround ruleset.")
|
||||
return revvie
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// SLAUGHTER DEMON //
|
||||
@@ -668,11 +593,11 @@
|
||||
required_candidates = 2
|
||||
weight = 8
|
||||
cost = 10
|
||||
requirements = list(101,101,70,50,40,30,30,20,15,15)
|
||||
requirements = list(101,101,70,50,40,30,30,30,30,30)
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
|
||||
high_population_requirement = 15
|
||||
var/datum/team/abductor_team/team
|
||||
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
|
||||
property_weights = list("extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
|
||||
repeatable_weight_decrease = 4
|
||||
repeatable = TRUE
|
||||
|
||||
@@ -742,15 +667,19 @@
|
||||
var/datum/antagonist/ninja/ninjadatum = new
|
||||
ninjadatum.helping_station = pick(TRUE,FALSE)
|
||||
if(ninjadatum.helping_station)
|
||||
mode.refund_threat(5)
|
||||
mode.refund_threat(cost+5)
|
||||
mode.log_threat("Ninja was helping station; [cost+5] cost refunded.")
|
||||
Mind.add_antag_datum(ninjadatum)
|
||||
|
||||
if(Ninja.mind != Mind) //something has gone wrong!
|
||||
throw EXCEPTION("Ninja created with incorrect mind")
|
||||
stack_trace("Ninja created with incorrect mind")
|
||||
|
||||
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
|
||||
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
|
||||
return Ninja
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
|
||||
return
|
||||
|
||||
#undef ABDUCTOR_MAX_TEAMS
|
||||
#undef REVENANT_SPAWN_THRESHOLD
|
||||
|
||||
@@ -623,8 +623,7 @@
|
||||
config_tag = "clownops"
|
||||
antag_datum = /datum/antagonist/nukeop/clownop
|
||||
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
|
||||
requirements = list(101,101,101,101,101,101,101,101,101,101)
|
||||
high_population_requirement = 101
|
||||
weight = 1
|
||||
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "story_potential" = 2, "valid" = 2)
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
/datum/dynamic_storyteller
|
||||
var/name = "none"
|
||||
var/config_tag = null
|
||||
var/desc = "A coder's idiocy."
|
||||
var/list/property_weights = list()
|
||||
var/curve_centre = 0
|
||||
var/curve_width = 1.8
|
||||
var/name = "none" // Name for voting.
|
||||
var/config_tag = null // Config tag for config weights.
|
||||
var/desc = "A coder's idiocy." // Description for voting.
|
||||
var/list/property_weights = list() // See below.
|
||||
var/curve_centre = 0 // As GLOB.dynamic_curve_centre.
|
||||
var/curve_width = 1.8 // As GLOB.dynamic_curve_width.
|
||||
var/forced_threat_level = -1
|
||||
/*
|
||||
NO_ASSASSIN: Will not have permanent assassination targets.
|
||||
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
|
||||
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
|
||||
*/
|
||||
var/flags = 0
|
||||
var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote
|
||||
var/event_frequency_lower = 6 MINUTES
|
||||
var/event_frequency_upper = 20 MINUTES
|
||||
var/datum/game_mode/dynamic/mode = null
|
||||
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
|
||||
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
|
||||
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
|
||||
var/pop_antag_ratio = 5 // How many non-antags there should be vs antags.
|
||||
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
|
||||
|
||||
/**
|
||||
Property weights are:
|
||||
@@ -80,7 +86,7 @@ Property weights are:
|
||||
var/chance = 0
|
||||
// If the high pop override is in effect, we reduce the impact of population on the antag injection chance
|
||||
var/high_pop_factor = (mode.current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
|
||||
var/max_pop_per_antag = max(5,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
|
||||
var/max_pop_per_antag = max(pop_antag_ratio,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
|
||||
if (!mode.current_players[CURRENT_LIVING_ANTAGS].len)
|
||||
chance += 80 // No antags at all? let's boost those odds!
|
||||
else
|
||||
@@ -173,12 +179,13 @@ Property weights are:
|
||||
name = "Chaotic"
|
||||
config_tag = "chaotic"
|
||||
curve_centre = 10
|
||||
desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard."
|
||||
desc = "High chaos modes. Revs, wizard, clock cult. Multiple antags at once. Chaos is kept up all round."
|
||||
property_weights = list("extended" = -1, "chaos" = 10)
|
||||
weight = 1
|
||||
event_frequency_lower = 2 MINUTES
|
||||
event_frequency_upper = 10 MINUTES
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
pop_antag_ratio = 4
|
||||
var/refund_cooldown = 0
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
|
||||
@@ -189,14 +196,14 @@ Property weights are:
|
||||
|
||||
/datum/dynamic_storyteller/cowabunga/do_process()
|
||||
if(refund_cooldown < world.time)
|
||||
mode.refund_threat(20)
|
||||
mode.log_threat("Cowabunga it is. Refunded 20 threat. Threat is now [mode.threat].")
|
||||
refund_cooldown = world.time + 600 SECONDS
|
||||
mode.refund_threat(40)
|
||||
mode.log_threat("Chaotic storyteller refunded 40 threat. Threat is now [mode.threat].")
|
||||
refund_cooldown = world.time + 1200 SECONDS
|
||||
|
||||
/datum/dynamic_storyteller/team
|
||||
name = "Teamwork"
|
||||
config_tag = "teamwork"
|
||||
desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph."
|
||||
desc = "Modes where the crew must band together. Nukies, xenos, blob. Only one antag threat at once."
|
||||
curve_centre = 2
|
||||
curve_width = 1.5
|
||||
weight = 2
|
||||
@@ -209,56 +216,71 @@ Property weights are:
|
||||
/datum/dynamic_storyteller/conversion
|
||||
name = "Conversion"
|
||||
config_tag = "conversion"
|
||||
desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs."
|
||||
desc = "Conversion antags. Cults, revs."
|
||||
curve_centre = 3
|
||||
curve_width = 1
|
||||
weight = 2
|
||||
weight = 0
|
||||
flags = WAROPS_ALWAYS_ALLOWED
|
||||
property_weights = list("valid" = 1, "conversion" = 20)
|
||||
|
||||
/datum/dynamic_storyteller/classic
|
||||
name = "Random"
|
||||
config_tag = "random"
|
||||
desc = "Chaos: varies. Variation: highest. No special weights attached."
|
||||
weight = 6
|
||||
flags = USE_PREF_WEIGHTS
|
||||
desc = "No special weights attached. Anything goes."
|
||||
weight = 4
|
||||
curve_width = 4
|
||||
pop_antag_ratio = 7
|
||||
flags = USE_PREF_WEIGHTS
|
||||
|
||||
/datum/dynamic_storyteller/memes
|
||||
/datum/dynamic_storyteller/story
|
||||
name = "Story"
|
||||
config_tag = "story"
|
||||
desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor."
|
||||
weight = 4
|
||||
flags = USE_PREF_WEIGHTS
|
||||
curve_width = 4
|
||||
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
pop_antag_ratio = 7
|
||||
property_weights = list("story_potential" = 10)
|
||||
|
||||
/datum/dynamic_storyteller/suspicion
|
||||
name = "Intrigue"
|
||||
config_tag = "intrigue"
|
||||
desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult."
|
||||
weight = 4
|
||||
flags = USE_PREF_WEIGHTS
|
||||
curve_width = 4
|
||||
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
|
||||
weight = 2
|
||||
curve_width = 2
|
||||
pop_antag_ratio = 7
|
||||
property_weights = list("trust" = -5)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended
|
||||
name = "Calm"
|
||||
config_tag = "calm"
|
||||
desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant."
|
||||
desc = "Low-chaos round. Few antags. No conversion."
|
||||
curve_centre = -3
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
weight = 1
|
||||
pop_antag_ratio = 10
|
||||
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
|
||||
|
||||
/datum/dynamic_storyteller/no_antag
|
||||
name = "Extended"
|
||||
config_tag = "semiextended"
|
||||
desc = "No standard antags. Threatening events may still spawn."
|
||||
curve_centre = -5
|
||||
curve_width = 0.5
|
||||
flags = NO_ASSASSIN
|
||||
weight = 2
|
||||
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
|
||||
weight = 1
|
||||
property_weights = list("extended" = 2)
|
||||
|
||||
/datum/dynamic_storyteller/liteextended/get_injection_chance(dry_run = FALSE)
|
||||
return ..()/2
|
||||
/datum/dynamic_storyteller/no_antag/roundstart_draft()
|
||||
return list()
|
||||
|
||||
/datum/dynamic_storyteller/no_antag/get_injection_chance(dry_run)
|
||||
return 0
|
||||
|
||||
/datum/dynamic_storyteller/extended
|
||||
name = "Extended"
|
||||
name = "Super Extended"
|
||||
config_tag = "extended"
|
||||
desc = "Chaos: none. Variation: none. Likely antags: none."
|
||||
desc = "No antags. No dangerous events."
|
||||
curve_centre = -20
|
||||
weight = 0
|
||||
curve_width = 0.5
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/datum/team/gang/zerog
|
||||
name = "Zero-G"
|
||||
color = "#C0C0C0"
|
||||
inner_outfits = list(/obj/item/clothing/under/suit_jacket/white)
|
||||
inner_outfits = list(/obj/item/clothing/under/suit/white)
|
||||
outer_outfits = list(/obj/item/clothing/suit/hooded/wintercoat)
|
||||
|
||||
/datum/team/gang/max
|
||||
@@ -33,13 +33,13 @@
|
||||
/datum/team/gang/blasto
|
||||
name = "Blasto"
|
||||
color = "#000080"
|
||||
inner_outfits = list(/obj/item/clothing/under/suit_jacket/navy)
|
||||
inner_outfits = list(/obj/item/clothing/under/suit/navy)
|
||||
outer_outfits = list(/obj/item/clothing/suit/jacket/miljacket)
|
||||
|
||||
/datum/team/gang/waffle
|
||||
name = "Waffle"
|
||||
color = "#808000" //shared color with cyber, but they can keep brown cause waffles.
|
||||
inner_outfits = list(/obj/item/clothing/under/suit_jacket/green)
|
||||
inner_outfits = list(/obj/item/clothing/under/suit/green)
|
||||
outer_outfits = list(/obj/item/clothing/suit/poncho)
|
||||
|
||||
/datum/team/gang/north
|
||||
@@ -87,7 +87,7 @@
|
||||
/datum/team/gang/tunnel
|
||||
name = "Tunnel"
|
||||
color = "#FF00FF" //Gave the leather jacket to the tunnel gang over diablo.
|
||||
inner_outfits = list(/obj/item/clothing/under/villain)
|
||||
inner_outfits = list(/obj/item/clothing/under/costume/villain)
|
||||
outer_outfits = list(/obj/item/clothing/suit/jacket/leather)
|
||||
|
||||
/datum/team/gang/diablo
|
||||
@@ -123,13 +123,13 @@
|
||||
/datum/team/gang/h
|
||||
name = "H"
|
||||
color = "#993333"
|
||||
inner_outfits = list(/obj/item/clothing/under/jabroni) //Why not?
|
||||
inner_outfits = list(/obj/item/clothing/under/costume/jabroni) //Why not?
|
||||
outer_outfits = list(/obj/item/clothing/suit/toggle/owlwings)
|
||||
|
||||
/datum/team/gang/rigatonifamily
|
||||
name = "Rigatoni family"
|
||||
color = "#cc9900" // p a s t a colored
|
||||
inner_outfits = list(/obj/item/clothing/under/rank/chef)
|
||||
inner_outfits = list(/obj/item/clothing/under/rank/civilian/chef)
|
||||
outer_outfits = list(/obj/item/clothing/suit/apron/chef)
|
||||
|
||||
/datum/team/gang/weed
|
||||
|
||||
@@ -220,11 +220,11 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds
|
||||
|
||||
/datum/gang_item/weapon/ammo/sleeper_ammo
|
||||
/*/datum/gang_item/weapon/ammo/sleeper_ammo //no. absolutely no.
|
||||
name = "Illicit Soporific Cartridges"
|
||||
id = "sniper_ammo"
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific
|
||||
cost = 15 //who the fuck thought a ONE-HIT K.O. for 15 gbp IN AN ENVIRONMENT WHERE WE'RE GETTING RID OF HARDSTUNS is a GOOD IDEA
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific*/
|
||||
|
||||
/datum/gang_item/weapon/machinegun
|
||||
name = "Mounted Machine Gun"
|
||||
|
||||
@@ -54,6 +54,6 @@
|
||||
return
|
||||
var/mob/living/carbon/human/H = gangster_mind.current // we are sure the dude's human cause it's checked in attack()
|
||||
H.silent = max(H.silent, 5)
|
||||
H.Knockdown(100)
|
||||
H.DefaultCombatKnockdown(100)
|
||||
gangster_mind.add_antag_datum(/datum/antagonist/gang, gang)
|
||||
return TRUE
|
||||
@@ -165,7 +165,7 @@
|
||||
/datum/outfit/syndicate/full
|
||||
name = "Syndicate Operative - Full Kit"
|
||||
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
glasses = /obj/item/clothing/glasses/night/syndicate
|
||||
mask = /obj/item/clothing/mask/gas/syndicate
|
||||
suit = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
|
||||
@@ -180,7 +180,7 @@
|
||||
/datum/outfit/syndicate/lone
|
||||
name = "Syndicate Operative - Lone"
|
||||
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
glasses = /obj/item/clothing/glasses/night/syndicate
|
||||
mask = /obj/item/clothing/mask/gas/syndicate
|
||||
suit = /obj/item/clothing/suit/space/syndicate/black/red
|
||||
head = /obj/item/clothing/head/helmet/space/syndicate/black/red
|
||||
|
||||
@@ -86,8 +86,10 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
if(M)
|
||||
. += M
|
||||
|
||||
/datum/objective/proc/find_target()
|
||||
/datum/objective/proc/find_target(dupe_search_range, blacklist)
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
if(!dupe_search_range)
|
||||
dupe_search_range = get_owners()
|
||||
var/list/possible_targets = list()
|
||||
var/try_target_late_joiners = FALSE
|
||||
for(var/I in owners)
|
||||
@@ -96,7 +98,8 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
try_target_late_joiners = TRUE
|
||||
for(var/datum/mind/possible_target in get_crewmember_minds())
|
||||
if(!(possible_target in owners) && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && is_unique_objective(possible_target))
|
||||
possible_targets += possible_target
|
||||
if(!(possible_target in blacklist))
|
||||
possible_targets += possible_target
|
||||
if(try_target_late_joiners)
|
||||
var/list/all_possible_targets = possible_targets.Copy()
|
||||
for(var/I in all_possible_targets)
|
||||
@@ -1075,7 +1078,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK))
|
||||
hoarded_item = I
|
||||
|
||||
|
||||
|
||||
|
||||
GLOBAL_LIST_EMPTY(possible_sabotages)
|
||||
@@ -1092,7 +1095,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
|
||||
if(!GLOB.possible_sabotages.len)//Only need to fill the list when it's needed.
|
||||
for(var/I in subtypesof(/datum/sabotage_objective))
|
||||
new I
|
||||
|
||||
|
||||
/datum/objective/sabotage/find_target()
|
||||
var/list/datum/mind/owners = get_owners()
|
||||
var/approved_targets = list()
|
||||
@@ -1155,3 +1158,26 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
|
||||
|
||||
/datum/objective/flavor/wizard
|
||||
flavor_file = "strings/flavor_objectives/wizard.txt"
|
||||
|
||||
/datum/objective/contract
|
||||
var/payout = 0
|
||||
var/payout_bonus = 0
|
||||
var/area/dropoff = null
|
||||
var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected,
|
||||
/area/solar/,
|
||||
/area/ruin/, //thank you station space ruins
|
||||
/area/science/test_area/,
|
||||
/area/shuttle/))
|
||||
|
||||
/datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen.
|
||||
var/found = FALSE
|
||||
while(!found)
|
||||
var/area/dropoff_area = pick(GLOB.sortedAreas)
|
||||
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !is_type_in_typecache(dropoff_area, blacklisted_areas))
|
||||
dropoff = dropoff_area
|
||||
found = TRUE
|
||||
|
||||
/datum/objective/contract/proc/dropoff_check(mob/user, mob/target) // Check if both the contractor and contract target are at the dropoff point.
|
||||
var/area/user_area = get_area(user)
|
||||
var/area/target_area = get_area(target)
|
||||
return (istype(user_area, dropoff) && istype(target_area, dropoff))
|
||||
|
||||
@@ -205,13 +205,18 @@
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/boh
|
||||
name = "a bag of holding."
|
||||
name = "a type of bag of holding."
|
||||
targetitem = /obj/item/storage/backpack/holding
|
||||
difficulty = 10
|
||||
|
||||
/datum/objective_item/special/hypercell
|
||||
name = "a hyper-capacity power cell."
|
||||
targetitem = /obj/item/stock_parts/cell/hyper
|
||||
/datum/objective_item/special/adv_surgical_drapes
|
||||
name = "a set of smart surgical drapes."
|
||||
targetitem = /obj/item/surgical_drapes/advanced
|
||||
difficulty = 10 //would be 15 but cmo rarely have it on themselfs and leave it in their lockers...
|
||||
|
||||
/datum/objective_item/special/bluespace
|
||||
name = "a bluespace power cell."
|
||||
targetitem = /obj/item/stock_parts/cell/bluespace
|
||||
difficulty = 5
|
||||
|
||||
/datum/objective_item/special/laserpointer
|
||||
|
||||
@@ -23,34 +23,27 @@
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/datum/sabotage_objective/processing/proc/check_condition_processing()
|
||||
return 100
|
||||
return 1
|
||||
|
||||
/datum/sabotage_objective/processing/process()
|
||||
check_condition_processing()
|
||||
if(won >= 100)
|
||||
if(won >= 1)
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
|
||||
/datum/sabotage_objective/processing/check_conditions()
|
||||
return won
|
||||
|
||||
/datum/sabotage_objective/processing/power_sink
|
||||
name = "Drain at least 1 gigajoule of power using a power sink."
|
||||
name = "Drain at least 100 megajoules of power using a power sink."
|
||||
sabotage_type = "powersink"
|
||||
special_equipment = list(/obj/item/powersink)
|
||||
special_equipment = list(/obj/item/sbeacondrop/powersink)
|
||||
var/sink_found = FALSE
|
||||
var/count = 0
|
||||
|
||||
/datum/sabotage_objective/processing/power_sink/check_condition_processing()
|
||||
count += 1
|
||||
if(count==10 || sink_found) // doesn't need to fire that often unless a sink exists
|
||||
var/sink_found_this_time = FALSE
|
||||
for(var/datum/powernet/PN in GLOB.powernets)
|
||||
for(var/obj/item/powersink/sink in PN.nodes)
|
||||
sink_found_this_time = TRUE
|
||||
won = max(won,sink.power_drained/1e9)
|
||||
sink_found = sink_found_this_time
|
||||
count = 0
|
||||
return FALSE
|
||||
for(var/s in GLOB.power_sinks)
|
||||
var/obj/item/powersink/sink = s
|
||||
won = max(won,sink.power_drained/1e8)
|
||||
|
||||
/obj/item/paper/guides/antag/supermatter_sabotage
|
||||
info = "Ways to sabotage a supermatter:<br>\
|
||||
|
||||
Reference in New Issue
Block a user