mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
|
||||
3
code/datums/gamemode/malf.dm
Normal file
3
code/datums/gamemode/malf.dm
Normal file
@@ -0,0 +1,3 @@
|
||||
/datum/gamemode/malf
|
||||
name = "Malfunction"
|
||||
factions_allowed = list(/datum/faction/malf)
|
||||
@@ -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..."})
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
sandbox
|
||||
sandbox
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user