From 2191a2c33dae2cfa0e4162e92ca00ce5080d1ec6 Mon Sep 17 00:00:00 2001 From: Ikarrus Date: Wed, 1 Jul 2015 23:05:22 -0600 Subject: [PATCH] Datum-Based Gangs --- code/__DEFINES/hud.dm | 7 +- code/__HELPERS/names.dm | 15 - code/controllers/subsystem/ticker.dm | 4 +- code/datums/hud.dm | 7 +- code/datums/martial.dm | 4 +- code/datums/mind.dm | 187 +++--- code/game/gamemodes/gang/dominator.dm | 87 ++- code/game/gamemodes/gang/gang.dm | 561 ++++-------------- code/game/gamemodes/gang/gang_datum.dm | 214 +++++++ code/game/gamemodes/gang/gang_pen.dm | 64 +- code/game/gamemodes/gang/recaller.dm | 272 +++++---- code/game/gamemodes/intercept_report.dm | 2 +- code/game/objects/effects/decals/crayon.dm | 33 +- code/game/objects/items/robot/robot_parts.dm | 2 +- code/game/objects/items/toys.dm | 24 +- .../objects/items/weapons/implants/implant.dm | 6 +- code/game/objects/structures/ai_core.dm | 2 +- code/modules/admin/player_panel.dm | 24 +- code/modules/admin/topic.dm | 18 +- code/modules/admin/verbs/one_click_antag.dm | 30 +- code/modules/mob/dead/observer/observer.dm | 9 +- .../mob/living/carbon/human/human_defense.dm | 2 +- .../mob/living/carbon/human/species.dm | 2 +- code/modules/mob/living/living.dm | 11 +- code/modules/mob/living/silicon/login.dm | 2 +- .../modules/mob/living/silicon/robot/login.dm | 2 +- icons/obj/device.dmi | Bin 27983 -> 28375 bytes icons/obj/machines/dominator.dmi | Bin 4191 -> 28836 bytes tgstation.dme | 1 + 29 files changed, 706 insertions(+), 886 deletions(-) create mode 100644 code/game/gamemodes/gang/gang_datum.dm diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index d2c854462a8..f4f703601a7 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -22,7 +22,6 @@ #define ANTAG_HUD_CULT 5 #define ANTAG_HUD_REV 6 #define ANTAG_HUD_OPS 7 -#define ANTAG_HUD_GANG_A 8 -#define ANTAG_HUD_GANG_B 9 -#define ANTAG_HUD_WIZ 10 -#define ANTAG_HUD_SHADOW 11 + +#define ANTAG_HUD_WIZ 8 +#define ANTAG_HUD_SHADOW 9 diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index ca085a415c4..e5976a5c460 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -131,21 +131,6 @@ var/syndicate_name = null syndicate_name = name return name -var/gang_name_pool = list("Clandestine", "Prima", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Donk", "Gene", "Gib", "Tunnel", "Diablo", "Psyke", "Osiron", "Sleeping Carp") -var/gang_A_name = null -var/gang_B_name = null -/proc/gang_name(var/gang) - if(!gang_A_name || !gang_B_name) - gang_A_name = pick(gang_name_pool) - gang_name_pool -= gang_A_name - gang_B_name = pick(gang_name_pool) - gang_name_pool -= gang_B_name - - if(gang == "A") - return gang_A_name - if(gang == "B") - return gang_B_name - //Traitors and traitor silicons will get these. Revs will not. var/syndicate_code_phrase//Code phrase for traitors. diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 190819bd28d..31b485b79e3 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -101,7 +101,7 @@ var/datum/subsystem/ticker/ticker if(!mode.explosion_in_progress && mode.check_finished() || force_ending) current_state = GAME_STATE_FINISHED auto_toggle_ooc(1) // Turn it on - declare_completion() + declare_completion(force_ending) spawn(50) if(mode.station_was_nuked) world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke") @@ -407,7 +407,7 @@ var/datum/subsystem/ticker/ticker //calls auto_declare_completion_* for all modes for(var/handler in typesof(/datum/game_mode/proc)) if (findtext("[handler]","auto_declare_completion_")) - call(mode, handler)() + call(mode, handler)(force_ending) //Print a list of antagonists to the server log var/list/total_antagonists = list() diff --git a/code/datums/hud.dm b/code/datums/hud.dm index e1fa433e26f..e0d48eeaad6 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -9,8 +9,6 @@ var/datum/atom_hud/huds = list( \ ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \ ANTAG_HUD_REV = new/datum/atom_hud/antag(), \ ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \ - ANTAG_HUD_GANG_A = new/datum/atom_hud/antag(), \ - ANTAG_HUD_GANG_B = new/datum/atom_hud/antag(), \ ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \ ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \ ) @@ -56,6 +54,9 @@ var/datum/atom_hud/huds = list( \ //MOB PROCS /mob/proc/reload_huds() - for(var/datum/atom_hud/hud in huds) + var/gang_huds = list() + for(var/datum/gang/G in ticker.mode.gangs) + gang_huds += G.ganghud + for(var/datum/atom_hud/hud in (huds|gang_huds)) if(src in hud.hudusers) hud.add_hud_to(src) diff --git a/code/datums/martial.dm b/code/datums/martial.dm index 8c5c136980e..3077c715218 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -461,8 +461,8 @@ return user << "You begin to read the scroll..." user << "And all at once the secrets of the Sleeping Carp fill your mind. The ancient clan's martial teachings have been imbued into this scroll. As you read through it, \ - these secrets flood into your mind and body. You now know the martial techniques of the Sleeping Carp. Your hand-to-hand combat has become much more effective, and you may now perform powerful \ - combination attacks. To learn more about these combos, use the Recall Teachings ability in the Sleeping Carp tab." + these secrets flood into your mind and body.
You now know the martial techniques of the Sleeping Carp. Your hand-to-hand combat has become much more effective, and you may now perform powerful \ + combination attacks.
To learn more about these combos, use the Recall Teachings ability in the Sleeping Carp tab." user.verbs += /mob/living/carbon/human/proc/sleeping_carp_help var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null) theSleepingCarp.teach(user) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b4dc9608a3d..86e067d45c0 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -55,6 +55,7 @@ var/miming = 0 // Mime's vow of silence var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD + var/datum/gang/gang_datum //Which gang this mind belongs to, if any /datum/mind/New(var/key) src.key = key @@ -163,7 +164,7 @@ /datum/mind/proc/remove_gang() - ticker.mode.remove_gangster(src,0,1) + ticker.mode.remove_gangster(src,0,1,1) remove_objectives() /datum/mind/proc/remove_malf() @@ -223,10 +224,10 @@ alert("Not before round-start!", "Alert") return - var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
" + var/out = "" out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
" out += "Assigned role: [assigned_role]. Edit
" - out += "Factions and special roles:
" + out += "Faction and special role: [special_role]
" var/list/sections = list( "revolution", @@ -250,7 +251,7 @@ if (assigned_role in command_positions) text += "HEAD|loyal|employee|headrev|rev" else if (src in ticker.mode.head_revolutionaries) - text = "head|loyal|employee|HEADREV|rev" + text += "head|loyal|employee|HEADREV|rev" text += "
Flash: give" var/list/L = current.get_contents() @@ -285,46 +286,43 @@ if (ticker.mode.config_tag=="gang") text = uppertext(text) text = "[text]: " - if (src in ticker.mode.A_bosses) - text += "loyal|none|(A) gangster BOSS|(B) gangster boss" - text += "
Equipment: give" - - var/list/L = current.get_contents() - var/obj/item/device/gangtool/gangtool = locate() in L - if (gangtool) - text += "|take." - else - text += "." - - else if (src in ticker.mode.B_bosses) - text += "loyal|none|(A) gangster boss|(B) gangster BOSS" - text += "
Equipment: give" - - var/list/L = current.get_contents() - var/obj/item/device/gangtool/gangtool = locate() in L - if (gangtool) - text += "|take." - else - text += "." - - else if (src in ticker.mode.A_gang) - text += "loyal|none|(A) GANGSTER boss|(B) gangster boss" - else if (src in ticker.mode.B_gang) - text += "loyal|none|(A) gangster boss|(B) GANGSTER boss" - else if(isloyal(current)) - text += "LOYAL|none|(A) gangster boss|(B) gangster boss" + text += "[isloyal(current) ? "LOYAL" : "loyal"]|" + if(src in ticker.mode.get_all_gangsters()) + text += "none" else - text += "loyal|NONE|(A) gangster boss|(B) gangster boss" - + text += "NONE" if(current && current.client && current.client.prefs.be_special & BE_GANG) - text += "|Enabled in Prefs" + text += "|Enabled in Prefs
" else - text += "|Disabled in Prefs" + text += "|Disabled in Prefs
" + for(var/datum/gang/G in ticker.mode.gangs) + text += "[G.name]: " + if(src in (G.gangsters)) + text += "GANGSTER" + else + text += "gangster" + text += "|" + if(src in (G.bosses)) + text += "GANG LEADER" + else + text += "gang leader" + text += "
" + + if(gang_colors_pool) + text += "Create New Gang" + + if(src in ticker.mode.get_gang_bosses()) + text += "
Equipment: give" + var/list/L = current.get_contents() + var/obj/item/device/gangtool/gangtool = locate() in L + if (gangtool) + text += "|take" sections["gang"] = text + /** CULT ***/ text = "cult" if (ticker.mode.config_tag=="cult") @@ -538,12 +536,12 @@ if (sections["traitor"]) out += sections["traitor"]+"
" if (sections["changeling"]) - out += sections["changeling"]+"
" + out += sections["changeling"]+"

" sections -= "traitor" sections -= "changeling" else if (sections[ticker.mode.config_tag]) - out += sections[ticker.mode.config_tag]+"
" + out += sections[ticker.mode.config_tag]+"

" sections -= ticker.mode.config_tag for (var/i in sections) if (sections[i]) @@ -551,8 +549,6 @@ if (((src in ticker.mode.head_revolutionaries) || \ - (src in ticker.mode.A_bosses) || \ - (src in ticker.mode.B_bosses) || \ (src in ticker.mode.traitors) || \ (src in ticker.mode.syndicates)) && \ istype(current,/mob/living/carbon/human) ) @@ -571,7 +567,7 @@ text += "." //hiel grammar out += text - out += "
" + out += "

" out += "Memory:
" out += memory @@ -588,7 +584,9 @@ out += "Announce objectives

" - usr << browse(out, "window=edit_memory[src];size=500x500") + var/datum/browser/popup = new(usr, "edit_memory[src]", "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]", 500, 600) + popup.set_content(out) + popup.open() /datum/mind/Topic(href, href_list) if(!check_rights(R_ADMIN)) return @@ -823,6 +821,10 @@ else flash.broken = 0 + + +//////////////////// GANG MODE + else if (href_list["gang"]) switch(href_list["gang"]) if("clear") @@ -830,48 +832,6 @@ message_admins("[key_name_admin(usr)] has de-gang'ed [current].") log_admin("[key_name(usr)] has de-gang'ed [current].") - if("agang") - if(src in ticker.mode.A_gang) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.add_gangster(src,"A",0) - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A).") - log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A).") - - if("aboss") - if(src in ticker.mode.A_bosses) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.A_bosses += src - src.special_role = "[gang_name("A")] Gang (A) Boss" - ticker.mode.update_gang_icons_added(src, "A") - current << "You are a [gang_name("A")] Gang Boss!" - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") - log_admin("[key_name(usr)] has added [current] to the [gang_name("A")] Gang (A) leadership.") - ticker.mode.forge_gang_objectives(src) - ticker.mode.greet_gang(src,0) - - if("bgang") - if(src in ticker.mode.B_gang) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.add_gangster(src,"B",0) - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B).") - log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B).") - - if("bboss") - if(src in ticker.mode.B_bosses) - return - ticker.mode.remove_gangster(src, 0, 2) - ticker.mode.B_bosses += src - src.special_role = "[gang_name("B")] Gang (B) Boss" - ticker.mode.update_gang_icons_added(src, "B") - current << "You are a [gang_name("B")] Gang Boss!" - message_admins("[key_name_admin(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") - log_admin("[key_name(usr)] has added [current] to the [gang_name("B")] Gang (B) leadership.") - ticker.mode.forge_gang_objectives(src) - ticker.mode.greet_gang(src,0) - if("equip") switch(ticker.mode.equip_gang(current)) if(1) @@ -890,6 +850,51 @@ for(var/obj/item/toy/crayon/spraycan/gang/SC in L) qdel(SC) + if("new") + if(gang_colors_pool.len) + var/list/names = list("Random") + gang_name_pool + var/list/colors = list("Random") + gang_colors_pool + var/gangname = input("Pick a gang name.","Select Name") as null|anything in names + if(gangname) + var/gangcolor = input("Pick a gang color.","Select Color") as null|anything in colors + if(gangcolor && gang_colors_pool.len) //Check again just in case another admin made max gangs at the same time + if(!(gangname in gang_name_pool)) + gangname = null + if(!(gangcolor in gang_colors_pool)) + gangcolor = null + var/datum/gang/newgang = new(null,gangname,gangcolor) + ticker.mode.gangs += newgang + message_admins("[key_name_admin(usr)] has created the [newgang.name] Gang[gangcolor ? " with the color [gangcolor]" : ""].") + log_admin("[key_name(usr)] has created the [newgang.name] Gang[gangcolor ? " with the color [gangcolor]" : ""].") + + else if (href_list["gangboss"]) + var/datum/gang/G = locate(href_list["gangboss"]) in ticker.mode.gangs + if(!G || (src in G.bosses)) + return + ticker.mode.remove_gangster(src,0,2,1) + G.bosses += src + gang_datum = G + special_role = "[G.name] Gang Boss" + G.add_gang_hud(src) + current << "You are a [G.name] Gang Boss!" + message_admins("[key_name_admin(usr)] has added [current] to the [G.name] Gang leadership.") + log_admin("[key_name(usr)] has added [current] to the [G.name] Gang leadership.") + ticker.mode.forge_gang_objectives(src) + ticker.mode.greet_gang(src,0) + + else if (href_list["gangster"]) + var/datum/gang/G = locate(href_list["gangster"]) in ticker.mode.gangs + if(!G || (src in G.gangsters)) + return + ticker.mode.remove_gangster(src,0,2,1) + ticker.mode.add_gangster(src,G,0) + message_admins("[key_name_admin(usr)] has added [current] to the [G.name] Gang (A).") + log_admin("[key_name(usr)] has added [current] to the [G.name] Gang (A).") + +///////////////////////////////// + + + else if (href_list["cult"]) switch(href_list["cult"]) if("clear") @@ -1213,6 +1218,7 @@ if (!isnull(crystals)) if (suplink) suplink.uses = crystals + message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].") log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].") if("uplink") if (!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors))) @@ -1386,14 +1392,11 @@ fail |= !ticker.mode.equip_revolutionary(current) -/datum/mind/proc/make_Gang(var/gang) - special_role = "[gang_name(gang)] Gang ([gang]) Boss" - if(gang=="A") - ticker.mode.A_bosses += src - else if(gang=="B") - ticker.mode.B_bosses += src - ticker.mode.update_gang_icons_added(src, gang) - ticker.mode.forge_gang_objectives(src, gang) +/datum/mind/proc/make_Gang(var/datum/gang/G) + special_role = "[G.name] Gang Boss" + G.bosses += src + G.add_gang_hud(src) + ticker.mode.forge_gang_objectives(src) ticker.mode.greet_gang(src) ticker.mode.equip_gang(current) diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm index 0a6f4a0e471..d1e7a6ceaab 100644 --- a/code/game/gamemodes/gang/dominator.dm +++ b/code/game/gamemodes/gang/dominator.dm @@ -8,13 +8,11 @@ layer = 3.6 var/maxhealth = 200 var/health = 200 - var/gang + var/datum/gang/gang var/operating = 0 /obj/machinery/dominator/New() - if(!istype(ticker.mode, /datum/game_mode/gang)) - qdel(src) - return + ..() SetLuminosity(2) /obj/machinery/dominator/examine(mob/user) @@ -23,15 +21,9 @@ user << "It looks completely busted." return - var/datum/game_mode/gang/mode = ticker.mode - var/time = null - if(gang == "A") - if(isnum(mode.A_timer)) - time = max(mode.A_timer, 0) - if(gang == "B") - if(isnum(mode.B_timer)) - time = max(mode.B_timer, 0) - if(isnum(time)) + var/time + if(gang && isnum(gang.dom_timer)) + time = max(gang.dom_timer, 0) if(time > 0) user << "Hostile Takeover in progress. Estimated [time] seconds remain." else @@ -41,14 +33,17 @@ user << "System Integrity: [round((health/maxhealth)*100,1)]%" /obj/machinery/dominator/process() - var/datum/game_mode/gang/mode = ticker.mode - if(((gang == "A") && mode.A_timer) || ((gang == "B") && mode.B_timer)) - playsound(loc, 'sound/items/timer.ogg', 30, 0) + ..() + if(gang && isnum(gang.dom_timer)) + if(gang.dom_timer > 0) + playsound(loc, 'sound/items/timer.ogg', 30, 0) + else + SSmachine.processing -= src /obj/machinery/dominator/proc/healthcheck(var/damage) var/iconname = "dominator" if(gang) - iconname += "-[gang]" + iconname += "-[gang.color]" SetLuminosity(3) var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread @@ -59,10 +54,10 @@ if(prob(damage*2)) sparks.set_up(5, 1, src) sparks.start() - else + else if(operating >= 0) sparks.set_up(5, 1, src) sparks.start() - iconname += "-damaged" + overlays += "damage" if(operating != -1) if(health <= 0) @@ -75,13 +70,15 @@ qdel(src) /obj/machinery/dominator/proc/set_broken() - var/datum/game_mode/gang/mode = ticker.mode - if(gang == "A") - mode.A_timer = "OFFLINE" - if(gang == "B") - mode.B_timer = "OFFLINE" if(gang) - if(!isnum(mode.A_timer) && !isnum(mode.B_timer)) + gang.dom_timer = "OFFLINE" + + var/takeover_in_progress = 0 + for(var/datum/gang/G in ticker.mode.gangs) + if(isnum(G.dom_timer)) + takeover_in_progress = 1 + break + if(!takeover_in_progress) SSshuttle.emergencyNoEscape = 0 if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) SSshuttle.emergency.mode = SHUTTLE_DOCKED @@ -93,10 +90,11 @@ if(get_security_level() == "delta") set_security_level("red") - ticker.mode.message_gangtools(((gang=="A") ? ticker.mode.A_tools : ticker.mode.B_tools),"Hostile takeover cancelled: Dominator is no longer operational.",1,1) + gang.message_gangtools("Hostile takeover cancelled: Dominator is no longer operational.",1,1) SetLuminosity(0) icon_state = "dominator-broken" + overlays.Cut() operating = -1 SSmachine.processing -= src @@ -145,46 +143,33 @@ examine(user) return - var/datum/game_mode/gang/mode = ticker.mode - var/gang_territory - var/timer + var/datum/gang/tempgang - var/tempgang - if(user.mind in (ticker.mode.A_gang|ticker.mode.A_bosses)) - tempgang = "A" - gang_territory = ticker.mode.A_territory.len - timer = mode.A_timer - else if(user.mind in (ticker.mode.B_gang|ticker.mode.B_bosses)) - tempgang = "B" - gang_territory = ticker.mode.B_territory.len - timer = mode.B_timer - - if(!tempgang) + if(user.mind in ticker.mode.get_all_gangsters()) + tempgang = user.mind.gang_datum + else examine(user) return - if(isnum(timer)) + if(isnum(tempgang.dom_timer)) user << "Error: Hostile Takeover is already in progress." return - if(tempgang == "A" ? !mode.A_dominations : !mode.B_dominations) + if(!tempgang.dom_attempts) user << "Error: Unable to breach station network. Firewall has logged our signature and is blocking all further attempts." return - var/time = max(300,900 - ((round((gang_territory/start_state.num_territories)*200, 1) - 60) * 15)) - if(alert(user,"With [round((gang_territory/start_state.num_territories)*100, 1)]% station control, a takeover will require [time] seconds.\nYour gang will be unable to gain influence while it is active.\nThe entire station will likely be alerted to it once it starts.\nYou have [tempgang == "A" ? mode.A_dominations : mode.B_dominations] attempt(s) remaining. Are you ready?","Confirm","Ready","Later") == "Ready") + var/time = max(300,900 - ((round((tempgang.territory.len/start_state.num_territories)*200, 1) - 60) * 15)) + if(alert(user,"With [round((tempgang.territory.len/start_state.num_territories)*100, 1)]% station control, a takeover will require [time] seconds.\nYour gang will be unable to gain influence while it is active.\nThe entire station will likely be alerted to it once it starts.\nYou have [tempgang.dom_attempts] attempt(s) remaining. Are you ready?","Confirm","Ready","Later") == "Ready") if ((!in_range(src, user) || !istype(src.loc, /turf))) return 0 gang = tempgang - if(gang == "A") - mode.A_dominations -- - else - mode.B_dominations -- - mode.domination(gang,1,src) - src.name = "[gang_name(gang)] Gang [src.name]" + gang.dom_attempts -- + gang.domination(1,src) + src.name = "[gang.name] Gang [src.name]" healthcheck(0) operating = 1 - ticker.mode.message_gangtools(((gang=="A") ? ticker.mode.A_tools : ticker.mode.B_tools),"Hostile takeover in progress: Estimated [time] seconds until victory.") + gang.message_gangtools("Hostile takeover in progress: Estimated [time] seconds until victory.") SSmachine.processing += src /obj/machinery/dominator/attack_alien(mob/living/user) diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index 7db5a3acf65..5acc917a566 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -1,41 +1,24 @@ //gang.dm //Gang War Game Mode +var/list/gang_name_pool = list("Clandestine", "Prima", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Donk", "Gene", "Gib", "Tunnel", "Diablo", "Psyke", "Osiron", "Sleeping Carp") +var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple") + /datum/game_mode - var/list/datum/mind/A_gang = list() //gang A Members - var/list/datum/mind/B_gang = list() //gang B Members - var/list/datum/mind/A_bosses = list() //gang A Bosses - var/list/datum/mind/B_bosses = list() //gang B Bosses - var/obj/item/device/gangtool/A_tools = list() - var/obj/item/device/gangtool/B_tools = list() + var/list/datum/gang/gangs = list() var/datum/gang_points/gang_points - var/A_style - var/B_style - var/A_fighting_style - var/B_fighting_style - var/list/A_territory = list() - var/list/B_territory = list() - var/list/A_territory_new = list() - var/list/A_territory_lost = list() - var/list/B_territory_new = list() - var/list/B_territory_lost = list() + /datum/game_mode/gang name = "gang war" config_tag = "gang" antag_flag = BE_GANG restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") - required_players = 20 + required_players = 2 required_enemies = 2 recommended_enemies = 2 enemy_minimum_age = 14 - var/finished = 0 - // Victory timers - var/A_timer = "OFFLINE" - var/B_timer = "OFFLINE" - //How many attempts at domination each team is allowed - var/A_dominations = 3 - var/B_dominations = 3 + /////////////////////////// //Announces the game type// /////////////////////////// @@ -55,13 +38,28 @@ restricted_jobs += "Assistant" //Spawn more bosses depending on server population - assign_bosses(1) - if(num_players() >= 30) //30 - assign_bosses() - if(num_players() >= 40) //40 - assign_bosses() + var/gangs_to_create = 2 + if(num_players() >= 6) + gangs_to_create ++ - if(!A_bosses.len || !B_bosses.len) + for(var/i=1 to gangs_to_create) + if(!antag_candidates.len) + break + + //Create the gang + var/datum/gang/G = new() + gangs += G + + //Now assign a boss for the gang + var/datum/mind/boss = pick(antag_candidates) + antag_candidates -= boss + G.bosses += boss + boss.gang_datum = G + boss.special_role = "[G.name] Gang Boss" + boss.restricted_roles = restricted_jobs + log_game("[boss.key] has been selected as the Boss for the [G.name] Gang") + + if(gangs.len < 2) //Need at least two gangs return 0 return 1 @@ -69,89 +67,30 @@ /datum/game_mode/gang/post_setup() spawn(rand(10,100)) - for(var/datum/mind/boss_mind in A_bosses) - update_gang_icons_added(boss_mind, "A") - forge_gang_objectives(boss_mind, "A") - greet_gang(boss_mind) - equip_gang(boss_mind.current) - - for(var/datum/mind/boss_mind in B_bosses) - update_gang_icons_added(boss_mind, "B") - forge_gang_objectives(boss_mind, "B") - greet_gang(boss_mind) - equip_gang(boss_mind.current) - - modePlayer += A_bosses - modePlayer += B_bosses - assign_gang_fighting_style() + for(var/datum/gang/G in gangs) + for(var/datum/mind/boss_mind in G.bosses) + G.add_gang_hud(boss_mind) + forge_gang_objectives(boss_mind) + greet_gang(boss_mind) + equip_gang(boss_mind.current) + modePlayer += boss_mind ..() -/datum/game_mode/gang/process(seconds) - if(!finished) - if(isnum(A_timer)) - A_timer -= seconds - if(isnum(B_timer)) - B_timer -= seconds - - check_win() - -/datum/game_mode/gang/proc/assign_bosses(var/leader) - if(antag_candidates.len < 2) //Not enough bosses - return - - var/datum/mind/boss = pick(antag_candidates) - A_bosses += boss - antag_candidates -= boss - boss.special_role = "[gang_name("A")] Gang (A) [leader ? "Boss" : "Lieutenant"]" - boss.restricted_roles = restricted_jobs - log_game("[boss.key] has been selected as a [leader ? "Boss" : "Lieutenant"] for the [gang_name("A")] Gang (A)") - - boss = pick(antag_candidates) - B_bosses += boss - antag_candidates -= boss - boss.special_role = "[gang_name("B")] Gang (B) [leader ? "Boss" : "Lieutenant"]" - boss.restricted_roles = restricted_jobs - log_game("[boss.key] has been selected as a [leader ? "Boss" : "Lieutenant"] for the [gang_name("B")] Gang (B)") /datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind) - if(istype(ticker.mode, /datum/game_mode/gang)) - var/datum/objective/rival_obj = new - rival_obj.owner = boss_mind - rival_obj.explanation_text = "Preform a hostile takeover of the station with a Dominator." - boss_mind.objectives += rival_obj - -/datum/game_mode/proc/assign_gang_fighting_style() - var/aName = gang_name("A") - if(aName == "Sleeping Carp") - A_fighting_style = "martial" - else - A_fighting_style = "normal" - var/bName = gang_name("B") - if(bName == "Sleeping Carp") - B_fighting_style = "martial" - else - B_fighting_style = "normal" + var/datum/objective/rival_obj = new + rival_obj.owner = boss_mind + rival_obj.explanation_text = "Be the first gang to successfully takeover the station with a Dominator." + boss_mind.objectives += rival_obj /datum/game_mode/proc/greet_gang(var/datum/mind/boss_mind, var/you_are=1) var/obj_count = 1 - var/isboss = (boss_mind==A_bosses[1] || boss_mind==B_bosses[1]) if (you_are) - boss_mind.current << "You are [isboss ? "the Boss of" : "a Lieutenant in"] the [(boss_mind in A_bosses) ? gang_name("A") : gang_name("B")] Gang!" + boss_mind.current << "You are the Boss of the [boss_mind.gang_datum.name] Gang!" for(var/datum/objective/objective in boss_mind.objectives) boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ -/datum/game_mode/gang/proc/domination(var/gang,var/modifier=1,var/obj/dominator) - if(gang=="A") - A_timer = max(300,900 - ((round((A_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier - if(gang=="B") - B_timer = max(300,900 - ((round((B_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier - if(gang && dominator) - var/area/domloc = get_area(dominator.loc) - priority_announce("Network breach detected in [initial(domloc.name)]. The [gang_name(gang)] Gang is attempting to seize control of the station!","Network Alert") - set_security_level("delta") - SSshuttle.emergencyNoEscape = 1 - /////////////////////////////////////////////////////////////////////////// //This equips the bosses with their gear, and makes the clown not clumsy// /////////////////////////////////////////////////////////////////////////// @@ -159,21 +98,16 @@ if(!istype(mob)) return - var/isboss if (mob.mind) - isboss = (mob.mind==A_bosses[1] || mob.mind==B_bosses[1]) if (mob.mind.assigned_role == "Clown") mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." mob.dna.remove_mutation(CLOWNMUT) - var/obj/item/device/gangtool/gangtool - if(isboss) - gangtool = new(mob) - else - var/obj/item/device/gangtool/lt/lt_tool = new(mob) - gangtool = lt_tool + var/obj/item/device/gangtool/gangtool = new(mob) var/obj/item/weapon/pen/gang/T = new(mob) var/obj/item/toy/crayon/spraycan/gang/SC = new(mob) + SC.colour = mob.mind.gang_datum.color_hex + SC.update_icon() var/list/slots = list ( "backpack" = slot_in_backpack, @@ -211,243 +145,105 @@ return . -//Used by recallers when purchasing a gang outfit. First time a gang outfit is purchased the buyer decides a gang style which is stored so gang outfits are uniform -/datum/game_mode/proc/gang_outfit(mob/living/carbon/user,var/obj/item/device/gangtool/gangtool,var/gang) - if(!user || !gangtool || !gang) - return 0 - if(!gangtool.can_use(user)) - return 0 - - var/gang_style_list = list("Gang Colored Jumpsuits","Gang Colored Suits","Black Suits","White Suits","Leather Jackets","Leather Overcoats","Puffer Jackets","Tactical Turtlenecks","Soviet Uniforms") - var/style - if(gang == "A") - if(!A_style) - if(gangtool.outfits >=3) //Gives the gang boss a few minutes to pick a style first before someone else gets to - A_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list - else - user << "Your gang boss hasn't picked a style yet!" - style = A_style - - if(gang == "B") - if(!B_style) - if(gangtool.outfits >=3) //Gives the gang boss a few minutes to pick a style first before someone else gets to - B_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list - else - user << "Your gang boss hasn't picked a style yet!" - style = B_style - - if(!style) - return 0 - - if(gangtool.can_use(user) && (((gang == "A") ? gang_points.A : gang_points.B) >= 1)) - var/outfit_path - switch(style) - if("Gang Colored Jumpsuits") - if(gang == "A") - outfit_path = /obj/item/clothing/under/color/blue - if(gang == "B") - outfit_path = /obj/item/clothing/under/color/red - if("Gang Colored Suits") - if(gang == "A") - outfit_path = /obj/item/clothing/under/suit_jacket/navy - if(gang == "B") - outfit_path = /obj/item/clothing/under/suit_jacket/burgundy - if("Black Suits") - outfit_path = /obj/item/clothing/under/suit_jacket/charcoal - if("White Suits") - outfit_path = /obj/item/clothing/under/suit_jacket/white - if("Puffer Jackets") - outfit_path = /obj/item/clothing/suit/jacket/puffer - if("Leather Jackets") - outfit_path = /obj/item/clothing/suit/jacket/leather - if("Leather Overcoats") - outfit_path = /obj/item/clothing/suit/jacket/leather/overcoat - if("Soviet Uniforms") - outfit_path = /obj/item/clothing/under/soviet - if("Tactical Turtlenecks") - outfit_path = /obj/item/clothing/under/syndicate - - if(outfit_path) - var/obj/item/clothing/outfit = new outfit_path(user.loc) - outfit.armor = list(melee = 20, bullet = 30, laser = 10, energy = 10, bomb = 20, bio = 0, rad = 0) - outfit.desc += " Tailored for the [gang_name(gang)] Gang to offer the wearer moderate protection against ballistics and physical trauma." - outfit.gang = gang - user.put_in_any_hand_if_possible(outfit) - return 1 - - return 0 - -///////////////////////////////////////////// -//Checks if the either gang have won or not// -///////////////////////////////////////////// -/datum/game_mode/gang/check_win() - var/winner = 0 - - if(isnum(A_timer)) - if(A_timer < 0) - winner += 1 - if(isnum(B_timer)) - if(B_timer < 0) - winner += 2 - - if(winner) - if(winner == 3) //Edge Case: If both dominators activate at the same time - domination("A",0.5) - domination("B",0.5) - priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting hostile runtimes appears to have delayed both attempts.","Network Alert") - else if(winner == 1) - finished = "A" //Gang A wins - else if(winner == 2) - finished = "B" //Gang B wins - -/////////////////////////////// -//Checks if the round is over// -/////////////////////////////// -/datum/game_mode/gang/check_finished() - if(finished) - return 1 - return ..() //Check for evacuation/nuke - /////////////////////////////////////////// //Deals with converting players to a gang// /////////////////////////////////////////// -/datum/game_mode/proc/add_gangster(datum/mind/gangster_mind, var/gang, var/check = 1) - if(gangster_mind in (A_bosses | A_gang | B_bosses | B_gang)) +/datum/game_mode/proc/add_gangster(datum/mind/gangster_mind, var/datum/gang/G, var/check = 1) + if(!G || (gangster_mind in get_all_gangsters())) return 0 if(check && isloyal(gangster_mind.current)) //Check to see if the potential gangster is implanted return 1 - if(gang == "A") - A_gang += gangster_mind - else - B_gang += gangster_mind + G.gangsters += gangster_mind + gangster_mind.gang_datum = G if(check) if(iscarbon(gangster_mind.current)) var/mob/living/carbon/carbon_mob = gangster_mind.current carbon_mob.silent = max(carbon_mob.silent, 5) carbon_mob.flash_eyes(1, 1) gangster_mind.current.Stun(5) - gangster_mind.current << "You are now a member of the [gang_name(gang)] Gang!" + gangster_mind.current << "You are now a member of the [G.name] Gang!" gangster_mind.current << "Help your bosses take over the station by claiming territory with special spraycans only they can provide. Simply spray on any unclaimed area of the station." gangster_mind.current << "You can identify your bosses by their red \[G\] icon." - gangster_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [gang_name(gang)] Gang ([gang])!" - gangster_mind.special_role = "[gang_name(gang)] Gang ([gang])" - update_gang_icons_added(gangster_mind,gang) + gangster_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [G.name] Gang!" + gangster_mind.special_role = "[G.name] Gangster" + G.add_gang_hud(gangster_mind) return 2 //////////////////////////////////////////////////////////////////// //Deals with players reverting to neutral (Not a gangster anymore)// //////////////////////////////////////////////////////////////////// -/datum/game_mode/proc/remove_gangster(datum/mind/gangster_mind, var/beingborged, var/silent, var/exclude_bosses=0) - var/gang - - if(!exclude_bosses) - if(gangster_mind in A_bosses) - A_bosses -= gangster_mind - gang = "A" - - if(gangster_mind in B_bosses) - B_bosses -= gangster_mind - gang = "B" - - if(gangster_mind in A_gang) - A_gang -= gangster_mind - gang = "A" - - if(gangster_mind in B_gang) - B_gang -= gangster_mind - gang = "B" - - if(!gang) //not a valid gangster +/datum/game_mode/proc/remove_gangster(datum/mind/gangster_mind, var/beingborged, var/silent, var/remove_bosses=0) + var/datum/gang/gang = gangster_mind.gang_datum + if(!gang) return + for(var/datum/gang/G in gangs) + G.gangsters -= gangster_mind + if(remove_bosses) + G.bosses -= gangster_mind + gangster_mind.special_role = null + gangster_mind.gang_datum = null + if(silent < 2) - gangster_mind.current.attack_log += "\[[time_stamp()]\] Has reformed and defected from the [gang_name(gang)] Gang ([gang])!" + gangster_mind.current.attack_log += "\[[time_stamp()]\] Has reformed and defected from the [gang.name] Gang!" if(beingborged) if(!silent) gangster_mind.current.visible_message("The frame beeps contentedly from the MMI before initalizing it.") gangster_mind.current << "The frame's firmware detects and deletes your criminal behavior! You are no longer a gangster!" - message_admins("[key_name_admin(gangster_mind.current)] ? (FLW) has been borged while being a member of the [gang_name(gang)] Gang ([gang]). They are no longer a gangster.") + message_admins("[key_name_admin(gangster_mind.current)] ? (FLW) has been borged while being a member of the [gang.name] Gang. They are no longer a gangster.") else if(!silent) gangster_mind.current.Paralyse(5) gangster_mind.current.visible_message("[gangster_mind.current] looks like they've given up the life of crime!") gangster_mind.current << "You have been reformed! You are no longer a gangster!
You try as hard as you can, but you can't seem to recall any of the identities of your former gangsters...
" - update_gang_icons_removed(gangster_mind, gang) + gang.remove_gang_hud(gangster_mind) -/////////////////////// -//Add/remove gang HUD// -/////////////////////// -/datum/game_mode/proc/get_gang_hud(var/gang) - var/datum/atom_hud/antag/ganghud = null - switch(gang) - if("A") ganghud = huds[ANTAG_HUD_GANG_A] - if("B") ganghud = huds[ANTAG_HUD_GANG_B] - return ganghud +//////////////// +//Helper Procs// +//////////////// -/datum/game_mode/proc/get_gang_bosses(var/gang) - var/bosses = null - switch(gang) - if("A") bosses = A_bosses - if("B") bosses = B_bosses - return bosses +/datum/game_mode/proc/get_all_gangsters() + var/list/all_gangsters = list() + all_gangsters += get_gangsters() + all_gangsters += get_gang_bosses() + return all_gangsters -/datum/game_mode/proc/update_gang_icons_added(datum/mind/recruit_mind, var/gang) - var/datum/atom_hud/antag/ganghud = get_gang_hud(gang) - var/bosses = get_gang_bosses(gang) - if(!ganghud) - ERROR("Invalid gang in update_gang_icons_added(): [gang]") +/datum/game_mode/proc/get_gangsters() + var/list/gangsters = list() + for(var/datum/gang/G in gangs) + gangsters += G.gangsters + return gangsters - ganghud.join_hud(recruit_mind.current) - set_antag_hud(recruit_mind.current, ((recruit_mind in bosses) ? "gang_boss" : "gangster")) - -/datum/game_mode/proc/update_gang_icons_removed(datum/mind/defector_mind, var/gang) - var/datum/atom_hud/antag/ganghud = get_gang_hud(gang) - if(!ganghud) - ERROR("Invalid gang in update_gang_icons_removed(): [gang]") - - ganghud.leave_hud(defector_mind.current) - set_antag_hud(defector_mind.current, null) +/datum/game_mode/proc/get_gang_bosses() + var/list/gang_bosses = list() + for(var/datum/gang/G in gangs) + gang_bosses += G.bosses + return gang_bosses ////////////////////////////////////////////////////////////////////// //Announces the end of the game with all relavent information stated// ////////////////////////////////////////////////////////////////////// -/datum/game_mode/gang/declare_completion() - if(!finished) +/datum/game_mode/gang/declare_completion(datum/gang/winner) + if(!winner) world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before either gang could claim it!"]" else - world << "The [get_gang_bosses(finished)] Gang successfully performed a hostile takeover of the station!!" + world << "The [winner.name] Gang successfully performed a hostile takeover of the station!!" ..() return 1 -/datum/game_mode/proc/auto_declare_completion_gang() - var/winner - var/datum/game_mode/gang/game_mode = ticker.mode - if(istype(game_mode)) - if(game_mode.finished) - winner = game_mode.finished - else - winner = "Draw" - - if(A_bosses.len || A_gang.len) - if(winner) - world << "
The [gang_name("A")] Gang was [winner=="A" ? "victorious" : "defeated"] with [round((A_territory.len/start_state.num_territories)*100, 1)]% control of the station!" - world << "
The [gang_name("A")] Gang Bosses were:" - gang_membership_report(A_bosses) - world << "
The [gang_name("A")] Gangsters were:" - gang_membership_report(A_gang) +/datum/game_mode/proc/auto_declare_completion_gang(datum/gang/winner) + for(var/datum/gang/G in gangs) + world << "
The [G.name] Gang was [winner==G ? "victorious" : "defeated"] with [round((G.territory.len/start_state.num_territories)*100, 1)]% control of the station!" + world << "
The [G.name] Gang Bosses were:" + gang_membership_report(G.bosses) + world << "
The [G.name] Gangsters were:" + gang_membership_report(G.gangsters) world << "
" - if(B_bosses.len || B_gang.len) - if(winner) - world << "
The [gang_name("B")] Gang was [winner=="B" ? "victorious" : "defeated"] with [round((B_territory.len/start_state.num_territories)*100, 1)]% control of the station!
" - world << "
The [gang_name("B")] Gang Bosses were:" - gang_membership_report(B_bosses) - world << "
The [gang_name("B")] Gangsters were:" - gang_membership_report(B_gang) - world << "
" + /datum/game_mode/proc/gang_membership_report(var/list/membership) var/text = "" @@ -474,161 +270,30 @@ ////////////////////////////////////////////////////////// /datum/gang_points - var/A = 15 - var/B = 15 var/next_point_interval = 1800 var/next_point_time -/datum/gang_points/proc/start() +/datum/gang_points/New() next_point_time = world.time + next_point_interval - spawn(next_point_interval) - income() + SSobj.processing += src -/datum/gang_points/proc/income() - var/A_added_names = "" - var/B_added_names = "" - var/A_lost_names = "" - var/B_lost_names = "" +/datum/gang_points/process(seconds) + var/list/winners = list() //stores the winners if there are any - //Process lost territories - for(var/area in ticker.mode.A_territory_lost) - if(A_lost_names == "") - A_lost_names += ":
" + for(var/datum/gang/G in ticker.mode.gangs) + if(world.time > next_point_time) + G.income() + next_point_time = world.time + next_point_interval + + if(isnum(G.dom_timer)) + G.dom_timer -= seconds/10 + if(G.dom_timer < 0) + winners += G + + if(winners.len) + if(winners.len > 1) //Edge Case: If more than one dominator complete at the same time + for(var/datum/gang/G in winners) + G.domination(0.5) + priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting takeover attempts appears to have restarted.","Network Alert") else - A_lost_names += ", " - A_lost_names += "[ticker.mode.A_territory_lost[area]], " - ticker.mode.A_territory -= area - - for(var/area in ticker.mode.B_territory_lost) - if(B_lost_names == "") - B_lost_names += ":
" - else - B_lost_names += ", " - B_lost_names += "[ticker.mode.B_territory_lost[area]], " - ticker.mode.B_territory -= area - - var/datum/game_mode/gang/gangmode - if(istype(ticker.mode, /datum/game_mode/gang)) - gangmode = ticker.mode - - //Count uniformed gangsters - var/A_uniformed = 0 - var/B_uniformed = 0 - for(var/datum/mind/gangmind in (ticker.mode.A_gang|ticker.mode.A_bosses|ticker.mode.B_gang|ticker.mode.B_bosses)) - if(ishuman(gangmind.current)) - var/mob/living/carbon/human/gangster = gangmind.current - //Gangster must be alive and on station - if((gangster.stat == DEAD) || (gangster.z > ZLEVEL_STATION)) - continue - - var/obj/item/clothing/outfit - var/obj/item/clothing/gang_outfit - if(gangster.w_uniform) - outfit = gangster.w_uniform - if(outfit.gang) - gang_outfit = outfit - if(gangster.wear_suit) - outfit = gangster.wear_suit - if(outfit.gang) - gang_outfit = outfit - - if(gang_outfit) - gangster << "The [gang_name(gang_outfit.gang)] Gang's influence grows as you wear [gang_outfit]." - if(gang_outfit.gang == "A") - A_uniformed ++ - else - B_uniformed ++ - - //Calculate and report influence growth - ticker.mode.message_gangtools(ticker.mode.A_tools,"*---------*
[gang_name("A")] Gang Status Report:") - var/A_message = "" - if(gangmode && isnum(gangmode.A_timer)) - var/new_time = max(300,gangmode.A_timer - ((ticker.mode.A_territory.len + A_uniformed) * 2)) - if(new_time < gangmode.A_timer) - A_message += "Takeover shortened by [gangmode.A_timer - new_time] seconds for defending [ticker.mode.A_territory.len] territories and [A_uniformed] uniformed gangsters.
" - gangmode.A_timer = new_time - A_message += "[gangmode.A_timer] seconds remain in hostile takeover." - else - var/A_new = min(999,A + 15 + (A_uniformed * 2) + ticker.mode.A_territory.len) - if(A_new != A) - A_message += "Gang influence has increased by [A_new - A] for defending [ticker.mode.A_territory.len] territories and [A_uniformed] uniformed gangsters.
" - A = A_new - A_message += "Your gang now has [A] influence." - ticker.mode.message_gangtools(ticker.mode.A_tools,A_message,0) - - ticker.mode.message_gangtools(ticker.mode.B_tools,"[gang_name("B")] Gang Status Report:") - var/B_message = "" - if(gangmode && isnum(gangmode.B_timer)) - var/new_time = max(300,gangmode.B_timer - ((ticker.mode.B_territory.len + B_uniformed) * 2)) - if(new_time < gangmode.B_timer) - A_message += "Takeover shortened by [gangmode.B_timer - new_time] seconds for defending [ticker.mode.B_territory.len] territories and [B_uniformed] uniformed gangsters.
" - gangmode.B_timer = new_time - B_message += "[gangmode.B_timer] seconds remain hostile takeover." - else - var/B_new = min(999,B + 15 + (B_uniformed * 2) + ticker.mode.B_territory.len) - if(B_new != B) - A_message += "Gang influence has increased by [B_new - B] for defending [ticker.mode.B_territory.len] territories and [B_uniformed] uniformed gangsters.
" - B = B_new - B_message += "Your gang now has [B] influence." - ticker.mode.message_gangtools(ticker.mode.B_tools,B_message,0) - - - //Remove territories they already own from the buffer, so if they got tagged over, they can still earn income if they tag it back before the next status report - ticker.mode.A_territory_new -= ticker.mode.A_territory - ticker.mode.B_territory_new -= ticker.mode.B_territory - - //Process new territories - for(var/area in ticker.mode.A_territory_new) - if(A_added_names == "") - A_added_names += ":
" - else - A_added_names += ", " - A_added_names += "[ticker.mode.A_territory_new[area]]" - ticker.mode.A_territory += area - - for(var/area in ticker.mode.B_territory_new) - if(B_added_names == "") - B_added_names += ":
" - else - B_added_names += ", " - B_added_names += "[ticker.mode.B_territory_new[area]]" - ticker.mode.B_territory += area - - //Report territory changes - ticker.mode.message_gangtools(ticker.mode.A_tools,"[ticker.mode.A_territory_new.len] new territories
[A_added_names]",0) - ticker.mode.message_gangtools(ticker.mode.B_tools,"[ticker.mode.B_territory_new.len] new territories
[B_added_names]",0,) - ticker.mode.message_gangtools(ticker.mode.A_tools,"[ticker.mode.A_territory_lost.len] territories lost
[A_lost_names]",0) - ticker.mode.message_gangtools(ticker.mode.B_tools,"[ticker.mode.B_territory_lost.len] territories lost
[B_lost_names]",0) - - //Clear the lists - ticker.mode.A_territory_new = list() - ticker.mode.B_territory_new = list() - ticker.mode.A_territory_lost = list() - ticker.mode.B_territory_lost = list() - - var/A_control = round((ticker.mode.A_territory.len/start_state.num_territories)*100, 1) - var/B_control = round((ticker.mode.B_territory.len/start_state.num_territories)*100, 1) - ticker.mode.message_gangtools((ticker.mode.A_tools),"Your gang now has [A_control]% control of the station.
*---------*",0) - ticker.mode.message_gangtools((ticker.mode.B_tools),"Your gang now has [B_control]% control of the station.
*---------*",0) - - //Increase outfit stock - for(var/obj/item/device/gangtool/tool in (ticker.mode.A_tools | ticker.mode.B_tools)) - tool.outfits = min(tool.outfits+2,5) - - //Restart the counter - start() - -//////////////////////////////////////////////// -//Sends a message to the boss via his gangtool// -//////////////////////////////////////////////// - -/datum/game_mode/proc/message_gangtools(var/list/gangtools,var/message,var/beep=1,var/warning) - if(!gangtools.len || !message) - return - for(var/obj/item/device/gangtool/tool in gangtools) - var/mob/living/mob = get(tool.loc,/mob/living) - if(mob && mob.mind && mob.stat == CONSCIOUS) - if(((tool.gang == "A") && ((mob.mind in A_gang) || (mob.mind in A_bosses))) || ((tool.gang == "B") && ((mob.mind in B_gang) || (mob.mind in B_bosses)))) - mob << "\icon[tool] [message]" - if(beep) - playsound(mob.loc, 'sound/machines/twobeep.ogg', 50, 1) \ No newline at end of file + ticker.force_ending = winners[1] diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm new file mode 100644 index 00000000000..9e87bf4b11b --- /dev/null +++ b/code/game/gamemodes/gang/gang_datum.dm @@ -0,0 +1,214 @@ +//gang_datum.dm +//Datum-based gangs + +/datum/gang + var/name = "ERROR" + var/color = "white" + var/color_hex = "#FFFFFF" + var/list/datum/mind/gangsters = list() //gang B Members + var/list/datum/mind/bosses = list() //gang A Bosses + var/list/obj/item/device/gangtool/gangtools = list() + var/style + var/fighting_style = "normal" + var/list/territory = list() + var/list/territory_new = list() + var/list/territory_lost = list() + var/dom_timer = "OFFLINE" + var/dom_attempts = 2 + var/points = 15 + var/datum/atom_hud/antag/ganghud + +/datum/gang/New(loc,gangname,gangcolor) + if(!gang_colors_pool.len) + message_admins("WARNING: Maximum number of gangs have been exceeded!") + ERROR("WARNING: Maximum number of gangs have been exceeded!") + else + color = (gangcolor ? gangcolor : pick(gang_colors_pool)) + gang_colors_pool -= color + switch(color) + if("red") + color_hex = "#DA0000" + if("orange") + color_hex = "#FF9300" + if("yellow") + color_hex = "#FFF200" + if("green") + color_hex = "#A8E61D" + if("blue") + color_hex = "#00B7EF" + if("purple") + color_hex = "#DA00FF" + + name = (gangname ? gangname : pick(gang_name_pool)) + gang_name_pool -= name + if(name == "Sleeping Carp") + fighting_style = "martial" + + ganghud = new() + log_game("The [name] Gang has been created. Their gang color is [color].") + +/datum/gang/proc/add_gang_hud(datum/mind/recruit_mind) + ganghud.join_hud(recruit_mind.current) + ticker.mode.set_antag_hud(recruit_mind.current, ((recruit_mind in bosses) ? "gang_boss" : "gangster")) + +/datum/gang/proc/remove_gang_hud(datum/mind/defector_mind) + ganghud.leave_hud(defector_mind.current) + ticker.mode.set_antag_hud(defector_mind.current, null) + +/datum/gang/proc/domination(var/modifier=1,var/obj/dominator) + dom_timer = max(300,900 - ((round((territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier + if(dominator) + var/area/domloc = get_area(dominator.loc) + priority_announce("Network breach detected in [initial(domloc.name)]. The [src] Gang is attempting to seize control of the station!","Network Alert") + set_security_level("delta") + SSshuttle.emergencyNoEscape = 1 + +//////////////////////////////////////////// OUTFITS + + +//Used by recallers when purchasing a gang outfit. First time a gang outfit is purchased the buyer decides a gang style which is stored so gang outfits are uniform +/datum/gang/proc/gang_outfit(mob/living/carbon/user,var/obj/item/device/gangtool/gangtool) + if(!user || !gangtool) + return 0 + if(!gangtool.can_use(user)) + return 0 + + var/gang_style_list = list("Gang Colors","Black Suits","White Suits","Leather Jackets","Leather Overcoats","Puffer Jackets","Military Jackets","Tactical Turtlenecks","Soviet Uniforms") + if(!style && gangtool.boss) //Only the boss gets to pick a style + style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list + + if(gangtool.can_use(user) && (gangtool.outfits >= 1)) + var/outfit_path + switch(style) + if(null || "Gang Colors") + outfit_path = text2path("/obj/item/clothing/under/color/[color]") + if("Black Suits") + outfit_path = /obj/item/clothing/under/suit_jacket/charcoal + if("White Suits") + outfit_path = /obj/item/clothing/under/suit_jacket/white + if("Puffer Jackets") + outfit_path = /obj/item/clothing/suit/jacket/puffer + if("Leather Jackets") + outfit_path = /obj/item/clothing/suit/jacket/leather + if("Leather Overcoats") + outfit_path = /obj/item/clothing/suit/jacket/leather/overcoat + if("Military Jackets") + outfit_path = /obj/item/clothing/suit/miljacket + if("Soviet Uniforms") + outfit_path = /obj/item/clothing/under/soviet + if("Tactical Turtlenecks") + outfit_path = /obj/item/clothing/under/syndicate + + if(outfit_path) + var/obj/item/clothing/outfit = new outfit_path(user.loc) + outfit.armor = list(melee = 20, bullet = 30, laser = 10, energy = 10, bomb = 20, bio = 0, rad = 0) + outfit.desc += " Tailored for the [name] Gang to offer the wearer moderate protection against ballistics and physical trauma." + outfit.gang = src + user.put_in_any_hand_if_possible(outfit) + return 1 + + return 0 + + +//////////////////////////////////////////// MESSAGING + + +/datum/gang/proc/message_gangtools(var/message,var/beep=1,var/warning) + if(!gangtools.len || !message) + return + for(var/obj/item/device/gangtool/tool in gangtools) + var/mob/living/mob = get(tool.loc,/mob/living) + if(mob && mob.mind && mob.stat == CONSCIOUS) + if(mob.mind.gang_datum == src) + mob << "\icon[tool] [message]" + if(beep) + playsound(mob.loc, 'sound/machines/twobeep.ogg', 50, 1) + + +//////////////////////////////////////////// INCOME + + +/datum/gang/proc/income() + if(!bosses.len) + return + + var/added_names = "" + var/lost_names = "" + + //Process lost territories + for(var/area in territory_lost) + if(lost_names == "") + lost_names += ":
" + else + lost_names += ", " + lost_names += "[territory_lost[area]], " + territory -= area + + //Count uniformed gangsters + var/uniformed = 0 + for(var/datum/mind/gangmind in (gangsters|bosses)) + if(ishuman(gangmind.current)) + var/mob/living/carbon/human/gangster = gangmind.current + //Gangster must be alive and on station + if((gangster.stat == DEAD) || (gangster.z > ZLEVEL_STATION)) + continue + + var/obj/item/clothing/outfit + var/obj/item/clothing/gang_outfit + if(gangster.w_uniform) + outfit = gangster.w_uniform + if(outfit.gang == src) + gang_outfit = outfit + if(gangster.wear_suit) + outfit = gangster.wear_suit + if(outfit.gang == src) + gang_outfit = outfit + + if(gang_outfit) + gangster << "The [src] Gang's influence grows as you wear [gang_outfit]." + uniformed ++ + + //Calculate and report influence growth + message_gangtools("*---------*
[src] Gang Status Report:") + var/message = "" + if(isnum(dom_timer)) + var/new_time = max(300,dom_timer - ((territory.len + uniformed) * 2)) + if(new_time < dom_timer) + message += "Takeover shortened by [dom_timer - new_time] seconds for defending [territory.len] territories and [uniformed] uniformed gangsters.
" + dom_timer = new_time + message += "[dom_timer] seconds remain in hostile takeover." + else + var/points_new = min(999,points + 15 + (uniformed * 2) + territory.len) + if(points_new != points) + message += "Gang influence has increased by [points_new - points] for defending [territory.len] territories and [uniformed] uniformed gangsters.
" + points = points_new + message += "Your gang now has [points] influence." + message_gangtools(message,0) + + + //Remove territories they already own from the buffer, so if they got tagged over, they can still earn income if they tag it back before the next status report + territory_new -= territory + + //Process new territories + for(var/area in territory_new) + if(added_names == "") + added_names += ":
" + else + added_names += ", " + added_names += "[territory_new[area]]" + territory += area + + //Report territory changes + message_gangtools("[territory_new.len] new territories
[added_names]",0) + message_gangtools("[territory_lost.len] territories lost
[lost_names]",0) + + //Clear the lists + territory_new = list() + territory_lost = list() + + var/control = round((territory.len/start_state.num_territories)*100, 1) + message_gangtools("Your gang now has [control]% control of the station.
*---------*",0) + + //Increase outfit stock + for(var/obj/item/device/gangtool/tool in gangtools) + tool.outfits = min(tool.outfits+1,5) \ No newline at end of file diff --git a/code/game/gamemodes/gang/gang_pen.dm b/code/game/gamemodes/gang/gang_pen.dm index 679f0aa6a59..fb13d18fd30 100644 --- a/code/game/gamemodes/gang/gang_pen.dm +++ b/code/game/gamemodes/gang/gang_pen.dm @@ -4,45 +4,50 @@ /obj/item/weapon/pen/gang origin_tech = "materials=2;syndicate=5" var/cooldown + var/last_used = 0 + var/charges = 1 /obj/item/weapon/pen/gang/attack(mob/living/M, mob/user) if(!istype(M)) return if(ishuman(M) && ishuman(user) && M.stat != DEAD) - if(user.mind && ((user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses))) + if(user.mind && (user.mind in ticker.mode.get_gang_bosses())) if(..(M,user,1)) if(cooldown) user << "[src] needs more time to recharge before it can be used." return if(M.client) M.mind_initialize() //give them a mind datum if they don't have one. - if(user.mind in ticker.mode.A_bosses) - var/recruitable = ticker.mode.add_gangster(M.mind,"A") - switch(recruitable) - if(2) - M.Paralyse(5) - cooldown(max(0,ticker.mode.B_gang.len - ticker.mode.A_gang.len)) - if(1) - user << "This mind is resistant to recruitment!" - else - user << "This mind has already been recruited into a gang!" - else if(user.mind in ticker.mode.B_bosses) - var/recruitable = ticker.mode.add_gangster(M.mind,"B") - switch(recruitable) - if(2) - M.Paralyse(5) - cooldown(max(0,ticker.mode.A_gang.len - ticker.mode.B_gang.len)) - if(1) - user << "This mind is resistant to recruitment!" - else - user << "This mind has already been recruited into a gang!" + var/datum/gang/G = user.mind.gang_datum + var/recruitable = ticker.mode.add_gangster(M.mind,G) + switch(recruitable) + if(2) + M.Paralyse(5) + cooldown(G) + if(1) + user << "This mind is resistant to recruitment!" + else + user << "This mind has already been recruited into a gang!" return ..() -/obj/item/weapon/pen/gang/proc/cooldown(modifier) +/obj/item/weapon/pen/gang/proc/cooldown(datum/gang/gang) + var/cooldown_time = 1200+(600*gang.bosses.len) // 1recruiter=3mins, 2recruiters=4mins, 3recruiters=5 mins + cooldown = 1 icon_state = "pen_blink" - spawn(max(50,1800-(modifier*300))) + + charges = max(0,charges-1) + var/time_passed = world.time - last_used + var/time = time_passed/cooldown_time + for(null, time>=cooldown_time, time-=cooldown_time) //get 1 charge every cooldown interval + charges++ + + last_used = world.time - time + + if(charges) + cooldown_time = 50 + spawn(cooldown_time) cooldown = 0 icon_state = "pen" var/mob/M = get(src, /mob) @@ -57,7 +62,7 @@ name = "gang implant" desc = "Makes you a gangster or such." activated = 0 - var/gang + var/datum/gang/gang /obj/item/weapon/implant/gang/New(loc,var/setgang) ..() @@ -81,11 +86,12 @@ if(I != src) qdel(I) - ticker.mode.remove_gangster(target.mind,0,1,1) - if(ticker.mode.add_gangster(target.mind,gang)) - target.Paralyse(5) - else - target.visible_message("[target] seems to resist the implant!", "You feel the influence of your enemies try to invade your mind!") + if(target.stat != DEAD) + ticker.mode.remove_gangster(target.mind,0,1) + if(ticker.mode.add_gangster(target.mind,gang)) + target.Paralyse(5) + else + target.visible_message("[target] seems to resist the implant!", "You feel the influence of your enemies try to invade your mind!") qdel(src) /obj/item/weapon/implanter/gang/New(loc,var/gang) diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm index ca88f7c986b..15a1440bdfc 100644 --- a/code/game/gamemodes/gang/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -1,25 +1,24 @@ //gangtool device /obj/item/device/gangtool name = "suspicious device" - desc = "A strange device of sorts. Hard to really make out what it actually does just by looking." - icon_state = "gangtool" + desc = "A strange device of sorts. Hard to really make out what it actually does if you don't know how to operate it." + icon_state = "gangtool-white" item_state = "walkietalkie" throwforce = 0 w_class = 1.0 throw_speed = 3 throw_range = 7 flags = CONDUCT - var/gang //Which gang uses this? + var/datum/gang/gang //Which gang uses this? var/boss = 1 //If this gangtool belongs to the big boss var/recalling = 0 var/outfits = 3 + var/free_pen = 0 + var/promotable = 1 /obj/item/device/gangtool/New() //Initialize supply point income if it hasn't already been started if(!ticker.mode.gang_points) ticker.mode.gang_points = new /datum/gang_points(ticker.mode) - ticker.mode.gang_points.start() - if(boss) - desc += " Looks important." /obj/item/device/gangtool/attack_self(mob/user) if (!can_use(user)) @@ -28,23 +27,25 @@ var/dat if(!gang) dat += "This device is not registered.

" - dat += "Register Device
" + if(user.mind in ticker.mode.get_gang_bosses()) + if(promotable && user.mind.gang_datum.bosses < 3) + dat += "Give this device to another member of your organization to use to promote them to Lieutenant.
" + dat += "If this is meant as a spare device for yourself:
" + else + dat += "No promotions available: All positions filled.
" + dat += "Register Device
" + else if (promotable && user.mind.gang_datum.bosses < 3) + dat += "You have been selected for a promotion!
" + dat += "Register Device
" + else + dat += "No promotions available: All positions filled.
" else - var/datum/game_mode/gang/gangmode - if(istype(ticker.mode, /datum/game_mode/gang)) - gangmode = ticker.mode + if(isnum(gang.dom_timer)) + dat += "
Takeover In Progress:
[gang.dom_timer] seconds remain

" - var/gang_size = ((gang == "A")? (ticker.mode.A_bosses.len+ticker.mode.A_gang.len) : (ticker.mode.B_bosses.len+ticker.mode.B_gang.len)) - var/gang_territory = ((gang == "A")? ticker.mode.A_territory.len : ticker.mode.B_territory.len) - var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) - var/timer - if(gangmode) - timer = ((gang == "A") ? gangmode.A_timer : gangmode.B_timer) - if(isnum(timer)) - dat += "
Takeover In Progress:
[timer] seconds remain

" - - dat += "Registration: [gang_name(gang)] Gang [boss ? "Boss" : "Lieutenant"]
" - dat += "Organization Size: [gang_size] | Station Control: [round((gang_territory/start_state.num_territories)*100, 1)]%
" + var/points = gang.points + dat += "Registration: [gang.name] Gang [boss ? "Boss" : "Lieutenant"]
" + dat += "Organization Size: [gang.gangsters.len + gang.bosses.len] | Station Control: [round((gang.territory.len/start_state.num_territories)*100, 1)]%
" dat += "Gang Influence: [points] | Outfit Stock: [outfits]
" dat += "Time until Influence grows: [(points >= 999) ? ("--:--") : (time2text(ticker.mode.gang_points.next_point_time - world.time, "mm:ss"))]
" dat += "
" @@ -55,8 +56,7 @@ dat += "Create Armored Gang Outfit
" else dat += "Create Gang Outfit (Restocking)
" - if(gangmode) - dat += "Recall Emergency Shuttle
" + dat += "Recall Emergency Shuttle
" dat += "
" dat += "Purchase Weapons:
" @@ -65,7 +65,7 @@ // NORMAL GANG // ///////////////// - if(!gangmode || (gang == "A" && gangmode.A_fighting_style == "normal") || (gang == "B" && gangmode.B_fighting_style == "normal")) //If the gamemode is not gang, always use standard loadout. + if(gang.fighting_style == "normal") dat += "(10 Influence) " if(points >= 10) dat += "Switchblade
" @@ -102,7 +102,7 @@ // MARTIAL ARTS // ////////////////// - else if((gang == "A" && gangmode.A_fighting_style == "martial") || (gang == "B" && gangmode.B_fighting_style == "martial")) + else if(gang.fighting_style == "martial") dat += "(10 Influence) " if(points >= 10) dat += "Bo Staff
" @@ -146,28 +146,33 @@ else dat += "Implant Breaker
" - dat += "(50 Influence) " - if(points >= 50) + if(free_pen) + dat += "(GET ONE FREE) " + else + dat += "(50 Influence) " + if((points >= 50)||free_pen) dat += "Recruitment Pen
" else dat += "Recruitment Pen
" - dat += "(30 Influence) " - if(points >= 30) - dat += "Spare Gangtool
" + var/gangtooltext = "Spare Gangtool" + if(boss && gang.bosses.len < 3) + gangtooltext = "Promote a Gangster" + dat += "(10 Influence) " + if(points >= 10) + dat += "[gangtooltext]
" else - dat += "Spare Gangtool
" + dat += "[gangtooltext]
" - if(gangmode) - if(gang == "A" ? !gangmode.A_dominations : !gangmode.B_dominations) - dat += "(Out of stock) Station Dominator" + if(!gang.dom_attempts) + dat += "(Out of stock) Station Dominator" + else + dat += "(30 Influence) " + if(points >= 30) + dat += "Station Dominator
" else - dat += "(30 Influence) " - if(points >= 30) - dat += "Station Dominator
" - else - dat += "Station Dominator
" - dat += "(Estimated Takeover Time: [round(max(300,900 - ((round((gang_territory/start_state.num_territories)*200, 10) - 60) * 15))/60,1)] minutes)
" + dat += "Station Dominator
" + dat += "(Estimated Takeover Time: [round(max(300,900 - ((round((gang.territory.len/start_state.num_territories)*200, 10) - 60) * 15))/60,1)] minutes)
" dat += "
" dat += "Refresh
" @@ -189,108 +194,107 @@ return if(href_list["register"]) - register_device(usr) + if(promotable) + register_device(usr) else if(!gang) //Gangtool must be registered before you can use the functions below return if(href_list["purchase"]) - var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) + var/pointcost var/item_type switch(href_list["purchase"]) if("spraycan") - if(points >= 5) + if(gang.points >= 5) item_type = /obj/item/toy/crayon/spraycan/gang - points = 5 + pointcost = 5 if("switchblade") - if(points >= 10) + if(gang.points >= 10) item_type = /obj/item/weapon/switchblade - points = 10 + pointcost = 10 if("pistol") - if(points >= 25) + if(gang.points >= 25) item_type = /obj/item/weapon/gun/projectile/automatic/pistol - points = 25 + pointcost = 25 if("10mmammo") - if(points >= 10) + if(gang.points >= 10) item_type = /obj/item/ammo_box/magazine/m10mm - points = 10 + pointcost = 10 if("uzi") - if(points >= 50) + if(gang.points >= 50) item_type = /obj/item/weapon/gun/projectile/automatic/mini_uzi - points = 50 + pointcost = 50 if("9mmammo") - if(points >= 20) + if(gang.points >= 20) item_type = /obj/item/ammo_box/magazine/uzim9mm - points = 20 + pointcost = 20 if("scroll") - if(points >= 30) + if(gang.points >= 30) item_type = /obj/item/weapon/sleeping_carp_scroll usr << "Anyone who reads the sleeping carp scroll will learn secrets of the sleeping carp martial arts style." - points = 30 + pointcost = 30 if("wrestlingbelt") - if(points >= 20) + if(gang.points >= 20) item_type = /obj/item/weapon/storage/belt/champion/wrestling usr << "Anyone wearing the wresting belt will know how to be effective with wrestling." - points = 20 + pointcost = 20 if("bostaff") - if(points >= 10) + if(gang.points >= 10) item_type = /obj/item/weapon/twohanded/bostaff - points = 10 + pointcost = 10 if("C4") - if(points >= 10) + if(gang.points >= 10) item_type = /obj/item/weapon/c4 - points = 10 + pointcost = 10 if("pen") - if(points >= 50) + if((gang.points >= 50) || free_pen) item_type = /obj/item/weapon/pen/gang usr << "More recruitmen pens will allow you to recruit gangsters faster. Only gang leaders can recruit with pens." - points = 50 + if(!free_pen) + pointcost = 50 if("implant") - if(points >= 10) + if(gang.points >= 10) item_type = /obj/item/weapon/implanter/gang usr << "The implant breaker is a single-use device that destroys all implants within the target before trying to recruit them to your gang. Also works on enemy gangsters." - points = 10 + pointcost = 10 if("gangtool") - if(points >= 30) - item_type = /obj/item/device/gangtool/lt - points = 30 + if(gang.points >= 10) + if(boss) + item_type = /obj/item/device/gangtool/spare + if(gang.bosses.len < 3) + usr << "Gangtools allow you to promote a gangster to be your Lieutenant. Simply have them register the gangtool. You may promote up to [3-gang.bosses.len] more Lieutenants" + else + item_type = /obj/item/device/gangtool/spare/lt + pointcost = 10 if("dominator") - if(istype(ticker.mode, /datum/game_mode/gang)) - var/datum/game_mode/gang/mode = ticker.mode - if(isnum((gang == "A") ? mode.A_timer : mode.B_timer)) + if(!gang.dom_attempts) + return + + var/area/usrarea = get_area(usr.loc) + var/usrturf = get_turf(usr.loc) + if(initial(usrarea.name) == "Space" || istype(usrturf,/turf/space) || usr.z != 1) + usr << "You can only use this on the station!" + return + + for(var/obj/obj in usrturf) + if(obj.density) + usr << "There's not enough room here!" return - if(gang == "A" ? !mode.A_dominations : !mode.B_dominations) - return - - var/area/usrarea = get_area(usr.loc) - var/usrturf = get_turf(usr.loc) - if(initial(usrarea.name) == "Space" || istype(usrturf,/turf/space) || usr.z != 1) - usr << "You can only use this on the station!" - return - - for(var/obj/obj in usrturf) - if(obj.density) - usr << "There's not enough room here!" - return - - if(points >= 30) - item_type = /obj/machinery/dominator - usr << "The dominator will secure your gang's dominance over the station. Turn it on when you are ready to defend it." - points = 30 + if(gang.points >= 30) + item_type = /obj/machinery/dominator + usr << "The dominator will secure your gang's dominance over the station. Turn it on when you are ready to defend it." + pointcost = 30 if(item_type) - if(gang == "A") - ticker.mode.gang_points.A -= points - else if(gang == "B") - ticker.mode.gang_points.B -= points + gang.points -= pointcost if(ispath(item_type)) var/obj/purchased = new item_type(get_turf(usr),gang) var/mob/living/carbon/human/H = usr H.put_in_any_hand_if_possible(purchased) - if(points) - ticker.mode.message_gangtools(((gang=="A")? ticker.mode.A_tools : ticker.mode.B_tools), "A [href_list["purchase"]] was purchased by [usr] for [points] Influence.") - log_game("A [href_list["purchase"]] was purchased by [key_name(usr)] for [points] Influence.") + if(pointcost) + gang.message_gangtools("A [href_list["purchase"]] was purchased by [usr.real_name] for [pointcost] Influence.") + log_game("A [href_list["purchase"]] was purchased by [key_name(usr)] ([gang.name] Gang) for [pointcost] Influence.") else usr << "Not enough influence." @@ -301,7 +305,7 @@ recall(usr) if("outfit") if(outfits > 0) - if(ticker.mode.gang_outfit(usr,src,gang)) + if(gang.gang_outfit(usr,src)) outfits -= 1 if("ping") ping_gang(usr) @@ -317,69 +321,70 @@ if(user.z > 2) user << "\icon[src]Error: Station out of range." return - var/list/members = list() - if(gang == "A") - members += ticker.mode.A_bosses | ticker.mode.A_gang - else if(gang == "B") - members += ticker.mode.B_bosses | ticker.mode.B_gang + var/list/members = list(gang.gangsters + gang.bosses) if(members.len) - var/ping = "[gang_name(gang)] [boss ? "Gang Boss" : "Lieutenant"] [user.real_name]: [message]" + var/ping = "[gang.name] [boss ? "Gang Boss" : "Lieutenant"]: [message]" for(var/datum/mind/ganger in members) if((ganger.current.z <= 2) && (ganger.current.stat == CONSCIOUS)) ganger.current << ping for(var/mob/M in dead_mob_list) M << ping - log_game("[key_name(user)] Messaged [gang_name(gang)] Gang ([gang]): [message].") + log_game("[key_name(user)] Messaged [gang.name] Gang: [message].") /obj/item/device/gangtool/proc/register_device(var/mob/user) - if(user.mind in ticker.mode.A_bosses) - ticker.mode.A_tools += src - gang = "A" - icon_state = "gangtool-a" - else if(user.mind in ticker.mode.B_bosses) - ticker.mode.B_tools += src - gang = "B" - icon_state = "gangtool-b" - if(!gang) + if(user.mind in ticker.mode.get_all_gangsters()) + gang = user.mind.gang_datum + gang.gangtools += src + icon_state = "gangtool-[gang.color]" + if(!(user.mind in gang.bosses)) + ticker.mode.remove_gangster(user.mind, 0, 2) + gang.bosses += user.mind + user.mind.special_role = "[gang.name] Gang Lieutenant" + gang.add_gang_hud(user.mind) + log_game("[key_name(user)] has been promoted to Lieutenant in the [gang.name] Gang") + free_pen = 1 + gang.message_gangtools("[user] has been promoted to Lieutenant.") + user << "You have been promoted to Lieutenant!" + ticker.mode.forge_gang_objectives(user.mind) + ticker.mode.greet_gang(user.mind,0) + user << "The Gangtool you registered will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station." + user << "Unlike regular gangsters, you may use recruitment pens to add recruits to your gang. Use them on unsuspecting crew members to recruit them. Don't forget to get your one free pen from the gangtool." + else usr << "ACCESS DENIED: Unauthorized user." /obj/item/device/gangtool/proc/recall(mob/user) if(!can_use(user)) return 0 - if(!istype(ticker.mode, /datum/game_mode/gang)) - return 0 - - var/datum/game_mode/gang/mode = ticker.mode - mode.message_gangtools(((gang=="A")? ticker.mode.A_tools : ticker.mode.B_tools), "[usr] is attempting to recall the emergency shuttle.") + gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.") recalling = 1 loc << "\icon[src]Generating shuttle recall order with codes retrieved from last call signal..." sleep(rand(100,300)) if(SSshuttle.emergency.mode != SHUTTLE_CALL) //Shuttle can only be recalled when it's moving to the station - user << "\icon[src]Emergency shuttle cannot be recalled at this time." + user << "\icon[src]Emergency shuttle cannot be recalled at this time." recalling = 0 return 0 loc << "\icon[src]Shuttle recall order generated. Accessing station long-range communication arrays..." sleep(rand(100,300)) - if(gang == "A" ? !mode.A_dominations : !mode.B_dominations) - user << "\icon[src]Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts." + if(!gang.dom_attempts) + user << "\icon[src]Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts." recalling = 0 return 0 var/turf/userturf = get_turf(user) if(userturf.z != 1) //Shuttle can only be recalled while on station - user << "\icon[src]Error: Device out of range of station communication arrays." + user << "\icon[src]Error: Device out of range of station communication arrays." recalling = 0 return 0 var/datum/station_state/end_state = new /datum/station_state() end_state.count() if((100 * start_state.score(end_state)) < 70) //Shuttle cannot be recalled if the station is too damaged - user << "\icon[src]Error: Station communication systems compromised. Unable to establish connection." + user << "\icon[src]Error: Station communication systems compromised. Unable to establish connection." recalling = 0 return 0 loc << "\icon[src]Comm arrays accessed. Broadcasting recall signal..." @@ -404,21 +409,14 @@ return if(!(src in user.contents)) return - - var/success if(user.mind) - if(gang) - if((gang == "A") && (user.mind in ticker.mode.A_bosses)) - success = 1 - else if((gang == "B") && (user.mind in ticker.mode.B_bosses)) - success = 1 - else - success = 1 - if(success) + if(gang && !(user.mind in gang.bosses)) + return return 1 - user << "\icon[src] ACCESS DENIED: Unauthorized user." - return 0 -/obj/item/device/gangtool/lt +/obj/item/device/gangtool/spare boss = 0 outfits = 1 + +/obj/item/device/gangtool/spare/lt + promotable = 0 \ No newline at end of file diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index 6fe17405212..730fff0d91a 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -229,7 +229,7 @@ /datum/intercept_text/proc/build_gang(datum/mind/correct_person) src.text += "

We have reports of criminal activity in close proximity to our operations within your sector." - src.text += "Ensure law and order is maintained on the station and be on the lookout for aggressive factionalism within the crew." + src.text += "Ensure law and order is maintained on the station and be on the lookout for territorial aggression within the crew." src.text += "In the event of a full-scale criminal takeover threat, sensitive research items are to be secured and the station evacuated ASAP." src.text += "

" diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 1c1d2cc4a54..2d89998c4d7 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -19,7 +19,6 @@ name = e_name desc = "A [name] drawn in crayon." if(type == "poseur tag") - gang_name() //Generate gang names so they get removed from the pool type = pick(gang_name_pool) icon_state = type @@ -31,37 +30,27 @@ /obj/effect/decal/cleanable/crayon/gang layer = 3.6 //Harder to hide - var/gang + var/datum/gang/gang -/obj/effect/decal/cleanable/crayon/gang/New(location, var/type, var/e_name = "gang tag", var/rotation = 0) - if(!type) +/obj/effect/decal/cleanable/crayon/gang/New(location, var/datum/gang/G, var/e_name = "gang tag", var/rotation = 0) + if(!type || !G) qdel(src) var/area/territory = get_area(location) var/color - if(type == "A") - gang = type - color = "#00B7EF" - icon_state = gang_name("A") - ticker.mode.A_territory_new |= list(territory.type = territory.name) - ticker.mode.A_territory_lost -= territory.type - else if(type == "B") - gang = type - color = "#DA0000" - icon_state = gang_name("B") - ticker.mode.B_territory_new |= list(territory.type = territory.name) - ticker.mode.B_territory_lost -= territory.type + gang = G + color = G.color_hex + icon_state = G.name + G.territory_new |= list(territory.type = territory.name) + G.territory_lost -= territory.type ..(location, color, icon_state, e_name, rotation) /obj/effect/decal/cleanable/crayon/gang/Destroy() var/area/territory = get_area(src) - if(gang == "A") - ticker.mode.A_territory_new -= territory.type - ticker.mode.A_territory_lost |= list(territory.type = territory.name) - if(gang == "B") - ticker.mode.B_territory_new -= territory.type - ticker.mode.B_territory_lost |= list(territory.type = territory.name) + if(gang) + gang.territory_new -= territory.type + gang.territory_lost |= list(territory.type = territory.name) ..() \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index e0629ec2f27..2e3c278c526 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -185,7 +185,7 @@ user << "Sticking a dead brain into the frame would sort of defeat the purpose!" return - if((BM.mind in ticker.mode.head_revolutionaries) || (BM.mind in ticker.mode.A_bosses) || (BM.mind in ticker.mode.B_bosses)) + if(BM.mind in (ticker.mode.head_revolutionaries|ticker.mode.get_gang_bosses())) user << "The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the MMI!" return diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 5bc5733aa4b..60de1efb596 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -420,28 +420,16 @@ var/gangID if(gang) //Determine gang affiliation - if(user.mind in (ticker.mode.A_bosses | ticker.mode.A_gang)) - temp = "[gang_name("A")] gang tag" - gangID = "A" - else if(user.mind in (ticker.mode.B_bosses | ticker.mode.B_gang)) - temp = "[gang_name("B")] gang tag" - gangID = "B" + gangID = user.mind.gang_datum //Check area validity. Reject space, player-created areas, and non-station z-levels. - if (gangID) + if(gangID) territory = get_area(target) if(territory && (territory.z == ZLEVEL_STATION) && territory.valid_territory) //Check if this area is already tagged by a gang if(!(locate(/obj/effect/decal/cleanable/crayon/gang) in target)) //Ignore the check if the tile being sprayed has a gang tag if(territory_claimed(territory, user)) return - /* - //Prevent people spraying from outside of the territory (ie. Maint walls) - var/area/user_area = get_area(user.loc) - if(istype(user_area) && (user_area.type != territory.type)) - user << "You cannot tag [territory] from the outside." - return - */ if(locate(/obj/machinery/power/apc) in (user.loc.contents | target.contents)) user << "You cannot tag here." return @@ -508,10 +496,10 @@ /obj/item/toy/crayon/proc/territory_claimed(var/area/territory,mob/user) var/occupying_gang - if(territory.type in (ticker.mode.A_territory | ticker.mode.A_territory_new)) - occupying_gang = gang_name("A") - if(territory.type in (ticker.mode.B_territory | ticker.mode.B_territory_new)) - occupying_gang = gang_name("B") + for(var/datum/gang/G in ticker.mode.gangs) + if(territory.type in (G.territory|G.territory_new)) + occupying_gang = G.name + break if(occupying_gang) user << "[territory] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!" return 1 diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 3dad31930c6..b8c72c0827b 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -238,11 +238,11 @@ /obj/item/weapon/implant/loyalty/implanted(mob/target) ..() - if((target.mind in (ticker.mode.head_revolutionaries | ticker.mode.A_bosses | ticker.mode.B_bosses)) || is_shadow_or_thrall(target)) + if((target.mind in (ticker.mode.head_revolutionaries | ticker.mode.get_gang_bosses())) || is_shadow_or_thrall(target)) target.visible_message("[target] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!") return 0 - if(target.mind in (ticker.mode.A_gang | ticker.mode.B_gang)) - ticker.mode.remove_gangster(target.mind,exclude_bosses=1) + if(target.mind in ticker.mode.get_gangsters()) + ticker.mode.remove_gangster(target.mind) target.visible_message("[src] was destroyed in the process!", "You feel a surge of loyalty towards Nanotrasen.") return 0 if(target.mind in ticker.mode.revolutionaries) diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm index 78c0856605f..8fe14f6d13c 100644 --- a/code/game/objects/structures/ai_core.dm +++ b/code/game/objects/structures/ai_core.dm @@ -162,7 +162,7 @@ ticker.mode.remove_cultist(M.brainmob.mind, 1) ticker.mode.remove_revolutionary(M.brainmob.mind, 1) - ticker.mode.remove_gangster(M.brainmob.mind, 1) + ticker.mode.remove_gangster(M.brainmob.mind, 1, remove_bosses=1) M.loc = src brain = M diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index f424d2cd7a9..5c290f9ba11 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -387,32 +387,16 @@ dat += "Head not found!" dat += "" - if(ticker.mode.A_bosses.len || ticker.mode.A_gang.len) - dat += "
" - for(var/datum/mind/N in ticker.mode.A_bosses) + for(var/datum/gang/G in ticker.mode.gangs) + dat += "
[gang_name("A")] Gang: [(ticker.mode.gang_points ? "[ticker.mode.gang_points.A] Influence, " : "")][round((ticker.mode.A_territory.len/start_state.num_territories)*100, 1)]% Control
" + for(var/datum/mind/N in G.bosses) var/mob/M = N.current if(!M) dat += "" else dat += "" dat += "" - for(var/datum/mind/N in ticker.mode.A_gang) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "
[G.name] Gang: [G.points] Influence | [round((G.territory.len/start_state.num_territories)*100, 1)]% Control
Gang Boss not found!
[M.real_name] (Boss)[M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]PM
[M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]PM
" - - if(ticker.mode.B_bosses.len || ticker.mode.B_gang.len) - dat += "
" - for(var/datum/mind/N in ticker.mode.B_bosses) - var/mob/M = N.current - if(!M) - dat += "" - else - dat += "" - dat += "" - for(var/datum/mind/N in ticker.mode.B_gang) + for(var/datum/mind/N in G.gangsters) var/mob/M = N.current if(M) dat += "" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 2b643231e19..062cc7f9378 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -103,11 +103,11 @@ new/datum/round_event/blob(strength) if("12") if(src.makeGangsters()) - message_admins("[key_name(usr)] started a gang war.") - log_admin("[key_name(usr)] started a gang war.") + message_admins("[key_name(usr)] created gangs.") + log_admin("[key_name(usr)] created gangs.") else - message_admins("[key_name(usr)] tried to start a gang war. Unfortunately, there were not enough candidates available.") - log_admin("[key_name(usr)] failed to start a gang war.") + message_admins("[key_name(usr)] tried to create gangs. Unfortunately, there were not enough candidates available.") + log_admin("[key_name(usr)] failed create gangs.") if("13") message_admins("[key_name(usr)] is creating a Centcom response team...") if(src.makeEmergencyresponseteam()) @@ -1491,6 +1491,16 @@ usr.client.cmd_admin_animalize(M) + else if(href_list["gangpoints"]) + var/datum/gang/G = locate(href_list["gangpoints"]) in ticker.mode.gangs + if(G) + var/newpoints = input("Set [G.name ] Gang's influence.","Set Influence",G.points) as null|num + if(newpoints) + message_admins("[key_name_admin(usr)] changed the [G.name] Gang's influence from [G.points] to [newpoints]") + log_admin("[key_name(usr)] changed the [G.name] Gang's influence from [G.points] to [newpoints]") + G.points = newpoints + G.message_gangtools("Your gang now has [G.points] influence.") + else if(href_list["adminplayeropts"]) var/mob/M = locate(href_list["adminplayeropts"]) show_player_panel(M) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 0f869613fa7..1c1d614050c 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -10,7 +10,7 @@ /datum/admins/proc/one_click_antag() - var/dat = {"Quick-Create Antagonist
+ var/dat = {" Make Traitors
Make Changelings
Make Revs
@@ -25,17 +25,10 @@ Make Abductor Team (Requires Ghosts)
Make Revenant (Requires Ghost)
"} -/* These dont work just yet - Ninja, aliens and deathsquad I have not looked into yet - Nuke team is getting a null mob returned from makebody() (runtime error: null.mind. Line 272) - - Make Space Ninja (Requires Ghosts)
- Make Aliens (Requires Ghosts)
- "} -*/ - usr << browse(dat, "window=oneclickantag;size=400x400") - return + var/datum/browser/popup = new(usr, "oneclickantag", "Quick-Create Antagonist", 400, 400) + popup.set_content(dat) + popup.open() /datum/admins/proc/makeMalfAImode() @@ -404,15 +397,20 @@ candidates += applicant if(candidates.len >= 2) - H = pick(candidates) - H.mind.make_Gang("A") - candidates.Remove(H) - H = pick(candidates) - H.mind.make_Gang("B") + for(var/needs_assigned=2,needs_assigned>0,needs_assigned--) + H = pick(candidates) + if(gang_colors_pool) + var/datum/gang/newgang = new() + ticker.mode.gangs += newgang + H.mind.make_Gang(newgang) + candidates.Remove(H) + else if(needs_assigned == 2) + return 0 return 1 return 0 + /datum/admins/proc/makeOfficial() var/mission = input("Assign a task for the official", "Assign Task", "Conduct a routine preformance review of [station_name()] and its Captain.") var/list/mob/dead/observer/candidates = getCandidates("Do you wish to be considered to be a Centcom Official?", "pAI") diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 5f4793276f2..1ce49c7de90 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -141,12 +141,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(malf.malf_mode_declared && (malf.apcs > 0)) stat(null, "Time left: [max(malf.AI_win_timeleft/malf.apcs, 0)]") - if(istype(ticker.mode, /datum/game_mode/gang)) - var/datum/game_mode/gang/mode = ticker.mode - if(isnum(mode.A_timer)) - stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") - if(isnum(mode.B_timer)) - stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + for(var/datum/gang/G in ticker.mode.gangs) + if(isnum(G.dom_timer)) + stat(null, "[G.name] Gang Takeover: [max(G.dom_timer, 0)]") /mob/dead/observer/verb/reenter_corpse() set category = "Ghost" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index b231ef67bec..7feb6af38b3 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -190,7 +190,7 @@ emp_act apply_effect(20, PARALYZE, armor) if(prob(I.force + min(100,100 - src.health)) && src != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(mind) - ticker.mode.remove_gangster(mind, exclude_bosses=1) + ticker.mode.remove_gangster(mind) if(bloody) //Apply blood if(wear_mask) wear_mask.add_blood(src) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index df7579f5190..e48091d5382 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -963,7 +963,7 @@ H.apply_effect(20, PARALYZE, armor) if(prob(I.force + ((100 - H.health)/2)) && H != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(H.mind) - ticker.mode.remove_gangster(H.mind, exclude_bosses=1) + ticker.mode.remove_gangster(H.mind) if(bloody) //Apply blood if(H.wear_mask) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 000893f5165..e953b963a16 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -829,12 +829,9 @@ Sorry Giacom. Please don't be mad :( if(statpanel("Status")) if(ticker) if(ticker.mode) - if(istype(ticker.mode, /datum/game_mode/gang)) - var/datum/game_mode/gang/mode = ticker.mode - if(isnum(mode.A_timer)) - stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") - if(isnum(mode.B_timer)) - stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + for(var/datum/gang/G in ticker.mode.gangs) + if(isnum(G.dom_timer)) + stat(null, "[G.name] Gang Takeover: [max(G.dom_timer, 0)]") /mob/living/cancel_camera() ..() @@ -864,4 +861,4 @@ Sorry Giacom. Please don't be mad :( //used in datum/reagents/reaction() proc /mob/living/proc/get_permeability_protection() - return 0 + return 0 diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index f8bed180209..201efb3297f 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -2,5 +2,5 @@ if(mind && ticker && ticker.mode) ticker.mode.remove_cultist(mind, 0) ticker.mode.remove_revolutionary(mind, 0) - ticker.mode.remove_gangster(mind, 0) + ticker.mode.remove_gangster(mind, remove_bosses=1) ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index 3a8a144d0eb..5d86cc4d2e5 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -4,7 +4,7 @@ regenerate_icons() show_laws(0) if(mind) ticker.mode.remove_revolutionary(mind) - if(mind) ticker.mode.remove_gangster(mind) + if(mind) ticker.mode.remove_gangster(mind,1,remove_bosses=1) /mob/living/silicon/robot/update_hotkey_mode() winset(src, null, "mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0") diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 092eb92a6ce01661c0ec8b1e2f0a91212dee0f5d..7b1f45f6d21e97dac46aace55df765f0fec0ae89 100644 GIT binary patch delta 7565 zcmZXYc{r4B^zdiwJKvNg+45~e*6hZT5>bp@XzaToYqoiiq9Te=vXpFDhRE2*k_g%N z!Psgr_H8iRJAHrG`^WEnpFf`GzRrEF`#$%1&UNn3IfFCc$vJT9zrbFEg-!4+w;-25 zuYh1Le>e#A_(NglARHsd@ndk;Twrrt@I8Q$Y4E-NOk~Dd&hus6)1RMpuW>dPW5ttw zJfN36db+>}QA5MAJ47w=?g9QpDLN|r{=8|q`(47?QJ>ydRqx;LgY)1MKR@X@sB9f{ zs|RFljcNp3$27TqtOcfm^D5umzBIJ77M|~$P{<1({@5QEWU_JZtEp$c31Lkc(h%@WzW~bp`U8$7bo8#(w4_iTTWT*Le7;#`o+3d>t=qU^ zUf;-zD}_T01Fr4)Zr!SFI_vkx?TbxnxlAX!TH4~nFr!$l3q#i#PfL=+k9nLhjPx#; z*zSu_n4#T&y1Y+?Wg>MTg+R;5qcn^6^^K{!0ZACQe$-=?XTBDO6fkjvSFv5JerY@loSe+^7^_VN4Mr}%LmK+^pKvc^HIx7aVzA)+-9 zO2k$dWo5R7$?#h=fHm}>S@Z+xV{rzGO2w^-XWtHe(s_76(|Q9l-jH^W+rV6SxA&8w zxp40O^*ZTOlUtkgf;dn5t+npK+0RU0gllYnOn1iIvHh;oUAqRV0o_hYh)t=@h($8W zYfdm}jwJiC0=HUg4qNYg4_n}JxF+{w|8V)$U(;`16iMCNpdNJW;7LnnQ z{9Qg-uA`vQ_q$YFBF0Q_Qtl}|_sWQ~+7lVw^_^~fBCd|{#Z(r-gzcsYDrI2rMyo#j zs**+to`nGI->U)dV%v!aYlrfG!;?aXrDOH?wvz|nt6`@1hXPx}P>XOnin*xA38bRjq`2C504z4Rh3 zNQ_mNrzWN`@gHWd#8|P*;{VWv4~M`1e3Y`aZgC|i%-UK6z5PK8g`e1rQpvebT@Ujg zzkXh-EVh+fFB15Xf=l=~DEjo7Pr!b9ofB?UjVDxl%z@EPO;x{WTmncdrZ-*nC4Rtt z>pKeXc3ImY^es$?PATpRg&bfhHFdbd@db?uk))#Q>q8d&)KcllADC8cbAV35-orF_ zmwBof!je0!yzMK6@_1IDujj^kytYbpMv;Sxxl~|eV5T*C_g~}2IYi7^bzN=r-Cb59 zOKQa|LdOi|Ckj4p*Yx0pkh1I0J`eJCQqLfwm52BOz;RD7Tx^HEIv8Twg>IoM=UAFL zTOl{^0AU@>nN;z^Ye&#qdCF)&B!A}(hoJ#mnK-@@M3w>(8mfH%1?J3kAK+e zDG|mzrdFwY2yPA1Bn2NOm@rh&&X+Pbh$WLq#GenaQHjElk#_w-Dw}UqnVnUUaly~edcGnV!u;^609(7Ulh1N^{*ymvF}7l@P4V?$BUZ~cDkiaHCgRVf& z4JD=LKq~QGLqh|3`?(lP+=8VQ@?iz2`FQE&vwtryZKGjyRWz}fK#U3D9)m6qgYM3a zGck;`K|APQ5PKXzn*lku4@W)>ta|O5q2b-T3cgPz|60Zp zH)MT!;jeGf4Z&bzHkP(TG0$4qU+q&pbV9z6kPu`zMHf#qjwil#sH{o+TXFw_P>9f9 zb7_(hBdSF&%ZnE;ZcuTssP^46p4ZjZ>NbtB3Pr%Z>>uN0*3}Ox z?z+0VqHCZ9DnsX?gh`s3~;QY)n?fujRN)77=Y*A0RGY z)@Q#i*{2mY3U8Is9r8pkKrY0F#V>>NX{#vHzbK{$9--+19HJp1hlkHN(T_WUodsPk z5zW=8(Qh7cKf1f|f6k$gyS97dh3rv%t(5oW>2>A7low}_#AQD1_1XCrJP>@yewt># zjDG@=IaRwWnm@hkX2 zKn5gfsRv}CR;i|WkO^|0NSBW|z&6zSpequnPtXiI%SvwW=!la9dX2Cxi*hTe*RNko z+kX9y9~Jrncw3zPy)Tjj%8JETd9)|%

;89HT&1f?To3JBytR%*^H%7Aw-Y{&(~- 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 delta 7170 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 z z;DKs6!4PuMY=&pc=`#t&ot5Z2MzM z_T3wsi+2AS^R@9~1*|o2_Pp`q7sVwYHzre0U!T&CKYXH^V)r}$TZUg2pyH`|Wge!s z+F&L>pu(rtFv}MZ0Vy3S^OWyTU z#NxvDwdW3sXEk-HpWHvh8O#w3R32E9>j@&4$HxtOBp!3u+g2o8BClbi4)=nKy<^%< zJl);(>gAZO^S|= zUflY`lmeKcEPc6od4DlfJUtbEcNoVdO<|9s$gEeHMNk;wwidJQY#CKms~weuG;g^< zLdMq&1FL3A_n6R(Axs2oOHZ}O-6lKdb;OfuSs);wsqZj|f)oYeqZDvEp%4-DL~L}g z*w|{{pOw!+pxCnr`h)_F@WxfFgSAH{l^lf~@NrD)>||>@B!e0|Q+p)qC*^@M!>n?- zd*Oe)$xfoiexjNoZF0M%eNw^4FEwt@u3dsLv}bXu6qNpI>KlKywRg-rI*)@uEf}E! zKN{P<7Dof-4I@^wvk-OOvll!f<3J+X>V;gx7Oe4N@dZU5rjwo7sLsXqSCuuX!Q%3O z{3L?WhPw3JjVRx#OCm+gJAX#yF|cR1%{Lq3ww6&7zgug2iRIMsY{#boc4bCHd<2!P zo_S_*>q&n^1RpPHZ_|lYraley$;Rf?B`{|5X>B^~Vha`Bm+MeQnyY4U@VploChhEJ zk5B;|w-r$*0U6Z6UR$%_HT%ADw~Ya3^tcsjs1BDWzK1&6CFT*jFbI&VgY=2BUn`#N zy3V$H^W^0Pb!?zfHo4~sT`KA@2_1Toxib-PGS!)tahzj3s}C4cKHQlyK_mlzfr-07 z3#jdW)h(z{&a4E?Q`ra5vnpPndsv(9WTrMO*rw*qTXD6f&E=`|A5mH0{(0c#_QAnH zIJ|<7D4Q|oc{-3P`!Zl7-`vFxc?rN46&G8r4P^|ZvQ0W*GL(HC^}yU4oJXCPD+bAZ z{KC+_;ixSu)0A2b=$QPTH>@Q1Jzj8~X`eT3KMGYrKVDxPx{DQ&ka%BGaueD3IXLCp z9d`4VFL}KFk`XHefICW5!wKYYuN*0caC37Dwrd6lk3w~$?w`kCIER~={oz^W3RKd6 z3E}<-f}x>r`LT?U)C^?3_gAI0n55+DdNzGoVbN)g!n4&~&c{(7g|HD> z;gCq!@Gd`I9UmreqUz(Q`CLwfTEY3%S)x}{}BsuoeZ*|X@dTW?~kVv+BgJ%Nl3_5A)YR?v$Ho$p*?zelaiC4>FT!6D*J%! zIl3~=o+3@DvrSlhSD~p`3@DA-!;WY;T?=ZWI{1+so4i8%x~5rmxeT2KA5q8R{+OJI zVpBqaEjzV>bl=5}NSC$<@@+H!0gT@A+rx7&5DvGGEG_-o)RZ=XF!ns%w*r~F8`_03 zEta2S(q(Dsg6MoFvT8Tf1oj2z3`t*(vnXcZ6?Ui2=lx9gpXju!s}(g8w0I)4rl)TXXII#_|5HImPrO+ct1le zSScqbXCMoj_4TW8zJlN_y8EMc!(k_7Z8ycm!9^t{xg{krcA5TgG5rEva>6ln&N-(? z4%d3(*1C%Io#$H`r&4UadQmkM@p10({f4p^-dG4`pE~NPxy?W0EccCErqC7*{$Tdk zcL$v7KJ`#_?PlS?#LEl|k7I@USZQ?>s2uSJW2%fSeG(kS3g zwv8%Y?4K4jTjBYXeI1b(l0_bUYDmHOukp?YY)K>}B+P9EiCb%|Zyg~RP7|N1ZMX+& zh97eKSy>5+8``@wJh3PYAQD(7*Ara#_Z&-&`s32*P8)hL63b+XiUYRyY5a!{jo z;+7U_XDe*x0KuCNzApKM-obAKBXGd3YcXF7ts zX?YpL7Cw}ryjG8?9#-q$gJG2qu%0AHuRkQvsCCm*LVV-|pNX@Iz<8R7lZv)hQ-`WC zya(K*V=>hE8KbV%S|Wf4hv+SoZgEu@UAOXQg6sja^~~vmlLc`G-|hmPyzPJQ1kUo@ zV)*drS1M`-TQtTcU*G7$s$Iew0R2T#;EI}B`k zzmF)w<>d2cw^WWgO+T9gUG~|tWjs&;iz{D`3d-8i{`j#~iQAOrou!mwr^2;s6xGuM zK)G47qThb@tIFp$#KgWi*0L(Q2?m;*_B$b43;qYo1urcxgB1ggZjhPjJuNNj?YJeh zFNRv+&YecIT4Q6QfuSMwKVsx;U%8_ESln3BNb;q-x#yfYb*U@!?VYn=am!Z1O-Jg| zWDDD>Zi?DkXMDPC0890#Ql5EU&zFdSg5P>@W+BEIXdyjLdkDCEYVK0qgp{#oMFrmbD=L{Y2C=f6%N zdrDr1uY*OwXM=9A&IkO#U2Va*xh>)NNa8~}b!~0>_k5adE`f6upqdyLWpP`lPcr3LkKWzFI0 zY-P`_R_6Psy{^A3e-srTm@0U08nj<&35Y}rP_YSu$WloGy4kl`Q$bY~{Z*}`q~z4` zDTfgv`RK?iv8lCs^6=7n2A}Nfi)45rK!|b>_tmS4fxA4Uv+qJYN?tcce)td^PmL&h zLmCFty^j%#FI?SnzP6+mLjf&glycB;5Yt4rvpGw7DrV80sj|+Oqo&DBT!oP7DugEv zg-y-?fN2{2LO%rcwY2oHehS2_vB&rWiGjd~wSBllUC^YX3PvCVdFX-=6{A4j16i^n zVuUn*a{oR&kZ*nIXQ4^ut4N2V?;meHuLz;Oz!9IA*!c+3I*th57(fnD5-v%JL597y zcbm!B4%PY9{6EeDA6=BZJ<`fy-hB29vVAz@jh|>uHM$}U|HOoxOwG!Cie#4~FdVbi79I2WEmYk5_`M8mf6}HWDa+Gnw#LPl(iIi~TfEG@! zr}(C{r8^(9d5d4=D+4LJwH2wu%)ocL7w#g-4fWy>iyyF>YNyo7zq4PMwOWrNNI+Wl z!_kU`{*R~B{4>9aL-k&i8(fRJ_6Yv>+XVe+G? z=v-U?$YmN2vNz=oYy17_1)lGMQ5?Yst5`9|s4bNMlf7(f{JpOa{H|G813z;vE93K- zJcp(6Dwr(d_AxVy+`7f?oiVvcmTNNK@!Vkr#da_8!6(P+$-VU_0@=1{o=I+Q%qsgJ z<(F%rAzvayj-X*B6f}NI(bwnrsRE1uU}=vVrokUXX^gaPe*?7?{7lybGV&+;*@Y<8 z@jd5}3;B71>$}&$x45)*88r|^{KU+O&!@B>Ea+V8oTp#?3Fc~j8aBcfCKK{6nGq@U zZ_QJnH>8_C38t~m@aE!ksf27sOEO0riU)DLTOon8NNQ(*E`UHFZ7rR9<##Q^ F{tJ!LUVQ)n diff --git a/icons/obj/machines/dominator.dmi b/icons/obj/machines/dominator.dmi index 7671dedff861b71fac4a138d489ec2da8d4212b5..f41019abe306db583cd773cc79778a120510d8f4 100644 GIT binary patch literal 28836 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¬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 Nzv~f~cl*vJ{1-$j?~DKd diff --git a/tgstation.dme b/tgstation.dme index e4604f20a06..138b0ce4f40 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -332,6 +332,7 @@ #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\gang\dominator.dm" #include "code\game\gamemodes\gang\gang.dm" +#include "code\game\gamemodes\gang\gang_datum.dm" #include "code\game\gamemodes\gang\gang_pen.dm" #include "code\game\gamemodes\gang\recaller.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm"

[gang_name("B")] Gang: [(ticker.mode.gang_points ? "[ticker.mode.gang_points.B] Influence, " : "")][round((ticker.mode.B_territory.len/start_state.num_territories)*100, 1)]% Control
Gang Boss not found!
[M.real_name] (Boss)[M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]PM
[M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]