diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm
new file mode 100644
index 00000000000..4fbae44af79
--- /dev/null
+++ b/code/game/gamemodes/gang/dominator.dm
@@ -0,0 +1,209 @@
+/obj/machinery/dominator
+ name = "dominator"
+ desc = "A visibly sinister device. Looks like you can break it if you hit it enough."
+ icon = 'icons/obj/machines/dominator.dmi'
+ icon_state = "dominator"
+ density = 1
+ anchored = 1.0
+ layer = 3.6
+ var/health = 200
+ var/gang
+ var/operating = 0
+ var/broken = 0
+
+/obj/machinery/dominator/New()
+ if(!istype(ticker.mode, /datum/game_mode/gang))
+ qdel(src)
+ return
+ SetLuminosity(2)
+
+/obj/machinery/dominator/examine(mob/user)
+ ..()
+ if(broken)
+ user << "It looks completely busted."
+ return
+
+ var/datum/game_mode/gang/mode = ticker.mode
+ var/time = null
+ if(isnum(mode.A_timer))
+ time = max(mode.A_timer, 0)
+ if(isnum(mode.B_timer))
+ time = max(mode.B_timer, 0)
+ if(isnum(time))
+ if(time > 0)
+ user << "Hostile Takeover in progress. Estimated [time] seconds remain."
+ else
+ user << "Hostile Takeover of [station_name()] successful. Have a great day."
+ else
+ user << "System on standby."
+ user << "System Integrity: [health/2]%"
+
+
+/obj/machinery/dominator/proc/healthcheck(var/damage)
+ var/iconname = "dominator"
+ if(gang)
+ iconname += "-[gang]"
+ SetLuminosity(3)
+
+ var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread
+
+ health -= damage
+
+ switch(health)
+ if(101 to INFINITY)
+ if(prob(damage*2))
+ sparks.set_up(5, 1, src)
+ sparks.start()
+ if(1 to 100)
+ sparks.set_up(5, 1, src)
+ sparks.start()
+ iconname += "-damaged"
+
+ if(!broken)
+ if(health <= 0)
+ set_broken()
+ else
+ icon_state = iconname
+
+ if(health <= -50)
+ new /obj/item/stack/sheet/plasteel(src.loc)
+ qdel(src)
+
+/obj/machinery/dominator/proc/set_broken()
+ if(!gang)
+ return
+ var/datum/game_mode/gang/mode = ticker.mode
+ if(gang == "A")
+ mode.A_timer = "OFFLINE"
+ if(gang == "B")
+ mode.B_timer = "OFFLINE"
+ if(!isnum(mode.A_timer) && !isnum(mode.B_timer))
+ SSshuttle.emergencyNoEscape = 0
+ if(SSshuttle.emergency.mode == SHUTTLE_STRANDED)
+ SSshuttle.emergency.mode = SHUTTLE_DOCKED
+ SSshuttle.emergency.timer = world.time
+ priority_announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority")
+ else
+ priority_announce("All hostile activity within station systems have ceased.","Network Alert")
+ SetLuminosity(0)
+ icon_state = "dominator-broken"
+ broken = 1
+
+/obj/machinery/dominator/Destroy()
+ if(!broken)
+ set_broken()
+ ..()
+
+/obj/machinery/dominator/emp_act(severity)
+ healthcheck(100)
+ ..()
+
+/obj/machinery/dominator/ex_act(severity, target)
+ if(target == src)
+ qdel(src)
+ return
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ if(2.0)
+ healthcheck(120)
+ if(3.0)
+ healthcheck(30)
+ return
+
+/obj/machinery/dominator/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.damage)
+ if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
+ playsound(src, 'sound/effects/bang.ogg', 50, 1)
+ visible_message("[src] was hit by [Proj].")
+ healthcheck(Proj.damage)
+ ..()
+
+/obj/machinery/dominator/blob_act()
+ healthcheck(110)
+
+/obj/machinery/dominator/attackby(I as obj, user as mob, params)
+
+ return
+
+/obj/machinery/dominator/attack_hand(mob/user)
+ if(operating||broken)
+ examine(user)
+ return
+
+ var/datum/game_mode/gang/mode = ticker.mode
+ var/gang_territory
+ var/timer
+
+ 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)
+ examine(user)
+ return
+
+ if(isnum(timer)) //In theory, this shouldn't happen. But if it does, they get this meme
+ user << "Error: Hostile Takeover is already in progress."
+ return
+
+ var/time = max(180,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.\nThe entire station will likely be alerted once it starts.\nYour gang must be prepared to defend this device throughout the duration.\nAre you ready?","Confirmation","Yes","No") == "Yes")
+ if ((!in_range(src, user) || !istype(src.loc, /turf)))
+ return 0
+ var/area/srcloc = get_area(src.loc)
+ gang = tempgang
+ mode.domination(gang,1,srcloc.name)
+ src.name = "[gang_name(gang)] Gang [src.name]"
+ healthcheck(0)
+ operating = 1
+
+/obj/machinery/dominator/attack_alien(mob/living/user)
+ user.do_attack_animation(src)
+ playsound(src, 'sound/effects/bang.ogg', 50, 1)
+ user.visible_message("[user] smashes against [src] with its claws.",\
+ "You smash against [src] with your claws.",\
+ "You hear metal scraping.")
+ healthcheck(15)
+
+/obj/machinery/dominator/attack_animal(mob/living/user as mob)
+ if(!isanimal(user))
+ return
+ var/mob/living/simple_animal/M = user
+ M.do_attack_animation(src)
+ if(M.melee_damage_upper <= 0)
+ return
+ healthcheck(M.melee_damage_upper)
+
+/obj/machinery/dominator/mech_melee_attack(obj/mecha/M)
+ if(M.damtype == "brute")
+ playsound(src, 'sound/effects/bang.ogg', 50, 1)
+ visible_message("[M.name] has hit [src].")
+ healthcheck(M.force)
+ return
+
+/obj/machinery/dominator/attack_hulk(mob/user)
+ playsound(src, 'sound/effects/bang.ogg', 50, 1)
+ user.visible_message("[user] smashes [src].",\
+ "You punch [src].",\
+ "You hear metal being slammed.")
+ healthcheck(5)
+
+/obj/machinery/dominator/attackby(obj/item/weapon/I as obj, mob/living/user as mob, params)
+ if(istype(I, /obj/item/weapon))
+ add_fingerprint(user)
+ user.changeNext_move(CLICK_CD_MELEE)
+ user.do_attack_animation(src)
+ if( (I.flags&NOBLUDGEON) || !I.force )
+ return
+ playsound(src, 'sound/weapons/smash.ogg', 50, 1)
+ visible_message("[user] has hit \the [src] with [I].")
+ if(I.damtype == BURN || I.damtype == BRUTE)
+ healthcheck(I.force)
+ return
diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm
index 6967dc894c7..97ed4eecbcd 100644
--- a/code/game/gamemodes/gang/gang.dm
+++ b/code/game/gamemodes/gang/gang.dm
@@ -15,6 +15,10 @@
var/list/A_territory_lost = list()
var/list/B_territory_new = list()
var/list/B_territory_lost = list()
+ var/gang_A_style
+ var/gang_A_headgear
+ var/gang_B_style
+ var/gang_B_headgear
/datum/game_mode/gang
name = "gang war"
@@ -26,14 +30,15 @@
recommended_enemies = 2
enemy_minimum_age = 14
var/finished = 0
- var/goal_scalar = 0.5 //Goal = Total territories x goal_scalar
-
+ // Victory timers
+ var/A_timer = "OFFLINE"
+ var/B_timer = "OFFLINE"
///////////////////////////
//Announces the game type//
///////////////////////////
/datum/game_mode/gang/announce()
world << "The current game mode is - Gang War!"
- world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by claiming more than [round(100*goal_scalar,1)]% of the station!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!"
+ world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by activating and defending a Dominator!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!"
///////////////////////////////////////////////////////////////////////////////
@@ -73,6 +78,15 @@
modePlayer += B_bosses
..()
+/datum/game_mode/gang/process(seconds)
+ if(!finished)
+ if(isnum(A_timer))
+ A_timer -= seconds
+ if(isnum(B_timer))
+ B_timer -= seconds
+
+ ticker.mode.check_win()
+
/datum/game_mode/gang/proc/assign_bosses()
var/datum/mind/boss = pick(antag_candidates)
A_bosses += boss
@@ -91,7 +105,7 @@
/datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind)
var/datum/objective/rival_obj = new
rival_obj.owner = boss_mind
- rival_obj.explanation_text = "Claim more than 50% the station before the [(boss_mind in A_bosses) ? gang_name("B") : gang_name("A")] Gang does."
+ rival_obj.explanation_text = "Preform a hostile takeover of the station with a Dominator."
boss_mind.objectives += rival_obj
@@ -103,6 +117,17 @@
boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]"
obj_count++
+/datum/game_mode/gang/proc/domination(var/gang,var/modifier=1,var/dominatorloc)
+ if(gang=="A")
+ A_timer = max(180,900 - ((round((ticker.mode.A_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier
+ if(gang=="B")
+ B_timer = max(180,900 - ((round((ticker.mode.B_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier
+ if(gang && dominatorloc)
+ priority_announce("Hostile runtimes detected in all station systems. A network breach by the [gang_name(gang)] Gang has been traced to [dominatorloc].","Network Alert")
+ if(get_security_level() != "delta")
+ set_security_level("red")
+ SSshuttle.emergencyNoEscape = 1
+
///////////////////////////////////////////////////////////////////////////
//This equips the bosses with their gear, and makes the clown not clumsy//
///////////////////////////////////////////////////////////////////////////
@@ -132,37 +157,107 @@
var/where = mob.equip_in_one_of_slots(gangtool, slots)
if (!where)
mob << "Your Syndicate benefactors were unfortunately unable to get you a Gangtool."
+ . += 1
else
gangtool.register_device(mob)
- mob << "The Gangtool in your [where] will allow you to use your influence to purchase items and prevent the station from evacuating before you can take over. Use it to recall the emergency shuttle from anywhere on the station."
+ mob << "The Gangtool in your [where] will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station."
mob << "You can also promote your gang members to lieutenant by giving them an unregistered gangtool. Lieutenants cannot be deconverted and are able to use recruitment pens and gangtools."
- . += 1
var/where2 = mob.equip_in_one_of_slots(T, slots)
if (!where2)
mob << "Your Syndicate benefactors were unfortunately unable to get you a recruitment pen to start."
+ . += 1
else
mob << "The recruitment pen in your [where2] will help you get your gang started. Use it on unsuspecting crew members to recruit them."
- . += 1
var/where3 = mob.equip_in_one_of_slots(SC, slots)
if (!where3)
mob << "Your Syndicate benefactors were unfortunately unable to get you a territory spraycan to start."
+ . += 1
else
mob << "The territory spraycan in your [where3] can be used to claim areas of the station for your gang. The more territory your gang controls, the more influence you get. Distribute these to your gangsters to grow your influence faster."
- . += 1
mob.update_icons()
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/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 Colors","Leather Jackets","Fine Suits")
+ var/style
+ var/headgear
+ if(gang == "A")
+ if(!gang_A_style)
+ gang_A_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list
+ if(gang_A_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes"))
+ gang_A_headgear = 1
+ style = gang_A_style
+ headgear = gang_A_headgear
+
+ if(gang == "B")
+ if(!gang_B_style)
+ gang_B_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list
+ if(gang_B_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes"))
+ gang_B_headgear = 1
+ style = gang_B_style
+ headgear = gang_B_headgear
+
+ if(!style)
+ return 0
+
+ if(gangtool.can_use(user) && (((gang == "A") ? gang_points.A : gang_points.B) >= 1))
+ switch(style)
+ if("Gang Colors")
+ if(gang == "A")
+ new /obj/item/clothing/under/color/blue(user.loc)
+ if(headgear)
+ new /obj/item/clothing/mask/bandana/blue(user.loc)
+ if(gang == "B")
+ new /obj/item/clothing/under/color/red(user.loc)
+ if(headgear)
+ new /obj/item/clothing/mask/bandana/red(user.loc)
+ if("Leather Jackets")
+ new /obj/item/clothing/suit/jacket/leather(user.loc)
+ if(headgear)
+ if(gang == "A")
+ new /obj/item/clothing/mask/bandana/blue(user.loc)
+ if(gang == "B")
+ new /obj/item/clothing/mask/bandana/red(user.loc)
+ if("Fine Suits")
+ new /obj/item/clothing/under/suit_jacket/really_black(user.loc)
+ if(headgear)
+ new /obj/item/clothing/head/fedora(user.loc)
+
+ return 1
+
+ return 0
+
/////////////////////////////////////////////
//Checks if the either gang have won or not//
/////////////////////////////////////////////
/datum/game_mode/gang/check_win()
- if(A_territory.len > (start_state.num_territories * goal_scalar))
- finished = "A" //Gang A wins
- else if(B_territory.len > (start_state.num_territories * goal_scalar))
- finished = "B" //Gang B wins
+ 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 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//
@@ -282,7 +377,7 @@
if(!finished)
world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before either gang could claim it!"]"
else
- world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang has claimed over [round(100*goal_scalar,1)]% of the station and has assumed control!"
+ world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang successfully preformed a hostile takeover of the station!!"
..()
return 1
@@ -338,8 +433,8 @@
//////////////////////////////////////////////////////////
/datum/gang_points
- var/A = 30
- var/B = 30
+ var/A = 25
+ var/B = 25
var/next_point_interval = 1800
var/next_point_time
@@ -429,12 +524,9 @@
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.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1)
+ //ticker.mode.message_gangtools((ticker.mode.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1)
ticker.mode.message_gangtools((ticker.mode.B_tools),"Your gang now has [B_control]% control of the station.",0)
- ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1)
-
- //Victory check
- ticker.mode.check_win()
+ //ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1)
//Restart the counter
start()
diff --git a/code/game/objects/items/devices/recaller.dm b/code/game/gamemodes/gang/recaller.dm
similarity index 72%
rename from code/game/objects/items/devices/recaller.dm
rename to code/game/gamemodes/gang/recaller.dm
index de3f046635c..addef28d740 100644
--- a/code/game/objects/items/devices/recaller.dm
+++ b/code/game/gamemodes/gang/recaller.dm
@@ -2,7 +2,7 @@
/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 = "recaller"
+ icon_state = "gangtool"
item_state = "walkietalkie"
throwforce = 0
w_class = 1.0
@@ -33,30 +33,28 @@
else
dat += "Register Device
"
else
+ var/datum/game_mode/gang/gangmode
+ if(istype(ticker.mode, /datum/game_mode/gang))
+ gangmode = ticker.mode
+
var/gang_size = ((gang == "A")? (ticker.mode.A_gang.len + ticker.mode.A_bosses.len) : (ticker.mode.B_gang.len + ticker.mode.B_bosses.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 += "