diff --git a/baystation12.dme b/baystation12.dme
index 081439ffe82..243ab8dc013 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -268,7 +268,6 @@
#include "code\game\gamemodes\events\holidays\Holidays.dm"
#include "code\game\gamemodes\events\holidays\Other.dm"
#include "code\game\gamemodes\extended\extended.dm"
-#include "code\game\gamemodes\heist\heist.dm"
#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
#include "code\game\gamemodes\malfunction\malfunction.dm"
#include "code\game\gamemodes\meteor\meteor.dm"
@@ -280,6 +279,9 @@
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\revolution\rp_revolution.dm"
#include "code\game\gamemodes\traitor\traitor.dm"
+#include "code\game\gamemodes\vox\vox.dm"
+#include "code\game\gamemodes\vox\heist\heist.dm"
+#include "code\game\gamemodes\vox\trade\trade.dm"
#include "code\game\gamemodes\wizard\rightandwrong.dm"
#include "code\game\gamemodes\wizard\soulstone.dm"
#include "code\game\gamemodes\wizard\spellbook.dm"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 60c8b88d908..bd801334546 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -300,7 +300,7 @@
if(BE_REV) roletext="revolutionary"
if(BE_CULTIST) roletext="cultist"
if(BE_NINJA) roletext="ninja"
- if(BE_RAIDER) roletext="raider"
+ if(BE_VOX) roletext="vox"
// Assemble a list of active players without jobbans.
for(var/mob/new_player/player in player_list)
diff --git a/code/game/gamemodes/heist/objectives.dm b/code/game/gamemodes/heist/objectives.dm
deleted file mode 100644
index c5197647fa1..00000000000
--- a/code/game/gamemodes/heist/objectives.dm
+++ /dev/null
@@ -1,170 +0,0 @@
-
-//Vox heist objectives.
-
-datum/objective/heist
- proc/choose_target()
- return
-
-datum/objective/heist/kidnap
- choose_target()
- var/list/roles = list("Chief Engineer","Research Director","Roboticist","Chemist","Station Engineer")
- var/list/possible_targets = list()
- var/list/priority_targets = list()
-
- for(var/datum/mind/possible_target in ticker.minds)
- if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && (possible_target.assigned_role != "MODE"))
- possible_targets += possible_target
- for(var/role in roles)
- if(possible_target.assigned_role == role)
- priority_targets += possible_target
- continue
-
- if(priority_targets.len > 0)
- target = pick(priority_targets)
- else if(possible_targets.len > 0)
- target = pick(possible_targets)
-
- if(target && target.current)
- explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive."
- else
- explanation_text = "Free Objective"
- return target
-
- check_completion()
- if(target && target.current)
- if (target.current.stat == 2)
- return 0 // They're dead. Fail.
- //if (!target.current.restrained())
- // return 0 // They're loose. Close but no cigar.
-
- var/area/shuttle/vox/station/A = locate()
- for(var/mob/living/carbon/human/M in A)
- if(target.current == M)
- return 1 //They're restrained on the shuttle. Success.
- else
- return 0
-
-datum/objective/heist/loot
-
- choose_target()
- var/loot = "an object"
- switch(rand(1,8))
- if(1)
- target = /obj/structure/particle_accelerator
- target_amount = 6
- loot = "a complete particle accelerator"
- if(2)
- target = /obj/machinery/the_singularitygen
- target_amount = 1
- loot = "a gravitational generator"
- if(3)
- target = /obj/machinery/power/emitter
- target_amount = 4
- loot = "four emitters"
- if(4)
- target = /obj/machinery/nuclearbomb
- target_amount = 1
- loot = "a nuclear bomb"
- if(5)
- target = /obj/item/weapon/gun
- target_amount = 6
- loot = "six guns"
- if(6)
- target = /obj/item/weapon/gun/energy
- target_amount = 4
- loot = "four energy guns"
- if(7)
- target = /obj/item/weapon/gun/energy/laser
- target_amount = 2
- loot = "two laser guns"
- if(8)
- target = /obj/item/weapon/gun/energy/ionrifle
- target_amount = 1
- loot = "an ion gun"
-
- explanation_text = "We are lacking in hardware. Steal [loot]."
-
- check_completion()
-
- var/total_amount = 0
-
- for(var/obj/O in locate(/area/shuttle/vox/station))
- if(istype(O,target)) total_amount++
- if(total_amount >= target_amount) return 1
-
- var/datum/game_mode/heist/H = ticker.mode
- for(var/datum/mind/raider in H.raiders)
- if(raider.current)
- for(var/obj/O in raider.current.get_contents())
- if(istype(O,target)) total_amount++
- if(total_amount >= target_amount) return 1
-
- return 0
-
-datum/objective/heist/salvage
-
- choose_target()
- switch(rand(1,8))
- if(1)
- target = "metal"
- target_amount = 300
- if(2)
- target = "glass"
- target_amount = 200
- if(3)
- target = "plasteel"
- target_amount = 100
- if(4)
- target = "plasma"
- target_amount = 100
- if(5)
- target = "silver"
- target_amount = 50
- if(6)
- target = "gold"
- target_amount = 20
- if(7)
- target = "uranium"
- target_amount = 20
- if(8)
- target = "diamond"
- target_amount = 20
-
- explanation_text = "Ransack the station and escape with [target_amount] [target]."
-
- check_completion()
-
- var/total_amount = 0
-
- for(var/obj/item/O in locate(/area/shuttle/vox/station))
- if(istype(O,/obj/item/stack/sheet))
- if(O.name == target)
- var/obj/item/stack/sheet/S = O
- total_amount += S.amount
-
- var/datum/game_mode/heist/H = ticker.mode
- for(var/datum/mind/raider in H.raiders)
- if(raider.current)
- for(var/obj/item/O in raider.current.get_contents())
- if(istype(O,/obj/item/stack/sheet))
- if(O.name == target)
- var/obj/item/stack/sheet/S = O
- total_amount += S.amount
-
- if(total_amount >= target_amount) return 1
- return 0
-
-
-datum/objective/heist/inviolate_crew
- explanation_text = "Do not leave any Vox behind, alive or dead."
-
- check_completion()
- var/datum/game_mode/heist/H = ticker.mode
- if(H.is_raider_crew_safe()) return 1
- return 0
-
-datum/objective/heist/inviolate_death
- explanation_text = "Follow the Inviolate. Minimise death and loss of resources."
- check_completion()
- if(vox_kills>5) return 0
- return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index 79404b3f8a6..f262818d656 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -745,181 +745,3 @@ datum/objective/absorb
/*-------ENDOF CULTIST------*/
*/
-//Vox heist objectives.
-
-datum/objective/heist
- proc/choose_target()
- return
-
-datum/objective/heist/kidnap
- choose_target()
- var/list/roles = list("Chief Engineer","Research Director","Roboticist","Chemist","Station Engineer")
- var/list/possible_targets = list()
- var/list/priority_targets = list()
-
- for(var/datum/mind/possible_target in ticker.minds)
- if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && (possible_target.assigned_role != "MODE"))
- possible_targets += possible_target
- for(var/role in roles)
- if(possible_target.assigned_role == role)
- priority_targets += possible_target
- continue
-
- if(priority_targets.len > 0)
- target = pick(priority_targets)
- else if(possible_targets.len > 0)
- target = pick(possible_targets)
-
- if(target && target.current)
- explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive."
- else
- explanation_text = "Free Objective"
- return target
-
- check_completion()
- if(target && target.current)
- if (target.current.stat == 2)
- return 0 // They're dead. Fail.
- //if (!target.current.restrained())
- // return 0 // They're loose. Close but no cigar.
-
- var/area/shuttle/vox/station/A = locate()
- for(var/mob/living/carbon/human/M in A)
- if(target.current == M)
- return 1 //They're restrained on the shuttle. Success.
- else
- return 0
-
-datum/objective/heist/loot
-
- choose_target()
- var/loot = "an object"
- switch(rand(1,8))
- if(1)
- target = /obj/structure/particle_accelerator
- target_amount = 6
- loot = "a complete particle accelerator"
- if(2)
- target = /obj/machinery/the_singularitygen
- target_amount = 1
- loot = "a gravitational generator"
- if(3)
- target = /obj/machinery/power/emitter
- target_amount = 4
- loot = "four emitters"
- if(4)
- target = /obj/machinery/nuclearbomb
- target_amount = 1
- loot = "a nuclear bomb"
- if(5)
- target = /obj/item/weapon/gun
- target_amount = 6
- loot = "six guns"
- if(6)
- target = /obj/item/weapon/gun/energy
- target_amount = 4
- loot = "four energy guns"
- if(7)
- target = /obj/item/weapon/gun/energy/laser
- target_amount = 2
- loot = "two laser guns"
- if(8)
- target = /obj/item/weapon/gun/energy/ionrifle
- target_amount = 1
- loot = "an ion gun"
-
- explanation_text = "We are lacking in hardware. Steal [loot]."
-
- check_completion()
-
- var/total_amount = 0
-
- for(var/obj/O in locate(/area/shuttle/vox/station))
- if(istype(O,target)) total_amount++
- for(var/obj/I in O.contents)
- if(istype(I,target)) total_amount++
- if(total_amount >= target_amount) return 1
-
- var/datum/game_mode/heist/H = ticker.mode
- for(var/datum/mind/raider in H.raiders)
- if(raider.current)
- for(var/obj/O in raider.current.get_contents())
- if(istype(O,target)) total_amount++
- if(total_amount >= target_amount) return 1
-
- return 0
-
-datum/objective/heist/salvage
-
- choose_target()
- switch(rand(1,8))
- if(1)
- target = "metal"
- target_amount = 300
- if(2)
- target = "glass"
- target_amount = 200
- if(3)
- target = "plasteel"
- target_amount = 100
- if(4)
- target = "plasma"
- target_amount = 100
- if(5)
- target = "silver"
- target_amount = 50
- if(6)
- target = "gold"
- target_amount = 20
- if(7)
- target = "uranium"
- target_amount = 20
- if(8)
- target = "diamond"
- target_amount = 20
-
- explanation_text = "Ransack the station and escape with [target_amount] [target]."
-
- check_completion()
-
- var/total_amount = 0
-
- for(var/obj/item/O in locate(/area/shuttle/vox/station))
-
- var/obj/item/stack/sheet/S
- if(istype(O,/obj/item/stack/sheet))
- if(O.name == target)
- S = O
- total_amount += S.amount
- for(var/obj/I in O.contents)
- if(istype(I,/obj/item/stack/sheet))
- if(I.name == target)
- S = I
- total_amount += S.amount
-
- var/datum/game_mode/heist/H = ticker.mode
- for(var/datum/mind/raider in H.raiders)
- if(raider.current)
- for(var/obj/item/O in raider.current.get_contents())
- if(istype(O,/obj/item/stack/sheet))
- if(O.name == target)
- var/obj/item/stack/sheet/S = O
- total_amount += S.amount
-
- if(total_amount >= target_amount) return 1
- return 0
-
-
-datum/objective/heist/inviolate_crew
- explanation_text = "Do not leave any Vox behind, alive or dead."
-
- check_completion()
- var/datum/game_mode/heist/H = ticker.mode
- if(H.is_raider_crew_safe()) return 1
- return 0
-
-datum/objective/heist/inviolate_death
- explanation_text = "Follow the Inviolate. Minimise death and loss of resources."
- check_completion()
- if(vox_kills>5) return 0
- return 1
\ No newline at end of file
diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/vox/heist/heist.dm
similarity index 77%
rename from code/game/gamemodes/heist/heist.dm
rename to code/game/gamemodes/vox/heist/heist.dm
index 29b01a1cdbd..baae4c5edac 100644
--- a/code/game/gamemodes/heist/heist.dm
+++ b/code/game/gamemodes/vox/heist/heist.dm
@@ -2,15 +2,10 @@
VOX HEIST ROUNDTYPE
*/
-#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken.
- //Would be nice to use vox-specific kills but is currently not feasible.
-
-var/global/vox_kills = 0 //Used to check the Inviolate.
-
/datum/game_mode/
var/list/datum/mind/raiders = list() //Antags.
-/datum/game_mode/heist
+/datum/game_mode/vox/heist
name = "heist"
config_tag = "heist"
required_players = 15
@@ -22,21 +17,21 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
var/list/raid_objectives = list() //Raid objectives.
- var/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective.
-/datum/game_mode/heist/announce()
+
+/datum/game_mode/vox/heist/announce()
world << "The current game mode is - Heist!"
world << "An unidentified bluespace signature has slipped past the Icarus and is approaching [station_name()]!"
world << "Whoever they are, they're likely up to no good. Protect the crew and station resources against this dastardly threat!"
world << "Raiders: Loot [station_name()] for anything and everything you need."
world << "Personnel: Repel the raiders and their low, low prices and/or crossbows."
-/datum/game_mode/heist/can_start()
+/datum/game_mode/vox/heist/can_start()
if(!..())
return 0
- var/list/candidates = get_players_for_role(BE_RAIDER)
+ var/list/candidates = get_players_for_role(BE_VOX)
var/raider_num = 0
//Check that we have enough vox.
@@ -59,10 +54,10 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
raider.special_role = "Vox Raider"
return 1
-/datum/game_mode/heist/pre_setup()
+/datum/game_mode/vox/heist/pre_setup()
return 1
-/datum/game_mode/heist/post_setup()
+/datum/game_mode/vox/heist/post_setup()
//Build a list of spawn points.
var/list/turf/raider_spawn = list()
@@ -118,25 +113,9 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
spawn (rand(waittime_l, waittime_h))
send_intercept()
-/datum/game_mode/heist/proc/is_raider_crew_safe()
- if(cortical_stacks.len == 0)
- return 0
- for(var/obj/stack in cortical_stacks)
- if (get_area(stack) != locate(/area/shuttle/vox/station))
- return 0
- return 1
-
-/datum/game_mode/heist/proc/is_raider_crew_alive()
-
- for(var/datum/mind/raider in raiders)
- if(raider.current)
- if(istype(raider.current,/mob/living/carbon/human) && raider.current.stat != 2)
- return 1
- return 0
-
-/datum/game_mode/heist/proc/forge_vox_objectives()
+/datum/game_mode/vox/heist/proc/forge_vox_objectives()
//Commented out for testing.
@@ -164,20 +143,20 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
objs += new /datum/objective/heist/inviolate_crew
objs += new /datum/objective/heist/inviolate_death */
- raid_objectives += new /datum/objective/heist/kidnap
- raid_objectives += new /datum/objective/heist/loot
- raid_objectives += new /datum/objective/heist/salvage
- raid_objectives += new /datum/objective/heist/inviolate_crew
- raid_objectives += new /datum/objective/heist/inviolate_death
+ raid_objectives += new /datum/objective/vox/heist/kidnap
+ raid_objectives += new /datum/objective/vox/heist/loot
+ raid_objectives += new /datum/objective/vox/heist/salvage
+ raid_objectives += new /datum/objective/vox/inviolate_crew
+ raid_objectives += new /datum/objective/vox/inviolate_death
- for(var/datum/objective/heist/O in raid_objectives)
+ for(var/datum/objective/vox/heist/O in raid_objectives)
O.choose_target()
return raid_objectives
-/datum/game_mode/heist/proc/greet_vox(var/datum/mind/raider)
+/datum/game_mode/vox/heist/proc/greet_vox(var/datum/mind/raider)
raider.current << "\blue You are a Vox Raider, fresh from the Shoal!"
- raider.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to Tau Ceti and much of the unexplored galaxy. You and the crew have come to the Exodus for plunder, trade or both."
+ raider.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to Tau Ceti and much of the unexplored galaxy. You and the crew have come to the Exodus for plunder."
raider.current << "\blue Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious."
raider.current << "\blue Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!"
var/obj_count = 1
@@ -186,7 +165,7 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
obj_count++
-/datum/game_mode/heist/declare_completion()
+/datum/game_mode/vox/heist/declare_completion()
//No objectives, go straight to the feedback.
if(!(raid_objectives.len)) return ..()
@@ -213,13 +192,13 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
win_group = "Crew"
//Now we modify that result by the state of the vox crew.
- if(!is_raider_crew_alive())
+ if(!is_vox_crew_alive())
win_type = "Major"
win_group = "Crew"
win_msg += "The Vox Raiders have been wiped out!"
- else if(!is_raider_crew_safe())
+ else if(!is_vox_crew_safe())
if(win_group == "Crew" && win_type == "Minor")
win_type = "Major"
@@ -253,7 +232,7 @@ var/global/vox_kills = 0 //Used to check the Inviolate.
..()
-/datum/game_mode/heist/check_finished()
- if (!(is_raider_crew_alive()) || (vox_shuttle_location && (vox_shuttle_location == "start")))
+/datum/game_mode/vox/heist/check_finished()
+ if (!(is_vox_crew_alive()) || (vox_shuttle_location && (vox_shuttle_location == "start")))
return 1
return ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/vox/trade/trade.dm b/code/game/gamemodes/vox/trade/trade.dm
new file mode 100644
index 00000000000..da5eeec9c85
--- /dev/null
+++ b/code/game/gamemodes/vox/trade/trade.dm
@@ -0,0 +1,214 @@
+/*
+VOX TRADE ROUNDTYPE
+*/
+
+/datum/game_mode/
+ var/list/datum/mind/traders = list() //Antags.
+
+
+/datum/game_mode/vox/trade
+ name = "trade"
+ config_tag = "trade"
+ required_players = 10
+ required_players_secret = 10
+ required_enemies = 4
+ recommended_enemies = 6
+
+ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
+ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
+
+ var/list/trade_objectives = list() //Trade objectives.
+
+/datum/game_mode/vox/trade/announce()
+ world << "The current game mode is - Traders!"
+ world << "An unidentified bluespace signature has slipped past the Icarus and is approaching [station_name()]!"
+ world << "Whoever they are, they're likely up to no good. Protect the crew and station resources against this dastardly threat!"
+ world << "Traders: Trade with [station_name()] for anything and everything you need."
+ world << "Personnel: Perform your duties normally, earn extra cash to trade with the Vox."
+
+/datum/game_mode/vox/trade/can_start()
+
+ if(!..())
+ return 0
+
+ var/list/candidates = get_players_for_role(BE_VOX)
+ var/trader_num = 0
+
+ //Check that we have enough vox.
+ if(candidates.len < required_enemies)
+ return 0
+ else if(candidates.len < recommended_enemies)
+ trader_num = candidates.len
+ else
+ trader_num = recommended_enemies
+
+ //Grab candidates randomly until we have enough.
+ while(trader_num > 0)
+ var/datum/mind/new_trader = pick(candidates)
+ traders += new_trader
+ candidates -= new_trader
+ trader_num--
+
+ for(var/datum/mind/trader in traders)
+ trader.assigned_role = "MODE"
+ trader.special_role = "Vox Traders"
+ return 1
+
+/datum/game_mode/vox/trade/pre_setup()
+ return 1
+
+/datum/game_mode/vox/trade/post_setup()
+
+ //Build a list of spawn points.
+ var/list/turf/trader_spawn = list()
+
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == "voxstart")
+ trader_spawn += get_turf(L)
+ del(L)
+ continue
+
+ //Generate objectives for the group.
+ trade_objectives = forge_vox_objectives()
+
+ var/index = 1
+
+ //Spawn the vox!
+ for(var/datum/mind/trader in traders)
+
+ if(index > trader_spawn.len)
+ index = 1
+
+ trader.current.loc = trader_spawn[index]
+ index++
+
+ var/sounds = rand(2,8)
+ var/i = 0
+ var/newname = ""
+
+ while(i<=sounds)
+ i++
+ newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah"))
+
+ var/mob/living/carbon/human/vox = trader.current
+
+ vox.real_name = capitalize(newname)
+ vox.name = vox.real_name
+ vox.age = rand(12,20)
+ vox.dna.mutantrace = "vox"
+ vox.set_species("Vox")
+ vox.languages = list() // Removing language from chargen.
+ vox.flavor_text = ""
+ vox.add_language("Vox-pidgin")
+ vox.h_style = "Short Vox Quills"
+ vox.f_style = "Shaved"
+ for(var/datum/organ/external/limb in vox.organs)
+ limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT)
+ vox.equip_vox_raider()
+ vox.regenerate_icons()
+
+ trader.objectives = trade_objectives
+ greet_vox(trader)
+
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+
+
+
+/datum/game_mode/vox/trade/proc/forge_vox_objectives()
+
+
+
+
+ trade_objectives += new /datum/objective/vox/trade/raw_materials
+ trade_objectives += new /datum/objective/vox/trade/trade
+ trade_objectives += new /datum/objective/vox/inviolate_crew
+ trade_objectives += new /datum/objective/vox/inviolate_death
+
+ for(var/datum/objective/vox/trade/O in trade_objectives)
+ O.choose_target()
+
+ return trade_objectives
+
+/datum/game_mode/vox/trade/proc/greet_vox(var/datum/mind/trader)
+ trader.current << "\blue You are a Vox Trader, fresh from the Shoal!"
+ trader.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to Tau Ceti and much of the unexplored galaxy. You and the crew have come to the Exodus for trade."
+ trader.current << "\blue Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious."
+ trader.current << "\blue Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!"
+ var/obj_count = 1
+ for(var/datum/objective/objective in trader.objectives)
+ trader.current << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+
+
+/datum/game_mode/vox/trade/declare_completion()
+
+ //No objectives, go straight to the feedback.
+ if(!(trade_objectives.len)) return ..()
+
+ var/win_type = "Major"
+ var/win_group = "Crew"
+ var/win_msg = ""
+
+ var/success = trade_objectives.len
+
+ //Decrease success for failed objectives.
+ for(var/datum/objective/O in trade_objectives)
+ if(!(O.check_completion())) success--
+
+ //Set result by objectives.
+ if(success == trade_objectives.len)
+ win_type = "Major"
+ win_group = "Vox"
+ else if(success > 2)
+ win_type = "Minor"
+ win_group = "Vox"
+ else
+ win_type = "Minor"
+ win_group = "Crew"
+
+ //Now we modify that result by the state of the vox crew.
+ if(!is_vox_crew_alive())
+
+ win_type = "Major"
+ win_group = "Crew"
+ win_msg += "The Vox Traders have been wiped out!"
+
+ else if(!is_vox_crew_safe())
+
+ if(win_group == "Crew" && win_type == "Minor")
+ win_type = "Major"
+
+ win_group = "Crew"
+ win_msg += "The Vox Traders have left someone behind!"
+
+ else
+
+ if(win_group == "Vox")
+ if(win_type == "Minor")
+
+ win_type = "Major"
+ win_msg += "The Vox Traders escaped the station!"
+ else
+ win_msg += "The Vox Traders were repelled!"
+
+ world << "\red [win_type] [win_group] victory!"
+ world << "[win_msg]"
+ feedback_set_details("round_end_result","trade - [win_type] [win_group]")
+
+ var/count = 1
+ for(var/datum/objective/objective in trade_objectives)
+ if(objective.check_completion())
+ world << "
Objective #[count]: [objective.explanation_text] Success!"
+ feedback_add_details("traitor_objective","[objective.type]|SUCCESS")
+ else
+ world << "
Objective #[count]: [objective.explanation_text] Fail."
+ feedback_add_details("traitor_objective","[objective.type]|FAIL")
+ count++
+
+ ..()
+
+/datum/game_mode/vox/trade/check_finished()
+ if (!(is_vox_crew_alive()) || (vox_shuttle_location && (vox_shuttle_location == "start")))
+ return 1
+ return ..()
\ No newline at end of file
diff --git a/code/game/gamemodes/vox/vox.dm b/code/game/gamemodes/vox/vox.dm
new file mode 100644
index 00000000000..40042e98ac9
--- /dev/null
+++ b/code/game/gamemodes/vox/vox.dm
@@ -0,0 +1,334 @@
+#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken.
+ //Would be nice to use vox-specific kills but is currently not feasible.
+
+var/global/vox_kills = 0 //Used to check the Inviolate.
+
+/datum/game_mode/
+ var/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective.
+
+//Vox global procs
+
+/datum/game_mode/vox/proc/is_vox_crew_safe()
+
+ if(cortical_stacks.len == 0)
+ return 0
+
+ for(var/obj/stack in cortical_stacks)
+ if (get_area(stack) != locate(/area/shuttle/vox/station))
+ return 0
+ return 1
+
+/datum/game_mode/vox/proc/is_vox_crew_alive()
+
+ for(var/datum/mind/raider in raiders)
+ if(raider.current)
+ if(istype(raider.current,/mob/living/carbon/human) && raider.current.stat != 2)
+ return 1
+ return 0
+
+
+
+//Vox global objectives.
+
+datum/objective/vox
+ proc/choose_target()
+ return
+
+datum/objective/vox/inviolate_crew
+ explanation_text = "Do not leave any Vox behind, alive or dead."
+
+ check_completion()
+ var/datum/game_mode/vox/H = ticker.mode
+ if(H.is_vox_crew_safe()) return 1
+ return 0
+
+datum/objective/vox/inviolate_death
+ explanation_text = "Follow the Inviolate. Minimise death and loss of resources."
+ check_completion()
+ if(vox_kills>5) return 0
+ return 1
+
+
+//Vox heist objectives.
+
+
+
+datum/objective/vox/heist/kidnap
+ choose_target()
+ var/list/roles = list("Chief Engineer","Research Director","Roboticist","Chemist","Station Engineer")
+ var/list/possible_targets = list()
+ var/list/priority_targets = list()
+
+ for(var/datum/mind/possible_target in ticker.minds)
+ if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && (possible_target.assigned_role != "MODE"))
+ possible_targets += possible_target
+ for(var/role in roles)
+ if(possible_target.assigned_role == role)
+ priority_targets += possible_target
+ continue
+
+ if(priority_targets.len > 0)
+ target = pick(priority_targets)
+ else if(possible_targets.len > 0)
+ target = pick(possible_targets)
+
+ if(target && target.current)
+ explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive."
+ else
+ explanation_text = "Free Objective"
+ return target
+
+ check_completion()
+ if(target && target.current)
+ if (target.current.stat == 2)
+ return 0 // They're dead. Fail.
+ //if (!target.current.restrained())
+ // return 0 // They're loose. Close but no cigar.
+
+ var/area/shuttle/vox/station/A = locate()
+ for(var/mob/living/carbon/human/M in A)
+ if(target.current == M)
+ return 1 //They're restrained on the shuttle. Success.
+ else
+ return 0
+
+datum/objective/vox/heist/loot
+
+ choose_target()
+ var/loot = "an object"
+ switch(rand(1,8))
+ if(1)
+ target = /obj/structure/particle_accelerator
+ target_amount = 6
+ loot = "a complete particle accelerator"
+ if(2)
+ target = /obj/machinery/the_singularitygen
+ target_amount = 1
+ loot = "a gravitational generator"
+ if(3)
+ target = /obj/machinery/power/emitter
+ target_amount = 4
+ loot = "four emitters"
+ if(4)
+ target = /obj/machinery/nuclearbomb
+ target_amount = 1
+ loot = "a nuclear bomb"
+ if(5)
+ target = /obj/item/weapon/gun
+ target_amount = 6
+ loot = "six guns"
+ if(6)
+ target = /obj/item/weapon/gun/energy
+ target_amount = 4
+ loot = "four energy guns"
+ if(7)
+ target = /obj/item/weapon/gun/energy/laser
+ target_amount = 2
+ loot = "two laser guns"
+ if(8)
+ target = /obj/item/weapon/gun/energy/ionrifle
+ target_amount = 1
+ loot = "an ion gun"
+
+ explanation_text = "We are lacking in hardware. Steal [loot]."
+
+ check_completion()
+
+ var/total_amount = 0
+
+ for(var/obj/O in locate(/area/shuttle/vox/station))
+ if(istype(O,target)) total_amount++
+ for(var/obj/I in O.contents)
+ if(istype(I,target)) total_amount++
+ if(total_amount >= target_amount) return 1
+
+ var/datum/game_mode/vox/heist/H = ticker.mode
+ for(var/datum/mind/raider in H.raiders)
+ if(raider.current)
+ for(var/obj/O in raider.current.get_contents())
+ if(istype(O,target)) total_amount++
+ if(total_amount >= target_amount) return 1
+
+ return 0
+
+datum/objective/vox/heist/salvage
+
+ choose_target()
+ switch(rand(1,8))
+ if(1)
+ target = "metal"
+ target_amount = 300
+ if(2)
+ target = "glass"
+ target_amount = 200
+ if(3)
+ target = "plasteel"
+ target_amount = 100
+ if(4)
+ target = "plasma"
+ target_amount = 100
+ if(5)
+ target = "silver"
+ target_amount = 50
+ if(6)
+ target = "gold"
+ target_amount = 20
+ if(7)
+ target = "uranium"
+ target_amount = 20
+ if(8)
+ target = "diamond"
+ target_amount = 20
+
+ explanation_text = "Ransack the station and escape with [target_amount] [target]."
+
+ check_completion()
+
+ var/total_amount = 0
+
+ for(var/obj/item/O in locate(/area/shuttle/vox/station))
+
+ var/obj/item/stack/sheet/S
+ if(istype(O,/obj/item/stack/sheet))
+ if(O.name == target)
+ S = O
+ total_amount += S.amount
+ for(var/obj/I in O.contents)
+ if(istype(I,/obj/item/stack/sheet))
+ if(I.name == target)
+ S = I
+ total_amount += S.amount
+
+ var/datum/game_mode/vox/heist/H = ticker.mode
+ for(var/datum/mind/raider in H.raiders)
+ if(raider.current)
+ for(var/obj/item/O in raider.current.get_contents())
+ if(istype(O,/obj/item/stack/sheet))
+ if(O.name == target)
+ var/obj/item/stack/sheet/S = O
+ total_amount += S.amount
+
+ if(total_amount >= target_amount) return 1
+ return 0
+
+
+//Vox Trade Objectives
+
+datum/objective/vox/trade/trade
+
+ choose_target()
+ var/loot = "an object"
+ switch(rand(1,8))
+ if(1)
+ target = /obj/structure/particle_accelerator
+ target_amount = 6
+ loot = "a complete particle accelerator"
+ if(2)
+ target = /obj/machinery/the_singularitygen
+ target_amount = 1
+ loot = "a gravitational generator"
+ if(3)
+ target = /obj/machinery/power/emitter
+ target_amount = 4
+ loot = "four emitters"
+ if(4)
+ target = /obj/machinery/nuclearbomb
+ target_amount = 1
+ loot = "a nuclear bomb"
+ if(5)
+ target = /obj/item/weapon/gun
+ target_amount = 6
+ loot = "six guns"
+ if(6)
+ target = /obj/item/weapon/gun/energy
+ target_amount = 4
+ loot = "four energy guns"
+ if(7)
+ target = /obj/item/weapon/gun/energy/laser
+ target_amount = 2
+ loot = "two laser guns"
+ if(8)
+ target = /obj/item/weapon/gun/energy/ionrifle
+ target_amount = 1
+ loot = "an ion gun"
+
+ explanation_text = "We are lacking in hardware. Trade for [loot]."
+
+ check_completion()
+
+ var/total_amount = 0
+
+ for(var/obj/O in locate(/area/shuttle/vox/station))
+ if(istype(O,target)) total_amount++
+ for(var/obj/I in O.contents)
+ if(istype(I,target)) total_amount++
+ if(total_amount >= target_amount) return 1
+
+ var/datum/game_mode/vox/trade/H = ticker.mode
+ for(var/datum/mind/trader in H.traders)
+ if(trader.current)
+ for(var/obj/O in trader.current.get_contents())
+ if(istype(O,target)) total_amount++
+ if(total_amount >= target_amount) return 1
+
+ return 0
+
+datum/objective/vox/trade/raw_materials
+
+ choose_target()
+ switch(rand(1,8))
+ if(1)
+ target = "metal"
+ target_amount = 300
+ if(2)
+ target = "glass"
+ target_amount = 200
+ if(3)
+ target = "plasteel"
+ target_amount = 100
+ if(4)
+ target = "plasma"
+ target_amount = 100
+ if(5)
+ target = "silver"
+ target_amount = 50
+ if(6)
+ target = "gold"
+ target_amount = 20
+ if(7)
+ target = "uranium"
+ target_amount = 20
+ if(8)
+ target = "diamond"
+ target_amount = 20
+
+ explanation_text = "Trade with the crew for [target_amount] [target]."
+
+ check_completion()
+
+ var/total_amount = 0
+
+ for(var/obj/item/O in locate(/area/shuttle/vox/station))
+
+ var/obj/item/stack/sheet/S
+ if(istype(O,/obj/item/stack/sheet))
+ if(O.name == target)
+ S = O
+ total_amount += S.amount
+ for(var/obj/I in O.contents)
+ if(istype(I,/obj/item/stack/sheet))
+ if(I.name == target)
+ S = I
+ total_amount += S.amount
+
+ var/datum/game_mode/vox/trade/H = ticker.mode
+ for(var/datum/mind/trader in H.traders)
+ if(trader.current)
+ for(var/obj/item/O in trader.current.get_contents())
+ if(istype(O,/obj/item/stack/sheet))
+ if(O.name == target)
+ var/obj/item/stack/sheet/S = O
+ total_amount += S.amount
+
+ if(total_amount >= target_amount) return 1
+ return 0
\ No newline at end of file
diff --git a/code/game/machinery/computer/vox_shuttle.dm b/code/game/machinery/computer/vox_shuttle.dm
index 6854949cd28..055d223830a 100644
--- a/code/game/machinery/computer/vox_shuttle.dm
+++ b/code/game/machinery/computer/vox_shuttle.dm
@@ -115,9 +115,9 @@ var/global/announce_vox_departure = 1 //Stealth systems - give an announcement o
vox_shuttle_location = "station"
if(href_list["start"])
- if(ticker && (istype(ticker.mode,/datum/game_mode/heist)))
+ if(ticker && (istype(ticker.mode,/datum/game_mode/vox/heist) || istype(ticker.mode,/datum/game_mode/vox/trade)))
if(!warning)
- user << "\red Returning to dark space will end your raid and report your success or failure. If you are sure, press the button again."
+ user << "\red Returning to dark space will end your mission and report your success or failure. If you are sure, press the button again."
warning = 1
return
vox_move_to(/area/shuttle/vox/station)
diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm
index be4b04f42fe..ddac3e7a62f 100644
--- a/code/modules/admin/verbs/vox_raiders.dm
+++ b/code/modules/admin/verbs/vox_raiders.dm
@@ -72,8 +72,8 @@ var/global/vox_tick = 1
affected.implants += I
I.part = affected
- if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) )
- var/datum/game_mode/heist/M = ticker.mode
+ if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/vox/heist ) ) )
+ var/datum/game_mode/vox/heist/M = ticker.mode
M.cortical_stacks += I
vox_tick++
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 95ebdf20117..ed8a6e8f8ee 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -74,7 +74,7 @@
verbs -= /mob/living/carbon/proc/release_control
//Check for heist mode kill count.
- if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist) ) )
+ if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/vox/heist) || istype( ticker.mode,/datum/game_mode/vox/trade) ) )
//Check for last assailant's mutantrace.
/*if( LAssailant && ( istype( LAssailant,/mob/living/carbon/human ) ) )
var/mob/living/carbon/human/V = LAssailant
diff --git a/code/setup.dm b/code/setup.dm
index 8f4b0341cc1..e07e14525df 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -647,7 +647,7 @@ var/list/TAGGERLOCATIONS = list("Disposals",
#define BE_CULTIST 256
#define BE_MONKEY 512
#define BE_NINJA 1024
-#define BE_RAIDER 2048
+#define BE_VOX 2048
#define BE_PLANT 4096
var/list/be_special_flags = list(
@@ -662,7 +662,7 @@ var/list/be_special_flags = list(
"Cultist" = BE_CULTIST,
"Monkey" = BE_MONKEY,
"Ninja" = BE_NINJA,
- "Raider" = BE_RAIDER,
+ "Vox" = BE_VOX,
"Diona" = BE_PLANT
)