diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index ea2cfe38c62..c1288516e19 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -350,7 +350,7 @@ var/global/datum/controller/gameticker/ticker
proc/create_characters()
for(var/mob/new_player/player in player_list)
if(player.ready && player.mind)
- if(player.mind.assigned_role=="AI")
+ if(player.mind.assigned_role == "AI" || player.mind.special_role == "malfunctioning AI")
player.close_spawn_windows()
player.AIize()
else if(!player.mind.assigned_role)
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index 4684d94410d..fdca56bd5cc 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -20,6 +20,7 @@
var/station_captured = 0
var/to_nuke_or_not_to_nuke = 0
var/apcs = 0 //Adding dis to track how many APCs the AI hacks. --NeoFite
+ var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here
/datum/game_mode/malfunction/announce()
@@ -27,15 +28,36 @@
The AI on the satellite has malfunctioned and must be destroyed.
The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have [AI_win_timeleft/60] minutes to disable it."}
+/datum/game_mode/malfunction/get_players_for_role(var/role = BE_MALF)
+ var/roletext = get_roletext(role)
+
+ var/datum/job/ai/DummyAIjob = new
+ for(var/mob/new_player/player in player_list)
+ if(player.client && player.ready)
+ if(player.client.prefs.be_special & BE_MALF)
+ if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, "AI") && !jobban_isbanned(player, roletext) && DummyAIjob.player_old_enough(player.client))
+ if(player_old_enough_antag(player.client,role))
+ antag_candidates += player.mind
+ antag_candidates = shuffle(antag_candidates)
+ return antag_candidates
/datum/game_mode/malfunction/pre_setup()
- for(var/mob/new_player/player in player_list)
- if(player.mind && player.mind.assigned_role == "AI" && (player.client.prefs.be_special & BE_MALF))
- malf_ai+=player.mind
- if(malf_ai.len)
- return 1
- return 0
+ get_players_for_role(BE_MALF)
+ var/datum/mind/chosen_ai
+ if(!antag_candidates.len)
+ return 0
+ for(var/i = required_enemies, i > 0, i--)
+ chosen_ai=pick(antag_candidates)
+ malf_ai += chosen_ai
+ antag_candidates -= malf_ai
+ if (malf_ai.len < required_enemies)
+ return 0
+ for(var/datum/mind/ai_mind in malf_ai)
+ ai_mind.assigned_role = "MODE"
+ ai_mind.special_role = "malfunctioning AI"//So they actually have a special role/N
+ log_game("[ai_mind.key] (ckey) has been selected as a malf AI")
+ return 1
/datum/game_mode/malfunction/post_setup()
for(var/datum/mind/AI_mind in malf_ai)
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index 48e4dc6937a..0d43e6628e2 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -226,26 +226,22 @@ var/global/datum/controller/occupations/job_master
if(!job) return 0
if((job.title == "AI") && (config) && (!config.allow_ai)) return 0
+ if(ticker.mode.name == "AI malfunction") // malf. AIs are pre-selected before jobs
+ for (var/datum/mind/mAI in ticker.mode.malf_ai)
+ AssignRole(mAI.current, "AI")
+ ai_selected++
+ if(ai_selected) return 1
+ return 0
+
for(var/i = job.total_positions, i > 0, i--)
for(var/level = 1 to 3)
var/list/candidates = list()
- if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf
- candidates = FindOccupationCandidates(job, level, BE_MALF)
- else
- candidates = FindOccupationCandidates(job, level)
+ candidates = FindOccupationCandidates(job, level)
if(candidates.len)
var/mob/new_player/candidate = pick(candidates)
if(AssignRole(candidate, "AI"))
ai_selected++
break
- //Malf NEEDS an AI so force one if we didn't get a player who wanted it
- if((ticker.mode.name == "AI malfunction")&&(!ai_selected))
- unassigned = shuffle(unassigned)
- for(var/mob/new_player/player in unassigned)
- if(jobban_isbanned(player, "AI")) continue
- if(AssignRole(player, "AI"))
- ai_selected++
- break
if(ai_selected) return 1
return 0
diff --git a/paradise.dme b/paradise.dme
index 0ef0ebfd4d9..12a0fd41387 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -5,6 +5,84 @@
// END_INTERNALS
// BEGIN_FILE_DIR
#define FILE_DIR .
+#define FILE_DIR "code"
+#define FILE_DIR "code/modules"
+#define FILE_DIR "code/modules/jungle"
+#define FILE_DIR "code/modules/shieldgen"
+#define FILE_DIR "html"
+#define FILE_DIR "html/images"
+#define FILE_DIR "icons"
+#define FILE_DIR "icons/48x48"
+#define FILE_DIR "icons/ass"
+#define FILE_DIR "icons/atmos"
+#define FILE_DIR "icons/effects"
+#define FILE_DIR "icons/effects/unused"
+#define FILE_DIR "icons/mecha"
+#define FILE_DIR "icons/misc"
+#define FILE_DIR "icons/mob"
+#define FILE_DIR "icons/mob/human_races"
+#define FILE_DIR "icons/mob/human_races/cyberlimbs"
+#define FILE_DIR "icons/mob/human_races/masks"
+#define FILE_DIR "icons/mob/human_races/monkeys"
+#define FILE_DIR "icons/mob/in-hand"
+#define FILE_DIR "icons/mob/in-hand/left"
+#define FILE_DIR "icons/mob/in-hand/right"
+#define FILE_DIR "icons/mob/otherHuman"
+#define FILE_DIR "icons/mob/species"
+#define FILE_DIR "icons/mob/species/armalis"
+#define FILE_DIR "icons/mob/species/skrell"
+#define FILE_DIR "icons/mob/species/tajaran"
+#define FILE_DIR "icons/mob/species/unathi"
+#define FILE_DIR "icons/mob/species/vox"
+#define FILE_DIR "icons/mob/spirits"
+#define FILE_DIR "icons/NTOS"
+#define FILE_DIR "icons/NTOS/battery_icons"
+#define FILE_DIR "icons/obj"
+#define FILE_DIR "icons/obj/assemblies"
+#define FILE_DIR "icons/obj/atmospherics"
+#define FILE_DIR "icons/obj/clothing"
+#define FILE_DIR "icons/obj/clothing/species"
+#define FILE_DIR "icons/obj/clothing/species/skrell"
+#define FILE_DIR "icons/obj/clothing/species/tajaran"
+#define FILE_DIR "icons/obj/clothing/species/unathi"
+#define FILE_DIR "icons/obj/clothing/species/vox"
+#define FILE_DIR "icons/obj/doors"
+#define FILE_DIR "icons/obj/flora"
+#define FILE_DIR "icons/obj/machines"
+#define FILE_DIR "icons/obj/pipes"
+#define FILE_DIR "icons/obj/power_cond"
+#define FILE_DIR "icons/obj/tram"
+#define FILE_DIR "icons/pda_icons"
+#define FILE_DIR "icons/pods"
+#define FILE_DIR "icons/spideros_icons"
+#define FILE_DIR "icons/stamp_icons"
+#define FILE_DIR "icons/Testing"
+#define FILE_DIR "icons/turf"
+#define FILE_DIR "icons/vehicles"
+#define FILE_DIR "icons/vending_icons"
+#define FILE_DIR "nano"
+#define FILE_DIR "nano/images"
+#define FILE_DIR "sound"
+#define FILE_DIR "sound/AI"
+#define FILE_DIR "sound/ambience"
+#define FILE_DIR "sound/effects"
+#define FILE_DIR "sound/effects/turret"
+#define FILE_DIR "sound/effects/wind"
+#define FILE_DIR "sound/guitar"
+#define FILE_DIR "sound/hallucinations"
+#define FILE_DIR "sound/items"
+#define FILE_DIR "sound/machines"
+#define FILE_DIR "sound/mecha"
+#define FILE_DIR "sound/misc"
+#define FILE_DIR "sound/music"
+#define FILE_DIR "sound/piano"
+#define FILE_DIR "sound/turntable"
+#define FILE_DIR "sound/violin"
+#define FILE_DIR "sound/voice"
+#define FILE_DIR "sound/voice/complionator"
+#define FILE_DIR "sound/voice/Serithi"
+#define FILE_DIR "sound/vox_fem"
+#define FILE_DIR "sound/weapons"
// END_FILE_DIR
// BEGIN_PREFERENCES
#define DEBUG