mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-20 20:45:28 +01:00
Ports Families gamemode to Dynamic roundstart + midround rulesets (#51244)
* stage one doesn't compile yet * step 2 added newer changes and goof's balance requests. still doesn't compile * phase 3 somewhere along the way, wanted code got fucked, and i have to commit to switch branches to debug it better * documentation, first dyn rulesets -deprecates a proc nobody needed -documents a lot of things, hopefully enough of them -reorganizes a lot of things to allow for admin-spawned families -adds dynamic rulesets (unfinished, debug settings left in) -hopefully finally fixes wanted level displays. all code sucks; ui code sucks especially. why can i put an acid level on a screen element? Fuck you -implements fully functional jewish qabbalah system to replace families gamemode. discover secret names of god + knowledge of universe structure through study of tanach and talmud, use them to secure the station for israel 2 -introduces gay agenda to unsuspecting stationgoers -remind me to check out gang tag code for mentions of ssticker.mode etc. if one of my later commits doesn't say i did that * finishes up rulesets -rulesets work now -hopefully cleaned up the debug code for them -minor adjustment to check_wanted_level() proc to ensure wanted stars update appearance correctly post-space cops -i resisted the urge to modify one of the systems so that it was more "elegant" or whatever because knowing my luck it'd result in another 10 years of failures and tests -checked out gang tag code; seems fine. perhaps the only part of families code i haven't gotten my mitts on. hopefully it won't break -you can now print fully functional geneseed organs from the roundstart medlathe for use in self-augmentation -consumed my soul and replaced it with a pathetic, empty husk -implemented social security number skimming operation -removed herobrine * addressing issues from the github * suggestions cleanin some things up * more tweaks goof requested on discord that i ensure 3 families every time, and adding the highlander ruleset flag makes sense because it means the 1-2 families-revs or families-nukies punch is less likely * adjustments for midround ruleset -wanted level no longer cares about deaths that happened before the handler's pre_setup_analogue() proc is called -midround ruleset will not trigger if more people have died during the shift than there were people readied up at roundstart (in addition to the minimum population of 36). -changes to antagonist code; only nonhumans may roll antagonist. if you have more than 1 hour of time spent playing as a human you are ineligible. something something 13% * #51315 compatibility removes useless "high_population_requirement" vars on families rulesets * moves stuff team creation should have gone in create_team() not on_gain() since the former gets called directly before the latter * shuffles some procs removes unnecessasry blocking_rules list for roundstart families gamemode
This commit is contained in:
@@ -488,8 +488,6 @@
|
||||
var/list/all_antagonists = list()
|
||||
|
||||
for(var/datum/team/A in GLOB.antagonist_teams)
|
||||
if(!A.members)
|
||||
continue
|
||||
all_teams |= A
|
||||
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
icon = 'icons/obj/gang/wanted_160x32.dmi'
|
||||
icon_state = "wanted_0"
|
||||
screen_loc = ui_wanted_lvl
|
||||
///Wanted level, affects the hud icon.
|
||||
var/level
|
||||
///Boolean, have the cops arrived? If so, the icon stops changing and remains the same.
|
||||
var/cops_arrived
|
||||
/// Wanted level, affects the hud icon. Level 0 is default, and the level 0 icon is blank, so in case of no families gamemode (and thus no wanted level), this HUD element will never appear.
|
||||
var/level = 0
|
||||
/// Boolean, have the cops arrived? If so, the icon stops changing and remains the same.
|
||||
var/cops_arrived = 0
|
||||
|
||||
/obj/screen/wanted/New()
|
||||
return ..()
|
||||
|
||||
/obj/screen/wanted/Initialize()
|
||||
. = ..()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
level = F.wanted_level
|
||||
cops_arrived = F.cops_arrived
|
||||
update_icon()
|
||||
|
||||
/obj/screen/wanted/MouseEntered(location,control,params)
|
||||
|
||||
@@ -539,11 +539,12 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
if(highlander_executed)
|
||||
return FALSE
|
||||
|
||||
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
|
||||
if((new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat) || forced)
|
||||
new_rule.trim_candidates()
|
||||
if (new_rule.ready(forced))
|
||||
spend_threat(new_rule.cost)
|
||||
threat_log += "[worldtime2text()]: Forced rule [new_rule.name] spent [new_rule.cost]"
|
||||
new_rule.pre_execute()
|
||||
if (new_rule.execute()) // This should never fail since ready() returned 1
|
||||
if(new_rule.flags & HIGHLANDER_RULESET)
|
||||
highlander_executed = TRUE
|
||||
|
||||
@@ -207,6 +207,72 @@
|
||||
M.mind.add_antag_datum(newTraitor)
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// FAMILIES //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/midround/families
|
||||
name = "Family Head Aspirants"
|
||||
persistent = TRUE
|
||||
antag_flag = ROLE_FAMILIES
|
||||
protected_roles = list("Prisoner", "Head of Personnel")
|
||||
restricted_roles = list("Cyborg", "AI", "Security Officer", "Warden", "Detective", "Head of Security", "Captain")
|
||||
required_candidates = 6 // gotta have 'em ALL
|
||||
weight = 1
|
||||
cost = 25
|
||||
requirements = list(101,101,101,101,101,80,50,30,10,10)
|
||||
flags = HIGHLANDER_RULESET
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/families)
|
||||
minimum_players = 36
|
||||
antag_cap = list(6,6,6,6,6,6,6,6,6,6)
|
||||
/// A reference to the handler that is used to run pre_execute(), execute(), etc..
|
||||
var/datum/gang_handler/handler
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/trim_candidates()
|
||||
..()
|
||||
candidates = living_players
|
||||
for(var/mob/living/player in candidates)
|
||||
if(issilicon(player))
|
||||
candidates -= player
|
||||
continue
|
||||
if(is_centcom_level(player.z))
|
||||
candidates -= player
|
||||
continue
|
||||
if(player.mind && (player.mind.special_role || player.mind.antag_datums?.len > 0))
|
||||
candidates -= player
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/acceptable(population = 0, threat_level = 0)
|
||||
if(GLOB.deaths_during_shift > round(mode.roundstart_pop_ready / 2))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/ready(forced = FALSE)
|
||||
if (required_candidates > living_players.len)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/pre_execute()
|
||||
..()
|
||||
handler = new /datum/gang_handler(candidates,restricted_roles)
|
||||
handler.gangs_to_generate = (antag_cap[indice_pop] / 2)
|
||||
handler.gang_balance_cap = clamp((indice_pop - 3), 2, 5) // gang_balance_cap by indice_pop: (2,2,2,2,2,3,4,5,5,5)
|
||||
handler.midround_ruleset = TRUE
|
||||
return handler.pre_setup_analogue()
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/execute()
|
||||
return handler.post_setup_analogue(TRUE)
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/clean_up()
|
||||
QDEL_NULL(handler)
|
||||
..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/rule_process()
|
||||
return handler.process_analogue()
|
||||
|
||||
/datum/dynamic_ruleset/midround/families/round_result()
|
||||
return handler.set_round_result_analogue()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
|
||||
@@ -450,6 +450,48 @@
|
||||
SSticker.mode_result = "loss - rev heads killed"
|
||||
SSticker.news_report = REVS_LOSE
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// FAMILIES //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families
|
||||
name = "Families"
|
||||
persistent = TRUE
|
||||
antag_flag = ROLE_FAMILIES
|
||||
protected_roles = list("Prisoner", "Head of Personnel")
|
||||
restricted_roles = list("Cyborg", "AI", "Security Officer", "Warden", "Detective", "Head of Security", "Captain")
|
||||
required_candidates = 6 // gotta have 'em ALL
|
||||
weight = 2
|
||||
cost = 30
|
||||
requirements = list(101,101,101,101,101,70,40,10,10,10)
|
||||
flags = HIGHLANDER_RULESET
|
||||
minimum_players = 36
|
||||
antag_cap = list(6,6,6,6,6,6,6,6,6,6)
|
||||
/// A reference to the handler that is used to run pre_execute(), execute(), etc..
|
||||
var/datum/gang_handler/handler
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families/pre_execute()
|
||||
..()
|
||||
handler = new /datum/gang_handler(candidates,restricted_roles)
|
||||
handler.gangs_to_generate = (antag_cap[indice_pop] / 2)
|
||||
handler.gang_balance_cap = clamp((indice_pop - 3), 2, 5) // gang_balance_cap by indice_pop: (2,2,2,2,2,3,4,5,5,5)
|
||||
return handler.pre_setup_analogue()
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families/execute()
|
||||
return handler.post_setup_analogue(TRUE)
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families/clean_up()
|
||||
QDEL_NULL(handler)
|
||||
..()
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families/rule_process()
|
||||
return handler.process_analogue()
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/families/round_result()
|
||||
return handler.set_round_result_analogue()
|
||||
|
||||
// Admin only rulesets. The threat requirement is 101 so it is not possible to roll them.
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
@@ -1,20 +1,3 @@
|
||||
#define LOWPOP_FAMILIES_COUNT 50
|
||||
|
||||
#define TWO_STARS_HIGHPOP 11
|
||||
#define THREE_STARS_HIGHPOP 16
|
||||
#define FOUR_STARS_HIGHPOP 21
|
||||
#define FIVE_STARS_HIGHPOP 31
|
||||
|
||||
#define TWO_STARS_LOW 6
|
||||
#define THREE_STARS_LOW 9
|
||||
#define FOUR_STARS_LOW 12
|
||||
#define FIVE_STARS_LOW 15
|
||||
|
||||
#define CREW_SIZE_MIN 4
|
||||
#define CREW_SIZE_MAX 8
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(deaths_during_shift, 0)
|
||||
/datum/game_mode/gang
|
||||
name = "Families"
|
||||
config_tag = "families"
|
||||
@@ -28,478 +11,40 @@ GLOBAL_VAR_INIT(deaths_during_shift, 0)
|
||||
reroll_friendly = FALSE
|
||||
restricted_jobs = list("Cyborg", "AI", "Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel")//N O
|
||||
protected_jobs = list()
|
||||
var/check_counter = 0
|
||||
var/endtime = null
|
||||
var/start_time = null
|
||||
var/fuckingdone = FALSE
|
||||
var/time_to_end = 60 MINUTES
|
||||
var/gangs_to_generate = 3
|
||||
var/list/gangs_to_use
|
||||
var/list/datum/mind/gangbangers = list()
|
||||
var/list/datum/mind/pigs = list()
|
||||
var/list/datum/mind/undercover_cops = list()
|
||||
var/list/gangs = list()
|
||||
var/gangs_still_alive = 0
|
||||
var/sent_announcement = FALSE
|
||||
var/list/gang_locations = list()
|
||||
var/cops_arrived = FALSE
|
||||
var/gang_balance_cap = 5
|
||||
var/wanted_level = 0
|
||||
|
||||
/// A reference to the handler that is used to run pre_setup(), post_setup(), etc..
|
||||
var/datum/gang_handler/handler
|
||||
|
||||
/datum/game_mode/gang/warriors
|
||||
name = "Warriors"
|
||||
config_tag = "warriors"
|
||||
announce_text = "Can you survive this onslaught?"
|
||||
gangs_to_generate = 11
|
||||
gang_balance_cap = 3
|
||||
|
||||
/datum/game_mode/gang/warriors/pre_setup()
|
||||
gangs_to_use = subtypesof(/datum/antagonist/gang)
|
||||
gangs_to_generate = gangs_to_use.len
|
||||
. = ..()
|
||||
handler = new /datum/gang_handler(antag_candidates,restricted_jobs)
|
||||
var/list/datum/antagonist/gang/gangs_to_generate = subtypesof(/datum/antagonist/gang)
|
||||
handler.gangs_to_generate = gangs_to_generate.len
|
||||
handler.gang_balance_cap = 3
|
||||
return handler.pre_setup_analogue()
|
||||
|
||||
/datum/game_mode/gang/pre_setup()
|
||||
gangs_to_use = subtypesof(/datum/antagonist/gang)
|
||||
for(var/j = 0, j < gangs_to_generate, j++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/gangbanger = antag_pick(antag_candidates)
|
||||
gangbangers += gangbanger
|
||||
gangbanger.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(gangbanger)] has been selected as a starting gangster!")
|
||||
antag_candidates.Remove(gangbanger)
|
||||
for(var/j = 0, j < gangs_to_generate, j++)
|
||||
if(!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/one_eight_seven_on_an_undercover_cop = antag_pick(antag_candidates)
|
||||
pigs += one_eight_seven_on_an_undercover_cop
|
||||
undercover_cops += one_eight_seven_on_an_undercover_cop
|
||||
one_eight_seven_on_an_undercover_cop.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(one_eight_seven_on_an_undercover_cop)] has been selected as a starting undercover cop!")
|
||||
antag_candidates.Remove(one_eight_seven_on_an_undercover_cop)
|
||||
endtime = world.time + time_to_end
|
||||
start_time = world.time
|
||||
return TRUE
|
||||
handler = new /datum/gang_handler(antag_candidates,restricted_jobs)
|
||||
return handler.pre_setup_analogue()
|
||||
|
||||
/datum/game_mode/gang/Destroy()
|
||||
QDEL_NULL(handler)
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/gang/post_setup()
|
||||
var/replacement_gangsters = 0
|
||||
var/replacement_cops = 0
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
if(!ishuman(gangbanger.current))
|
||||
gangbangers.Remove(gangbanger)
|
||||
log_game("[gangbanger] was not a human, and thus has lost their gangster role.")
|
||||
replacement_gangsters++
|
||||
if(replacement_gangsters)
|
||||
for(var/j = 0, j < replacement_gangsters, j++)
|
||||
if(!antag_candidates.len)
|
||||
log_game("Unable to find more replacement gangsters. Not all of the gangs will spawn.")
|
||||
break
|
||||
var/datum/mind/gangbanger = antag_pick(antag_candidates)
|
||||
gangbangers += gangbanger
|
||||
log_game("[key_name(gangbanger)] has been selected as a replacement gangster!")
|
||||
for(var/datum/mind/undercover_cop in undercover_cops)
|
||||
if(!ishuman(undercover_cop.current))
|
||||
undercover_cops.Remove(undercover_cop)
|
||||
pigs.Remove(undercover_cop)
|
||||
log_game("[undercover_cop] was not a human, and thus has lost their undercover cop role.")
|
||||
replacement_cops++
|
||||
if(replacement_cops)
|
||||
for(var/j = 0, j < replacement_cops, j++)
|
||||
if(!antag_candidates.len)
|
||||
log_game("Unable to find more replacement undercover cops. Not all of the gangs will spawn.")
|
||||
break
|
||||
var/datum/mind/undercover_cop = antag_pick(antag_candidates)
|
||||
undercover_cops += undercover_cop
|
||||
pigs += undercover_cop
|
||||
log_game("[key_name(undercover_cop)] has been selected as a replacement undercover cop!")
|
||||
for(var/datum/mind/undercover_cop in undercover_cops)
|
||||
var/datum/antagonist/ert/families/undercover_cop/one_eight_seven_on_an_undercover_cop = new()
|
||||
undercover_cop.add_antag_datum(one_eight_seven_on_an_undercover_cop)
|
||||
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
var/gang_to_use = pick_n_take(gangs_to_use)
|
||||
var/datum/antagonist/gang/new_gangster = new gang_to_use()
|
||||
var/datum/team/gang/ballas = new /datum/team/gang()
|
||||
new_gangster.my_gang = ballas
|
||||
new_gangster.starter_gangster = TRUE
|
||||
gangs += ballas
|
||||
ballas.add_member(gangbanger)
|
||||
ballas.name = new_gangster.gang_name
|
||||
|
||||
ballas.acceptable_clothes = new_gangster.acceptable_clothes.Copy()
|
||||
ballas.free_clothes = new_gangster.free_clothes.Copy()
|
||||
ballas.my_gang_datum = new_gangster
|
||||
|
||||
for(var/C in ballas.free_clothes)
|
||||
var/obj/O = new C(gangbanger.current)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"right pocket" = ITEM_SLOT_RPOCKET
|
||||
)
|
||||
var/mob/living/carbon/human/H = gangbanger.current
|
||||
var/equipped = H.equip_in_one_of_slots(O, slots)
|
||||
if(!equipped)
|
||||
to_chat(gangbanger.current, "Unfortunately, you could not bring your [O] to this shift. You will need to find one.")
|
||||
qdel(O)
|
||||
|
||||
gangbanger.add_antag_datum(new_gangster)
|
||||
gangbanger.current.playsound_local(gangbanger.current, 'sound/ambience/antag/thatshowfamiliesworks.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
to_chat(gangbanger.current, "<B>As you're the first gangster, your uniform and spraycan are in your inventory!</B>")
|
||||
addtimer(CALLBACK(src, .proc/announce_gang_locations), 5 MINUTES)
|
||||
addtimer(CALLBACK(src, .proc/five_minute_warning), time_to_end - 5 MINUTES)
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
handler.post_setup_analogue(FALSE)
|
||||
gamemode_ready = TRUE
|
||||
..()
|
||||
|
||||
/datum/game_mode/gang/proc/announce_gang_locations()
|
||||
var/list/readable_gang_names = list()
|
||||
for(var/GG in gangs)
|
||||
var/datum/team/gang/G = GG
|
||||
readable_gang_names += "[G.name]"
|
||||
var/finalized_gang_names = english_list(readable_gang_names)
|
||||
priority_announce("Julio G coming to you live from Radio Los Spess! We've been hearing reports of gang activity on [station_name()], with the [finalized_gang_names] duking it out, looking for fresh territory and drugs to sling! Stay safe out there for the hour 'till the space cops get there, and keep it cool, yeah?\n\n The local jump gates are shut down for about an hour due to some maintenance troubles, so if you wanna split from the area you're gonna have to wait an hour. \n Play music, not gunshots, I say. Peace out!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg')
|
||||
sent_announcement = TRUE
|
||||
|
||||
/datum/game_mode/gang/proc/five_minute_warning()
|
||||
priority_announce("Julio G coming to you live from Radio Los Spess! The space cops are closing in on [station_name()] and will arrive in about 5 minutes! Better clear on out of there if you don't want to get hurt!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg')
|
||||
|
||||
/datum/game_mode/gang/set_round_result()
|
||||
var/alive_gangsters = 0
|
||||
var/alive_cops = 0
|
||||
for(var/G in gangbangers)
|
||||
var/datum/mind/gangbanger = G
|
||||
if(!ishuman(gangbanger.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/H = gangbanger.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_gangsters++
|
||||
for(var/B in pigs)
|
||||
var/datum/mind/bacon = B
|
||||
if(!ishuman(bacon.current)) // always returns false
|
||||
continue
|
||||
var/mob/living/carbon/human/H = bacon.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_cops++
|
||||
if(alive_gangsters > alive_cops)
|
||||
SSticker.mode_result = "win - gangs survived"
|
||||
SSticker.news_report = GANG_OPERATING
|
||||
return TRUE
|
||||
SSticker.mode_result = "loss - police destroyed the gangs"
|
||||
SSticker.news_report = GANG_DESTROYED
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/gang/process()
|
||||
check_wanted_level()
|
||||
check_counter++
|
||||
if(check_counter >= 5)
|
||||
if (world.time > endtime && !fuckingdone)
|
||||
fuckingdone = TRUE
|
||||
send_in_the_fuzz()
|
||||
check_counter = 0
|
||||
|
||||
check_tagged_turfs()
|
||||
check_gang_clothes()
|
||||
check_rollin_with_crews()
|
||||
|
||||
///Checks if our wanted level has changed. Only actually does something post the initial announcement and until the cops are here. After that its locked.
|
||||
/datum/game_mode/gang/proc/check_wanted_level()
|
||||
if(!sent_announcement || cops_arrived)
|
||||
return
|
||||
var/new_wanted_level
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(GLOB.deaths_during_shift)
|
||||
if(0 to TWO_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_HIGHPOP to THREE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_HIGHPOP to FOUR_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_HIGHPOP to FIVE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_HIGHPOP to INFINITY)
|
||||
new_wanted_level = 5
|
||||
else
|
||||
switch(GLOB.deaths_during_shift)
|
||||
if(0 to TWO_STARS_LOW-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_LOW to THREE_STARS_LOW-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_LOW to FOUR_STARS_LOW-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_LOW to FIVE_STARS_LOW-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_LOW to INFINITY)
|
||||
new_wanted_level = 5
|
||||
update_wanted_level(new_wanted_level)
|
||||
|
||||
///Updates the icon states for everyone and sends outs announcements regarding the police.
|
||||
/datum/game_mode/gang/proc/update_wanted_level(newlevel)
|
||||
if(newlevel > wanted_level)
|
||||
on_gain_wanted_level(newlevel)
|
||||
else if (newlevel < wanted_level)
|
||||
on_lower_wanted_level(newlevel)
|
||||
wanted_level = newlevel
|
||||
for(var/i in GLOB.player_list)
|
||||
var/mob/M = i
|
||||
if(!M.hud_used?.wanted_lvl)
|
||||
continue
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.wanted_lvl.level = newlevel
|
||||
H.wanted_lvl.cops_arrived = cops_arrived
|
||||
H.wanted_lvl.update_icon()
|
||||
|
||||
/datum/game_mode/gang/proc/on_gain_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(2)
|
||||
announcement_message = "Small amount of police vehicles have been spotted en route towards [station_name()]. They will arrive at the 50 minute mark."
|
||||
endtime = start_time + 50 MINUTES
|
||||
if(3)
|
||||
announcement_message = "A large detachment police vehicles have been spotted en route towards [station_name()]. They will arrive at the 40 minute mark."
|
||||
endtime = start_time + 40 MINUTES
|
||||
if(4)
|
||||
announcement_message = "A detachment of top-trained agents has been spotted on their way to [station_name()]. They will arrive at the 35 minute mark."
|
||||
endtime = start_time + 35 MINUTES
|
||||
if(5)
|
||||
announcement_message = "The fleet enroute to [station_name()] now consists of national guard personnel. They will arrive at the 30 minute mark."
|
||||
endtime = start_time + 30 MINUTES
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/datum/game_mode/gang/proc/on_lower_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(1)
|
||||
announcement_message = "There are now only a few police vehicle headed towards [station_name()]. They will arrive at the 60 minute mark."
|
||||
endtime = start_time + 60 MINUTES
|
||||
if(2)
|
||||
announcement_message = "There seem to be fewer police vehicles headed towards [station_name()]. They will arrive at the 50 minute mark."
|
||||
endtime = start_time + 50 MINUTES
|
||||
if(3)
|
||||
announcement_message = "There are no longer top-trained agents in the fleet headed towards [station_name()]. They will arrive at the 40 minute mark."
|
||||
endtime = start_time + 40 MINUTES
|
||||
if(4)
|
||||
announcement_message = "The convoy enroute to [station_name()] seems to no longer consist of national guard personnel. They will arrive at the 35 minute mark."
|
||||
endtime = start_time + 35 MINUTES
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/datum/game_mode/gang/proc/send_in_the_fuzz()
|
||||
var/team_size
|
||||
var/cops_to_send
|
||||
var/announcement_message = "PUNK ASS BALLA BITCH"
|
||||
var/announcer = "Spinward Stellar Coalition"
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 9
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 11
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 12
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
else
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 5
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 6
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 7
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
|
||||
priority_announce(announcement_message, announcer, 'sound/effects/families_police.ogg')
|
||||
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to help clean up crime on this station?", "deathsquad", null)
|
||||
|
||||
|
||||
if(candidates.len)
|
||||
//Pick the (un)lucky players
|
||||
var/numagents = min(team_size,candidates.len)
|
||||
|
||||
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
|
||||
var/index = 0
|
||||
while(numagents && candidates.len)
|
||||
var/spawnloc = spawnpoints[index+1]
|
||||
//loop through spawnpoints one at a time
|
||||
index = (index + 1) % spawnpoints.len
|
||||
var/mob/dead/observer/chosen_candidate = pick(candidates)
|
||||
candidates -= chosen_candidate
|
||||
if(!chosen_candidate.key)
|
||||
continue
|
||||
|
||||
//Spawn the body
|
||||
var/mob/living/carbon/human/cop = new(spawnloc)
|
||||
chosen_candidate.client.prefs.copy_to(cop)
|
||||
cop.key = chosen_candidate.key
|
||||
|
||||
//Give antag datum
|
||||
var/datum/antagonist/ert/ert_antag = new cops_to_send
|
||||
|
||||
cop.mind.add_antag_datum(ert_antag)
|
||||
cop.mind.assigned_role = ert_antag.name
|
||||
SSjob.SendToLateJoin(cop)
|
||||
|
||||
//Logging and cleanup
|
||||
log_game("[key_name(cop)] has been selected as an [ert_antag.name]")
|
||||
numagents--
|
||||
cops_arrived = TRUE
|
||||
update_wanted_level() //Will make sure our icon updates properly
|
||||
addtimer(CALLBACK(src, .proc/end_hostile_sit), 10 MINUTES)
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/gang/proc/end_hostile_sit()
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
|
||||
|
||||
/datum/game_mode/gang/proc/check_tagged_turfs()
|
||||
for(var/T in GLOB.gang_tags)
|
||||
var/obj/effect/decal/cleanable/crayon/gang/tag = T
|
||||
if(tag.my_gang)
|
||||
tag.my_gang.adjust_points(50)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/game_mode/gang/proc/check_gang_clothes() // TODO: make this grab the sprite itself, average out what the primary color would be, then compare how close it is to the gang color so I don't have to manually fill shit out for 5 years for every gang type
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(!H.mind || !H.client)
|
||||
continue
|
||||
var/datum/antagonist/gang/is_gangster = H.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
for(var/clothing in list(H.head, H.wear_mask, H.wear_suit, H.w_uniform, H.back, H.gloves, H.shoes, H.belt, H.s_store, H.glasses, H.ears, H.wear_id))
|
||||
if(is_gangster)
|
||||
if(is_type_in_list(clothing, is_gangster.acceptable_clothes))
|
||||
is_gangster.add_gang_points(10)
|
||||
else
|
||||
for(var/G in gangs)
|
||||
var/datum/team/gang/gang_clothes = G
|
||||
if(is_type_in_list(clothing, gang_clothes.acceptable_clothes))
|
||||
gang_clothes.adjust_points(5)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/datum/game_mode/gang/proc/check_rollin_with_crews()
|
||||
var/list/areas_to_check = list()
|
||||
for(var/G in gangbangers)
|
||||
var/datum/mind/gangster = G
|
||||
areas_to_check += get_area(gangster.current)
|
||||
for(var/AA in areas_to_check)
|
||||
var/area/A = AA
|
||||
var/list/gang_members = list()
|
||||
for(var/mob/living/carbon/human/H in A)
|
||||
if(H.stat || !H.mind || !H.client)
|
||||
continue
|
||||
var/datum/antagonist/gang/is_gangster = H.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(is_gangster)
|
||||
gang_members[is_gangster.my_gang]++
|
||||
CHECK_TICK
|
||||
if(gang_members.len)
|
||||
for(var/datum/team/gang/gangsters in gang_members)
|
||||
if(gang_members[gangsters] >= CREW_SIZE_MIN)
|
||||
if(gang_members[gangsters] >= CREW_SIZE_MAX)
|
||||
gangsters.adjust_points(5) // Discourage larger clumps, spread ur people out
|
||||
else
|
||||
gangsters.adjust_points(10)
|
||||
handler.process_analogue()
|
||||
|
||||
/datum/game_mode/gang/set_round_result()
|
||||
return handler.set_round_result_analogue()
|
||||
|
||||
/datum/game_mode/gang/generate_report()
|
||||
return "Potential violent criminal activity has been detected on board your station, and we believe the Spinward Stellar Coalition may be conducting an audit of us. Keep an eye out for tagging of turf, color coordination, and suspicious people asking you to say things a little closer to their chest."
|
||||
|
||||
/datum/game_mode/gang/send_intercept(report = 0)
|
||||
return
|
||||
|
||||
/datum/game_mode/gang/special_report()
|
||||
var/list/report = list()
|
||||
var/highest_point_value = 0
|
||||
var/highest_gang = "Leet Like Jeff K"
|
||||
report += "<span class='header'>The families in the round were:</span>"
|
||||
var/objective_failures = TRUE
|
||||
for(var/datum/team/gang/GG in gangs)
|
||||
if(GG.my_gang_datum.check_gang_objective())
|
||||
objective_failures = FALSE
|
||||
break
|
||||
for(var/datum/team/gang/G in gangs)
|
||||
report += "<span class='header'>[G.name]:</span>"
|
||||
if(G.members.len)
|
||||
report += "[G.my_gang_datum.roundend_category] were:"
|
||||
report += printplayerlist(G.members)
|
||||
report += "<span class='header'>Points: [G.points]</span>"
|
||||
report += "<span class='header'>Objective: [G.my_gang_datum.gang_objective]</span>"
|
||||
if(G.my_gang_datum.check_gang_objective())
|
||||
report += "<span class='greentext'>The family completed their objective!</span>"
|
||||
else
|
||||
report += "<span class='redtext'>The family failed their objective!</span>"
|
||||
else
|
||||
report += "<span class='redtext'>The family was wiped out!</span>"
|
||||
if(!objective_failures)
|
||||
if(G.points >= highest_point_value && G.members.len && G.my_gang_datum.check_gang_objective())
|
||||
highest_point_value = G.points
|
||||
highest_gang = G.name
|
||||
else
|
||||
if(G.points >= highest_point_value && G.members.len)
|
||||
highest_point_value = G.points
|
||||
highest_gang = G.name
|
||||
var/alive_gangsters = 0
|
||||
var/alive_cops = 0
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
if(gangbanger.current)
|
||||
if(!ishuman(gangbanger.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/H = gangbanger.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_gangsters++
|
||||
for(var/datum/mind/bacon in pigs)
|
||||
if(bacon.current)
|
||||
if(!ishuman(bacon.current)) // always returns false
|
||||
continue
|
||||
var/mob/living/carbon/human/H = bacon.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_cops++
|
||||
if(alive_gangsters > alive_cops)
|
||||
if(!objective_failures)
|
||||
report += "<span class='header greentext'>[highest_gang] won the round by completing their objective and having the most points!</span>"
|
||||
else
|
||||
report += "<span class='header greentext'>[highest_gang] won the round by having the most points!</span>"
|
||||
else if(alive_gangsters == alive_cops)
|
||||
report += "<span class='header redtext'>Legend has it the police and the families are still duking it out to this day!</span>"
|
||||
else
|
||||
report += "<span class='header greentext'>The police put the boots to the families, medium style!</span>"
|
||||
|
||||
|
||||
return "<div class='panel redborder'>[report.Join("<br>")]</div>"
|
||||
|
||||
@@ -0,0 +1,614 @@
|
||||
#define LOWPOP_FAMILIES_COUNT 50
|
||||
|
||||
#define TWO_STARS_HIGHPOP 11
|
||||
#define THREE_STARS_HIGHPOP 16
|
||||
#define FOUR_STARS_HIGHPOP 21
|
||||
#define FIVE_STARS_HIGHPOP 31
|
||||
|
||||
#define TWO_STARS_LOW 6
|
||||
#define THREE_STARS_LOW 9
|
||||
#define FOUR_STARS_LOW 12
|
||||
#define FIVE_STARS_LOW 15
|
||||
|
||||
#define CREW_SIZE_MIN 4
|
||||
#define CREW_SIZE_MAX 8
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(deaths_during_shift, 0)
|
||||
|
||||
/**
|
||||
* # Families gamemode / dynamic ruleset handler
|
||||
*
|
||||
* A special datum used by the families gamemode and dynamic rulesets to centralize code. "Family" and "gang" used interchangeably in code.
|
||||
*
|
||||
* This datum centralizes code used for the families gamemode / dynamic rulesets. Families incorporates a significant
|
||||
* amount of unique processing; without this datum, that could would be duplicated. To ensure the maintainability
|
||||
* of the families gamemode / rulesets, the code was moved to this datum. The gamemode / rulesets instance this
|
||||
* datum, pass it lists (lists are passed by reference; removing candidates here removes candidates in the gamemode),
|
||||
* and call its procs. Additionally, the families antagonist datum and families induction package also
|
||||
* contain vars that reference this datum, allowing for new families / family members to add themselves
|
||||
* to this datum's lists thereof (primarily used for point calculation). Despite this, the basic team mechanics
|
||||
* themselves should function regardless of this datum's instantiation, should a player have the gang or cop
|
||||
* antagonist datum added to them through methods external to the families gamemode / rulesets.
|
||||
*
|
||||
*/
|
||||
/datum/gang_handler
|
||||
/// A counter used to minimize the overhead of computationally intensive, periodic family point gain checks. Used and set internally.
|
||||
var/check_counter = 0
|
||||
/// The time, in deciseconds, that the datum's pre_setup() occured at. Used in end_time. Used and set internally.
|
||||
var/start_time = null
|
||||
/// The time, in deciseconds, that the space cops will arrive at. Calculated based on wanted level and start_time. Used and set internally.
|
||||
var/end_time = null
|
||||
/// Whether the gamemode-announcing announcement has been sent. Used and set internally.
|
||||
var/sent_announcement = FALSE
|
||||
/// Whether the "5 minute warning" announcement has been sent. Used and set internally.
|
||||
var/sent_second_announcement = FALSE
|
||||
/// Whether the space cops have arrived. Set internally; used internally, and for updating the wanted HUD.
|
||||
var/cops_arrived = FALSE
|
||||
/// The current wanted level. Set internally; used internally, and for updating the wanted HUD.
|
||||
var/wanted_level
|
||||
/// List of all /datum/team/gang. Used internally; added to externally by /datum/antagonist/gang when it generates a new /datum/team/gang.
|
||||
var/list/gangs = list()
|
||||
/// List of all family member minds. Used internally; added to internally, and externally by /obj/item/gang_induction_package when used to induct a new family member.
|
||||
var/list/gangbangers = list()
|
||||
/// List of all undercover cop minds. Used and set internally.
|
||||
var/list/undercover_cops = list()
|
||||
/// The number of families (and 1:1 corresponding undercover cops) that should be generated. Can be set externally; used internally.
|
||||
var/gangs_to_generate = 3
|
||||
/// The number of family members more that a family may have over other active families. Can be set externally; used internally.
|
||||
var/gang_balance_cap = 5
|
||||
/// Whether the handler corresponds to a ruleset that does not trigger at round start. Should be set externally only if applicable; used internally.
|
||||
var/midround_ruleset = FALSE
|
||||
/// Keeps track of the amount of deaths since the calling of pre_setup_analogue() if this is a midround handler. Used to prevent a high wanted level due to a large amount of deaths during the shift prior to the activation of this handler / the midround ruleset.
|
||||
var/deaths_during_shift_at_beginning = 0
|
||||
|
||||
/// List of all eligible starting family members / undercover cops. Set externally (passed by reference) by gamemode / ruleset; used internally. Note that dynamic uses a list of mobs to handle candidates while game_modes use lists of minds! Don't be fooled!
|
||||
var/list/antag_candidates = list()
|
||||
/// List of jobs not eligible for starting family member / undercover cop. Set externally (passed by reference) by gamemode / ruleset; used internally.
|
||||
var/list/restricted_jobs
|
||||
|
||||
/**
|
||||
* Sets antag_candidates and restricted_jobs.
|
||||
*
|
||||
* Sets the antag_candidates and restricted_jobs lists to the equivalent
|
||||
* lists of its instantiating game_mode / dynamic_ruleset datum. As lists
|
||||
* are passed by reference, the variable set in this datum and the passed list
|
||||
* list used to set it are literally the same; changes to one affect the other.
|
||||
* Like all New() procs, called when the datum is first instantiated.
|
||||
* There's an annoying caveat here, though -- dynamic rulesets don't have
|
||||
* lists of minds for candidates, they have lists of mobs. Ghost mobs, before
|
||||
* the round has started. But we still want to preserve the structure of the candidates
|
||||
* list by not duplicating it and making sure to remove the candidates as we use them.
|
||||
* So there's a little bit of boilerplate throughout to preserve the sanctity of this reference.
|
||||
* Arguments:
|
||||
* * given_candidates - The antag_candidates list or equivalent of the datum instantiating this one.
|
||||
* * revised_restricted - The restricted_jobs list or equivalent of the datum instantiating this one.
|
||||
*/
|
||||
/datum/gang_handler/New(list/given_candidates, list/revised_restricted)
|
||||
antag_candidates = given_candidates
|
||||
restricted_jobs = revised_restricted
|
||||
|
||||
/**
|
||||
* pre_setup() or pre_execute() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the pre_setup() or pre_execute() phase, after first instantiation
|
||||
* and the modification of gangs_to_generate, gang_balance_cap, and midround_ruleset.
|
||||
* It is intended to take the place of the code that would normally occupy the pre_setup()
|
||||
* or pre_execute() proc, were the code localized to the game_mode or dynamic_ruleset datum respectively
|
||||
* as opposed to this handler. As such, it picks players to be chosen for starting familiy members
|
||||
* or undercover cops prior to assignment to jobs. Sets start_time, default end_time,
|
||||
* and the current value of deaths_during_shift, to ensure the wanted level only cares about
|
||||
* the deaths since this proc has been called.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/pre_setup_analogue()
|
||||
for(var/j = 0, j < gangs_to_generate, j++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates) // original used antag_pick, but that's local to game_mode and rulesets use pick_n_take so this is fine maybe
|
||||
var/datum/mind/gangbanger
|
||||
if(istype(taken, /mob))
|
||||
var/mob/T = taken
|
||||
gangbanger = T.mind
|
||||
else
|
||||
gangbanger = taken
|
||||
gangbangers += gangbanger
|
||||
gangbanger.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(gangbanger)] has been selected as a starting gangster!")
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags += gangbanger
|
||||
for(var/j = 0, j < gangs_to_generate, j++)
|
||||
if(!antag_candidates.len)
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates)
|
||||
var/datum/mind/undercover_cop
|
||||
if(istype(taken, /mob))
|
||||
var/mob/T = taken
|
||||
undercover_cop = T.mind
|
||||
else
|
||||
undercover_cop = taken
|
||||
undercover_cops += undercover_cop
|
||||
undercover_cop.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(undercover_cop)] has been selected as a starting undercover cop!")
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags += undercover_cop
|
||||
deaths_during_shift_at_beginning = GLOB.deaths_during_shift // don't want to mix up pre-families and post-families deaths
|
||||
start_time = world.time
|
||||
end_time = start_time + ((60 MINUTES) / (midround_ruleset ? 2 : 1)) // midround families rounds end quicker
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* post_setup() or execute() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the post_setup() or execute() phase, after the pre_setup() / pre_execute() phase.
|
||||
* It is intended to take the place of the code that would normally occupy the pre_setup()
|
||||
* or pre_execute() proc. As such, it ensures that all prospective starting family members /
|
||||
* undercover cops are eligible, and picks replacements if there were ineligible cops / family members.
|
||||
* It then assigns gear to the finalized family members and undercover cops, adding them to its lists,
|
||||
* and sets the families announcement proc (that does the announcing) to trigger in five minutes.
|
||||
* Additionally, if given the argument TRUE, it will return FALSE if there are no eligible starting family members.
|
||||
* This is only to be done if the instantiating datum is a dynamic_ruleset, as these require returns
|
||||
* while a game_mode is not expected to return early during this phase.
|
||||
* Arguments:
|
||||
* * return_if_no_gangs - Boolean that determines if the proc should return FALSE should it find no eligible family members. Should be used for dynamic only.
|
||||
*/
|
||||
/datum/gang_handler/proc/post_setup_analogue(return_if_no_gangs = FALSE)
|
||||
var/replacement_gangsters = 0
|
||||
var/replacement_cops = 0
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
if(!ishuman(gangbanger.current))
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags -= gangbanger
|
||||
gangbangers.Remove(gangbanger)
|
||||
log_game("[gangbanger] was not a human, and thus has lost their gangster role.")
|
||||
replacement_gangsters++
|
||||
if(replacement_gangsters)
|
||||
for(var/j = 0, j < replacement_gangsters, j++)
|
||||
if(!antag_candidates.len)
|
||||
log_game("Unable to find more replacement gangsters. Not all of the gangs will spawn.")
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates)
|
||||
var/datum/mind/gangbanger
|
||||
if(istype(taken, /mob)) // boilerplate needed because antag_candidates might not contain minds
|
||||
var/mob/T = taken
|
||||
gangbanger = T.mind
|
||||
else
|
||||
gangbanger = taken
|
||||
gangbangers += gangbanger
|
||||
log_game("[key_name(gangbanger)] has been selected as a replacement gangster!")
|
||||
for(var/datum/mind/undercover_cop in undercover_cops)
|
||||
if(!ishuman(undercover_cop.current))
|
||||
undercover_cops.Remove(undercover_cop)
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags -= undercover_cop
|
||||
log_game("[undercover_cop] was not a human, and thus has lost their undercover cop role.")
|
||||
replacement_cops++
|
||||
if(replacement_cops)
|
||||
for(var/j = 0, j < replacement_cops, j++)
|
||||
if(!antag_candidates.len)
|
||||
log_game("Unable to find more replacement undercover cops. Not all of the cops will spawn.")
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates)
|
||||
var/datum/mind/undercover_cop
|
||||
if(istype(taken, /mob))
|
||||
var/mob/T = taken
|
||||
undercover_cop = T.mind
|
||||
else
|
||||
undercover_cop = taken
|
||||
undercover_cops += undercover_cop
|
||||
log_game("[key_name(undercover_cop)] has been selected as a replacement undercover cop!")
|
||||
|
||||
if(!gangbangers.len)
|
||||
if(return_if_no_gangs)
|
||||
return FALSE // ending early is bad if we're not in dynamic
|
||||
|
||||
for(var/datum/mind/undercover_cop in undercover_cops)
|
||||
var/datum/antagonist/ert/families/undercover_cop/one_eight_seven_on_an_undercover_cop = new()
|
||||
undercover_cop.add_antag_datum(one_eight_seven_on_an_undercover_cop)
|
||||
|
||||
var/list/gangs_to_use = subtypesof(/datum/antagonist/gang)
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
var/gang_to_use = pick_n_take(gangs_to_use)
|
||||
var/datum/antagonist/gang/new_gangster = new gang_to_use()
|
||||
new_gangster.handler = src
|
||||
new_gangster.starter_gangster = TRUE
|
||||
gangbanger.add_antag_datum(new_gangster)
|
||||
// see /datum/antagonist/gang/create_team() for how the gang team datum gets instantiated and added to our gangs list
|
||||
|
||||
addtimer(CALLBACK(src, .proc/announce_gang_locations), 5 MINUTES)
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* process() or rule_process() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the process() or rule_process() phase, after post_setup() or
|
||||
* execute() and at regular intervals thereafter. process() and rule_process() are optional
|
||||
* for a game_mode / dynamic_ruleset, but are important for this gamemode. It is of central
|
||||
* importance to the gamemode's flow, calculating wanted level updates, family point gain,
|
||||
* and announcing + executing the arrival of the space cops, achieved through calling internal procs.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/process_analogue()
|
||||
check_wanted_level()
|
||||
check_counter++
|
||||
if(check_counter >= 5)
|
||||
if(world.time > (end_time - 5 MINUTES) && !sent_second_announcement)
|
||||
five_minute_warning()
|
||||
addtimer(CALLBACK(src, .proc/send_in_the_fuzz), 5 MINUTES)
|
||||
|
||||
check_counter = 0
|
||||
|
||||
check_tagged_turfs()
|
||||
check_gang_clothes()
|
||||
check_rollin_with_crews()
|
||||
|
||||
/**
|
||||
* set_round_result() or round_result() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done by the set_round_result() or round_result() procs, at roundend.
|
||||
* Sets the ticker subsystem to the correct result based off of the relative populations
|
||||
* of space cops and family members.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/set_round_result_analogue()
|
||||
var/alive_gangsters = 0
|
||||
var/alive_cops = 0
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
if(!ishuman(gangbanger.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/H = gangbanger.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_gangsters++
|
||||
for(var/datum/mind/bacon in get_antag_minds(/datum/antagonist/ert/families))
|
||||
if(!ishuman(bacon.current)) // always returns false
|
||||
continue
|
||||
var/mob/living/carbon/human/H = bacon.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_cops++
|
||||
if(alive_gangsters > alive_cops)
|
||||
SSticker.mode_result = "win - gangs survived"
|
||||
SSticker.news_report = GANG_OPERATING
|
||||
return TRUE
|
||||
SSticker.mode_result = "loss - police destroyed the gangs"
|
||||
SSticker.news_report = GANG_DESTROYED
|
||||
return FALSE
|
||||
|
||||
/// Internal. Announces the presence of families to the entire station and sets sent_announcement to true to allow other checks to occur.
|
||||
/datum/gang_handler/proc/announce_gang_locations()
|
||||
var/list/readable_gang_names = list()
|
||||
for(var/GG in gangs)
|
||||
var/datum/team/gang/G = GG
|
||||
readable_gang_names += "[G.name]"
|
||||
var/finalized_gang_names = english_list(readable_gang_names)
|
||||
priority_announce("Julio G coming to you live from Radio Los Spess! We've been hearing reports of gang activity on [station_name()], with the [finalized_gang_names] duking it out, looking for fresh territory and drugs to sling! Stay safe out there for the [midround_ruleset ? "half-hour" : "hour"] 'till the space cops get there, and keep it cool, yeah?\n\n The local jump gates are shut down for about an hour due to some maintenance troubles, so if you wanna split from the area you're gonna have to wait an hour. \n Play music, not gunshots, I say. Peace out!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg')
|
||||
sent_announcement = TRUE
|
||||
check_wanted_level() // i like it when the wanted level updates at the same time as the announcement
|
||||
|
||||
/// Internal. Announces that space cops will arrive in 5 minutes and sets sent_second_announcement to true to freeze
|
||||
/datum/gang_handler/proc/five_minute_warning()
|
||||
priority_announce("Julio G coming to you live from Radio Los Spess! The space cops are closing in on [station_name()] and will arrive in about 5 minutes! Better clear on out of there if you don't want to get hurt!", "Radio Los Spess", 'sound/voice/beepsky/radio.ogg')
|
||||
sent_second_announcement = TRUE
|
||||
|
||||
/// Internal. Checks if our wanted level has changed; calls update_wanted_level. Only updates wanted level post the initial announcement and until the cops show up. After that, it's locked.
|
||||
/datum/gang_handler/proc/check_wanted_level()
|
||||
if(cops_arrived)
|
||||
update_wanted_level(wanted_level) // at this point, we still want to update people's star huds, even though they're mostly locked, because not everyone is around for the last update before the rest of this proc gets shut off forever, and that's when the wanted bar switches from gold stars to red / blue to signify the arrival of the space cops
|
||||
return
|
||||
if(!sent_announcement)
|
||||
return
|
||||
var/new_wanted_level
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(GLOB.deaths_during_shift - deaths_during_shift_at_beginning) // if this is a midround ruleset, we only care about the deaths since the families were activated, not since shiftstart
|
||||
if(0 to TWO_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_HIGHPOP to THREE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_HIGHPOP to FOUR_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_HIGHPOP to FIVE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_HIGHPOP to INFINITY)
|
||||
new_wanted_level = 5
|
||||
else
|
||||
switch(GLOB.deaths_during_shift - deaths_during_shift_at_beginning)
|
||||
if(0 to TWO_STARS_LOW-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_LOW to THREE_STARS_LOW-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_LOW to FOUR_STARS_LOW-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_LOW to FIVE_STARS_LOW-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_LOW to INFINITY)
|
||||
new_wanted_level = 5
|
||||
update_wanted_level(new_wanted_level)
|
||||
|
||||
/// Internal. Updates the icon states for everyone, and calls procs that send out announcements / change the end_time if the wanted level has changed.
|
||||
/datum/gang_handler/proc/update_wanted_level(newlevel)
|
||||
if(newlevel > wanted_level)
|
||||
on_gain_wanted_level(newlevel)
|
||||
else if (newlevel < wanted_level)
|
||||
on_lower_wanted_level(newlevel)
|
||||
wanted_level = newlevel
|
||||
for(var/i in GLOB.player_list)
|
||||
var/mob/M = i
|
||||
if(!M.hud_used?.wanted_lvl)
|
||||
continue
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.wanted_lvl.level = newlevel
|
||||
H.wanted_lvl.cops_arrived = cops_arrived
|
||||
H.wanted_lvl.update_icon()
|
||||
|
||||
/// Internal. Updates the end_time and sends out an announcement if the wanted level has increased. Called by update_wanted_level().
|
||||
/datum/gang_handler/proc/on_gain_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(2)
|
||||
if(!sent_second_announcement) // when you hear that they're "arriving in 5 minutes," that's a goddamn guarantee
|
||||
end_time = start_time + ((50 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "Small amount of police vehicles have been spotted en route towards [station_name()]."
|
||||
if(3)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((40 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "A large detachment police vehicles have been spotted en route towards [station_name()]."
|
||||
if(4)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((35 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "A detachment of top-trained agents has been spotted on their way to [station_name()]."
|
||||
if(5)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((30 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "The fleet enroute to [station_name()] now consists of national guard personnel."
|
||||
if(!midround_ruleset) // stops midround rulesets from announcing janky ass times
|
||||
announcement_message += " They will arrive at the [(end_time - start_time) / (1 MINUTES)] minute mark."
|
||||
if(newlevel == 1) // specific exception to stop the announcement from triggering right after the families themselves are announced because aesthetics
|
||||
return
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/// Internal. Updates the end_time and sends out an announcement if the wanted level has decreased. Called by update_wanted_level().
|
||||
/datum/gang_handler/proc/on_lower_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(1)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((60 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "There are now only a few police vehicle headed towards [station_name()]."
|
||||
if(2)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((50 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "There seem to be fewer police vehicles headed towards [station_name()]."
|
||||
if(3)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((40 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "There are no longer top-trained agents in the fleet headed towards [station_name()]."
|
||||
if(4)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((35 MINUTES) / (midround_ruleset ? 2 : 1))
|
||||
announcement_message = "The convoy enroute to [station_name()] seems to no longer consist of national guard personnel."
|
||||
if(!midround_ruleset)
|
||||
announcement_message += " They will arrive at the [(end_time - start_time) / (1 MINUTES)] minute mark."
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/// Internal. Polls ghosts and sends in a team of space cops according to the wanted level, accompanied by an announcement. Will let the shuttle leave 10 minutes after sending. Freezes the wanted level.
|
||||
/datum/gang_handler/proc/send_in_the_fuzz()
|
||||
var/team_size
|
||||
var/cops_to_send
|
||||
var/announcement_message = "PUNK ASS BALLA BITCH"
|
||||
var/announcer = "Spinward Stellar Coalition"
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 9
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 11
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 12
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
else
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 5
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 6
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 7
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
|
||||
priority_announce(announcement_message, announcer, 'sound/effects/families_police.ogg')
|
||||
var/list/candidates = pollGhostCandidates("Do you want to help clean up crime on this station?", "deathsquad", null)
|
||||
|
||||
|
||||
if(candidates.len)
|
||||
//Pick the (un)lucky players
|
||||
var/numagents = min(team_size,candidates.len)
|
||||
|
||||
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
|
||||
var/index = 0
|
||||
while(numagents && candidates.len)
|
||||
var/spawnloc = spawnpoints[index+1]
|
||||
//loop through spawnpoints one at a time
|
||||
index = (index + 1) % spawnpoints.len
|
||||
var/mob/dead/observer/chosen_candidate = pick(candidates)
|
||||
candidates -= chosen_candidate
|
||||
if(!chosen_candidate.key)
|
||||
continue
|
||||
|
||||
//Spawn the body
|
||||
var/mob/living/carbon/human/cop = new(spawnloc)
|
||||
chosen_candidate.client.prefs.copy_to(cop)
|
||||
cop.key = chosen_candidate.key
|
||||
|
||||
//Give antag datum
|
||||
var/datum/antagonist/ert/families/ert_antag = new cops_to_send
|
||||
|
||||
cop.mind.add_antag_datum(ert_antag)
|
||||
cop.mind.assigned_role = ert_antag.name
|
||||
SSjob.SendToLateJoin(cop)
|
||||
|
||||
//Logging and cleanup
|
||||
log_game("[key_name(cop)] has been selected as an [ert_antag.name]")
|
||||
numagents--
|
||||
cops_arrived = TRUE
|
||||
update_wanted_level(wanted_level) // gotta make sure everyone's wanted level display looks nice
|
||||
addtimer(CALLBACK(src, .proc/end_hostile_sit), 10 MINUTES)
|
||||
return TRUE
|
||||
|
||||
/// Internal. Clears the hostile environment, letting the shuttle leave.
|
||||
/datum/gang_handler/proc/end_hostile_sit()
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
|
||||
/// Internal. Assigns points to families according to gang tags.
|
||||
/datum/gang_handler/proc/check_tagged_turfs()
|
||||
for(var/T in GLOB.gang_tags)
|
||||
var/obj/effect/decal/cleanable/crayon/gang/tag = T
|
||||
if(tag.my_gang)
|
||||
tag.my_gang.adjust_points(50)
|
||||
CHECK_TICK
|
||||
|
||||
/// Internal. Assigns points to families according to clothing of all currently living humans.
|
||||
/datum/gang_handler/proc/check_gang_clothes() // TODO: make this grab the sprite itself, average out what the primary color would be, then compare how close it is to the gang color so I don't have to manually fill shit out for 5 years for every gang type
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list)
|
||||
if(!H.mind || !H.client)
|
||||
continue
|
||||
var/datum/antagonist/gang/is_gangster = H.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
for(var/clothing in list(H.head, H.wear_mask, H.wear_suit, H.w_uniform, H.back, H.gloves, H.shoes, H.belt, H.s_store, H.glasses, H.ears, H.wear_id))
|
||||
if(is_gangster)
|
||||
if(is_type_in_list(clothing, is_gangster.acceptable_clothes))
|
||||
is_gangster.add_gang_points(10)
|
||||
else
|
||||
for(var/G in gangs)
|
||||
var/datum/team/gang/gang_clothes = G
|
||||
if(is_type_in_list(clothing, gang_clothes.acceptable_clothes))
|
||||
gang_clothes.adjust_points(5)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/// Internal. Assigns points to families according to groups of nearby family members.
|
||||
/datum/gang_handler/proc/check_rollin_with_crews()
|
||||
var/list/areas_to_check = list()
|
||||
for(var/G in gangbangers)
|
||||
var/datum/mind/gangster = G
|
||||
areas_to_check += get_area(gangster.current)
|
||||
for(var/AA in areas_to_check)
|
||||
var/area/A = AA
|
||||
var/list/gang_members = list()
|
||||
for(var/mob/living/carbon/human/H in A)
|
||||
if(H.stat || !H.mind || !H.client)
|
||||
continue
|
||||
var/datum/antagonist/gang/is_gangster = H.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(is_gangster)
|
||||
gang_members[is_gangster.my_gang]++
|
||||
CHECK_TICK
|
||||
if(gang_members.len)
|
||||
for(var/datum/team/gang/gangsters in gang_members)
|
||||
if(gang_members[gangsters] >= CREW_SIZE_MIN)
|
||||
if(gang_members[gangsters] >= CREW_SIZE_MAX)
|
||||
gangsters.adjust_points(5) // Discourage larger clumps, spread ur people out
|
||||
else
|
||||
gangsters.adjust_points(10)
|
||||
|
||||
|
||||
/// Hijacks the space cops' roundend results to say if cops / a gang won the round. Included in the same file as the gang_handler as it's far more related to the gamemode than it is to the beat cop datum; it's kind of hacky.
|
||||
/datum/antagonist/ert/families/beatcop/roundend_report_footer()
|
||||
var/list/all_gangs = list()
|
||||
for(var/datum/team/gang/G in GLOB.antagonist_teams)
|
||||
all_gangs += G
|
||||
if(!all_gangs.len)
|
||||
return ..()
|
||||
var/list/all_gangsters = get_antag_minds(/datum/antagonist/gang)
|
||||
var/list/all_cops = get_antag_minds(/datum/antagonist/ert/families)
|
||||
var/report
|
||||
var/highest_point_value = 0
|
||||
var/highest_gang = "Leet Like Jeff K"
|
||||
var/objective_failures = TRUE
|
||||
|
||||
for(var/G in all_gangs)
|
||||
var/datum/team/gang/GG = G
|
||||
if(GG.my_gang_datum.check_gang_objective())
|
||||
objective_failures = FALSE
|
||||
break
|
||||
for(var/G in all_gangs)
|
||||
var/datum/team/gang/GG = G
|
||||
if(!objective_failures)
|
||||
if(GG.points >= highest_point_value && GG.members.len && GG.my_gang_datum.check_gang_objective())
|
||||
highest_point_value = GG.points
|
||||
highest_gang = GG.name
|
||||
else
|
||||
if(GG.points >= highest_point_value && GG.members.len)
|
||||
highest_point_value = GG.points
|
||||
highest_gang = GG.name
|
||||
var/alive_gangsters = 0
|
||||
var/alive_cops = 0
|
||||
for(var/M in all_gangsters)
|
||||
var/datum/mind/gangbanger = M
|
||||
if(gangbanger.current)
|
||||
if(!ishuman(gangbanger.current))
|
||||
continue
|
||||
var/mob/living/carbon/human/H = gangbanger.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_gangsters++
|
||||
for(var/M in all_cops)
|
||||
var/datum/mind/bacon = M
|
||||
if(bacon.current)
|
||||
if(!ishuman(bacon.current)) // always returns false
|
||||
continue
|
||||
var/mob/living/carbon/human/H = bacon.current
|
||||
if(H.stat)
|
||||
continue
|
||||
alive_cops++
|
||||
|
||||
if(alive_gangsters > alive_cops)
|
||||
if(!objective_failures)
|
||||
report = "<span class='header greentext'>[highest_gang] won the round by completing their objective and having the most points!</span>"
|
||||
else
|
||||
report = "<span class='header greentext'>[highest_gang] won the round by having the most points!</span>"
|
||||
else if(alive_gangsters == alive_cops)
|
||||
report = "<span class='header redtext'>Legend has it the police and the families are still duking it out to this day!</span>"
|
||||
else
|
||||
report = "<span class='header greentext'>The police put the boots to the families, medium style!</span>"
|
||||
|
||||
return "</div><div class='panel redborder'>[report]" // </div> at the front not the back because this proc is intended for normal text not a whole new panel
|
||||
@@ -2,7 +2,11 @@
|
||||
name = "family signup package"
|
||||
icon = 'icons/obj/gang/signup_points.dmi'
|
||||
icon_state = "signup_book"
|
||||
/// References the active families gamemode handler (if one exists), for adding new family members to.
|
||||
var/datum/gang_handler/handler
|
||||
/// The typepath of the gang antagonist datum that the person who uses the package should have added to them -- remember that the distinction between e.g. Ballas and Grove Street is on the antag datum level, not the team datum level.
|
||||
var/gang_to_use
|
||||
/// The team datum that the person who uses this package should be added to.
|
||||
var/datum/team/gang/team_to_use
|
||||
|
||||
|
||||
@@ -19,27 +23,29 @@
|
||||
return
|
||||
var/datum/antagonist/gang/is_gangster = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(is_gangster && is_gangster.starter_gangster)
|
||||
if(is_gangster.my_gang == team_to_use)
|
||||
to_chat(user, "You started your family. You don't need to join it.")
|
||||
return
|
||||
to_chat(user, "You started your family. You can't turn your back on it now.")
|
||||
return
|
||||
attempt_join_gang(user)
|
||||
|
||||
/obj/item/gang_induction_package/proc/add_to_gang(var/mob/living/user)
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
/// Adds the user to the family that this package corresponds to, dispenses the free_clothes of that family, and adds them to the handler if it exists.
|
||||
/obj/item/gang_induction_package/proc/add_to_gang(mob/living/user)
|
||||
var/datum/antagonist/gang/swappin_sides = new gang_to_use()
|
||||
user.mind.add_antag_datum(swappin_sides)
|
||||
swappin_sides.handler = handler
|
||||
user.mind.add_antag_datum(swappin_sides, team_to_use)
|
||||
var/policy = get_policy(ROLE_FAMILIES)
|
||||
if(policy)
|
||||
to_chat(user, policy)
|
||||
swappin_sides.my_gang = team_to_use
|
||||
user.playsound_local(user, 'sound/ambience/antag/thatshowfamiliesworks.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
team_to_use.add_member(user.mind)
|
||||
for(var/threads in team_to_use.free_clothes)
|
||||
new threads(get_turf(user))
|
||||
if (!F.gangbangers.Find(user.mind))
|
||||
F.gangbangers += user.mind
|
||||
if (!isnull(handler) && !handler.gangbangers.Find(user.mind)) // if we have a handler and they're not tracked by it
|
||||
handler.gangbangers += user.mind
|
||||
team_to_use.adjust_points(30)
|
||||
|
||||
|
||||
/// Checks if the user is trying to use the package of the family they are in, and if not, adds them to the family, with some differing processing depending on whether the user is already a family member.
|
||||
/obj/item/gang_induction_package/proc/attempt_join_gang(mob/living/user)
|
||||
if(user && user.mind)
|
||||
var/datum/antagonist/gang/is_gangster = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
|
||||
@@ -6,14 +6,3 @@
|
||||
continue
|
||||
if(!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type)
|
||||
. += A.owner
|
||||
|
||||
//Get all teams [of type team_type]
|
||||
/proc/get_all_teams(team_type)
|
||||
. = list()
|
||||
for(var/V in GLOB.antagonists)
|
||||
var/datum/antagonist/A = V
|
||||
if(!A.owner)
|
||||
continue
|
||||
var/datum/team/T = A.get_team()
|
||||
if(!team_type || istype(T,team_type))
|
||||
. |= T
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
|
||||
var/list/current_teams = list()
|
||||
for(var/datum/team/abductor_team/T in get_all_teams(/datum/team/abductor_team))
|
||||
for(var/datum/team/abductor_team/T in GLOB.antagonist_teams)
|
||||
current_teams[T.name] = T
|
||||
var/choice = input(admin,"Add to which team ?") as null|anything in (current_teams + "new team")
|
||||
if (choice == "new team")
|
||||
|
||||
@@ -207,8 +207,11 @@
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.wanted_lvl = new /obj/screen/wanted
|
||||
H.infodisplay += H.wanted_lvl
|
||||
var/obj/screen/wanted/giving_wanted_lvl = new /obj/screen/wanted()
|
||||
H.wanted_lvl = giving_wanted_lvl
|
||||
giving_wanted_lvl.hud = H
|
||||
H.infodisplay += giving_wanted_lvl
|
||||
H.mymob.client.screen += giving_wanted_lvl
|
||||
|
||||
|
||||
/datum/antagonist/ert/families/remove_innate_effects(mob/living/mob_override)
|
||||
@@ -250,18 +253,19 @@
|
||||
random_names = FALSE
|
||||
|
||||
/datum/antagonist/ert/families/undercover_cop/on_gain()
|
||||
for(var/C in free_clothes)
|
||||
var/obj/O = new C(owner.current)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"right pocket" = ITEM_SLOT_RPOCKET
|
||||
)
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/equipped = H.equip_in_one_of_slots(O, slots)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Unfortunately, you could not bring your [O] to this shift. You will need to find one.")
|
||||
qdel(O)
|
||||
if(istype(owner.current, /mob/living/carbon/human))
|
||||
for(var/C in free_clothes)
|
||||
var/obj/O = new C(owner.current)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"right pocket" = ITEM_SLOT_RPOCKET
|
||||
)
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/equipped = H.equip_in_one_of_slots(O, slots)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Unfortunately, you could not bring your [O] to this shift. You will need to find one.")
|
||||
qdel(O)
|
||||
. = ..()
|
||||
|
||||
|
||||
|
||||
@@ -1,16 +1,94 @@
|
||||
/datum/antagonist/gang
|
||||
name = "Family Member"
|
||||
roundend_category = "gangsters"
|
||||
var/gang_name = "Leet Like Jeff K"
|
||||
var/gang_id = "LLJK"
|
||||
var/datum/team/gang/my_gang
|
||||
var/list/acceptable_clothes = list()
|
||||
var/list/free_clothes = list()
|
||||
var/datum/action/cooldown/spawn_induction_package/package_spawner = new()
|
||||
var/gang_objective = "Be super cool and stuff."
|
||||
var/starter_gangster = FALSE
|
||||
antag_hud_type = ANTAG_HUD_GANGSTER
|
||||
antag_hud_name = "hud_gangster"
|
||||
antagpanel_category = "Family"
|
||||
show_in_antagpanel = FALSE // i don't *think* this base class is buggy but it's too worthless to test
|
||||
/// The overarching family that the owner of this datum is a part of. Family teams are generic and imprinted upon by the per-person antagonist datums.
|
||||
var/datum/team/gang/my_gang
|
||||
/// The name of the family corresponding to this family member datum.
|
||||
var/gang_name = "Leet Like Jeff K"
|
||||
/// The abbreviation of the family corresponding to this family member datum.
|
||||
var/gang_id = "LLJK"
|
||||
/// The list of clothes that are acceptable to show allegiance to this family.
|
||||
var/list/acceptable_clothes = list()
|
||||
/// The list of clothes that are given to family members upon induction into the family.
|
||||
var/list/free_clothes = list()
|
||||
/// The action used to spawn family induction packages.
|
||||
var/datum/action/cooldown/spawn_induction_package/package_spawner = new()
|
||||
/// The textual description of the family's overarching objective.
|
||||
var/gang_objective = "Be super cool and stuff."
|
||||
/// Whether or not this family member is the first of their family.
|
||||
var/starter_gangster = FALSE
|
||||
|
||||
/// A reference to the handler datum that manages the families gamemode. In case of no handler (admin-spawned during round), this will be null; this is fine.
|
||||
var/datum/gang_handler/handler
|
||||
|
||||
/datum/antagonist/gang/get_team()
|
||||
return my_gang
|
||||
|
||||
/datum/antagonist/gang/get_admin_commands()
|
||||
. = ..()
|
||||
.["Give extra equipment"] = CALLBACK(src,.proc/equip_gangster_in_inventory)
|
||||
|
||||
/datum/antagonist/gang/create_team(team_given) // gets called whenever add_antag_datum() is called on a mind
|
||||
if(team_given)
|
||||
my_gang = team_given
|
||||
return
|
||||
/* if team_given is falsey, this gang member didn't join a gang by using a recruitment package. so there are two things we need to consider
|
||||
1. does a gang handler exist -- does this round have a gang_handler instanced by the families gamemode or ruleset?
|
||||
2. does the gang we're trying to join already exist?
|
||||
if 1 is true and 2 is false, we were probably added by the gang_handler, and probably already have a "handler" var.
|
||||
if we don't have a "handler" var, and a gang_handler exists, we need to grab it, since our "handler" is null.
|
||||
if the gang exists, we need to join it; if the gang doesn't exist, we need to make it. */
|
||||
var/found_gang = FALSE
|
||||
if(!starter_gangster) // if they're a starter gangster according to the handler, we don't need to check this shit
|
||||
for(var/datum/team/gang/G in GLOB.antagonist_teams)
|
||||
if(G.my_gang_datum.handler) // if one of the gangs in the gang list has a handler, nab that
|
||||
handler = G.my_gang_datum.handler
|
||||
if(G.name == gang_name)
|
||||
my_gang = G
|
||||
found_gang = TRUE
|
||||
break
|
||||
if(!found_gang)
|
||||
var/new_gang = new /datum/team/gang()
|
||||
my_gang = new_gang
|
||||
if(handler) // if we have a handler, the handler should track this gang
|
||||
handler.gangs += my_gang
|
||||
my_gang.name = gang_name
|
||||
my_gang.gang_id = gang_id
|
||||
my_gang.acceptable_clothes = acceptable_clothes.Copy()
|
||||
my_gang.free_clothes = free_clothes.Copy()
|
||||
my_gang.my_gang_datum = src
|
||||
starter_gangster = TRUE
|
||||
|
||||
/datum/antagonist/gang/on_gain()
|
||||
if(starter_gangster)
|
||||
equip_gangster_in_inventory()
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/thatshowfamiliesworks.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
..()
|
||||
|
||||
/datum/antagonist/gang/on_removal()
|
||||
if(my_gang.my_gang_datum == src) // if we're the first gangster, we need to replace ourselves so that objectives function correctly
|
||||
var/datum/antagonist/gang/replacement_datum = new type()
|
||||
replacement_datum.handler = handler
|
||||
replacement_datum.my_gang = my_gang
|
||||
my_gang.my_gang_datum = replacement_datum
|
||||
/* all we need to replace; the gang's "my_gang_datum" is just a person's datum because we assign it while we
|
||||
have that datum onhand. it would be easier if all of the code the gang team calls on its my_gang_datum was
|
||||
just in the team datum itself, and there were different types of teams instead of different types of gangster
|
||||
that imprint on generic teams, but i'm too lazy to refactor THAT too */
|
||||
..()
|
||||
|
||||
/datum/antagonist/gang/greet()
|
||||
to_chat(owner.current, "<B>As you're the first gangster, your uniform and spraycan are in your inventory!</B>")
|
||||
|
||||
to_chat(owner.current, "<B><font size=3 color=red>[gang_name] for life!</font></B>")
|
||||
to_chat(owner.current, "<B><font size=2 color=red>You're a member of the [gang_name] now!<br>Tag turf with a spraycan, wear your group's colors, and recruit more gangsters with the Induction Packages!</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Don't fuck with non-gangsters unless they fuck with you first.</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Don't blow shit up or make the station uninhabitable.</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Family's Objective:</B> [gang_objective]</font>")
|
||||
|
||||
/datum/antagonist/gang/apply_innate_effects(mob/living/mob_override)
|
||||
..()
|
||||
@@ -20,9 +98,11 @@
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.wanted_lvl = new /obj/screen/wanted
|
||||
H.infodisplay += H.wanted_lvl
|
||||
|
||||
var/obj/screen/wanted/giving_wanted_lvl = new /obj/screen/wanted()
|
||||
H.wanted_lvl = giving_wanted_lvl
|
||||
giving_wanted_lvl.hud = H
|
||||
H.infodisplay += giving_wanted_lvl
|
||||
H.mymob.client.screen += giving_wanted_lvl
|
||||
|
||||
/datum/antagonist/gang/remove_innate_effects(mob/living/mob_override)
|
||||
package_spawner.Remove(owner.current)
|
||||
@@ -34,25 +114,118 @@
|
||||
QDEL_NULL(H.wanted_lvl)
|
||||
..()
|
||||
|
||||
|
||||
/datum/antagonist/gang/get_team()
|
||||
return my_gang
|
||||
|
||||
/datum/antagonist/gang/proc/add_gang_points(var/points_to_add)
|
||||
/// Passes points gained to the family team.
|
||||
/datum/antagonist/gang/proc/add_gang_points(points_to_add)
|
||||
if(my_gang)
|
||||
my_gang.adjust_points(points_to_add)
|
||||
|
||||
/datum/antagonist/gang/proc/check_gang_objective() // used to determine if a gang has completed their special objective
|
||||
/// Determines if a gang has completed their special objective.
|
||||
/datum/antagonist/gang/proc/check_gang_objective()
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/greet()
|
||||
to_chat(owner.current, "<B><font size=3 color=red>[gang_name] for life!</font></B>")
|
||||
to_chat(owner.current, "<B><font size=2 color=red>You're a member of the [gang_name] now!<br>Tag turf with a spraycan, wear your group's colors, and recruit more gangsters with the Induction Packages!</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Don't fuck with non-gangsters unless they fuck with you first.</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Don't blow shit up or make the station uninhabitable.</font></B>")
|
||||
to_chat(owner.current, "<B><font size=4 color=red>Family's Objective:</B> [gang_objective]</font>")
|
||||
/// Gives a gangster their equipment in their backpack and / or pockets.
|
||||
/datum/antagonist/gang/proc/equip_gangster_in_inventory()
|
||||
if(istype(owner.current, /mob/living/carbon/human))
|
||||
for(var/C in my_gang.free_clothes)
|
||||
var/obj/O = new C(owner.current)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"right pocket" = ITEM_SLOT_RPOCKET
|
||||
)
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/equipped = H.equip_in_one_of_slots(O, slots)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Unfortunately, you could not bring your [O] to this shift. You will need to find one.")
|
||||
qdel(O)
|
||||
|
||||
/datum/team/gang
|
||||
/// The number of points this family has gained. Used for determining a victor if multiple families complete their objectives.
|
||||
var/points = 0
|
||||
/// The abbreviation of this family.
|
||||
var/gang_id = "LLJK"
|
||||
/// The list of clothes that are acceptable to show allegiance to this family.
|
||||
var/list/acceptable_clothes = list()
|
||||
/// The list of clothes that are given to family members upon induction into the family.
|
||||
var/list/free_clothes = list()
|
||||
/// The specific, occupied family member antagonist datum that is used to reach the handler / check objectives, and from which the above properties (sans points) are inherited.
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
|
||||
/datum/team/gang/roundend_report()
|
||||
var/list/report = list()
|
||||
report += "<span class='header'>[name]:</span>"
|
||||
if(!members.len)
|
||||
report += "<span class='redtext'>The family was wiped out!</span>"
|
||||
else if(my_gang_datum.check_gang_objective())
|
||||
report += "<span class='greentext'>The family completed their objective!</span>"
|
||||
else
|
||||
report += "<span class='redtext big'>The family failed their objective!</span>"
|
||||
report += "Objective: [my_gang_datum.gang_objective]"
|
||||
report += "Points: [points]"
|
||||
if(members.len)
|
||||
report += "[my_gang_datum.roundend_category] were:"
|
||||
report += printplayerlist(members)
|
||||
|
||||
return "<div class='panel redborder'>[report.Join("<br>")]</div>"
|
||||
|
||||
/// Adds points to the points var.
|
||||
/datum/team/gang/proc/adjust_points(var/points_to_adjust)
|
||||
points += points_to_adjust
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package
|
||||
name = "Create Induction Package"
|
||||
desc = "Generate an induction package for your family."
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "recruit"
|
||||
icon_icon = 'icons/obj/gang/actions.dmi'
|
||||
cooldown_time = 300
|
||||
/// The family antagonist datum of the "owner" of this action.
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package/Trigger()
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(!my_gang_datum)
|
||||
return FALSE
|
||||
if(!istype(owner, /mob/living/carbon/human))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat)
|
||||
return FALSE
|
||||
|
||||
var/gang_balance_cap // we need some stuff to fall back on if we're handlerless
|
||||
if(my_gang_datum.handler)
|
||||
gang_balance_cap = my_gang_datum.handler.gang_balance_cap
|
||||
else
|
||||
gang_balance_cap = 5 //just a filler default value
|
||||
|
||||
var/lowest_gang_count = my_gang_datum.my_gang.members.len
|
||||
for(var/datum/team/gang/TT in GLOB.antagonist_teams)
|
||||
var/alive_gangsters = 0
|
||||
for(var/datum/mind/gangers in TT.members)
|
||||
if(ishuman(gangers.current) && gangers.current.client && !gangers.current.stat)
|
||||
alive_gangsters++
|
||||
if(!alive_gangsters || TT.members.len <= 1) // Dead or inactive gangs don't count towards the cap.
|
||||
continue
|
||||
if(TT != my_gang_datum.my_gang)
|
||||
if(alive_gangsters < lowest_gang_count)
|
||||
lowest_gang_count = alive_gangsters
|
||||
if(my_gang_datum.my_gang.members.len >= (lowest_gang_count + gang_balance_cap))
|
||||
to_chat(H, "Your gang is pretty packed right now. You don't need more members just yet. If the other families expand, you can recruit more members.")
|
||||
return FALSE
|
||||
to_chat(H, "You pull an induction package from your pockets and place it on the ground.")
|
||||
var/obj/item/gang_induction_package/GP = new(get_turf(H))
|
||||
GP.name = "\improper [my_gang_datum.name] signup package"
|
||||
GP.handler = my_gang_datum.handler
|
||||
GP.gang_to_use = my_gang_datum.type
|
||||
GP.team_to_use = my_gang_datum.my_gang
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/red
|
||||
show_in_antagpanel = TRUE
|
||||
name = "San Fierro Triad"
|
||||
roundend_category = "The San Fierro Triad gangsters"
|
||||
gang_name = "San Fierro Triad"
|
||||
@@ -70,14 +243,15 @@
|
||||
antag_hud_name = "Triad"
|
||||
|
||||
/datum/antagonist/gang/red/check_gang_objective()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
for(var/datum/mind/M in F.undercover_cops)
|
||||
for(var/C in get_antag_minds(/datum/antagonist/ert/families/undercover_cop))
|
||||
var/datum/mind/M = C
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(considered_alive(H))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/purple
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Ballas"
|
||||
roundend_category = "The Ballas gangsters"
|
||||
gang_name = "Ballas"
|
||||
@@ -104,6 +278,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/green
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Grove Street Families"
|
||||
roundend_category = "The Grove Street Families gangsters"
|
||||
gang_name = "Grove Street Families"
|
||||
@@ -119,6 +294,7 @@
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
gang_objective = "We lost a lot of territory recently. We gotta get that shit back. Make sure 45 rooms are tagged for Grove Street."
|
||||
antag_hud_name = "Grove"
|
||||
|
||||
/datum/antagonist/gang/green/check_gang_objective()
|
||||
var/tag_amount = 0
|
||||
for(var/T in GLOB.gang_tags)
|
||||
@@ -129,8 +305,8 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/antagonist/gang/russian_mafia
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Russian Mafia"
|
||||
roundend_category = "The Russian mafiosos"
|
||||
gang_name = "Russian Mafia"
|
||||
@@ -147,22 +323,20 @@
|
||||
antag_hud_name = "Russian"
|
||||
|
||||
/datum/antagonist/gang/russian_mafia/check_gang_objective()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
for(var/M in F.gangbangers)
|
||||
var/datum/mind/MI = M
|
||||
if(MI.has_antag_datum(src.type))
|
||||
if(!considered_alive(MI.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
var/list/items_to_check = MI.current.GetAllContents()
|
||||
for(var/I in items_to_check)
|
||||
var/obj/IT = I
|
||||
if(istype(IT, /obj/item/reagent_containers/food/drinks/bottle))
|
||||
continue
|
||||
return FALSE // didnt pass the bottle check, no point in continuing to loop
|
||||
for(var/R in get_antag_minds(/datum/antagonist/gang/russian_mafia))
|
||||
var/datum/mind/M = R
|
||||
if(!considered_alive(M.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
var/list/items_to_check = M.current.GetAllContents()
|
||||
for(var/I in items_to_check)
|
||||
var/obj/IT = I
|
||||
if(istype(IT, /obj/item/reagent_containers/food/drinks/bottle))
|
||||
continue
|
||||
return FALSE // didnt pass the bottle check, no point in continuing to loop
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/antagonist/gang/italian_mob
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Italian Mob"
|
||||
roundend_category = "The Italian mobsters"
|
||||
gang_name = "Italian Mob"
|
||||
@@ -178,13 +352,12 @@
|
||||
antag_hud_name = "Italian"
|
||||
|
||||
/datum/antagonist/gang/italian_mob/check_gang_objective()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
for(var/M in F.gangbangers)
|
||||
var/datum/mind/MI = M
|
||||
if(MI.has_antag_datum(src.type))
|
||||
if(considered_alive(MI.current))
|
||||
for(var/I in get_antag_minds(/datum/antagonist/gang/italian_mob))
|
||||
var/datum/mind/M = I
|
||||
if(M.has_antag_datum(src.type))
|
||||
if(considered_alive(M.current))
|
||||
continue
|
||||
if(istype(MI.current.loc, /obj/structure/closet/crate/coffin))
|
||||
if(istype(M.current.loc, /obj/structure/closet/crate/coffin))
|
||||
continue
|
||||
return FALSE
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
@@ -194,6 +367,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/tunnel_snakes
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Tunnel Snakes"
|
||||
roundend_category = "The Tunnel Snakes"
|
||||
gang_name = "Tunnel Snakes"
|
||||
@@ -224,6 +398,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/vagos
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Los Santos Vagos"
|
||||
roundend_category = "The Los Santos Vagos gangsters"
|
||||
gang_name = "Los Santos Vagos"
|
||||
@@ -239,7 +414,6 @@
|
||||
gang_objective = "Orders from up high. We need to up our drug operation. Ensure that at least 25% of the station is addicted to meth."
|
||||
antag_hud_name = "Vagos"
|
||||
|
||||
|
||||
/datum/antagonist/gang/vagos/check_gang_objective()
|
||||
var/people_on_station = 0
|
||||
var/people_on_crack = 0
|
||||
@@ -256,8 +430,8 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/antagonist/gang/henchmen
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Monarch Crew"
|
||||
roundend_category = "The Monarch henchmen"
|
||||
gang_name = "Monarch Crew"
|
||||
@@ -282,6 +456,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/yakuza
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Tojo Clan"
|
||||
roundend_category = "The Yakuza"
|
||||
gang_name = "Tojo Clan"
|
||||
@@ -311,6 +486,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/jackbros
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Jack Bros"
|
||||
roundend_category = "The Hee-hos"
|
||||
gang_name = "Jack Bros"
|
||||
@@ -328,20 +504,18 @@
|
||||
antag_hud_name = "JackFrost"
|
||||
|
||||
/datum/antagonist/gang/jackbros/check_gang_objective()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
for(var/M in F.gangbangers)
|
||||
var/datum/mind/MI = M
|
||||
if(MI.has_antag_datum(src.type))
|
||||
if(!considered_alive(MI.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
if(ishuman(MI.current))
|
||||
var/mob/living/carbon/human/H = MI.current
|
||||
if(H.get_assignment() == "Captain")
|
||||
return TRUE
|
||||
for(var/J in get_antag_minds(/datum/antagonist/gang/jackbros))
|
||||
var/datum/mind/M = J
|
||||
if(!considered_alive(M.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
if(ishuman(M.current))
|
||||
var/mob/living/carbon/human/H = M.current
|
||||
if(H.get_assignment() == "Captain")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/antagonist/gang/dutch
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Dutch van der Linde's Gang"
|
||||
roundend_category = "Dutch's outlaws"
|
||||
gang_name = "Dutch van der Linde's Gang"
|
||||
@@ -359,79 +533,18 @@
|
||||
antag_hud_name = "Dutch"
|
||||
|
||||
/datum/antagonist/gang/dutch/check_gang_objective()
|
||||
var/datum/game_mode/gang/F = SSticker.mode
|
||||
for(var/M in F.gangbangers)
|
||||
var/datum/mind/MI = M
|
||||
if(MI.has_antag_datum(src.type))
|
||||
if(!considered_alive(MI.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
var/list/items_to_check = MI.current.GetAllContents()
|
||||
for(var/I in items_to_check)
|
||||
var/obj/IT = I
|
||||
if(istype(IT, /obj/item/stack/sheet/mineral/gold))
|
||||
continue
|
||||
return FALSE // didnt pass the bar check, no point in continuing to loop
|
||||
for(var/D in get_antag_minds(/datum/antagonist/gang/dutch))
|
||||
var/datum/mind/M = D
|
||||
if(!considered_alive(M.current))
|
||||
continue // dead people cant really do the objective lol
|
||||
var/list/items_to_check = M.current.GetAllContents()
|
||||
for(var/I in items_to_check)
|
||||
var/obj/IT = I
|
||||
if(istype(IT, /obj/item/stack/sheet/mineral/gold))
|
||||
continue
|
||||
return FALSE // didnt pass the bar check, no point in continuing to loop
|
||||
var/obj/machinery/ore_silo/S = GLOB.ore_silo_default
|
||||
var/datum/component/material_container/mat_container = S.GetComponent(/datum/component/material_container)
|
||||
if(mat_container.materials[SSmaterials.GetMaterialRef(/datum/material/gold)] >= 2000) // if theres at least 1 bar of gold left in the silo, they've failed to heist all of it
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/team/gang
|
||||
var/points = 0
|
||||
var/gang_id = "LLJK"
|
||||
var/list/acceptable_clothes = list()
|
||||
var/list/free_clothes = list()
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
|
||||
/datum/team/gang/proc/adjust_points(var/points_to_adjust)
|
||||
points += points_to_adjust
|
||||
|
||||
/datum/team/gang/roundend_report()
|
||||
return
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package
|
||||
name = "Create Induction Package"
|
||||
desc = "Generate an induction package for your family."
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "recruit"
|
||||
icon_icon = 'icons/obj/gang/actions.dmi'
|
||||
cooldown_time = 300
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package/Trigger()
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(!my_gang_datum)
|
||||
return FALSE
|
||||
if(!istype(owner, /mob/living/carbon/human))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat)
|
||||
return FALSE
|
||||
|
||||
var/datum/game_mode/gang/mode = SSticker.mode
|
||||
var/lowest_gang_count = my_gang_datum.my_gang.members.len
|
||||
for(var/datum/team/gang/TT in mode.gangs)
|
||||
var/alive_gangsters = 0
|
||||
for(var/datum/mind/gangers in TT.members)
|
||||
if(ishuman(gangers.current) && gangers.current.client && !gangers.current.stat)
|
||||
alive_gangsters++
|
||||
if(!alive_gangsters || TT.members.len <= 1) // Dead or inactive gangs don't count towards the cap.
|
||||
continue
|
||||
if(TT != my_gang_datum.my_gang)
|
||||
if(alive_gangsters < lowest_gang_count)
|
||||
lowest_gang_count = alive_gangsters
|
||||
if(my_gang_datum.my_gang.members.len >= (lowest_gang_count + mode.gang_balance_cap))
|
||||
to_chat(H, "Your gang is pretty packed right now. You don't need more members just yet. If the other families expand, you can recruit more members.")
|
||||
return FALSE
|
||||
to_chat(H, "You pull an induction package from your pockets and place it on the ground.")
|
||||
var/obj/item/gang_induction_package/GP = new(get_turf(H))
|
||||
GP.name = "\improper [my_gang_datum.name] signup package"
|
||||
GP.gang_to_use = my_gang_datum.type
|
||||
GP.team_to_use = my_gang_datum.my_gang
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
@@ -687,6 +687,7 @@
|
||||
#include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm"
|
||||
#include "code\game\gamemodes\extended\extended.dm"
|
||||
#include "code\game\gamemodes\gang\gang.dm"
|
||||
#include "code\game\gamemodes\gang\gang_handler.dm"
|
||||
#include "code\game\gamemodes\gang\gang_things.dm"
|
||||
#include "code\game\gamemodes\meteor\meteor.dm"
|
||||
#include "code\game\gamemodes\meteor\meteors.dm"
|
||||
|
||||
Reference in New Issue
Block a user