mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-22 08:01:16 +00:00
Instead of trying to get the necessary antags no matter what, mode setup will now treat a lack of volunary antags just like a lack of total players and abort the mode.
355 lines
13 KiB
Plaintext
355 lines
13 KiB
Plaintext
//This file was auto-corrected by findeclaration.exe on 29/05/2012 15:03:04
|
|
|
|
/*
|
|
* GAMEMODES (by Rastaf0)
|
|
*
|
|
* In the new mode system all special roles are fully supported.
|
|
* You can have proper wizards/traitors/changelings/cultists during any mode.
|
|
* Only two things really depends on gamemode:
|
|
* 1. Starting roles, equipment and preparations
|
|
* 2. Conditions of finishing the round.
|
|
*
|
|
*/
|
|
|
|
|
|
/datum/game_mode
|
|
var/name = "invalid"
|
|
var/config_tag = null
|
|
var/intercept_hacked = 0
|
|
var/votable = 1
|
|
var/probability = 1
|
|
var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm
|
|
var/explosion_in_progress = 0 //sit back and relax
|
|
var/list/datum/mind/modePlayer = new
|
|
var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist
|
|
var/list/protected_jobs = list() // Jobs that can't be tratiors because
|
|
var/list/logtraitors = list()
|
|
var/required_players = 1
|
|
var/required_enemies = 0
|
|
var/recommended_enemies = 0
|
|
var/uplink_welcome
|
|
var/uplink_uses
|
|
var/uplink_items = {"Highly Visible and Dangerous Weapons;
|
|
/obj/item/weapon/gun/projectile:6:Revolver;
|
|
/obj/item/ammo_magazine/a357:2:Ammo-357;
|
|
/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow;
|
|
/obj/item/weapon/melee/energy/sword:4:Energy Sword;
|
|
/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle;
|
|
/obj/item/weapon/storage/emp_kit:3:5 EMP Grenades;
|
|
Whitespace:Seperator;
|
|
Stealthy and Inconspicuous Weapons;
|
|
/obj/item/weapon/pen/sleepypen:3:Sleepy Pen;
|
|
/obj/item/weapon/soap/syndie:1:Syndicate Soap;
|
|
/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge;
|
|
Whitespace:Seperator;
|
|
Stealth and Camouflage Items;
|
|
/obj/item/clothing/under/chameleon:4:Chameleon Jumpsuit, with armor.;
|
|
/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes;
|
|
/obj/item/weapon/card/id/syndicate:3:Agent ID card;
|
|
/obj/item/clothing/mask/gas/voice:4:Voice Changer;
|
|
/obj/item/device/chameleon:4:Chameleon-Projector;
|
|
/obj/item/weapon/stamperaser:1:Stamp Remover and Forger;
|
|
Whitespace:Seperator;
|
|
Devices and Tools;
|
|
/obj/item/weapon/card/emag:4:Cryptographic Sequencer (Limited uses, almost full access);
|
|
/obj/item/device/hacktool:3:Hacktool (Slow, but stealthy. Unlimited uses);
|
|
/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox;
|
|
/obj/item/device/encryptionkey/traitor:3:Traitor Radio Key;
|
|
/obj/item/device/encryptionkey/binary:3:Binary Translator Key;
|
|
/obj/item/weapon/storage/syndie_kit/space:3:Space Suit;
|
|
/obj/item/clothing/glasses/thermal:3:Thermal Imaging Glasses;
|
|
/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module;
|
|
/obj/item/weapon/plastique:2:C-4 (Destroys walls, not people);
|
|
/obj/item/weapon/syndie/c4explosive:4:Low Power Explosive Charge, with Detonator;
|
|
/obj/item/device/powersink:5:Powersink (DANGER!);
|
|
/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!);
|
|
/obj/item/weapon/circuitboard/teleporter:10:Teleporter Circuit Board;
|
|
Whitespace:Seperator;
|
|
Implants;
|
|
/obj/item/weapon/storage/syndie_kit/imp_freedom:3:Freedom Implant;
|
|
/obj/item/weapon/storage/syndie_kit/imp_compress:5:Compressed Matter Implant;
|
|
/obj/item/weapon/storage/syndie_kit/imp_explosive:6:Explosive Implant;
|
|
/obj/item/weapon/storage/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals);
|
|
Whitespace:Seperator;
|
|
Badassery;
|
|
/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"}
|
|
|
|
// Items removed from above:
|
|
/*
|
|
/obj/item/weapon/syndie/c4explosive/heavy:7:High (!) Power Explosive Charge, with Detonator;
|
|
/obj/item/weapon/cloaking_device:4:Cloaking Device; //Replacing cloakers with thermals. -Pete
|
|
*/
|
|
|
|
/datum/game_mode/proc/announce() //to be calles when round starts
|
|
world << "<B>Notice</B>: [src] did not define announce()"
|
|
|
|
|
|
///can_start()
|
|
///Checks to see if the game can be setup and ran with the current number of players or whatnot.
|
|
/datum/game_mode/proc/can_start()
|
|
var/playerC = 0
|
|
for(var/mob/new_player/player in world)
|
|
if((player.client)&&(player.ready))
|
|
playerC++
|
|
if(playerC >= required_players)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
///pre_setup()
|
|
///Attempts to select players for special roles the mode might have.
|
|
/datum/game_mode/proc/pre_setup()
|
|
return 1
|
|
|
|
|
|
///post_setup()
|
|
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
|
|
/datum/game_mode/proc/post_setup()
|
|
feedback_set_details("round_start","[time2text(world.realtime)]")
|
|
if(ticker && ticker.mode)
|
|
feedback_set_details("game_mode","[ticker.mode]")
|
|
if(revdata)
|
|
feedback_set_details("revision","[revdata.revision]")
|
|
feedback_set_details("server_ip","[world.internet_address]")
|
|
return 1
|
|
|
|
|
|
///process()
|
|
///Called by the gameticker
|
|
/datum/game_mode/proc/process()
|
|
return 0
|
|
|
|
|
|
/datum/game_mode/proc/check_finished() //to be called by ticker
|
|
if(emergency_shuttle.location==2 || station_was_nuked)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
/datum/game_mode/proc/declare_completion()
|
|
var/clients = 0
|
|
var/surviving_humans = 0
|
|
var/surviving_total = 0
|
|
var/ghosts = 0
|
|
var/escaped_humans = 0
|
|
var/escaped_total = 0
|
|
var/escaped_on_pod_1 = 0
|
|
var/escaped_on_pod_2 = 0
|
|
var/escaped_on_pod_3 = 0
|
|
var/escaped_on_pod_5 = 0
|
|
var/escaped_on_shuttle = 0
|
|
|
|
var/list/area/escape_locations = list(/area/shuttle/escape/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom)
|
|
|
|
for(var/mob/M in world)
|
|
if(M.client)
|
|
clients++
|
|
if(ishuman(M))
|
|
if(!M.stat)
|
|
surviving_humans++
|
|
if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
|
|
escaped_humans++
|
|
if(!M.stat)
|
|
surviving_total++
|
|
if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
|
|
escaped_total++
|
|
|
|
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape/centcom)
|
|
escaped_on_shuttle++
|
|
|
|
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod1/centcom)
|
|
escaped_on_pod_1++
|
|
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod2/centcom)
|
|
escaped_on_pod_2++
|
|
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod3/centcom)
|
|
escaped_on_pod_3++
|
|
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod5/centcom)
|
|
escaped_on_pod_5++
|
|
|
|
if(isobserver(M))
|
|
ghosts++
|
|
|
|
if(clients > 0)
|
|
feedback_set("round_end_clients",clients)
|
|
if(ghosts > 0)
|
|
feedback_set("round_end_ghosts",ghosts)
|
|
if(surviving_humans > 0)
|
|
feedback_set("survived_human",surviving_humans)
|
|
if(surviving_total > 0)
|
|
feedback_set("survived_total",surviving_total)
|
|
if(escaped_humans > 0)
|
|
feedback_set("escaped_human",escaped_humans)
|
|
if(escaped_total > 0)
|
|
feedback_set("escaped_total",escaped_total)
|
|
if(escaped_on_shuttle > 0)
|
|
feedback_set("escaped_on_shuttle",escaped_on_shuttle)
|
|
if(escaped_on_pod_1 > 0)
|
|
feedback_set("escaped_on_pod_1",escaped_on_pod_1)
|
|
if(escaped_on_pod_2 > 0)
|
|
feedback_set("escaped_on_pod_2",escaped_on_pod_2)
|
|
if(escaped_on_pod_3 > 0)
|
|
feedback_set("escaped_on_pod_3",escaped_on_pod_3)
|
|
if(escaped_on_pod_5 > 0)
|
|
feedback_set("escaped_on_pod_5",escaped_on_pod_5)
|
|
|
|
|
|
return 0
|
|
|
|
|
|
/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere.
|
|
return 0
|
|
|
|
/datum/game_mode/proc/latespawn(var/mob)
|
|
|
|
/datum/game_mode/proc/send_intercept()
|
|
var/intercepttext = "<FONT size = 3><B>Cent. Com. Update</B> Requested staus information:</FONT><HR>"
|
|
intercepttext += "<B> Cent. Com has recently been contacted by the following syndicate affiliated organisations in your area, please investigate any information you may have:</B>"
|
|
|
|
var/list/possible_modes = list()
|
|
possible_modes.Add("revolution", "wizard", "nuke", "traitor", "malf", "changeling", "cult")
|
|
possible_modes -= "[ticker.mode]"
|
|
var/number = pick(2, 3)
|
|
var/i = 0
|
|
for(i = 0, i < number, i++)
|
|
possible_modes.Remove(pick(possible_modes))
|
|
|
|
if(!intercept_hacked)
|
|
possible_modes.Insert(rand(possible_modes.len), "[ticker.mode]")
|
|
|
|
shuffle(possible_modes)
|
|
|
|
var/datum/intercept_text/i_text = new /datum/intercept_text
|
|
for(var/A in possible_modes)
|
|
if(modePlayer.len == 0)
|
|
intercepttext += i_text.build(A)
|
|
else
|
|
intercepttext += i_text.build(A, pick(modePlayer))
|
|
|
|
for (var/obj/machinery/computer/communications/comm in world)
|
|
if (!(comm.stat & (BROKEN | NOPOWER)) && comm.prints_intercept)
|
|
var/obj/item/weapon/paper/intercept = new /obj/item/weapon/paper( comm.loc )
|
|
intercept.name = "paper - 'Cent. Com. Status Summary'"
|
|
intercept.info = intercepttext
|
|
|
|
comm.messagetitle.Add("Cent. Com. Status Summary")
|
|
comm.messagetext.Add(intercepttext)
|
|
world << sound('commandreport.ogg')
|
|
|
|
/* command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.")
|
|
world << sound('intercept.ogg')
|
|
if(security_level < SEC_LEVEL_BLUE)
|
|
set_security_level(SEC_LEVEL_BLUE)*/
|
|
|
|
|
|
/datum/game_mode/proc/get_players_for_role(var/role, draft_people=0, override_jobbans=0)
|
|
var/list/candidates = list()
|
|
var/list/drafted = list()
|
|
var/datum/mind/applicant = null
|
|
|
|
var/roletext
|
|
switch(role)
|
|
if(BE_CHANGELING) roletext="changeling"
|
|
if(BE_TRAITOR) roletext="traitor"
|
|
if(BE_OPERATIVE) roletext="operative"
|
|
if(BE_WIZARD) roletext="wizard"
|
|
if(BE_REV) roletext="revolutionary"
|
|
if(BE_CULTIST) roletext="cultist"
|
|
if(BE_MEME) roletext="meme"
|
|
|
|
|
|
for(var/mob/new_player/player in world)
|
|
if(player.client && player.ready)
|
|
if(player.preferences.be_special & role)
|
|
if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans
|
|
candidates += player.mind // Get a list of all the people who want to be the antagonist for this round
|
|
|
|
if(restricted_jobs)
|
|
for(var/datum/mind/player in candidates)
|
|
for(var/job in restricted_jobs) // Remove people who want to be antagonist but have a job already that precludes it
|
|
if(player.assigned_role == job)
|
|
candidates -= player
|
|
|
|
if(candidates.len < recommended_enemies && draft_people)
|
|
for(var/mob/new_player/player in world)
|
|
if (player.client && player.ready)
|
|
if(!(player.preferences.be_special & role)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one
|
|
if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans
|
|
drafted += player.mind
|
|
|
|
if(restricted_jobs)
|
|
for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist
|
|
for(var/job in restricted_jobs)
|
|
if(player.assigned_role == job)
|
|
drafted -= player
|
|
|
|
while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates
|
|
if(drafted.len > 0)
|
|
applicant = pick(drafted)
|
|
if(applicant)
|
|
candidates += applicant
|
|
drafted.Remove(applicant)
|
|
|
|
else // Not enough scrubs, ABORT ABORT ABORT
|
|
break
|
|
|
|
if(candidates.len < recommended_enemies && override_jobbans) //If we still don't have enough people, we're going to start drafting banned people.
|
|
for(var/mob/new_player/player in world)
|
|
if (player.client && player.ready)
|
|
if(jobban_isbanned(player, "Syndicate") || jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans
|
|
drafted += player.mind
|
|
|
|
if(restricted_jobs)
|
|
for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist
|
|
for(var/job in restricted_jobs)
|
|
if(player.assigned_role == job)
|
|
drafted -= player
|
|
|
|
while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates
|
|
if(drafted.len > 0)
|
|
applicant = pick(drafted)
|
|
if(applicant)
|
|
candidates += applicant
|
|
drafted.Remove(applicant)
|
|
|
|
else // Not enough scrubs, ABORT ABORT ABORT
|
|
break
|
|
|
|
return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies
|
|
// recommended_enemies if the number of people with that role set to yes is less than recomended_enemies,
|
|
// Less if there are not enough valid players in the game entirely to make recommended_enemies.
|
|
|
|
|
|
/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/new_player/player)
|
|
if(player.preferences.be_special & role)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
/datum/game_mode/proc/num_players()
|
|
. = 0
|
|
for(var/mob/new_player/P in world)
|
|
if(P.client && P.ready)
|
|
. ++
|
|
|
|
|
|
///////////////////////////////////
|
|
//Keeps track of all living heads//
|
|
///////////////////////////////////
|
|
/datum/game_mode/proc/get_living_heads()
|
|
var/list/heads = list()
|
|
for(var/mob/living/carbon/human/player in world)
|
|
if(player.stat!=2 && player.mind && (player.mind.assigned_role in command_positions))
|
|
heads += player.mind
|
|
return heads
|
|
|
|
|
|
////////////////////////////
|
|
//Keeps track of all heads//
|
|
////////////////////////////
|
|
/datum/game_mode/proc/get_all_heads()
|
|
var/list/heads = list()
|
|
for(var/mob/player in world)
|
|
if(player.mind && (player.mind.assigned_role in command_positions))
|
|
heads += player.mind
|
|
return heads
|