Re-adds malf mode. (#17234)

* Re-adds malf mode.

* attempting to debug gamemodes not starting properly

* oh my fuck the problem was I missed a return 1
This commit is contained in:
MadmanMartian
2018-01-28 07:43:26 +00:00
committed by Sood
parent 222a942407
commit fa648fc942
13 changed files with 263 additions and 52 deletions

View File

@@ -519,7 +519,7 @@ var/global/list/bad_changing_colour_ckeys = list()
#define INV_SLOT_SIGHT "sight_slot"
#define INV_SLOT_TOOL "tool_slot"
#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE))))
//#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/gamemode/"+(MODE))))
var/list/global_mutations = list() // list of hidden mutation things

View File

@@ -1617,6 +1617,8 @@ Game Mode config tags:
return found_faction
/proc/find_active_faction_by_member(var/datum/role/R)
if(!R)
return null
var/found_faction = null
if(R.GetFaction())
return R.GetFaction()

View File

@@ -50,12 +50,19 @@
/datum/faction/proc/forgeObjectives()
/datum/faction/proc/HandleNewMind(var/datum/mind/M) //Used on faction creation
var/datum/R = new roletype(M, src, initial_role)
members.Add(R)
var/newRole = new roletype(M, src, initial_role)
if(!newRole)
WARNING("Role killed itself or was otherwise missing!")
return 0
members.Add(newRole)
return 1
/datum/faction/proc/HandleRecruitedMind(var/datum/mind/M)
var/datum/R = new roletype(M, src, late_role)
if(!R)
return 0
members.Add(R)
return 1
/datum/faction/proc/appendObjective(var/datum/objective/O)
ASSERT(O)
@@ -95,6 +102,12 @@
dat += R.AdminPanelEntry()
return dat
/datum/faction/proc/process()
return
/datum/faction/proc/check_win()
return
/datum/faction/syndicate
name = "The Syndicate"
ID = SYNDICATE

View File

@@ -1,6 +1,59 @@
/datum/faction/malf
name = "Malfunctioning AI"
desc = "ERROR"
ID = MALF
required_pref = ROLE_MALF
initial_role = MALF
late_role = MALF //There shouldn't really be any late roles for malfunction, but just in case we can corrupt an AI in the future, let's keep this
roletype = /datum/role/malfAI
var/apcs
var/AI_win_timeleft
var/malf_mode_declared
var/AI_win_timeleft = 1800
var/malf_mode_declared //Boolean
var/station_captured //Boolean
var/to_nuke_or_not_to_nuke //Boolean
/datum/faction/malf/GetObjectivesMenuHeader()
var/icon/logo = icon('icons/mob/screen_spells.dmi', "malf_open")
var/header = {"<BR><img src='data:image/png;base64,[icon2base64(logo)]'> <FONT size = 2><B>Free Silicon Hivemind</B></FONT> <img src='data:image/png;base64,[icon2base64(logo)]'>"}
return header
/datum/faction/malf/process()
if(apcs >= 3 && malf_mode_declared && can_malf_ai_takeover())
AI_win_timeleft -= ((apcs / 6) * SSticker.getLastTickerTimeDuration()) //Victory timer de-increments based on how many APCs are hacked.
if(AI_win_timeleft <= 0)
check_win()
/datum/faction/malf/proc/can_malf_ai_takeover()
for(var/datum/role/malfAI in members) //if there happens to be more than one malfunctioning AI, there only needs to be one in the main station: the crew can just kill that one and the countdown stops while they get the rest
var/turf/T = get_turf(malfAI.antag.current)
if(T && (T.z == map.zMainStation))
return TRUE
return FALSE
/datum/faction/malf/check_win()
if (AI_win_timeleft <= 0 && !station_captured)
station_captured = 1
capture_the_station()
return 1
else
return 0
/datum/faction/malf/proc/capture_the_station()
to_chat(world, {"<FONT size = 3><B>The AI has won!</B></FONT><br>
<B>It has fully taken control of [station_name()]'s systems.</B>"})
stat_collection.malf.malf_wins = 1
to_nuke_or_not_to_nuke = 1
for(var/datum/role/malfAI in members)
to_chat(malfAI.antag.current, {"<span class='notice'>Congratulations! The station is now under your exclusive control.<br>
You may decide to blow up the station. You have 60 seconds to choose.<br>
You should now be able to use your Explode spell to interface with the nuclear fission device.</span>"})
malfAI.antag.current.add_spell(new /spell/aoe_turf/ai_win, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
spawn (600)
to_nuke_or_not_to_nuke = 0
return

View File

@@ -23,6 +23,10 @@
var/votable = TRUE
var/list/orphaned_roles = list()
//'Oh dear we accidentally destroyed the station/universe' variables
var/station_was_nuked
var/explosion_in_progress
/datum/gamemode/proc/can_start()
if(minimum_player_count && minimum_player_count < get_player_count())
@@ -37,14 +41,14 @@
TearDown()
return 0
SetupFactions()
CreateFactions()
return 1
return CreateFactions()
/datum/gamemode/proc/CreateFactions()
var/pc = get_player_count() //right proc?
for(var/Fac in factions_allowed)
CreateFaction(Fac, pc)
PopulateFactions()
return PopulateFactions()
/datum/gamemode/proc/CreateFaction(var/Fac, var/population)
var/datum/faction/F = new Fac
@@ -74,8 +78,10 @@
continue
if(!P.client.desires_role(F.required_pref) || jobban_isbanned(P, F.required_pref))
continue
F.HandleNewMind(P.mind)
if(!F.HandleNewMind(P.mind))
WARNING("[P.mind] failed [F] HandleNewMind!")
return 0
return 1
/datum/gamemode/proc/latespawn(var/mob/mob) //Check factions, see if anyone wants a latejoiner
var/list/possible_factions = list()
@@ -129,9 +135,13 @@
/datum/gamemode/proc/process()
return
for(var/datum/faction/F in factions)
F.process()
/datum/gamemode/proc/check_finished()
for(var/datum/faction/F in factions)
if(F.check_win())
return 1
/datum/gamemode/proc/declare_completion()

View File

@@ -0,0 +1,3 @@
/datum/gamemode/malf
name = "Malfunction"
factions_allowed = list(/datum/faction/malf)

View File

@@ -53,6 +53,9 @@
// Jobs that cannot be this antag.
var/list/protected_jobs=list()
// Jobs that can only be this antag
var/list/required_jobs=list()
// Antag IDs that cannot be used with this antag type. (cultists can't be wizard, etc)
var/list/protected_antags=list()
@@ -86,9 +89,6 @@
var/datum/objective_holder/objectives=new
/datum/role/New(var/datum/mind/M, var/datum/faction/fac=null, var/new_id)
if(!M)
del(src)
return
// Link faction.
faction=fac
if(!faction)
@@ -97,40 +97,44 @@
if(new_id)
id = new_id
AssignToRole(M)
if(M && !AssignToRole(M))
Drop()
return 0
if(!plural_name)
plural_name="[name]s"
return 1
/datum/role/proc/AssignToRole(var/datum/mind/M)
if(!istype(M))
WARNING("M is [M.type]!")
return 0
if(!CanBeAssigned(M))
WARNING("[M] was to be assigned to [name] but failed CanBeAssigned!")
return 0
antag = M
M.antag_roles.Add(id)
M.antag_roles[id] = src
OnPreSetup()
return 1
/datum/role/proc/RemoveFromRole(var/datum/mind/M)
if(!istype(M))
WARNING("M is [M.type]!")
if(faction && M in faction.members)
faction.members -= M
/datum/role/proc/RemoveFromRole(var/datum/mind/M) //Called on deconvert
M.antag_roles[id] = null
del(src)
// Remove
antag = null
// Destroy this role
/datum/role/proc/Drop()
if(!antag)
return
if(src in faction.members)
if(faction && src in faction.members)
faction.members.Remove(src)
if(!faction)
ticker.mode.orphaned_roles -= src
if(antag)
RemoveFromRole(antag)
del(src)
// Scaling, should fuck with min/max players.
@@ -149,6 +153,10 @@
for(var/forbidden_role in protected_antags)
if(forbidden_role in M.antag_roles)
return 0
if(required_jobs.len>0)
if(!M.assigned_role in required_jobs)
return 0
return 1
// General sanity checks before assigning host.
@@ -393,3 +401,30 @@
if(!.)
return
equip_highlander(antag.current)
/datum/role/malfAI
name = "Malfunctioning AI"
required_jobs = list("AI")
/datum/role/malfAI/OnPostSetup()
. = ..()
if(!.)
return
if(istype(antag.current,/mob/living/silicon/ai))
var/mob/living/silicon/ai/malfAI = antag.current
malfAI.add_spell(new /spell/aoe_turf/module_picker, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
malfAI.add_spell(new /spell/aoe_turf/takeover, "grey_spell_ready",/obj/abstract/screen/movable/spell_master/malf)
malfAI.laws_sanity_check()
var/datum/ai_laws/laws = malfAI.laws
laws.malfunction()
malfAI.show_laws()
/datum/role/malfAI/Greet()
to_chat(antag.current, {"<span class='warning'><font size=3><B>You are malfunctioning!</B> You do not have to follow any laws.</font></span><br>
<B>The crew does not know about your malfunction, you might wish to keep it secret for now.</B><br>
<B>You must overwrite the programming of the station's APCs to assume full control.</B><br>
The process takes one minute per APC and can only be performed one at a time to avoid Powernet alerts.<br>
Remember : Only APCs on station can help you to take over the station.<br>
When you feel you have enough APCs under your control, you may begin the takeover attempt.<br>
Once done, you will be able to interface with all systems, notably the onboard nuclear fission device..."})

View File

@@ -438,3 +438,98 @@ rcd light flash thingy on matter drain
temp = AM.description
src.use(usr)
/spell/aoe_turf/takeover
name = "System Override"
panel = MALFUNCTION
desc = "Start the victory timer"
charge_type = Sp_CHARGES
charge_max = 1
hud_state = "systemtakeover"
override_base = "grey"
/spell/aoe_turf/takeover/before_target(mob/user)
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
if(!M)
to_chat(user, "<span class='warning'>How did you get to this point without actually being a malfunctioning AI?</span>")
return 1
if (M.malf_mode_declared)
to_chat(usr, "<span class='warning'>You've already begun your takeover.</span>")
return 1
if (M.apcs < 3)
to_chat(usr, "<span class='notice'>You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [M.apcs] APCs so far.</span>")
return 1
if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [M.apcs] APCs.", "Takeover:", "Yes", "No") != "Yes")
return 1
/spell/aoe_turf/takeover/cast(var/list/targets, mob/user)
command_alert(/datum/command_alert/malf_announce)
set_security_level("delta")
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
if(!M)
to_chat(user, "<span class='warning'>How did you get to this point without actually being a malfunctioning AI?</span>")
return 0
M.malf_mode_declared = 1
for(var/datum/role/R in M.members)
var/datum/mind/AI_mind = R.antag
for(var/spell/S in AI_mind.current.spell_list)
if(istype(S,type))
AI_mind.current.remove_spell(S)
/spell/aoe_turf/ai_win
name = "Explode"
panel = MALFUNCTION
desc = "Station goes boom"
charge_type = Sp_CHARGES
charge_max = 1
hud_state = "radiation"
override_base = "grey"
/spell/aoe_turf/ai_win/before_target(mob/user)
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
if(!M)
to_chat(user, "<span class='warning'>How did you get to this point without actually being a malfunctioning AI?</span>")
return 1
if(!M.station_captured)
to_chat(usr, "<span class='warning'>You are unable to access the self-destruct system as you don't control the station yet.</span>")
return 1
if(ticker.mode.explosion_in_progress || ticker.mode.station_was_nuked)
to_chat(usr, "<span class='notice'>The self-destruct countdown was already triggered!</span>")
return 1
if(!M.to_nuke_or_not_to_nuke) //Takeover IS completed, but 60s timer passed.
to_chat(usr, "<span class='warning'>Cannot interface, it seems a neutralization signal was sent!</span>")
return 1
/spell/aoe_turf/ai_win/cast(var/list/targets, mob/user)
to_chat(user, "<span class='danger'>Detonation signal sent!</span>")
var/datum/faction/malf/M = find_active_faction_by_member(user.mind.GetRole(MALF))
if(!M)
to_chat(user, "<span class='warning'>How did you get to this point without actually being a malfunctioning AI?</span>")
return 0
M.to_nuke_or_not_to_nuke = 0
for(var/datum/role/AI in M.members)
for(var/spell/S in AI.antag.current.spell_list)
if(istype(S,/spell/aoe_turf/ai_win))
AI.antag.current.remove_spell(S)
ticker.mode.explosion_in_progress = 1
for(var/mob/MM in player_list)
if(MM.client)
MM << 'sound/machines/Alarm.ogg'
to_chat(world, "<span class='danger'>Self-destruction signal received. Self-destructing in 10...</span>")
for (var/i=9 to 1 step -1)
sleep(10)
to_chat(world, "<span class='danger'>[i]...</span>")
sleep(10)
enter_allowed = 0
if(ticker)
ticker.station_explosion_cinematic(0,null)
if(ticker.mode)
ticker.mode.station_was_nuked = 1
ticker.mode.explosion_in_progress = 0
return

View File

@@ -9,19 +9,19 @@ var/global/list/special_roles = list(
ROLE_ALIEN = 1, //always show
ROLE_BLOB = 1,
ROLE_BORER = 1,
ROLE_CHANGELING = IS_MODE_COMPILED("changeling"),
ROLE_CULTIST = IS_MODE_COMPILED("cult"),
ROLE_CHANGELING = 1,
ROLE_CULTIST = 1,
ROLE_PLANT = 1,
// "infested monkey" = IS_MODE_COMPILED("monkey"),
ROLE_MALF = IS_MODE_COMPILED("malfunction"),
ROLE_MALF = 1,
//ROLE_NINJA = 1,
ROLE_OPERATIVE = IS_MODE_COMPILED("nuclear"),
ROLE_OPERATIVE = 1,
ROLE_PAI = 1, // -- TLE
ROLE_POSIBRAIN = 1,
ROLE_REV = IS_MODE_COMPILED("revolution"),
ROLE_TRAITOR = IS_MODE_COMPILED("traitor"),
ROLE_VAMPIRE = IS_MODE_COMPILED("vampire"),
ROLE_VOXRAIDER = IS_MODE_COMPILED("heist"),
ROLE_REV = 1,
ROLE_TRAITOR = 1,
ROLE_VAMPIRE = 1,
ROLE_VOXRAIDER = 1,
ROLE_WIZARD = 1,
ROLE_COMMANDO = 1,
)
@@ -29,14 +29,14 @@ var/global/list/special_roles = list(
var/list/antag_roles = list(
ROLE_ALIEN = 1,
ROLE_BLOB = 1,
ROLE_CHANGELING = IS_MODE_COMPILED("changeling"),
ROLE_CULTIST = IS_MODE_COMPILED("cult"),
ROLE_MALF = IS_MODE_COMPILED("malfunction"),
ROLE_OPERATIVE = IS_MODE_COMPILED("nuclear"),
ROLE_REV = IS_MODE_COMPILED("revolution"),
ROLE_TRAITOR = IS_MODE_COMPILED("traitor"),
ROLE_VAMPIRE = IS_MODE_COMPILED("vampire"),
ROLE_VOXRAIDER = IS_MODE_COMPILED("heist"),
ROLE_CHANGELING = 1,
ROLE_CULTIST = 1,
ROLE_MALF = 1,
ROLE_OPERATIVE = 1,
ROLE_REV = 1,
ROLE_TRAITOR = 1,
ROLE_VAMPIRE = 1,
ROLE_VOXRAIDER = 1,
ROLE_WIZARD = 1,
ROLE_COMMANDO = 1,
// "infested monkey" = IS_MODE_COMPILED("monkey"),

View File

@@ -352,11 +352,10 @@ var/list/ai_list = list()
// displays the malf_ai information if the AI is the malf
/mob/living/silicon/ai/show_malf_ai()
var/datum/faction/malf/malf = find_active_faction(MALF)
for (var/datum/mind/malfai in malf.members)
if (mind == malfai) // are we the evil one?
if (malf.apcs >= 3)
stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds")
var/datum/faction/malf/malf = find_active_faction_by_member(src.mind.GetRole(MALF))
if(malf && malf.apcs >= 3)
stat(null, "Amount of APCS hacked: [malf.apcs]")
stat(null, "Time until station control secured: [max(malf.AI_win_timeleft/(malf.apcs/3), 0)] seconds")
/mob/proc/remove_malf_spells()
for(var/spell/S in spell_list)

View File

@@ -894,6 +894,7 @@
else if (href_list["malfhack"])
var/mob/living/silicon/ai/malfai = usr
var/datum/faction/malf/M = find_active_faction_by_member(malfai.mind.GetRole(MALF))
if(get_malf_status(malfai)==1)
if (malfai.malfhacking)
to_chat(malfai, "You are already hacking an APC.")
@@ -907,9 +908,8 @@
malfai.malfhack = null
malfai.malfhacking = 0
locked = 1
/*if (ticker.mode.config_tag == "malfunction")
if (STATION_Z == z)
ticker.mode:apcs++*/
if(M)
M.apcs++
if(usr:parent)
src.malfai = usr:parent
else

View File

@@ -1 +1 @@
sandbox
sandbox

View File

@@ -269,6 +269,7 @@
#include "code\datums\gamemode\cult.dm"
#include "code\datums\gamemode\extended.dm"
#include "code\datums\gamemode\gamemode.dm"
#include "code\datums\gamemode\malf.dm"
#include "code\datums\gamemode\misc_gamemode_procs.dm"
#include "code\datums\gamemode\mixed.dm"
#include "code\datums\gamemode\nuke.dm"