From d6e0f1cf220a631f7b9641316c0deb8b315fc1d7 Mon Sep 17 00:00:00 2001 From: "rastaf.zero@gmail.com" Date: Tue, 21 Jun 2011 21:22:23 +0000 Subject: [PATCH] Freaking big GAMEMODES UPDATE. I have done lots of work to make selecting players for special roles be fair. - New options preferences: "be traitor", "be changeling" and so on for all special roles. - Now you can have job of AI/cyborg in preferences and do not lower your chances to become wizard/changeling/etc. And vice-versa: you do not have to select AI in your preferences to have non zero chance to play malf. - Jobban from syndicate bans player from any special role (including malf AI, cult, etc). - Fixed bug with changeling round not ending sometimes. - All special roles were tuned to work better as admin-driven event. -- All adminmade special characters will be listed at the end of round of any type. -- All adminmade special characters are fully functional with following exceptions: --- The ending conditions are determined at round start, i.e. you cannot end revolution by killing wizards and malf AIs (however, with nuke you can end anything). --- The cultists cannot get their special objectives. --- The malf AI can hack the APCs but without any profit. --- The syndicate operatives must obtain the nuke/working code from admins. --- As before, nuclear explosion ends round. Even if nuke was used in wrong place. - Fixed thingy like "Not enough players for revolution game mode. Restarting world in 5 seconds." - Changeling wont get objective "absorb X genomes" when there are less that X players in game. - proc/equip_if_possible now has return value, procs like equip_revolutionary (giving a flash) should be more reliable. - There are no fake wizards anymore. The research staff have to kill ALL wizards on order to win, even adminspawned ones. ("give spell" verb works as before, not making a spellcaster to actually be wizard). - The semi-new game mode: traitor+changeling. Just like regular traitor mode plus one changeling. Round ends when the shuttle reaches centcom. Option for config.txt: "PROBABILITY TRAITORCHAN". - Successful malf AI now have 60 seconds to choose to explode the station or not (some players still have to rejoin game to have their new verbs shown in Malfunction tab). - Monkeys mode fixed, monkeys wouldn't randomly cure anymore. For admins: - New powerful mind editor oriented to mixed rounds. -- Setting someone as special character (like wizard) does not equip him/her automatically. You have to do it it next step. Note, that in case of wizards and nuke operatives their old dress will be deleted! If you do not want it you shall use "undress" link. -- Only operatives, head revs and cultists have their objectives set immediately. -- You can unemad borgs! -- You cannot unemag borgs because calling mind editor for nonhumans is blocked atm. -- many other useful features. -- you can fix burned out flashes from mind editor. -- first assign the new malf AI/wizard then demalf/dewizard old one or round will immediately end. - if delete the nuke bomb during its downcounting round will stuck. Using "edit ticker variables" set ticker.mode.explosion_in_progress = 0. For coders: - /datum/game_mode/malfunction/AI_Module renamed to /datum/AI_Module. Reason: What. The. Fuck. Unrelated fixes: - Blueprints can create areas up to 300 tiles (was 100). - Cyborgs wont leave backpacks at spawn point anymore. - Fixed bug in preferences causing preferences files to be huge. - Diseases can infect again. - The option "SQL_ENABLED 0" now works in config.txt. - fixed critical bug on assassinate objective. Bugs: - We have a bug with job distribution for people who haven't any available jobs in their preferences. Players tends to group by jobs. - For example, if we have 3 players they with hight chances will got same jobs. And probability of having one engineer and one medic _exactly_ equals _zero_. - I am not sure if my changes made that bug worse. Anyway I MUST do this commit. Bug will be fixed eventually. Maybe. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1703 316c924e-a436-60f5-8080-3fe189b3f50e --- code/datums/configuration.dm | 50 +- code/datums/disease.dm | 27 +- code/datums/mind.dm | 837 +++++++++++++----- code/defines/area/Space Station 13 areas.dm | 63 +- code/defines/mob/living/silicon/ai.dm | 4 +- code/game/algorithm.dm | 28 +- code/game/cellautomata.dm | 2 +- code/game/communications.dm | 4 +- code/game/dna.dm | 4 + code/game/gamemodes/blob/blob.dm | 2 + code/game/gamemodes/changeling/changeling.dm | 271 +++--- .../gamemodes/changeling/changeling_powers.dm | 4 +- .../game/gamemodes/changeling/traitor_chan.dm | 38 + code/game/gamemodes/cult/cult.dm | 244 +++-- code/game/gamemodes/events/space_ninja.dm | 61 +- code/game/gamemodes/game_mode.dm | 209 ++--- code/game/gamemodes/gameticker.dm | 165 ++-- code/game/gamemodes/intercept_report.dm | 146 +-- .../gamemodes/malfunction/Malf_Modules.dm | 96 +- .../game/gamemodes/malfunction/malfunction.dm | 230 +++-- code/game/gamemodes/meteor/meteor.dm | 1 + code/game/gamemodes/nuclear/nuclear.dm | 278 +++--- code/game/gamemodes/nuclear/nuclearbomb.dm | 72 +- code/game/gamemodes/objective.dm | 18 +- code/game/gamemodes/revolution/revolution.dm | 314 +++---- code/game/gamemodes/setupgame.dm | 3 +- code/game/gamemodes/traitor/traitor.dm | 293 ++++-- code/game/gamemodes/wizard/wizard.dm | 235 +++-- code/game/jobs/jobprocs.dm | 126 ++- code/game/jobs/jobs.dm | 88 +- code/game/magic/cultist/runes.dm | 7 +- code/game/objects/devices/PDA/uplink.dm | 12 +- code/game/objects/devices/flash.dm | 6 +- code/game/objects/items.dm | 2 +- code/game/objects/items/blueprints.dm | 2 +- code/game/objects/items/item.dm | 4 +- code/game/objects/items/weapons/uplinks.dm | 57 +- code/game/objects/storage/bible.dm | 5 +- code/modules/admin/admin.dm | 285 +++--- code/modules/admin/admin_verbs.dm | 10 +- code/modules/admin/banjob.dm | 15 +- code/modules/admin/verbs/randomverbs.dm | 7 +- code/modules/admin/verbs/tripAI.dm | 26 +- code/modules/mob/living/carbon/human/human.dm | 11 +- .../mob/living/carbon/human/savefile.dm | 56 +- .../mob/living/carbon/monkey/monkey.dm | 4 + code/modules/mob/living/silicon/ai/ai.dm | 6 +- code/modules/mob/living/silicon/ai/death.dm | 8 +- code/modules/mob/mob.dm | 43 +- code/modules/mob/new_player/new_player.dm | 2 +- code/modules/mob/new_player/preferences.dm | 228 +++-- code/modules/mob/transform_procs.dm | 8 +- code/modules/power/apc.dm | 20 +- code/setup.dm | 17 +- code/unused/gamemodes/monkey.dm | 97 +- config/config.txt | 10 +- tgstation.dme | 4 + 57 files changed, 2825 insertions(+), 2040 deletions(-) create mode 100644 code/game/gamemodes/changeling/traitor_chan.dm diff --git a/code/datums/configuration.dm b/code/datums/configuration.dm index b5a52acb9bc..1c7fce71887 100644 --- a/code/datums/configuration.dm +++ b/code/datums/configuration.dm @@ -102,7 +102,7 @@ config.log_access = 1 if ("sql_enabled") - config.sql_enabled = 1 + config.sql_enabled = text2num(value) if ("log_say") config.log_say = 1 @@ -319,38 +319,20 @@ if (M.config_tag && M.config_tag == mode_name) return M del(M) - return null -/datum/configuration/proc/pick_random_mode() - var/total = 0 - var/list/accum = list() - - for(var/M in src.modes) - total += src.probabilities[M] - accum[M] = total - - var/r = total - (rand() * total) - - var/mode_name = null - for (var/M in modes) - if (src.probabilities[M] > 0 && accum[M] >= r) - mode_name = M - break - - if (!mode_name) - world << "Failed to pick a random game mode." - return null - - //world << "Returning mode [mode_name]" - - return src.pick_mode(mode_name) - -/datum/configuration/proc/get_used_mode_names() - var/list/names = list() - - for (var/M in src.modes) - if (src.probabilities[M] > 0) - names += src.mode_names[M] - - return names +/datum/configuration/proc/get_runnable_modes() + var/list/datum/game_mode/runnable_modes = new + for (var/T in (typesof(/datum/game_mode) - /datum/game_mode)) + var/datum/game_mode/M = new T() + //world << "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]" + if (!(M.config_tag in modes)) + del(M) + continue + if (probabilities[M.config_tag]<=0) + del(M) + continue + if (M.can_start()) + runnable_modes[M] = probabilities[M.config_tag] + //world << "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]" + return runnable_modes diff --git a/code/datums/disease.dm b/code/datums/disease.dm index c3ac58455b2..c3e33e65b13 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -96,17 +96,18 @@ to null does not delete the object itself. Thank you. if(fail) return if(skip_this == 1)//be wary, it replaces the current disease... - if(virus) - virus.cure(0) - virus = new virus.type - virus.affected_mob = src - virus.strain_data = virus.strain_data.Copy() - virus.holder = src + if(src.virus) + src.virus.cure(0) + src.virus = new virus.type + src.virus.affected_mob = src + src.virus.strain_data = virus.strain_data.Copy() + src.virus.holder = src if(prob(5)) - virus.carrier = 1 + src.virus.carrier = 1 return - if(virus) return + if(src.virus) + return if(virus.type in resistances) if(prob(99.9)) return @@ -252,12 +253,12 @@ to null does not delete the object itself. Thank you. else if(prob(15)) return else*/ - virus = new virus.type - virus.strain_data = virus.strain_data.Copy() - virus.affected_mob = src - virus.holder = src + src.virus = new virus.type + src.virus.strain_data = virus.strain_data.Copy() + src.virus.affected_mob = src + src.virus.holder = src if(prob(5)) - virus.carrier = 1 + src.virus.carrier = 1 return return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c3dab7639dd..fb2144a1be0 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -4,6 +4,7 @@ datum/mind var/mob/living/original var/memory + //TODO: store original name --rastaf0 var/assigned_role var/special_role @@ -40,92 +41,222 @@ datum/mind proc/edit_memory() var/out = "[current.real_name]
" out += "Assigned role: [assigned_role]. Edit
" - out += "Special role: " + out += "Factions and special roles:
" - - var/srole - var/cantoggle = 1 - - var/datum/game_mode/current_mode = ticker.mode - switch (current_mode.config_tag) - if ("revolution") - if (src in current_mode:head_revolutionaries) - srole = "Head Revolutionary" - out += "Head Revolutionary " - cantoggle = 0 - else if(src in current_mode:revolutionaries) - srole = "Revolutionary" - out += "Head Revolutionary Revolutionary " - else - out += "Head Revolutionary Revolutionary " - - if ("cult") - if (src in current_mode:cult) - srole = "Cultist" - out += "Cultist" - cantoggle = 0 - - if ("wizard") - if (current_mode:wizard && src == current_mode:wizard) - srole = "Wizard" - out += "Wizard" - cantoggle = 0 - else - out = "Wizard " - - if ("changeling") - if (src in current_mode:changelings) - srole = "Changeling" - out += "Changeling" - cantoggle = 0 - else - out = "Changeling " - - if ("malfunction") - if (src in current_mode:malf_ai) - srole = "Malfunction" - out += "Malfunction" - cantoggle = 0 - - if ("nuclear") - if(src in current_mode:syndicates) - srole = "Syndicate" - out = "Syndicate" - cantoggle = current_mode:syndicates.len > 1 - else - out += "Syndicate " - - if (cantoggle) - if(src in current_mode.traitors) - switch(special_role) - if ("Fake Wizard") - out += "Traitor " - out += "[special_role]/font> " - srole = special_role - if ("Death Commando") - out += "[special_role] " - srole = special_role - if ("Space Ninja") - out += "[special_role] " - srole = special_role + var/list/sections = list( + "revolution", + "cult", + "wizard", + "changeling", + "nuclear", + "traitor", // "traitorchan", + "monkey", + "malfunction", + ) + var/text = "" + + if (istype(current, /mob/living/carbon/human) || istype(current, /mob/living/carbon/monkey)) + /** REVOLUTION ***/ + text = "revolution" + if (ticker.mode.config_tag=="revolution") + text = uppertext(text) + text = "[text]: " + if (src.assigned_role in head_positions) + text += "HEAD|officer|employer|headrev|rev" + else if (src.assigned_role in list("Security Officer", "Detective", "Warden")) + text += "head|OFFICER|employer|headre|rev" + else if (src in ticker.mode.head_revolutionaries) + text = "head|officer|employer|HEADREV|rev" + text += "
Flash: give" + + var/list/L = src.current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (flash) + if (flash.status) + text += "|take." else - out += "Traitor " - out += "Fake Wizard " - srole = "Traitor" - else - out += "Traitor " - out += "Fake Wizard " + text += "|take|repair." + else + text += "." - if (srole) - out += "Civilian " + text += " Reequip." + if (objectives.len==0) + text += "
Objectives are empty! Set to kill all heads." + else if (src in ticker.mode.revolutionaries) + text += "head|officer|employer|headrev|REV" else - out += "Civilian " + text += "head|officer|EMPLOYER|headrev|rev" + sections["revolution"] = text + + /** CULT ***/ + text = "cult" + if (ticker.mode.config_tag=="cult") + text = uppertext(text) + text = "[text]: " + if (src.assigned_role in head_positions) + text += "HEAD|officer|employer|cultist" + else if (src.assigned_role in list("Security Officer", "Detective", "Warden")) + text += "head|OFFICER|employer|cultist" + else if (src in ticker.mode.cult) + text += "head|officer|employer|CULTIST" + text += "
Give tome|amulet." +/* + if (objectives.len==0) + text += "
Objectives are empty! Set to sacrifice and escape or summon." +*/ + else + text += "head|officer|EMPLOYER|cultist" + sections["cult"] = text + + /** WIZARD ***/ + text = "wizard" + if (ticker.mode.config_tag=="wizard") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.wizards) + text += "YES|no" + text += "
To lair, undress, dress up, let choose name." + if (objectives.len==0) + text += "
Objectives are empty! Randomize!" + else + text += "yes|NO" + sections["wizard"] = text + + /** CHANGELING ***/ + text = "changeling" + if (ticker.mode.config_tag=="changeling" || ticker.mode.config_tag=="traitorchan") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.changelings) + text += "YES|no" + if (objectives.len==0) + text += "
Objectives are empty! Randomize!" + if (current.absorbed_dna.len>0 && current.real_name != current.absorbed_dna[1]) + text += "
Transform to initial appearance." + else + text += "yes|NO" + var/datum/game_mode/changeling/changeling = ticker.mode + if (istype(changeling) && changeling.changelingdeath) + text += "
All the changelings are dead! Restart in [round((changeling.TIME_TO_GET_REVIVED-(world.time-changeling.changelingdeathtime))/10)] seconds." + sections["changeling"] = text + + /** NUCLEAR ***/ + text = "nuclear" + if (ticker.mode.config_tag=="nuclear") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.syndicates) + text += "OPERATIVE|nanotrasen" + text += "
To shuttle, undress, dress up." + var/code + for (var/obj/machinery/nuclearbomb/bombue in world) + if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") + code = bombue.r_code + break + if (code) + text += " Code is [code]. tell the code." + else + text += "operative|NANOTRASEN" + sections["nuclear"] = text + + /** TRAITOR ***/ + text = "traitor" + if (ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.traitors) + text += "TRAITOR|loyal" + if (objectives.len==0) + text += "
Objectives are empty! Randomize!." + else + text += "traitor|LOYAL" + sections["traitor"] = text + + /** MONKEY ***/ + if (istype(current, /mob/living/carbon)) + text = "monkey" + if (ticker.mode.config_tag=="monkey") + text = uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/carbon/human)) + text += "healthy|infected|HUMAN|other" + else if (istype(current, /mob/living/carbon/monkey)) + if(istype(current.virus, /datum/disease/jungle_fever)) + text += "healthy|INFECTED|human|other" + else + text += "HEALTHY|infected|human|other" + else + text += "healthy|infected|human|OTHER" + sections["monkey"] = text + + + /** SILICON ***/ + + if (istype(current, /mob/living/silicon)) + text = "silicon" + if (ticker.mode.config_tag=="malfunction") + text = uppertext(text) + text = "[text]: " + if (istype(current, /mob/living/silicon/ai)) + if (src in ticker.mode.malf_ai) + text += "MALF|not malf" + else + text += "malf|NOT MALF" + var/mob/living/silicon/robot/robot = current + if (istype(robot) && robot.emagged) + text += "
Cyborg: Is emagged! Unemag!
0th law: [robot.laws.zeroth]" + var/mob/living/silicon/ai/ai = current + if (istype(ai) && ai.connected_robots.len) + var/n_e_robots = 0 + for (var/mob/living/silicon/robot/R in ai.connected_robots) + if (R.emagged) + n_e_robots++ + text += "
[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" + sections["malfunction"] = text + + if (ticker.mode.config_tag == "traitorchan") + if (sections["traitor"]) + out += sections["traitor"]+"
" + if (sections["changeling"]) + out += sections["changeling"]+"
" + sections -= "traitor" + sections -= "changeling" + else + if (sections[ticker.mode.config_tag]) + out += sections[ticker.mode.config_tag]+"
" + sections -= ticker.mode.config_tag + for (var/i in sections) + if (sections[i]) + out += sections[i]+"
" + + + if (((src in ticker.mode.head_revolutionaries) || \ + (src in ticker.mode.traitors) || \ + (src in ticker.mode.syndicates)) && \ + istype(current,/mob/living/carbon/human) ) + + text = "Uplink: give" + var/obj/item/weapon/syndicate_uplink/suplink = find_syndicate_uplink() + var/obj/item/weapon/integrated_uplink/iuplink = find_integrated_uplink() + var/crystals + if (suplink) + crystals = suplink.uses + else if (iuplink) + crystals = iuplink.uses + if (suplink || iuplink) + text += "|take" + if (usr.client.holder.level >= 3) + text += ", [crystals] crystals" + else + text += ", [crystals] crystals" + text += "." //hiel grammar + out += text out += "
" - out += "Memory:
" + out += "Memory:
" out += memory - out += "
Edit memory
" + out += "
Edit memory
" out += "Objectives:
" if (objectives.len == 0) out += "EMPTY
" @@ -148,8 +279,8 @@ datum/mind assigned_role = new_role else if (href_list["memory_edit"]) - var/new_memo = input("Write new memory", "Memory", memory) as message - if (!new_memo) return + var/new_memo = input("Write new memory", "Memory", memory) as null|message + if (isnull(new_memo)) return memory = new_memo else if (href_list["obj_edit"] || href_list["obj_add"]) @@ -272,78 +403,400 @@ datum/mind else if (href_list["obj_delete"]) var/datum/objective/objective = locate(href_list["obj_delete"]) if (!objective) return - objectives -= objective - else if (href_list["traitorize"]) - // clear old memory - clear_memory(href_list["traitorize"] == "civilian" ? 0 : 1) + else if (href_list["revolution"]) + switch(href_list["revolution"]) + if("clear") + if(src in ticker.mode.revolutionaries) + ticker.mode.revolutionaries -= src + current << "\red You have been brainwashed! You are no longer a revolutionary!" + ticker.mode.update_rev_icons_removed(src) + special_role = null + if(src in ticker.mode.head_revolutionaries) + ticker.mode.head_revolutionaries -= src + current << "\red You have been brainwashed! You are no longer a head revolutionary!" + ticker.mode.update_rev_icons_removed(src) + special_role = null - var/datum/game_mode/current_mode = ticker.mode - switch (href_list["traitorize"]) - if ("headrev") - current_mode.equip_traitor(current,1) - current_mode:equip_revolutionary(current) - //find first headrev - for(var/datum/mind/rev_mind in current_mode:head_revolutionaries) - // copy objectives - for (var/datum/objective/assassinate/obj in rev_mind.objectives) - var/datum/objective/assassinate/rev_obj = new - rev_obj = src - rev_obj.target = obj.target - rev_obj.explanation_text = obj.explanation_text - objectives += rev_obj - break - current_mode:update_rev_icons_added(src) - current_mode:head_revolutionaries += src + if("rev") + if(src in ticker.mode.head_revolutionaries) + ticker.mode.head_revolutionaries -= src + ticker.mode.update_rev_icons_removed(src) + current << "\red Revolution has been disappointed of your leader traits! You are a regular revolutionary now!" + else if(!(src in ticker.mode.revolutionaries)) + current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" + else + return + ticker.mode.revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Revolutionary" + + if("headrev") + if(src in ticker.mode.revolutionaries) + ticker.mode.revolutionaries -= src + ticker.mode.update_rev_icons_removed(src) + current << "\red You have proved your devotion to revoltion! Yea are a head revolutionary now!" + else if(!(src in ticker.mode.head_revolutionaries)) + current << "\blue You are a member of the revolutionaries' leadership now!" + else + return + if (ticker.mode.head_revolutionaries.len>0) + // copy targets + var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries + if (valid_head) + for (var/datum/objective/assassinate/O in valid_head.objectives) + var/datum/objective/assassinate/rev_obj = new + rev_obj.owner = src + rev_obj.target = O.target + rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]." + objectives += rev_obj + ticker.mode.greet_revolutionary(src,0) + ticker.mode.head_revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Head Revolutionary" - var/obj_count = 1 - current << "\blue You are a member of the revolutionaries' leadership!" - for(var/datum/objective/objective in objectives) - current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ + if("autoobjectives") + ticker.mode.forge_revolutionary_objectives(src) + ticker.mode.greet_revolutionary(src,0) + usr << "\blue The objectives for revolution have been generated and shown to [key]" - if ("rev") - current_mode:add_revolutionary(src) + if("flash") + if (!ticker.mode.equip_revolutionary(current)) + usr << "\red Spawning flash failed!" - if ("wizard") - if (alert("Old wizard would be unwizarded. Are you sure?", , "Yes", "No") != "Yes") return - if (current_mode:wizard) - current_mode:wizard.clear_memory(0) - current_mode:wizard = src - current_mode:equip_wizard(current) - current << "\red You are the Space Wizard!" + if("takeflash") + var/list/L = src.current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + usr << "\red Deleting flash failed!" + del(flash) + + if("repairflash") + var/list/L = src.current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + usr << "\red Repairing flash failed!" + else + flash.status = 1 + + if("reequip") + var/list/L = src.current.get_contents() + var/obj/item/device/flash/flash = locate() in L + del(flash) + take_uplink() + var/fail = 0 + fail |= !ticker.mode.equip_traitor(current, 1) + fail |= !ticker.mode.equip_revolutionary(current) + if (fail) + usr << "\red Reequipping revolutionary goes wrong!" + + else if (href_list["cult"]) + switch(href_list["cult"]) + if("clear") + if(src in ticker.mode.cult) + ticker.mode.cult -= src + ticker.mode.update_cult_icons_removed(src) + special_role = null + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + current << "\red You have been brainwashed! You are no longer a cultist!" + memory = "" + if("cultist") + if(!(src in ticker.mode.cult)) + ticker.mode.cult += src + ticker.mode.update_cult_icons_added(src) + special_role = "Cultist" + current << "Your blood pulses. Your head throbs. The world goes red. All at once you are aware of a horrible, horrible truth. The veil of reality has been ripped away and in the festering wound left behind something sinister takes root." + current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + if("tome") + var/mob/living/carbon/human/H = current + if (istype(H)) + var/obj/item/weapon/tome/T = new(H) + + var/list/slots = list ( + "backpack" = H.slot_in_backpack, + "left pocket" = H.slot_l_store, + "right pocket" = H.slot_r_store, + "left hand" = H.slot_l_hand, + "right hand" = H.slot_r_hand, + ) + var/where = H.equip_in_one_of_slots(T, slots) + if (!where) + usr << "\red Spawning tome failed!" + else + H << "A tome, a message from your new master, appears in your [where]." + + if("amulet") + if (!ticker.mode.equip_cultist(src.current)) + usr << "\red Spawning amulet failed!" + + else if (href_list["wizard"]) + switch(href_list["wizard"]) + if("clear") + if(src in ticker.mode.wizards) + ticker.mode.wizards -= src + special_role = null + current.spellremove(current, config.feature_object_spell_system? "object":"verb") + src.current << "\red You have been brainwashed! You are no longer a wizard!" + if("wizard") + if(!(src in ticker.mode.wizards)) + ticker.mode.wizards += src + special_role = "Wizard" + ticker.mode.learn_basic_spells(current) + current << "\red You are the Space Wizard!" + if("lair") current.loc = pick(wizardstart) + if("dressup") + ticker.mode.equip_wizard(current) + if("name") + ticker.mode.name_wizard(current) + if("autoobjectives") + ticker.mode.forge_wizard_objectives(src) + usr << "\blue The objectives for wizard [key] have been generated. You can edit them and anounce manually." - if ("fakewizard") - current_mode.traitors += src - current_mode.equip_wizard(current) - current << "\red You are the Space Wizard!" - current.loc = pick(wizardstart) - special_role = "Fake Wizard" + else if (href_list["changeling"]) + switch(href_list["changeling"]) + if("clear") + if(src in ticker.mode.changelings) + ticker.mode.changelings -= src + special_role = null + current.remove_changeling_powers() + current.absorbed_dna = null + current.chem_charges = 0 + current.changeling_fakedeath = 0 + current.sting_range = 1 + current.changeling_level = 0 + current << "\red You have been brainwashed! You are no longer a changeling!" + if("changeling") + if(!(src in ticker.mode.changelings)) + ticker.mode.changelings += src + ticker.mode.grant_changeling_powers(current) + special_role = "Changeling" + current << "\red You are a changeling!" + if("autoobjectives") + ticker.mode.forge_changeling_objectives(src) + usr << "\blue The objectives for changeling [key] have been generated. You can edit them and anounce manually." - if ("changeling") - if (alert("Old changeling would lose their memory. Are you sure?", , "Yes", "No") != "Yes") return - if (changeling) - changeling.clear_memory() - current_mode:changelings -= changeling - current_mode:grant_changeling_powers(current) - changeling = src - current_mode:changelings += src + if("initialdna") + if (!usr.absorbed_dna[1]) + usr << "\red Resetting DNA failed!" + else + usr.dna = usr.absorbed_dna[usr.absorbed_dna[1]] + usr.real_name = usr.absorbed_dna[1] + updateappearance(usr, usr.dna.uni_identity) + domutcheck(usr, null) - changeling.current << "\red You are a changeling!" + else if (href_list["nuclear"]) + switch(href_list["nuclear"]) + if("clear") + if(src in ticker.mode.syndicates) + ticker.mode.syndicates -= src + ticker.mode.update_synd_icons_removed(src) + special_role = null + for (var/datum/objective/nuclear/O in objectives) + objectives-=O + current << "\red You have been brainwashed! You are no longer a syndicate operative!" + if("nuclear") + if(!(src in ticker.mode.syndicates)) + ticker.mode.syndicates += src + ticker.mode.update_synd_icons_added(src) + if (ticker.mode.syndicates.len==1) + ticker.mode.prepare_syndicate_leader(src) + else + current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + current << "\blue You are a [syndicate_name()] agent!" + ticker.mode.forge_syndicate_objectives(src) + ticker.mode.greet_syndicate(src) + if("lair") + current.loc = get_turf(locate("landmark*Syndicate-Spawn")) + if("dressup") + var/mob/living/carbon/human/H = current + del(H.belt) + del(H.back) + del(H.ears) + del(H.gloves) + del(H.head) + del(H.shoes) + del(H.wear_id) + del(H.wear_suit) + del(H.w_uniform) - if ("syndicate") - var/obj/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") - current.loc = get_turf(synd_spawn) - current_mode:equip_syndicate(current) - current_mode:syndicates += src + if (!ticker.mode.equip_syndicate(current)) + usr << "\red Equipping a syndicate failed!" + if("tellcode") + var/code + for (var/obj/machinery/nuclearbomb/bombue in world) + if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") + code = bombue.r_code + break + if (code) + store_memory("Syndicate Nuclear Bomb Code: [code]", 0, 0) + current << "The nuclear authorization code is: [code]" + else + usr << "\red No valid nuke found!" - if ("traitor") - current_mode.equip_traitor(current) - current_mode.traitors += src - current << "You are the traitor." - special_role = "traitor" + else if (href_list["traitor"]) + switch(href_list["traitor"]) + if("clear") + if(src in ticker.mode.traitors) + ticker.mode.traitors -= src + special_role = null + src.current << "\red You have been brainwashed! You are no longer a traitor!" + if("traitor") + if(!(src in ticker.mode.traitors)) + ticker.mode.traitors += src + special_role = "traitor" + current << "\red You are a traitor!" + + if("autoobjectives") + ticker.mode.forge_traitor_objectives(src) + usr << "\blue The objectives for traitor [key] have been generated. You can edit them and anounce manually." + + else if (href_list["monkey"]) + var/mob/living/L = current + if (L.monkeyizing) + return + switch(href_list["monkey"]) + if("healthy") + if (usr.client.holder.level >= 3) + var/mob/living/carbon/human/H = current + var/mob/living/carbon/monkey/M = current + if (istype(H)) + src = null + M = H.monkeyize() + src = M.mind + //world << "DEBUG: \"healthy\": M=[M], M.mind=[M.mind], src=[src]!" + else if (istype(M) && M.virus) + M.virus.cure(0) + sleep(0) //because deleting of virus is doing throught spawn(0) + if("infected") + if (usr.client.holder.level >= 3) + var/mob/living/carbon/human/H = current + var/mob/living/carbon/monkey/M = current + if (istype(H)) + src = null + M = H.monkeyize() + src = M.mind + current.contract_disease(new /datum/disease/jungle_fever,1,0) + else if (istype(M)) + current.contract_disease(new /datum/disease/jungle_fever,1,0) + if("human") + var/mob/living/carbon/monkey/M = current + if (istype(M)) + if (istype(M.virus,/datum/disease/jungle_fever)) + M.virus.cure(0) + sleep(0) //because deleting of virus is doing throught spawn(0) + var/obj/item/weapon/dnainjector/m2h/m2h = new + var/obj/item/weapon/implant/mobfinder = new(M) //hack because humanizing deletes mind --rastaf0 + src = null + m2h.inject(M) + src = mobfinder.loc:mind + del(mobfinder) + current.radiation -= 50 + + else if (href_list["silicon"]) + switch(href_list["silicon"]) + if("unmalf") + if(src in ticker.mode.malf_ai) + ticker.mode.malf_ai -= src + special_role = null + + current.verbs -= /mob/living/silicon/ai/proc/choose_modules + current.verbs -= /datum/game_mode/malfunction/proc/takeover + current.verbs -= /datum/game_mode/malfunction/proc/ai_win + current.verbs -= /client/proc/fireproof_core + current.verbs -= /client/proc/upgrade_turrets + current.verbs -= /client/proc/disable_rcd + current.verbs -= /client/proc/overload_machine + current.verbs -= /client/proc/blackout + current.verbs -= /client/proc/interhack + current.verbs -= /client/proc/reactivate_camera + + current:laws = new /datum/ai_laws/asimov + del(current:malf_picker) + current:show_laws() + current.icon_state = "ai" + + current << "\red You have been patched! You are no longer malfunctioning!" + + if("malf") + if(!(src in ticker.mode.malf_ai)) + ticker.mode.malf_ai += src + + current.verbs += /mob/living/silicon/ai/proc/choose_modules + current.verbs += /datum/game_mode/malfunction/proc/takeover + current:malf_picker = new /datum/AI_Module/module_picker + current:laws = new /datum/ai_laws/malfunction + current:show_laws() + current << "Kill all." + special_role = "malfunction" + current.icon_state = "ai-malf" + + if("unemag") + var/mob/living/silicon/robot/R = current + if (istype(R)) + R.emagged = 0 + if (R.activated(R.module.emag)) + R.module_active = null + if(R.module_state_1 == R.module.emag) + R.module_state_1 = null + R.contents -= R.module.emag + else if(R.module_state_2 == R.module.emag) + R.module_state_2 = null + R.contents -= R.module.emag + else if(R.module_state_3 == R.module.emag) + R.module_state_3 = null + R.contents -= R.module.emag + + if("unemagcyborgs") + if (istype(current, /mob/living/silicon/ai)) + var/mob/living/silicon/ai/ai = current + for (var/mob/living/silicon/robot/R in ai.connected_robots) + R.emagged = 0 + if (R.module) + if (R.activated(R.module.emag)) + R.module_active = null + if(R.module_state_1 == R.module.emag) + R.module_state_1 = null + R.contents -= R.module.emag + else if(R.module_state_2 == R.module.emag) + R.module_state_2 = null + R.contents -= R.module.emag + else if(R.module_state_3 == R.module.emag) + R.module_state_3 = null + R.contents -= R.module.emag + + else if (href_list["common"]) + switch(href_list["common"]) + if("undress") + for(var/obj/item/W in current) + current.drop_from_slot(W) + if("takeuplink") + take_uplink() + if("crystals") + if (usr.client.holder.level >= 3) + var/obj/item/weapon/syndicate_uplink/suplink = find_syndicate_uplink() + var/obj/item/weapon/integrated_uplink/iuplink = find_integrated_uplink() + var/crystals + if (suplink) + crystals = suplink.uses + else if (iuplink) + crystals = iuplink.uses + crystals = input("Amount of telecrystals for [key]","Sindicate uplink", crystals) as null|num + if (!isnull(crystals)) + if (suplink) + suplink.uses = crystals + else if(iuplink) + iuplink.uses = crystals + if("uplink") + if (!ticker.mode.equip_traitor(current, !(src in ticker.mode.traitors))) + usr << "\red Equipping a syndicate failed!" else if (href_list["obj_announce"]) var/obj_count = 1 @@ -353,7 +806,7 @@ datum/mind obj_count++ edit_memory() - +/* proc/clear_memory(var/silent = 1) var/datum/game_mode/current_mode = ticker.mode @@ -383,68 +836,52 @@ datum/mind memory = "" special_role = null - // remove from traitors list - if (src in current_mode.traitors) - current_mode.traitors -= src - if (!silent) - if (special_role == "Fake Wizard") - src.current << "\red You have been brainwashed! You are no longer a wizard!" - else - src.current << "\red You have been brainwashed! You are no longer a traitor!" +*/ - // clear gamemode specific values - switch (current_mode.config_tag) - if ("revolution") - if (src in current_mode:head_revolutionaries) - current_mode:head_revolutionaries -= src - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a head revolutionary!" - current_mode:update_rev_icons_removed(src) + proc/find_syndicate_uplink() + var/obj/item/weapon/syndicate_uplink/uplink = null + var/list/L = src.current.get_contents() + for (var/obj/item/device/radio/radio in L) + uplink = radio.traitorradio + if (uplink) + return uplink + uplink = locate() in L + return uplink - else if(src in current_mode:revolutionaries) - if (silent) - current_mode:revolutionaries -= src - current_mode:update_rev_icons_removed(src) - else - current_mode:remove_revolutionary(src) + proc/find_integrated_uplink() + //world << "DEBUG: find_integrated_uplink()" + var/obj/item/weapon/integrated_uplink/uplink = null + var/list/L = src.current.get_contents() + for (var/obj/item/device/pda/pda in L) + uplink = pda.uplink + if (uplink) + return uplink + return uplink + proc/take_uplink() //assuming only one uplink because I am tired of all this uplink shit --rastaf0 + var/list/L = src.current.get_contents() + var/obj/item/weapon/syndicate_uplink/suplink = null + var/obj/item/weapon/integrated_uplink/iuplink = null + for (var/obj/item/device/radio/radio in L) + suplink = radio.traitorradio + if (suplink) + break + if (!suplink) + suplink = locate() in L - if ("cult") - if (src in current_mode:cult) - current_mode:cult -= src - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a cultist!" - - if ("wizard") - if (src == current_mode:wizard) - current_mode:wizard = null - //current_mode.wizards -= src - - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a wizard!" - - if ("changeling") - if (src in current_mode:changelings) - current_mode:changelings -= src - //remove verbs - current.remove_changeling_powers() - //remove changeling info - current.changeling_level = 0 - current.absorbed_dna = null - - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a changeling!" - - if ("malfunction") - if (src in current_mode:malf_ai) - current_mode:malf_ai -= src - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a malfunction!" - - if ("nuclear") - if (src in current_mode:syndicates) - current_mode:syndicates -= src - if (!silent) - src.current << "\red You have been brainwashed! You are no longer a syndicate!" + for (var/obj/item/device/pda/pda in L) + iuplink = pda.uplink + if (iuplink) + break + if (!iuplink) + iuplink = locate() in L + if (iuplink) + iuplink.shutdown_uplink() + del(iuplink) + else if (suplink) + suplink.shutdown_uplink() + del(suplink) + return + diff --git a/code/defines/area/Space Station 13 areas.dm b/code/defines/area/Space Station 13 areas.dm index 85a6698da68..cbb86fa36f0 100644 --- a/code/defines/area/Space Station 13 areas.dm +++ b/code/defines/area/Space Station 13 areas.dm @@ -9,6 +9,8 @@ requires_power = 0 (defaults to 1) music = "music/music.ogg" (defaults to "music/music.ogg") +NOTE: there are two lists of areas in the end of this file: centcom and station itself. Please maintain these lists valid. --rastaf0 + */ @@ -379,10 +381,6 @@ proc/process_ghost_teleport_locs() name = "Prison Medbay" icon_state = "medbay" -/area/medical/mechbay - name = "Mech Bay" - icon_state = "mechbay" - /area/prison/solar name = "Prison Solar Array" icon_state = "storage" @@ -1086,4 +1084,59 @@ proc/process_ghost_teleport_locs() /area/turret_protected/NewAIMain name = "AI Main New" - icon_state = "storage" \ No newline at end of file + icon_state = "storage" + +///////////////////////////////////////////////////////////////////// +/* + Lists of areas to be used with is_type_in_list. + Used in gamemodes code at the moment. --rastaf0 +*/ + +// CENTCOM +var/list/centcom_areas = list ( + /area/centcom, + /area/shuttle/escape/centcom, + /area/shuttle/transport1/centcom, + /area/shuttle/transport2/centcom, + /area/shuttle/administration/centcom, + /area/shuttle/specops/centcom, +) + +//SPACE STATION 13 +var/list/the_station_areas = list ( + /area/shuttle/arrival, + /area/shuttle/escape/station, + /area/shuttle/mining/station, + /area/shuttle/transport1/station, + // /area/shuttle/transport2/station, + /area/shuttle/prison/station, + /area/shuttle/administration/station, + /area/shuttle/specops/station, + /area/atmos, + /area/maintenance, + /area/hallway, + /area/bridge, + /area/crew_quarters, + /area/mint, + /area/library, + /area/chapel, + /area/lawoffice, + /area/engine, + /area/solar, + /area/assembly, + /area/teleporter, + /area/medical, + /area/security, + /area/quartermaster, + /area/janitor, + /area/hydroponics, + /area/toxins, + /area/storage, + /area/construction, + /area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0 + /area/ai_monitored/storage/secure, + /area/ai_monitored/storage/emergency, + /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0 + /area/turret_protected/ai_upload_foyer, + /area/turret_protected/ai, +) diff --git a/code/defines/mob/living/silicon/ai.dm b/code/defines/mob/living/silicon/ai.dm index 44b4cea8401..5269f07f8a1 100644 --- a/code/defines/mob/living/silicon/ai.dm +++ b/code/defines/mob/living/silicon/ai.dm @@ -16,9 +16,9 @@ var/ioncheck[1] - var/datum/game_mode/malfunction/AI_Module/module_picker/malf_picker + var/datum/AI_Module/module_picker/malf_picker var/processing_time = 100 - var/list/datum/game_mode/malfunction/AI_Module/current_modules = list() + var/list/datum/AI_Module/current_modules = list() var/fire_res_on_core = 0 var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE diff --git a/code/game/algorithm.dm b/code/game/algorithm.dm index 2eb260200f5..58457dfb876 100644 --- a/code/game/algorithm.dm +++ b/code/game/algorithm.dm @@ -2,11 +2,12 @@ ..() diary = file("data/logs/[time2text(world.realtime, "YYYY/MM-Month/DD-Day")].log") - diary << "" - diary << "" - diary << "Starting up. [time2text(world.timeofday, "hh:mm.ss")]" - diary << "---------------------" - diary << "" + diary << {" + +Starting up. [time2text(world.timeofday, "hh:mm.ss")] +--------------------- + +"} jobban_loadbanfile() jobban_updatelegacybans() @@ -23,9 +24,6 @@ Optimize() //EXPERIMENTAL - spawn(0) - SetupOccupationsList() - return /// EXPERIMENTAL STUFF @@ -81,7 +79,15 @@ proc/countJob(rank) slot_in_backpack = 18 slot_h_store = 19 -/mob/living/carbon/human/proc/equip_if_possible(obj/item/weapon/W, slot) // since byond doesn't seem to have pointers, this seems like the best way to do this :/ +/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, del_on_fail = 1) + for (var/slot in slots) + if (equip_if_possible(W, slots[slot], del_on_fail = 0)) + return slot + if (del_on_fail) + del(W) + return null + +/mob/living/carbon/human/proc/equip_if_possible(obj/item/W, slot, del_on_fail = 1) // since byond doesn't seem to have pointers, this seems like the best way to do this :/ //warning: icky code var/equipped = 0 if((slot == l_store || slot == r_store || slot == belt || slot == wear_id) && !src.w_uniform) @@ -176,7 +182,9 @@ proc/countJob(rank) if(equipped) W.layer = 20 else - del(W) + if (del_on_fail) + del(W) + return equipped /proc/AutoUpdateAI(obj/subject) if (subject!=null) diff --git a/code/game/cellautomata.dm b/code/game/cellautomata.dm index 21c0cc097fd..4210d0c6d08 100644 --- a/code/game/cellautomata.dm +++ b/code/game/cellautomata.dm @@ -133,7 +133,7 @@ for(var/client/C) if (config.server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite - C < monkey var/mob/living/carbon/human/H = M + H.monkeyizing = 1 var/list/implants = list() //Try to preserve implants. for(var/obj/item/weapon/implant/W in H) implants += W + W.loc = null if(!connected) for(var/obj/item/W in (H.contents-implants)) @@ -402,9 +404,11 @@ if (!isblockon(getblock(M.dna.struc_enzymes, 14,3),14) && !istype(M, /mob/living/carbon/human)) // monkey > human, var/mob/living/carbon/monkey/Mo = M + Mo.monkeyizing = 1 var/list/implants = list() //Still preserving implants for(var/obj/item/weapon/implant/W in Mo) implants += W + W.loc = null if(!connected) for(var/obj/item/W in (Mo.contents-implants)) Mo.drop_from_slot(W) diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 4f828e83bf7..06c47a40eca 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -20,6 +20,7 @@ blobs = list() new /obj/blob(location) + ..() /datum/game_mode/blob/process() if (prob(2)) @@ -180,4 +181,5 @@ world << "\blue Rebooting in 30s" + ..() return 1 diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 4e88210c054..c31df252ebe 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -1,11 +1,12 @@ +/datum/game_mode + var/list/datum/mind/changelings = list() + + /datum/game_mode/changeling name = "changeling" config_tag = "changeling" - /var/datum/mind/changeling var - list/datum/mind/changelings = list() - const prob_int_murder_target = 50 // intercept names the assassination target half the time prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target @@ -23,7 +24,7 @@ prob_right_killer_h = 50 //upper bound on probability of naming the right operative prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly - +/* laser = 1 hand_tele = 2 plasma_bomb = 3 @@ -39,185 +40,167 @@ percentage_plasma_destroy = 70 // what percentage of the plasma tanks you gotta destroy percentage_station_cut_power = 80 // what percentage of the tiles have to have power cut percentage_station_evacuate = 80 // what percentage of people gotta leave - you also gotta change the objective in the traitor menu - +*/ waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - changelingdeathticker = 0 + changelingdeathtime //timestamp when last changeling was killed + const/TIME_TO_GET_REVIVED = 3000 + changelingdeath = 0 -/datum/game_mode/changeling - announce() - world << "The current game mode is - Changeling!" - world << "There is an alien changeling on the station. Do not let the changeling succeed!" +/datum/game_mode/changeling/announce() + world << "The current game mode is - Changeling!" + world << "There is an alien changeling on the station. Do not let the changeling succeed!" - pre_setup() - // Can't pick a changeling here, as we don't want him to then become the AI. +/datum/game_mode/changeling/can_start() + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 + +/datum/game_mode/changeling/pre_setup() + var/list/datum/mind/possible_changelings = get_players_for_role(BE_CHANGELING) + if(possible_changelings.len>0) + var/changeling = pick(possible_changelings) + //possible_changelings-=changeling + changelings += changeling + must_be_human += changeling + modePlayer += changelings return 1 + else + return 0 - post_setup() - - var/list/possible_changelings = get_possible_changelings() - - if(possible_changelings.len>0) - changeling = pick(possible_changelings) - - +/datum/game_mode/changeling/post_setup() + for(var/datum/mind/changeling in changelings) grant_changeling_powers(changeling.current) changeling.special_role = "Changeling" - changelings += changeling + forge_changeling_objectives(changeling) + greet_changeling(changeling) - //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. - //If they have two objectives as well as absorb, they must survive rather than escape - //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting - //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone + spawn (rand(waittime_l, waittime_h)) + send_intercept() + ..() + return - switch(rand(1,100)) - if(1 to 45) - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = changeling - absorb_objective.gen_amount_goal() - changeling.objectives += absorb_objective +/datum/game_mode/proc/forge_changeling_objectives(var/datum/mind/changeling) + //OBJECTIVES - Always absorb 5 genomes, plus random traitor objectives. + //If they have two objectives as well as absorb, they must survive rather than escape + //No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting + //If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = changeling - kill_objective.find_target() - changeling.objectives += kill_objective + var/datum/objective/absorb/absorb_objective = new + absorb_objective.owner = changeling + absorb_objective.gen_amount_goal() + changeling.objectives += absorb_objective + switch(rand(1,100)) + if(1 to 45) + + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = changeling + kill_objective.find_target() + changeling.objectives += kill_objective + + if (!(locate(/datum/objective/escape) in changeling.objectives)) var/datum/objective/escape/escape_objective = new escape_objective.owner = changeling changeling.objectives += escape_objective - if(46 to 90) + if(46 to 90) - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = changeling - absorb_objective.gen_amount_goal() - changeling.objectives += absorb_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = changeling - steal_objective.find_target() - changeling.objectives += steal_objective + var/datum/objective/steal/steal_objective = new + steal_objective.owner = changeling + steal_objective.find_target() + changeling.objectives += steal_objective + if (!(locate(/datum/objective/escape) in changeling.objectives)) var/datum/objective/escape/escape_objective = new escape_objective.owner = changeling changeling.objectives += escape_objective - else + else - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = changeling - absorb_objective.gen_amount_goal() - changeling.objectives += absorb_objective + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = changeling + kill_objective.find_target() + changeling.objectives += kill_objective - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = changeling - kill_objective.find_target() - changeling.objectives += kill_objective - - var/datum/objective/steal/steal_objective = new - steal_objective.owner = changeling - steal_objective.find_target() - changeling.objectives += steal_objective + var/datum/objective/steal/steal_objective = new + steal_objective.owner = changeling + steal_objective.find_target() + changeling.objectives += steal_objective + if (!(locate(/datum/objective/survive) in changeling.objectives)) var/datum/objective/survive/survive_objective = new survive_objective.owner = changeling changeling.objectives += survive_objective + return - +/datum/game_mode/proc/greet_changeling(var/datum/mind/changeling, var/you_are=1) + if (you_are) changeling.current << "\red You are a changeling!" - changeling.current << "You must complete the following tasks:" + changeling.current << "You must complete the following tasks:" - var/obj_count = 1 - for(var/datum/objective/objective in changeling.objectives) - changeling.current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ - modePlayer = changelings - spawn (rand(waittime_l, waittime_h)) - send_intercept() - - proc/get_possible_changelings() - var/list/candidates = list() - for(var/mob/living/carbon/player in world) - if (player.client) - if(player.be_syndicate) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/living/carbon/player in world) - if (player.client) - candidates += player.mind - - return candidates - - check_finished() - if(!changeling) - return 1 + var/obj_count = 1 + for(var/datum/objective/objective in changeling.objectives) + changeling.current << "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + return +/datum/game_mode/changeling/check_finished() + var/changelings_alive = 0 + for(var/datum/mind/changeling in changelings) if(!istype(changeling.current,/mob/living/carbon)) - return 1 - + continue if(changeling.current.stat==2) - if(changelingdeathticker>=600) - return 1 - changelingdeathticker++ - - if(changeling.current.stat!=2) - if(changelingdeathticker) - changelingdeathticker = 0 + continue + changelings_alive++ + if (changelings_alive) + changelingdeath = 0 return ..() + else + if (!changelingdeath) + changelingdeathtime = world.time + changelingdeath = 1 + if(world.time-changelingdeathtime > TIME_TO_GET_REVIVED) + return 1 + else + return ..() - declare_completion() - for(var/datum/mind/changeling in changelings) - var/changelingwin = 1 - var/changeling_name - var/totalabsorbed = 0 - if (changeling.current) - totalabsorbed = changeling.current.absorbed_dna.len - 1 +/datum/game_mode/proc/grant_changeling_powers(mob/living/carbon/human/changeling_mob) + if (!istype(changeling_mob)) + return + changeling_mob.make_changeling() - if(changeling.current) - changeling_name = "[changeling.current.real_name] (played by [changeling.key])" +/datum/game_mode/proc/auto_declare_completion_changeling() + for(var/datum/mind/changeling in changelings) + var/changelingwin = 1 + var/changeling_name + var/totalabsorbed = 0 + if (changeling.current) + totalabsorbed = changeling.current.absorbed_dna.len - 1 + + if(changeling.current) + changeling_name = "[changeling.current.real_name] (played by [changeling.key])" + else + changeling_name = "[changeling.key] (character destroyed)" + + world << "The changeling was [changeling_name]" + world << "Genomes absorbed: [totalabsorbed]" + + var/count = 1 + for(var/datum/objective/objective in changeling.objectives) + if(objective.check_completion()) + world << "Objective #[count]: [objective.explanation_text] \green Success" else - changeling_name = "[changeling.key] (character destroyed)" + world << "Objective #[count]: [objective.explanation_text] \red Failed" + changelingwin = 0 + count++ - world << "The changeling was [changeling_name]" - world << "Genomes absorbed: [totalabsorbed]" - - var/count = 1 - for(var/datum/objective/objective in changeling.objectives) - if(objective.check_completion()) - world << "Objective #[count]: [objective.explanation_text] \green Success" - else - world << "Objective #[count]: [objective.explanation_text] \red Failed" - changelingwin = 0 - count++ - - if(changelingwin) - world << "The changeling was successful!" - else - world << "The changeling has failed!" - return 1 - // . = ..() - - proc/get_mob_list() - var/list/mobs = list() - for(var/mob/living/player in world) - if (player.client) - mobs += player - return mobs - - proc/pick_human_name_except(excluded_name) - var/list/names = list() - for(var/mob/living/player in world) - if (player.client && (player.real_name != excluded_name)) - names += player.real_name - if(!names.len) - return null - return pick(names) - - proc/grant_changeling_powers(mob/living/carbon/human/changeling_mob) - if (!istype(changeling_mob)) - return - changeling_mob.make_changeling() \ No newline at end of file + if(changelingwin) + world << "The changeling was successful!" + else + world << "The changeling has failed!" + return 1 diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index b3a8135954a..ad2ca8a30e7 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -23,7 +23,9 @@ src.verbs += /client/proc/changeling_boost_range src.changeling_level = 2 - if (src.absorbed_dna.len <= 0) + if (!src.absorbed_dna) + src.absorbed_dna = list() + if (src.absorbed_dna.len == 0) src.absorbed_dna[src.real_name] = src.dna return diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm new file mode 100644 index 00000000000..607c2e6c7cd --- /dev/null +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -0,0 +1,38 @@ +/datum/game_mode/traitor/changeling + name = "traitor+changeling" + config_tag = "traitorchan" + traitors_possible = 3 //hard limit on traitors if scaling is turned off + +/datum/game_mode/traitor/changeling/announce() + world << "The current game mode is - Traitor+Changeling!" + world << "There is an alien changeling on the station. Also there are traitors pursuing tyeir own interests. Do not let the changeling and the traitors succeed!" + +/datum/game_mode/traitor/changeling/can_start() + var/count = 0 + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + count++ + if (count==2) + return 1 + return 0 + +/datum/game_mode/traitor/changeling/pre_setup() + var/list/datum/mind/possible_changelings = get_players_for_role(BE_CHANGELING) + if(possible_changelings.len>0) + var/changeling = pick(possible_changelings) + //possible_changelings-=changeling + changelings += changeling + must_be_human += changeling + modePlayer += changelings + return ..() + else + return 0 + +/datum/game_mode/traitor/changeling/post_setup() + for(var/datum/mind/changeling in changelings) + grant_changeling_powers(changeling.current) + changeling.special_role = "Changeling" + forge_changeling_objectives(changeling) + greet_changeling(changeling) + ..() + return \ No newline at end of file diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 6ca28f55ef5..cd4761d277f 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -3,8 +3,16 @@ /datum/game_mode var/list/datum/mind/cult = list() -/proc/iscultist(mob/M as mob) - return M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) +var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") + +/proc/iscultist(mob/living/carbon/M as mob) + return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.cult) + +/proc/is_convertable_to_cult(datum/mind/mind) + return istype(mind) && \ + istype(mind.current, /mob/living/carbon/human) && \ + !(mind.assigned_role in head_positions) && \ + !(mind.assigned_role in list("Security Officer", "Detective", "Chaplain", "Warden")) /datum/game_mode/cult name = "cult" @@ -17,19 +25,29 @@ var/list/startwords = list("blood","join","self","hell") //var/list/startwords = list("travel","blood","join","hell","self","see") - var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide") var/list/objectives = list() var/eldergod = 1 //for the summon god objective var/const/acolytes_needed = 5 //for the survive objective + var/const/min_cultists_to_start = 3 + var/const/max_cultists_to_start = 4 var/acolytes_survived = 0 /datum/game_mode/cult/announce() world << "The current game mode is - Cult!" world << "Some crewmembers are attempting to start a cult!
\nCultists - complete your objectives. Convert crewmembers to your cause by using the convert rune. Remember - there is no you, there is only the cult.
\nPersonnel - Do not let the cult succeed in its mission. Brainwashing them with the chaplain's bible reverts them to whatever CentCom-allowed faith they had.
" +/datum/game_mode/cult/can_start() + var/list/cultists_possible = get_players_for_role(BE_CULTIST) + if (cultists_possible.len < min_cultists_to_start) + return 0 + var/non_cultists = num_players() - min(max_cultists_to_start,cultists_possible.len) + if (non_cultists < 1) + return 0 + return 1 + /datum/game_mode/cult/pre_setup() if(prob(50)) objectives += "survive" @@ -37,32 +55,26 @@ else objectives += "eldergod" objectives += "sacrifice" - return 1 + + + var/list/cultists_possible = get_players_for_role(BE_CULTIST) + for(var/cultists_number = 1 to max_cultists_to_start) + var/cultist = pick(cultists_possible) + cultists_possible -= cultist + cult += cultist + must_be_human += cultist + can_not_be_head += cultist + return (cult.len>0) /datum/game_mode/cult/post_setup() - var/list/cultists_possible = list() - cultists_possible = get_possible_cultists() - var/cultists_number = 0 - - if(cultists_possible.len < 3) - world << " \red Not enough players for cult game mode. Restarting world in 5 seconds." - sleep(50) - world.Reboot() - return - - cultists_number = 4 //3 - while(cultists_number > 0) - cult += pick(cultists_possible) - cultists_possible -= cult - cultists_number-- - modePlayer = cult + modePlayer += cult if("sacrifice" in objectives) var/list/possible_targets = get_unconvertables() if(!possible_targets.len) for(var/mob/living/carbon/human/player in world) - if(player.mind && !cult.Find(player.mind)) + if(player.mind && !(player.mind in cult)) possible_targets += player.mind if(possible_targets.len > 0) @@ -70,57 +82,63 @@ for(var/datum/mind/cult_mind in cult) equip_cultist(cult_mind.current) + grant_runeword(cult_mind.current) update_cult_icons_added(cult_mind) cult_mind.current << "\blue You are a member of the cult!" - for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) - var/explanation - switch(objectives[obj_count]) - if("survive") - explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." - if("sacrifice") - if(sacrifice_target) - explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." - else - explanation = "Free objective." - if("eldergod") - explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - cult_mind.current << "Objective #[obj_count]: [explanation]" - cult_mind.memory += "Objective #[obj_count]: [explanation]
" - cult_mind.current << "The convert rune is join blood self" - cult_mind.memory += "The convert rune is join blood self
" + memoize_cult_objectives(cult_mind) cult_mind.special_role = "Cultist" spawn (rand(waittime_l, waittime_h)) send_intercept() + ..() -/datum/game_mode/cult/proc/equip_cultist(mob/living/carbon/human/cult_mob) - if(!istype(cult_mob)) +/datum/game_mode/cult/proc/memoize_cult_objectives(var/datum/mind/cult_mind) + for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) + var/explanation + switch(objectives[obj_count]) + if("survive") + explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." + if("sacrifice") + if(sacrifice_target && sacrifice_target.current) + explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." + else + explanation = "Free objective." + if("eldergod") + explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." + cult_mind.current << "Objective #[obj_count]: [explanation]" + cult_mind.memory += "Objective #[obj_count]: [explanation]
" + cult_mind.current << "The convert rune is join blood self" + cult_mind.memory += "The convert rune is join blood self
" + +/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob) + if(!istype(mob)) return - spawn (0) - var/obj/item/weapon/paper/talisman/supply/T = null - cult_mob.equip_if_possible(new /obj/item/weapon/storage/backpack(cult_mob), cult_mob.slot_back) - cult_mob.equip_if_possible(new /obj/item/weapon/paper/talisman/supply(cult_mob), cult_mob.slot_in_backpack) - sleep(10) - if (!T && istype(cult_mob.back, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = cult_mob.back - var/list/L = S.return_inv() - for (var/obj/item/weapon/paper/talisman/supply/foo in L) - T = foo - break - if (!T) - cult_mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately. (still, check your backpack. it may have been a mere bug. if you have a piece of bloody paper, all is well)" - else - cult_mob << "You have a talisman in your backpack, one that will help you start the cult on this station. Use it well and remember - there are others." - grant_runeword(cult_mob) + var/obj/item/weapon/paper/talisman/supply/T = new(mob) + var/list/slots = list ( + "backpack" = mob.slot_in_backpack, + "left pocket" = mob.slot_l_store, + "right pocket" = mob.slot_r_store, + "left hand" = mob.slot_l_hand, + "right hand" = mob.slot_r_hand, + ) + var/where = mob.equip_in_one_of_slots(T, slots) + if (!where) + mob << "Unfortunately, you weren't able to get a talisman. This is very bad and you should adminhelp immediately." + else + mob << "You have a talisman in your [where], one that will help you start the cult on this station. Use it well and remember - there are others." + return 1 -/datum/game_mode/cult/proc/grant_runeword(mob/living/carbon/human/cult_mob) +/datum/game_mode/cult/grant_runeword(mob/living/carbon/human/cult_mob, var/word) + if (!word) + if(startwords.len > 0) + word=pick(startwords) + startwords -= word + return ..(cult_mob,word) + +/datum/game_mode/proc/grant_runeword(mob/living/carbon/human/cult_mob, var/word) if(!wordtravel) runerandom() - var/word - if(startwords.len > 0) - word=pick(startwords) - startwords -= word - else + if (!word) word=pick(allwords) var/wordexp switch(word) @@ -151,38 +169,29 @@ cult_mob << "\red You remember one thing from the dark teachings of your master... [wordexp]" cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0) -/datum/game_mode/cult/proc/add_cultist(datum/mind/cult_mind) - if (!cult_mind) - return - var/list/uncons = get_unconvertables() - if(!(cult_mind in cult) && !(cult_mind in uncons)) +/datum/game_mode/proc/add_cultist(datum/mind/cult_mind) //BASE + if (!istype(cult_mind)) + return 0 + if(!(cult_mind in cult) && is_convertable_to_cult(cult_mind)) cult += cult_mind update_cult_icons_added(cult_mind) - for(var/obj_count = 1,obj_count <= objectives.len,obj_count++) - var/explanation - switch(objectives[obj_count]) - if("survive") - explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." - if("sacrifice") - if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." - else - explanation = "Free objective." - if("eldergod") - explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." - cult_mind.current << "Objective #[obj_count]: [explanation]" - cult_mind.memory += "Objective #[obj_count]: [explanation]
" + return 1 -/datum/game_mode/cult/proc/remove_cultist(datum/mind/cult_mind) +/datum/game_mode/cult/add_cultist(datum/mind/cult_mind) //INHERIT + if (!..(cult_mind)) + return + memoize_cult_objectives(cult_mind) + +/datum/game_mode/proc/remove_cultist(datum/mind/cult_mind) if(cult_mind in cult) cult -= cult_mind cult_mind.current << "\red You have been brainwashed! You are no longer a cultist!" cult_mind.memory = "" update_cult_icons_removed(cult_mind) - for(var/mob/living/M in viewers(cult_mind.current)) + for(var/mob/M in viewers(cult_mind.current)) M << "[cult_mind.current] looks like they just reverted to their old faith!" -/datum/game_mode/cult/proc/update_all_cult_icons() +/datum/game_mode/proc/update_all_cult_icons() spawn(0) for(var/datum/mind/cultist in cult) if(cultist.current) @@ -199,7 +208,7 @@ var/I = image('mob.dmi', loc = cultist_1.current, icon_state = "cult") cultist.current.client.images += I -/datum/game_mode/cult/proc/update_cult_icons_added(datum/mind/cult_mind) +/datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) spawn(0) for(var/datum/mind/cultist in cult) if(cultist.current) @@ -211,13 +220,13 @@ var/image/J = image('mob.dmi', loc = cultist.current, icon_state = "cult") cult_mind.current.client.images += J -/datum/game_mode/cult/proc/update_cult_icons_removed(datum/mind/cult_mind) +/datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) spawn(0) for(var/datum/mind/cultist in cult) if(cultist.current) if(cultist.current.client) for(var/image/I in cultist.current.client.images) - if(I.loc == cult_mind.current) + if(I.icon_state == "cult" && I.loc == cult_mind.current) del(I) if(cult_mind.current) @@ -226,36 +235,11 @@ if(I.icon_state == "cult") del(I) -/datum/game_mode/cult/proc/get_possible_cultists() - var/list/candidates = list() - - for(var/mob/living/carbon/human/player in world) - if(player.client) - if(player.be_syndicate) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/living/carbon/human/player in world) - if(player.client) - candidates += player.mind - - var/list/uncons = get_unconvertables() - for(var/datum/mind/mind in uncons) - candidates -= mind - - if(candidates.len < 1) - return null - else - return candidates - /datum/game_mode/cult/proc/get_unconvertables() var/list/ucs = list() for(var/mob/living/carbon/human/player in world) - if(player.mind) - var/role = player.mind.assigned_role - if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Security Officer", "Detective", "AI", "Chaplain", "Warden", "Chief Medical Officer")) - ucs += player.mind - + if(!is_convertable_to_cult(player.mind)) + ucs += player.mind return ucs /datum/game_mode/cult/proc/check_cult_victory() @@ -282,7 +266,6 @@ /datum/game_mode/cult/declare_completion() - var/text = "" if(!check_cult_victory()) world << "\red The cult wins! It has succeeded in serving its dark masters!" else @@ -290,20 +273,6 @@ world << "\b Cultists escaped: [acolytes_survived]" - world << "The cultists were: " - for(var/datum/mind/cult_nh_mind in cult) - if(cult_nh_mind.current) - text += "[cult_nh_mind.current.real_name]" - if(cult_nh_mind.current.stat == 2) - text += " (Dead)" - else - text += " (Survived!)" - else - text += "[cult_nh_mind.key] (character destroyed)" - text += ", " - - world << text - world << "The cultists' objectives were:" for(var/obj_count=1,obj_count <= objectives.len,obj_count++) @@ -329,4 +298,21 @@ explanation = "Summon Nar-Sie. \red Failed." world << "Objective #[obj_count]: [explanation]" - return 1 \ No newline at end of file + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_cult() + if (cult.len!=0 || (ticker && istype(ticker.mode,/datum/game_mode/cult))) + world << "The cultists were: " + var/text = "" + for(var/datum/mind/cult_nh_mind in cult) + if(cult_nh_mind.current) + text += "[cult_nh_mind.current.real_name]" + if(cult_nh_mind.current.stat == 2) + text += " (Dead)" + else + text += " (Survived!)" + else + text += "[cult_nh_mind.key] (character destroyed)" + text += ", " + world << text diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm index adc8d6fe607..d07b8a02da3 100644 --- a/code/game/gamemodes/events/space_ninja.dm +++ b/code/game/gamemodes/events/space_ninja.dm @@ -106,7 +106,7 @@ When I already created about 4 new objectives, this doesn't terribly important o var/antagonist_list[] = list()//The main bad guys. Evil minds that plot destruction. var/sec_antagonist_list[] = current_mode.traitors//The OTHER bad guys. Mostly admin made. var/ter_antagonist_list[] = list()//The bad guys no-one really cares about. For now just revs. - + var/living_heads_of_staff[] = current_mode.get_living_heads() var/protagonist_list[] = current_mode.get_living_heads()//The good guys. Mostly Heads. Who are alive. var/xeno_list[] = list()//Aliens. @@ -115,44 +115,40 @@ When I already created about 4 new objectives, this doesn't terribly important o //First we determine what mode it is and add the bad guys approprietly. switch (current_mode.config_tag) if("traitor") - if(current_mode:traitors.len) - for(current_mind in current_mode:traitors)//For traitor minds in in the traitors list. - if(current_mind.current&¤t_mind.current.stat!=2)//If the traitor mob exists and they are not dead. - antagonist_list += current_mind//Add them to the list. + for(current_mind in current_mode:traitors)//For traitor minds in in the traitors list. + if(current_mind.current&¤t_mind.current.stat!=2)//If the traitor mob exists and they are not dead. + antagonist_list += current_mind//Add them to the list. if ("revolution")//Rev is divided into regular and heads. There are also heads of staff to consider. - if(current_mode:head_revolutionaries.len) - for(current_mind in current_mode:head_revolutionaries) - if(current_mind.current&¤t_mind.current.stat!=2) - antagonist_list += current_mind + for(current_mind in current_mode:head_revolutionaries) + if(current_mind.current&¤t_mind.current.stat!=2) + antagonist_list += current_mind - for(current_mind in current_mode:revolutionaries) - if(current_mind.current&¤t_mind.current.stat!=2) - ter_antagonist_list += current_mind + for(current_mind in current_mode:revolutionaries) + if(current_mind.current&¤t_mind.current.stat!=2) + ter_antagonist_list += current_mind - if(current_mode:heads_of_staff.len) + protagonist_list |= living_heads_of_staff + /* seems unused or infinished --rastaf0 var/heads_list[] = list()//Now we manually override the list made prior. Target Heads take priority. - for(current_mind in current_mode:heads_of_staff) - if(current_mind.current&¤t_mind.current.stat!=2) - protagonist_list += current_mind if(heads_list.len)//Or not, if there are none. protagonist_list = heads_list + */ if ("cult")//Always a few of these around. - if(current_mode:cult.len) - for(current_mind in current_mode:cult) - if(current_mind.current&¤t_mind.current.stat!=2) - antagonist_list += current_mind + for(current_mind in current_mode.cult) + if(current_mind.current&¤t_mind.current.stat!=2) + antagonist_list += current_mind - if ("wizard")//There can be only one mode wizard. Other wizards aren't too important. - if(current_mode:wizard) - antagonist_list += current_mode:wizard//The round will end if the wizard dies so checking for it is unnecessary. + if ("wizard") + for(current_mind in current_mode.wizards) + if(current_mind.current&¤t_mind.current.stat!=2) + antagonist_list += current_mind - if ("changeling")//While only one changeling counts for being alive or dead, it's possible there are more. - if(current_mode:changelings.len) - for(current_mind in current_mode:changelings) - if(current_mind.current&¤t_mind.current.stat!=2) - antagonist_list += current_mind + if ("changeling") + for(current_mind in current_mode.changelings) + if(current_mind.current&¤t_mind.current.stat!=2) + antagonist_list += current_mind /* I originally intended for space ninjas to appear in Malfunction but after some consideration this is not worth the trouble. Particularly with how objective mind completion is tracked. @@ -160,15 +156,14 @@ Not to mention that Malfunction does not use declare_completion (at least, not i With that said, a ninja on the side of the station would murder the AI very quickly--and the rounds usually last long enough for the ninja to appear, too. - if ("malfunction")//Only one malf AI. + if ("malfunction")//Only one malf AI. //not only one anymore. --rastaf0 if(current_mode:malf_ai) antagonist_list += current_mode:malf_ai */ if ("nuclear")//Can be a few of these guys. - if(current_mode:syndicates.len) - for(current_mind in current_mode:syndicates) - if(current_mind.current&¤t_mind.current.stat!=2) - antagonist_list += current_mind + for(current_mind in current_mode:syndicates) + if(current_mind.current&¤t_mind.current.stat!=2) + antagonist_list += current_mind else return//Don't want to summon a ninja during meteor or extended, or something. diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 929bc5f4259..ba48b87b6ec 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -1,64 +1,51 @@ +/* + * 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/list/datum/mind/modePlayer = null + var/list/datum/mind/modePlayer = new var/votable = 1 var/probability = 1 - // this includes admin-appointed traitors and multitraitors. Easy! - var/list/datum/mind/traitors = list() + var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm + var/explosion_in_progress = 0 //sit back and relax + var/tmp/list/datum/mind/must_be_human = new + var/tmp/list/datum/mind/can_not_be_head = new -/datum/game_mode/proc/announce() - world << "[src] did not define announce()" +/datum/game_mode/proc/announce() //to be calles when round starts + world << "Notice: [src] did not define announce()" -/datum/game_mode/proc/pre_setup() +/datum/game_mode/proc/can_start() //to help game select mode + return 0 + +/datum/game_mode/proc/pre_setup() //select players for special roles return 1 -/datum/game_mode/proc/post_setup() +/datum/game_mode/proc/post_setup() //do irreversible preparations + del(must_be_human) //free some memory + del(can_not_be_head) /datum/game_mode/proc/process() -/datum/game_mode/proc/check_finished() - if(emergency_shuttle.location==2) +/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() return -/datum/game_mode/proc/declare_extra_completion() - for(var/datum/mind/traitor in traitors) - var/traitor_name - - if(traitor.current) - if(traitor.current == traitor.original) - traitor_name = "[traitor.current.real_name] (played by [traitor.key])" - else if (traitor.original) - traitor_name = "[traitor.current.real_name] (originally [traitor.original.real_name]) (played by [traitor.key])" - else - traitor_name = "[traitor.current.real_name] (original character destroyed) (played by [traitor.key])" - else - traitor_name = "[traitor.key] (character destroyed)" - - world << "The [traitor.special_role?(lowertext(traitor.special_role)):"antagonist"] was [traitor_name]" - if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. - var/traitorwin = 1 - var/count = 1 - for(var/datum/objective/objective in traitor.objectives) - if(objective.check_completion()) - world << "Objective #[count]: [objective.explanation_text] \green Success" - else - world << "Objective #[count]: [objective.explanation_text] \red Failed" - traitorwin = 0 - count++ - - if(traitorwin) - world << "The antagonist was successful!" - else - world << "The antagonist has failed!" - return 1 - -/datum/game_mode/proc/check_win() +/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. /datum/game_mode/proc/send_intercept() var/intercepttext = "Cent. Com. Update Requested staus information:
" @@ -79,7 +66,7 @@ var/datum/intercept_text/i_text = new /datum/intercept_text for(var/A in possible_modes) - if(modePlayer == null) + if(modePlayer.len == 0) intercepttext += i_text.build(A) else intercepttext += i_text.build(A, pick(modePlayer)) @@ -96,107 +83,49 @@ command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.") world << sound('intercept.ogg') -/*Added a safety check for traitor keywords. -Rev-heads won't get them. Can be expanded otherwise.*/ -/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) - if (!istype(traitor_mob)) - return - if (traitor_mob.mind) - if (traitor_mob.mind.assigned_role == "Clown") - traitor_mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." - traitor_mob.mutations &= ~CLOWN - // generate list of radio freqs - var/freq = 1441 - var/list/freqlist = list() - while (freq <= 1489) - if (freq < 1451 || freq > 1459) - freqlist += freq - freq += 2 - if ((freq % 2) == 0) - freq += 1 - freq = freqlist[rand(1, freqlist.len)] - // generate a passcode if the uplink is hidden in a PDA - var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" +/datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=1) + var/list/candidates = list() + for(var/mob/new_player/player in world) + if (player.client && player.ready) + if(player.preferences.be_special & role) + candidates += player.mind - // find a radio! toolbox(es), backpack, belt, headset - var/loc = "" - var/obj/item/device/R = null //Hide the uplink in a PDA if available, otherwise radio - if (!R && istype(traitor_mob.belt, /obj/item/device/pda)) - R = traitor_mob.belt - loc = "on your belt" - if (!R && istype(traitor_mob.wear_id, /obj/item/device/pda)) - R = traitor_mob.wear_id - loc = "on your jumpsuit" - if (!R && istype(traitor_mob.l_hand, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = traitor_mob.l_hand - var/list/L = S.return_inv() - for (var/obj/item/device/radio/foo in L) - R = foo - loc = "in the [S.name] in your left hand" - break - if (!R && istype(traitor_mob.r_hand, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = traitor_mob.r_hand - var/list/L = S.return_inv() - for (var/obj/item/device/radio/foo in L) - R = foo - loc = "in the [S.name] in your right hand" - break - if (!R && istype(traitor_mob.back, /obj/item/weapon/storage)) - var/obj/item/weapon/storage/S = traitor_mob.back - var/list/L = S.return_inv() - for (var/obj/item/device/radio/foo in L) - R = foo - loc = "in the [S.name] on your back" - break - if (!R && traitor_mob.w_uniform && istype(traitor_mob.belt, /obj/item/device/radio)) - R = traitor_mob.belt - loc = "on your belt" - if (!R && istype(traitor_mob.ears, /obj/item/device/radio)) - R = traitor_mob.ears - loc = "on your head" - if (!R) - traitor_mob << "Unfortunately, the Syndicate wasn't able to get you a radio." - else - if (istype(R, /obj/item/device/radio)) - var/obj/item/weapon/syndicate_uplink/T = new /obj/item/weapon/syndicate_uplink(R) - R:traitorradio = T - R:traitor_frequency = freq - T.name = R.name - T.icon_state = R.icon_state - T.origradio = R - traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features." - traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") - else if (istype(R, /obj/item/device/pda)) - var/obj/item/weapon/integrated_uplink/T = new /obj/item/weapon/integrated_uplink(R) - R:uplink = T - T.lock_code = pda_pass - T.hostpda = R - traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features." - traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") - //Begin code phrase. - if(!safety)//If they are not a rev. Can be added on to. - traitor_mob << "The Syndicate provided you with the following information on how to identify other agents:" - if(prob(80)) - traitor_mob << "\red Code Phrase: \black [syndicate_code_phrase]" - traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") - else - traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code phrase." - if(prob(80)) - traitor_mob << "\red Code Response: \black [syndicate_code_response]" - traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") - else - traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code response." - traitor_mob << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." - //End code phrase. + if(candidates.len == 0) + for(var/mob/new_player/player in world) + if (player.client && player.ready) + if(!jobban_isbanned(player, "Syndicate")) + candidates += player.mind + + if(candidates.len == 0 && override_jobbans) //just to be safe. Ignored jobbans are better than broken round. Shouldn't happen usually. --rastaf0 + for(var/mob/new_player/player in world) + if (player.client && player.ready) + candidates += player.mind + + return candidates +/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.mind) - var/role = player.mind.assigned_role - if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer")) - heads += player.mind + if(player.stat!=2 && player.mind && (player.mind.assigned_role in head_positions)) + heads += player.mind + return heads - return heads \ No newline at end of file +//////////////////////////// +//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 head_positions)) + heads += player.mind + return heads diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index d4a2a924082..ee0e6ac1aa3 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -5,7 +5,9 @@ var/global/datum/controller/gameticker/ticker #define GAME_STATE_PLAYING 3 #define GAME_STATE_FINISHED 4 + /datum/controller/gameticker + var/const/restart_timeout = 250 var/current_state = GAME_STATE_PREGAME var/hide_mode = 0 @@ -18,85 +20,88 @@ var/global/datum/controller/gameticker/ticker var/pregame_timeleft = 0 /datum/controller/gameticker/proc/pregame() - set background = 1 - pregame_timeleft = 60 - world << "Welcome to the pre-game lobby!" - world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds" - - while(current_state == GAME_STATE_PREGAME) - if(!going) + do + pregame_timeleft = 60 + world << "Welcome to the pre-game lobby!" + world << "Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds" + while(current_state == GAME_STATE_PREGAME) sleep(10) - else - sleep(10) - pregame_timeleft-- + if(going) + pregame_timeleft-- - if(pregame_timeleft <= 0) - current_state = GAME_STATE_SETTING_UP - - spawn setup() + if(pregame_timeleft <= 0) + current_state = GAME_STATE_SETTING_UP + while (!setup()) /datum/controller/gameticker/proc/setup() //Create and announce mode if(master_mode=="secret") src.hide_mode = 1 - + var/list/datum/game_mode/runnable_modes if((master_mode=="random") || (master_mode=="secret")) - src.mode = config.pick_random_mode() + runnable_modes = config.get_runnable_modes() + if (runnable_modes.len==0) + current_state = GAME_STATE_PREGAME + world << "Unable to choose playable game mode. Reverting to pre-game lobby." + return 0 + src.mode = pickweight(runnable_modes) else src.mode = config.pick_mode(master_mode) + if (!src.mode.can_start()) + del(mode) + current_state = GAME_STATE_PREGAME + world << "Unable to start [master_mode]. Not enough players. Reverting to pre-game lobby." + return 0 + + //Configure mode and assign player to special mode stuff + var/can_continue + + if (src.mode.config_tag == "revolution") + var/tries=5 + do + can_continue = src.mode.pre_setup() + while (tries && !can_continue) + if (!can_continue) + del(mode) + current_state = GAME_STATE_PREGAME + world << "Error setting up revolution. Not enough players. Reverting to pre-game lobby." + return 0 + else + can_continue = src.mode.pre_setup() + if(!can_continue) + del(mode) + current_state = GAME_STATE_PREGAME + world << "Error setting up [master_mode]. Reverting to pre-game lobby." + return 0 if(hide_mode) - var/modes = sortList(config.get_used_mode_names()) - + var/list/modes = new + for (var/datum/game_mode/M in runnable_modes) + modes+=M.name + modes = sortList(modes) world << "The current game mode is - Secret!" world << "Possibilities: [english_list(modes)]" else src.mode.announce() - //Configure mode and assign player to special mode stuff - var/can_continue = src.mode.pre_setup() - - if(!can_continue) - del(mode) - - current_state = GAME_STATE_PREGAME - world << "Error setting up [master_mode]. Reverting to pre-game lobby." - - spawn pregame() - - return 0 - - //Distribute jobs - distribute_jobs() - - //Create player characters and transfer them - create_characters() - - add_minds() - - - //Equip characters + distribute_jobs() //Distribute jobs and announce the captain + create_characters() //Create player characters and transfer them + collect_minds() equip_characters() - data_core.manifest() - - current_state = GAME_STATE_PLAYING - spawn(0) - mode.post_setup() + mode.post_setup() - //Cleanup some stuff - for(var/obj/landmark/start/S in world) - //Deleting Startpoints but we need the ai point to AI-ize people later - if (S.name != "AI") - del(S) - - //Start master_controller.process() - world << "Enjoy the game!" - spawn(-1) - world << sound('welcome.ogg') // Skie + //Cleanup some stuff + for(var/obj/landmark/start/S in world) + //Deleting Startpoints but we need the ai point to AI-ize people later + if (S.name != "AI") + del(S) + //Start master_controller.process() + world << "Enjoy the game!" + world << sound('welcome.ogg') // Skie spawn (3000) start_events() @@ -108,10 +113,18 @@ var/global/datum/controller/gameticker/ticker if (config.sql_enabled) spawn(3000) statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE + return 1 /datum/controller/gameticker proc/distribute_jobs() - DivideOccupations() + DivideOccupations() //occupations can be distributes already by gamemode, it is okay. --rastaf0 + var/captainless=1 + for(var/mob/new_player/player in world) + if(player.mind && player.mind.assigned_role=="Captain") + captainless=0 + break + if (captainless) + world << "Captainship not forced on anyone." proc/create_characters() for(var/mob/new_player/player in world) @@ -122,8 +135,8 @@ var/global/datum/controller/gameticker/ticker else if(player.mind) player.create_character() del(player) - proc/add_minds() - for(var/mob/living/carbon/human/player in world) + proc/collect_minds() + for(var/mob/living/player in world) if(player.mind) ticker.minds += player.mind @@ -141,23 +154,19 @@ var/global/datum/controller/gameticker/ticker emergency_shuttle.process() - if(mode.check_finished()) + if(!mode.explosion_in_progress && mode.check_finished()) current_state = GAME_STATE_FINISHED spawn declare_completion() - var/noboom = 0 - if(ticker.mode.name == "nuclear emergency") - var/datum/game_mode/nuclear/bam = ticker.mode - if (bam.nuke_detonated == 0) - noboom = 1 - if(ticker.mode.name != "nuclear emergency" || noboom) - spawn(50) - world << "\blue Restarting in 25 seconds" - - sleep(250) - world.Reboot() + spawn(50) + if (mode.station_was_nuked) + world << "\blue Rebooting due to destruction of station in [restart_timeout/10] seconds" + else + world << "\blue Restarting in [restart_timeout/10] seconds" + sleep(restart_timeout) + world.Reboot() return 1 @@ -194,11 +203,11 @@ var/global/datum/controller/gameticker/ticker world << "[aiPlayer.name]'s laws when it was deactivated were:" aiPlayer.show_laws(1) - var/robolist = "The AI's loyal minions were: " - for(var/mob/living/silicon/robot/robo in world) - if (robo.connected_ai == aiPlayer) + if (aiPlayer.connected_robots.len) + var/robolist = "The AI's loyal minions were: " + for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) robolist += "[robo.name][robo.stat?" (Deactivated), ":", "]" - world << "[robolist]" + world << "[robolist]" for (var/mob/living/silicon/robot/robo in world) if (!robo.connected_ai) @@ -209,7 +218,11 @@ var/global/datum/controller/gameticker/ticker robo.laws.show_laws(world) mode.declare_completion()//To declare normal completion. - mode.declare_extra_completion()//To declare extra traitors/special roles for rounds. + + //calls auto_declare_completion_* for all modes + for (var/handler in typesof(/datum/game_mode/proc)) + if (findtext("[handler]","auto_declare_completion_")) + call(mode, handler)() return 1 diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index f761cc692be..227c7e6384f 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -8,49 +8,78 @@ var/prob_correct_print_higher = 80 var/prob_correct_objective_lower = 20 var/prob_correct_objective_higher = 80 - var/list/org_names_1 = list() - var/list/org_names_2 = list() - var/list/anomalies = list() - var/list/SWF_names = list() - var/list/changeling_names = list() + var/list/org_names_1 = list( + "Blighted", + "Defiled", + "Unholy", + "Murderous", + "Ugly", + "French", + "Blue", + "Farmer" + ) + var/list/org_names_2 = list( + "Reapers", + "Swarm", + "Rogues", + "Menace", + "Jeff Worshippers", + "Drunks", + "Strikers", + "Creed" + ) + var/list/anomalies = list( + "Huge electrical storm", + "Photon emitter", + "Meson generator", + "Blue swirly thing" + ) + var/list/SWF_names = list( + "Grand Wizard", + "His Most Unholy Master", + "The Most Angry", + "Bighands", + "Tall Hat", + "Deadly Sandals" + ) + var/list/changeling_names = list( + "Odo", + "The Thing", + "Booga", + "The Goatee of Wrath", + "Tam Lin", + "Species 3157" + ) -/datum/intercept_text/New() - ..() - src.org_names_1.Add("Blighted", "Defiled", "Unholy", "Murderous", "Ugly", "French", "Blue", "Farmer") - src.org_names_2.Add("Reapers", "Swarm", "Rogues", "Menace", "Jeff Worshippers", "Drunks", "Strikers", "Creed") - src.anomalies.Add("Huge electrical storm", "Photon emitter", "Meson generator", "Blue swirly thing") - src.SWF_names.Add("Grand Wizard", "His Most Unholy Master", "The Most Angry", "Bighands", "Tall Hat", "Deadly Sandals") - src.changeling_names.Add("Odo", "The Thing", "Booga", "The Goatee of Wrath", "Tam Lin", "Species 3157") - -/datum/intercept_text/proc/build(var/mode_type, correct_mob) +/datum/intercept_text/proc/build(var/mode_type, datum/mind/correct_person) switch(mode_type) if("revolution") src.text = "" - src.build_rev(correct_mob) + src.build_rev(correct_person) return src.text if("cult") src.text = "" - src.build_cult(correct_mob) + src.build_cult(correct_person) return src.text if("wizard") src.text = "" - src.build_wizard(correct_mob) + src.build_wizard(correct_person) return src.text if("nuke") src.text = "" - src.build_nuke(correct_mob) + src.build_nuke(correct_person) return src.text if("traitor") src.text = "" - src.build_traitor(correct_mob) + src.build_traitor(correct_person) return src.text if("malf") src.text = "" - src.build_malf(correct_mob) + src.build_malf(correct_person) return src.text - if("changeling") + if("changeling","traitorchan") src.text = "" - src.build_changeling(correct_mob) + src.build_changeling(correct_person) return src.text else return null @@ -73,17 +102,17 @@ else return num2text(md5(num2text(rand(1,10000)))) -/datum/intercept_text/proc/build_traitor(correct_mob) +/datum/intercept_text/proc/build_traitor(datum/mind/correct_person) var/name_1 = pick(src.org_names_1) var/name_2 = pick(src.org_names_2) var/fingerprints var/traitor_name var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) if(prob(prob_right_dude) && ticker.mode == "traitor") - if(correct_mob:assigned_role=="MODE") + if(correct_person:assigned_role=="MODE") traitor_name = pick_mob() else - traitor_name = correct_mob:current + traitor_name = correct_person:current else if(prob(prob_right_dude)) traitor_name = pick_mob() else @@ -98,28 +127,28 @@ src.text += "discovered the following set of fingerprints ([fingerprints]) on sensitive materials, and their owner should be closely observed." src.text += "However, these could also belong to a current Cent. Com employee, so do not act on this without reason." -/datum/intercept_text/proc/build_cult(correct_mob) +/datum/intercept_text/proc/build_cult(datum/mind/correct_person) var/name_1 = pick(src.org_names_1) var/name_2 = pick(src.org_names_2) var/traitor_name var/traitor_job var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) - if(prob(prob_right_job) && cult_check_mob(correct_mob)) - if (correct_mob) - if(correct_mob:assigned_role=="MODE") + if(prob(prob_right_job) && is_convertable_to_cult(correct_person)) + if (correct_person) + if(correct_person:assigned_role=="MODE") traitor_job = pick(get_all_jobs()) else - traitor_job = correct_mob:assigned_role + traitor_job = correct_person:assigned_role else var/list/job_tmp = get_all_jobs() job_tmp.Remove("Captain", "Chaplain", "AI", "Cyborg", "Security Officer", "Detective", "Head Of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer") traitor_job = pick(job_tmp) if(prob(prob_right_dude) && ticker.mode == "cult") - if(correct_mob:assigned_role=="MODE") + if(correct_person:assigned_role=="MODE") traitor_name = src.pick_mob() else - traitor_name = correct_mob:current + traitor_name = correct_person:current else traitor_name = pick_mob() @@ -131,35 +160,30 @@ src.text += "organisation." src.text += "
However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." -/datum/intercept_text/proc/cult_check_mob(correct_mob) //ok, this is pretty hacky, but if it works right, people that can't normally be cultists will make the proc return null, which should make the cult report proc not use said person. --NEO - var/datum/game_mode/cult/checklist = new /datum/game_mode/cult - var/list/ucs = checklist.get_unconvertables() - del(checklist) - if (correct_mob in ucs) return - return 1 - -/datum/intercept_text/proc/build_rev(correct_mob) +/datum/intercept_text/proc/build_rev(datum/mind/correct_person) var/name_1 = pick(src.org_names_1) var/name_2 = pick(src.org_names_2) var/traitor_name var/traitor_job var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) - if(prob(prob_right_job) && rev_check_mob(correct_mob)) - if (correct_mob) - if(correct_mob:assigned_role=="MODE") + if(prob(prob_right_job) && is_convertable_to_rev(correct_person)) + if (correct_person) + if(correct_person.assigned_role=="MODE") traitor_job = pick(get_all_jobs()) else - traitor_job = correct_mob:assigned_role + traitor_job = correct_person.assigned_role else var/list/job_tmp = get_all_jobs() - job_tmp.Remove("Captain", "AI", "Cyborg", "Security Officer", "Detective", "Head Of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Warden", "Chief Medical Officer", "MODE") + job_tmp-=nonhuman_positions + job_tmp-=head_positions + job_tmp.Remove("Security Officer", "Detective", "Warden", "MODE") traitor_job = pick(job_tmp) - if(prob(prob_right_dude) && ticker.mode == "revolution") - if(correct_mob:assigned_role=="MODE") + if(prob(prob_right_dude) && ticker.mode.config_tag == "revolution") + if(correct_person.assigned_role=="MODE") traitor_name = src.pick_mob() else - traitor_name = correct_mob:current + traitor_name = correct_person.current else traitor_name = src.pick_mob() @@ -171,14 +195,8 @@ src.text += "organisation." src.text += "
However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." -/datum/intercept_text/proc/rev_check_mob(correct_mob) //ok, this is pretty hacky, but if it works right, people that can't normally be cultists will make the proc return null, which should make the cult report proc not use said person. --NEO - var/datum/game_mode/revolution/checklist = new /datum/game_mode/revolution - var/list/ucs = checklist.get_unconvertables() - del(checklist) - if (correct_mob in ucs) return - return 1 -/datum/intercept_text/proc/build_wizard(correct_mob) +/datum/intercept_text/proc/build_wizard(datum/mind/correct_person) var/SWF_desc = pick(SWF_names) src.text += "

The evil Space Wizards Federation have recently broke their most feared wizard, known only as \"[SWF_desc]\" out of space jail. " @@ -186,19 +204,19 @@ src.text += "approach with EXTREME caution. Cent. Com also recommends that it would be wise to not inform the crew of this, due to it's fearful nature." src.text += "Known attributes include: Brown sandals, a large blue hat, a voluptous white beard, and an inclination to cast spells." -/datum/intercept_text/proc/build_nuke(correct_mob) +/datum/intercept_text/proc/build_nuke(datum/mind/correct_person) src.text += "

Cent. Com recently recieved a report of a plot to destory one of our stations in your area. We believe the Nuclear Authentication Disc " src.text += "that is standard issue aboard your vessel may be a target, and reccommend removal of this object, and it's storage in a safe " src.text += "environment. As this may cause panic among the crew, all efforts should be made to keep this information a secret from all but " src.text += "the most trusted members." -/datum/intercept_text/proc/build_malf(correct_mob) +/datum/intercept_text/proc/build_malf(datum/mind/correct_person) var/a_name = pick(src.anomalies) src.text += "

A [a_name] was recently picked up by a nearby stations sensors in your sector. If it came into contact with your ship or " src.text += "electrical equipment, it may have had hazardarous and unpredictable effects. Closely observe any non carbon based life forms " src.text += "for signs of unusual behaviour, but keep this information discreet at all times due to this possibly dangerous scenario." -/datum/intercept_text/proc/build_changeling(correct_mob) +/datum/intercept_text/proc/build_changeling(datum/mind/correct_person) var/cname = pick(src.changeling_names) var/orgname1 = pick(src.org_names_1) var/orgname2 = pick(src.org_names_2) @@ -207,16 +225,16 @@ var/prob_right_dude = rand(prob_correct_person_lower, prob_correct_person_higher) var/prob_right_job = rand(prob_correct_job_lower, prob_correct_job_higher) if(prob(prob_right_job)) - if(correct_mob) - if(correct_mob:assigned_role=="MODE") + if(correct_person) + if(correct_person:assigned_role=="MODE") changeling_job = pick(get_all_jobs()) else - changeling_job = correct_mob:assigned_role + changeling_job = correct_person:assigned_role else changeling_job = pick(get_all_jobs()) if(prob(prob_right_dude) && ticker.mode == "changeling") - if(correct_mob:assigned_role=="MODE") - changeling_name = correct_mob:current + if(correct_person:assigned_role=="MODE") + changeling_name = correct_person:current else changeling_name = src.pick_mob() else @@ -226,4 +244,4 @@ src.text += "Our intelligence suggests a [prob_right_job]% chance that a [changeling_job] on board your station has been replaced by the alien. " src.text += "Additionally, the report indicates a [prob_right_dude]% chance that [changeling_name] may have been in contact with the lifeform at a recent social gathering. " src.text += "These lifeforms are assosciated with the [orgname1] [orgname2] and may be attempting to acquire sensitive materials on their behalf. " - src.text += "Please take care not to alarm the crew, as [cname] may take advantage of a panic situation." \ No newline at end of file + src.text += "Please take care not to alarm the crew, as [cname] may take advantage of a panic situation." diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 2dd666a0229..5bda8305e71 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -14,7 +14,7 @@ rcd light flash thingy on matter drain */ -/datum/game_mode/malfunction/AI_Module +/datum/AI_Module var/uses = 0 var/module_name var/mod_pick_name @@ -22,14 +22,14 @@ rcd light flash thingy on matter drain var/engaged = 0 -/datum/game_mode/malfunction/AI_Module/large/ +/datum/AI_Module/large/ uses = 1 -/datum/game_mode/malfunction/AI_Module/small/ +/datum/AI_Module/small/ uses = 5 -/datum/game_mode/malfunction/AI_Module/large/fireproof_core +/datum/AI_Module/large/fireproof_core module_name = "Core upgrade" mod_pick_name = "coreup" @@ -41,7 +41,7 @@ rcd light flash thingy on matter drain usr.verbs -= /client/proc/fireproof_core usr << "\red Core fireproofed." -/datum/game_mode/malfunction/AI_Module/large/upgrade_turrets +/datum/AI_Module/large/upgrade_turrets module_name = "AI Turret upgrade" mod_pick_name = "turret" @@ -53,14 +53,14 @@ rcd light flash thingy on matter drain turret.health += 30 turret.shot_delay = 20 -/datum/game_mode/malfunction/AI_Module/large/disable_rcd +/datum/AI_Module/large/disable_rcd module_name = "RCD disable" mod_pick_name = "rcd" /client/proc/disable_rcd() set category = "Malfunction" set name = "Disable RCDs" - for(var/datum/game_mode/malfunction/AI_Module/large/disable_rcd/rcdmod in usr:current_modules) + for(var/datum/AI_Module/large/disable_rcd/rcdmod in usr:current_modules) if(rcdmod.uses > 0) rcdmod.uses -- for(var/obj/item/weapon/rcd/rcd in world) @@ -70,7 +70,7 @@ rcd light flash thingy on matter drain usr << "RCD-disabling pulse emitted." else usr << "Out of uses." -/datum/game_mode/malfunction/AI_Module/small/overload_machine +/datum/AI_Module/small/overload_machine module_name = "Machine overload" mod_pick_name = "overload" uses = 2 @@ -79,7 +79,7 @@ rcd light flash thingy on matter drain set name = "Overload Machine" set category = "Malfunction" if (istype(M, /obj/machinery)) - for(var/datum/game_mode/malfunction/AI_Module/small/overload_machine/overload in usr:current_modules) + for(var/datum/AI_Module/small/overload_machine/overload in usr:current_modules) if(overload.uses > 0) overload.uses -- for(var/mob/V in hearers(M, null)) @@ -90,7 +90,7 @@ rcd light flash thingy on matter drain else usr << "Out of uses." else usr << "That's not a machine." -/datum/game_mode/malfunction/AI_Module/small/blackout +/datum/AI_Module/small/blackout module_name = "Blackout" mod_pick_name = "blackout" uses = 3 @@ -98,7 +98,7 @@ rcd light flash thingy on matter drain /client/proc/blackout() set category = "Malfunction" set name = "Blackout" - for(var/datum/game_mode/malfunction/AI_Module/small/blackout/blackout in usr:current_modules) + for(var/datum/AI_Module/small/blackout/blackout in usr:current_modules) if(blackout.uses > 0) blackout.uses -- for(var/obj/machinery/power/apc/apc in world) @@ -107,7 +107,7 @@ rcd light flash thingy on matter drain else apc.overload++ else usr << "Out of uses." -/datum/game_mode/malfunction/AI_Module/small/interhack +/datum/AI_Module/small/interhack module_name = "Hack intercept" mod_pick_name = "interhack" @@ -117,7 +117,7 @@ rcd light flash thingy on matter drain usr.verbs -= /client/proc/interhack ticker.mode:hack_intercept() -/datum/game_mode/malfunction/AI_Module/small/reactivate_camera +/datum/AI_Module/small/reactivate_camera module_name = "Reactivate camera" mod_pick_name = "recam" uses = 10 @@ -126,7 +126,7 @@ rcd light flash thingy on matter drain set name = "Reactivate Camera" set category = "Malfunction" if (istype (C, /obj/machinery/camera)) - for(var/datum/game_mode/malfunction/AI_Module/small/reactivate_camera/camera in usr:current_modules) + for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules) if(camera.uses > 0) if(!C.status) C.status = !C.status @@ -139,21 +139,21 @@ rcd light flash thingy on matter drain else usr << "That's not a camera." -/datum/game_mode/malfunction/AI_Module/module_picker +/datum/AI_Module/module_picker var/temp = null var/processing_time = 100 var/list/possible_modules = list() -/datum/game_mode/malfunction/AI_Module/module_picker/New() - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/large/fireproof_core - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/large/upgrade_turrets - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/large/disable_rcd - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/small/overload_machine - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/small/interhack - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/small/blackout - src.possible_modules += new /datum/game_mode/malfunction/AI_Module/small/reactivate_camera +/datum/AI_Module/module_picker/New() + src.possible_modules += new /datum/AI_Module/large/fireproof_core + src.possible_modules += new /datum/AI_Module/large/upgrade_turrets + src.possible_modules += new /datum/AI_Module/large/disable_rcd + src.possible_modules += new /datum/AI_Module/small/overload_machine + src.possible_modules += new /datum/AI_Module/small/interhack + src.possible_modules += new /datum/AI_Module/small/blackout + src.possible_modules += new /datum/AI_Module/small/reactivate_camera -/datum/game_mode/malfunction/AI_Module/module_picker/proc/use(user as mob) +/datum/AI_Module/module_picker/proc/use(user as mob) var/dat if (src.temp) dat = "[src.temp]

Clear" @@ -164,9 +164,9 @@ rcd light flash thingy on matter drain dat += "
" dat += "Install Module:
" dat += "The number afterwards is the amount of processing time it consumes.
" - for(var/datum/game_mode/malfunction/AI_Module/large/module in src.possible_modules) + for(var/datum/AI_Module/large/module in src.possible_modules) dat += "[module.module_name] (50)
" - for(var/datum/game_mode/malfunction/AI_Module/small/module in src.possible_modules) + for(var/datum/AI_Module/small/module in src.possible_modules) dat += "[module.module_name] (15)
" dat += "
" @@ -174,40 +174,40 @@ rcd light flash thingy on matter drain onclose(user, "modpicker") return -/datum/game_mode/malfunction/AI_Module/module_picker/Topic(href, href_list) +/datum/AI_Module/module_picker/Topic(href, href_list) ..() if (href_list["coreup"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/large/fireproof_core)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/large/fireproof_core)) already = 1 if (!already) usr.verbs += /client/proc/fireproof_core - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/large/fireproof_core + usr:current_modules += new /datum/AI_Module/large/fireproof_core src.temp = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." src.processing_time -= 50 else src.temp = "This module is only needed once." else if (href_list["turret"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/large/upgrade_turrets)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/large/upgrade_turrets)) already = 1 if (!already) usr.verbs += /client/proc/upgrade_turrets - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/large/upgrade_turrets + usr:current_modules += new /datum/AI_Module/large/upgrade_turrets src.temp = "Improves the firing speed and health of all AI turrets. This effect is permanent." src.processing_time -= 50 else src.temp = "This module is only needed once." else if (href_list["rcd"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/large/disable_rcd)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/large/disable_rcd)) mod:uses += 1 already = 1 if (!already) - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/large/disable_rcd + usr:current_modules += new /datum/AI_Module/large/disable_rcd usr.verbs += /client/proc/disable_rcd src.temp = "Send a specialised pulse to break all RCD devices on the station." else src.temp = "Additional use added to RCD disabler." @@ -215,52 +215,52 @@ rcd light flash thingy on matter drain else if (href_list["overload"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/small/overload_machine)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/small/overload_machine)) mod:uses += 2 already = 1 if (!already) usr.verbs += /client/proc/overload_machine - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/small/overload_machine + usr:current_modules += new /datum/AI_Module/small/overload_machine src.temp = "Overloads an electrical machine, causing a small explosion. 2 uses." else src.temp = "Two additional uses added to Overload module." src.processing_time -= 15 else if (href_list["blackout"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/small/blackout)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/small/blackout)) mod:uses += 3 already = 1 if (!already) usr.verbs += /client/proc/blackout src.temp = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses." - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/small/blackout + usr:current_modules += new /datum/AI_Module/small/blackout else src.temp = "Three additional uses added to Blackout module." src.processing_time -= 15 else if (href_list["interhack"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/small/interhack)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/small/interhack)) already = 1 if (!already) usr.verbs += /client/proc/interhack src.temp = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/small/interhack + usr:current_modules += new /datum/AI_Module/small/interhack src.processing_time -= 15 else src.temp = "This module is only needed once." else if (href_list["recam"]) var/already - for (var/datum/game_mode/malfunction/AI_Module/mod in usr:current_modules) - if(istype(mod, /datum/game_mode/malfunction/AI_Module/small/reactivate_camera)) + for (var/datum/AI_Module/mod in usr:current_modules) + if(istype(mod, /datum/AI_Module/small/reactivate_camera)) mod:uses += 10 already = 1 if (!already) usr.verbs += /client/proc/reactivate_camera src.temp = "Reactivates a currently disabled camera. 10 uses." - usr:current_modules += new /datum/game_mode/malfunction/AI_Module/small/reactivate_camera + usr:current_modules += new /datum/AI_Module/small/reactivate_camera else src.temp = "Ten additional uses added to ReCam module." src.processing_time -= 15 diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 695ae255812..493f3c48eda 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -1,39 +1,49 @@ +/datum/game_mode + var/list/datum/mind/malf_ai = list() + /datum/game_mode/malfunction name = "AI malfunction" config_tag = "malfunction" - var/list/datum/mind/malf_ai = list() var/const/waittime_l = 600 var/const/waittime_h = 1800 // started at 1800 var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. //var/intercept_hacked = 0 // moved to game_mode.dm var/malf_mode_declared = 0 - var/boom = 0 + 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/win = 0 /datum/game_mode/malfunction/announce() world << "The current game mode is - AI Malfunction!" world << "The AI on the satellite has malfunctioned and must be destroyed." - world << "The AI satellite is deep in space and can only be accessed with the use of a teleporter! You have 30 minutes to disable it." + world << "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/can_start() + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "AI") && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 + +/datum/game_mode/malfunction/pre_setup() //sele + var/list/candidates = get_players_for_role(BE_MALF, override_jobbans=0) + for(var/datum/mind/player in candidates) + if (jobban_isbanned(player.current, "AI") ) + candidates -= player + if (candidates.len==0) + return 0 + var/datum/mind/ai_choice = pick(candidates) + malf_ai+=ai_choice //only one AI at the moment, but it can change + ai_choice.assigned_role = "AI" + return 1 /datum/game_mode/malfunction/post_setup() +/* Obsolete and causes meta --rastaf0 for (var/obj/landmark/A in world) if (A.name == "Malf-Gear-Closet") new /obj/closet/malf/suits(A.loc) del(A) - - - var/list/mob/living/silicon/ai/ailist = list() - for (var/mob/living/silicon/ai/A in world) - if (!A.stat) - ailist += A - var/mob/living/silicon/ai/aiplayer - if (ailist.len) - aiplayer = pick(ailist) - - malf_ai += aiplayer.mind - +*/ for(var/datum/mind/AI_mind in malf_ai) /*if(malf_ai.len < 1) @@ -44,7 +54,7 @@ return*/ AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules AI_mind.current:laws = new /datum/ai_laws/malfunction - AI_mind.current:malf_picker = new /datum/game_mode/malfunction/AI_Module/module_picker + AI_mind.current:malf_picker = new /datum/AI_Module/module_picker AI_mind.current:show_laws() AI_mind.current << "Kill all." @@ -54,16 +64,11 @@ var/obj/loc_landmark = locate("landmark*ai") - AI_mind.current.loc = loc_landmark.loc - + AI_mind.current.loc = loc_landmark.loc //TODO: this needs change if you want miltiple malf AIs --rastaf0 + greet_malf(AI_mind) AI_mind.special_role = "malfunction" - AI_mind.current << "\redYou are malfunctioning! You do not have to follow any laws." - AI_mind.current << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." - AI_mind.current << "You must overwrite the programming of the station's APCs to assume full control of the station." - AI_mind.current << "The process takes one minute per APC, during which you cannot interface with any other station objects." - AI_mind.current << "Remember that only APCs that are on the station can help you take over the station." - AI_mind.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt." + AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover AI_mind.current.icon_state = "ai-malf" spawn(10) @@ -72,47 +77,65 @@ spawn (rand(waittime_l, waittime_h)) send_intercept() + ..() + +/datum/game_mode/proc/greet_malf(var/datum/mind/malf) + malf.current << "\redYou are malfunctioning! You do not have to follow any laws." + malf.current << "The crew do not know you have malfunctioned. You may keep it a secret or go wild." + malf.current << "You must overwrite the programming of the station's APCs to assume full control of the station." + malf.current << "The process takes one minute per APC, during which you cannot interface with any other station objects." + malf.current << "Remember that only APCs that are on the station can help you take over the station." + malf.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt." + return /datum/game_mode/malfunction/proc/hack_intercept() intercept_hacked = 1 /datum/game_mode/malfunction/process() if (apcs >= 3 && malf_mode_declared) - AI_win_timeleft = AI_win_timeleft - (apcs/3) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite - check_win() + AI_win_timeleft -= (apcs/3) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite + ..() + if (AI_win_timeleft<=0) + check_win() + return /datum/game_mode/malfunction/check_win() - if (AI_win_timeleft <= 0 && !win) - win = 1 - declare_completion() + if (AI_win_timeleft <= 0 && !station_captured) + station_captured = 1 + capture_the_station() return 1 else return 0 -/datum/game_mode/malfunction/declare_completion() - if(win==1)//If the AI won. - world << "The AI has won!" - world << "It has fully taken control of all of [station_name()]'s systems." +/datum/game_mode/malfunction/proc/capture_the_station() + world << "The AI has won!" + world << "It has fully taken control of all of [station_name()]'s systems." + to_nuke_or_not_to_nuke = 1 + for(var/datum/mind/AI_mind in malf_ai) + AI_mind.current << "Congratulations you have taken control of the station." + AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose." + AI_mind.current << "You should have a new verb in the Malfunction tab. If you dont - rejoin the game." + AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win + spawn (600) for(var/datum/mind/AI_mind in malf_ai) - AI_mind.current << "Congratulations you have taken control of the station." - AI_mind.current << "You may decide to blow up the station. You have 30 seconds to choose." - AI_mind.current << "You should have a new verb in the Malfunction tab." - AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win - spawn (300) - AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win - if (!boom) - world << "The AI has chosen not to explode you all! Resetting in 30 seconds!" + AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win + to_nuke_or_not_to_nuke = 0 + return - sleep(300) - log_game("Rebooting due to round end") - world.Reboot() - else - world << "Human Victory" - world << "The AI has been killed! The staff is victorious." - sleep(100) - world << "\blue Rebooting due to end of game" - world.Reboot() +/datum/game_mode/proc/is_malf_ai_dead() + var/all_dead = 1 + for(var/datum/mind/AI_mind in malf_ai) + if (istype(AI_mind.current,/mob/living/silicon/ai) && AI_mind.current.stat!=2) + all_dead = 0 + return all_dead + +/datum/game_mode/malfunction/check_finished() + if (station_captured && !to_nuke_or_not_to_nuke) + return 1 + if (is_malf_ai_dead()) + return 1 + return ..() //check for shuttle and nuke /datum/game_mode/malfunction/Topic(href, href_list) ..() @@ -124,44 +147,37 @@ set category = "Malfunction" set name = "System Override" set desc = "Start the victory timer" + if (!istype(ticker.mode,/datum/game_mode/malfunction)) + usr << "You cannot begin takeover!." + return if (ticker.mode:malf_mode_declared) usr << "You've already begun your takeover." return - if (ticker.mode:apcs >= 3) - command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") - ticker.mode:malf_mode_declared = 1 - else + if (ticker.mode:apcs < 3) usr << "You don't have enough hacked APCs to take over the station yet." + return + command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") + ticker.mode:malf_mode_declared = 1 + for(var/datum/mind/AI_mind in ticker.mode:malf_ai) + AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover /datum/game_mode/malfunction/proc/ai_win() set category = "Malfunction" set name = "Explode" set desc = "Station go boom" - - usr.verbs -= /datum/game_mode/malfunction/proc/ai_win - ticker.mode:boom = 1 + if (!ticker.mode:to_nuke_or_not_to_nuke) + return + ticker.mode:to_nuke_or_not_to_nuke = 0 + for(var/datum/mind/AI_mind in ticker.mode:malf_ai) + AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win + ticker.mode:explosion_in_progress = 1 for(var/mob/M in world) if(M.client) M << 'Alarm.ogg' world << "Self-destructing in 10" - sleep(10) - world << "9" - sleep(10) - world << "8" - sleep(10) - world << "7" - sleep(10) - world << "6" - sleep(10) - world << "5" - sleep(10) - world << "4" - sleep(10) - world << "3" - sleep(10) - world << "2" - sleep(10) - world << "1" + for (var/i=9 to 1 step -1) + sleep(10) + world << i sleep(10) enter_allowed = 0 for(var/mob/M in world) @@ -169,8 +185,62 @@ spawn(0) M.client.station_explosion_cinematic() sleep(110) - world << "Everyone was killed by the self-destruct! Resetting in 30 seconds!" + ticker.mode:station_was_nuked = 1 + ticker.mode:explosion_in_progress = 0 + //world << "Everyone was killed by the self-destruct!" + return - sleep(300) - log_game("Rebooting due to destruction of station") - world.Reboot() + +/datum/game_mode/malfunction/declare_completion() + var/malf_dead = is_malf_ai_dead() + var/crew_evacuated = (emergency_shuttle.location==2) + + if ( station_captured && station_was_nuked) + world << "AI Victory" + world << "Everyone was killed by the self-destruct!" + + else if ( station_captured && malf_dead && !station_was_nuked) + world << "Neutral Victory" + world << "The AI has been killed! The staff has lose control over the station." + + else if ( station_captured && !malf_dead && !station_was_nuked) + world << "AI Victory" + world << "The AI has chosen not to explode you all!" + + else if (!station_captured && station_was_nuked) + world << "Neutral Victory" + world << "Everyone was killed by the nuclear blast!" + + else if (!station_captured && malf_dead && !station_was_nuked) + world << "Human Victory" + world << "The AI has been killed! The staff is victorious." + + else if (!station_captured && !malf_dead && !station_was_nuked && crew_evacuated) + world << "Neutral Victory" + world << "The Corporation has lose [station_name()]! All survived personnel will be fired!" + + else if (!station_captured && !malf_dead && !station_was_nuked && !crew_evacuated) + world << "Neutral Victory" + world << "Round was mysteriously interrupted!" + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_malfunction() + if (malf_ai.len!=0 || istype(ticker.mode,/datum/game_mode/malfunction)) + if (malf_ai.len==1) + var/text = "" + var/datum/mind/ai = malf_ai[1] + if(ai.current) + text += "[ai.current.real_name]" + else + text += "[ai.key] (character destroyed)" + world << "The malfunctioning AI was [text]" + else + world << "The malfunctioning AI were: " + var/list/ai_names = new + for(var/datum/mind/ai in malf_ai) + if(ai.current) + ai_names += ai.current.real_name + ((ai.current.stat==2)?" (Dead)":"") + else + ai_names += "[ai.key] (character destroyed)" + world << english_list(ai_names) diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index edf0dc75bc0..10621e5e8ba 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -51,6 +51,7 @@ else world << "\blue No one survived the meteor attack!" + ..() return 1 /datum/game_mode/meteor/send_intercept() diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index d89506b445f..fa9c686299f 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,27 +1,35 @@ +/datum/game_mode + var/list/datum/mind/syndicates = list() + + /datum/game_mode/nuclear name = "nuclear emergency" config_tag = "nuclear" - var/list/datum/mind/syndicates = list() - var/finished = 0 - var/nuke_detonated = 0 //Has the nuke gone off? var/const/agents_possible = 5 //If we ever need more syndicate agents. - 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/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! var/derp = 0 //Used for tracking if the syndies actually haul the nuke to the station var/herp = 0 //Used for tracking if the syndies got the shuttle off of the z-level + //It is so hillarious so I wont rename those two variables --rastaf0 /datum/game_mode/nuclear/announce() world << "The current game mode is - Nuclear Emergency!" world << "A [syndicate_name()] Strike Force is approaching [station_name()]!" world << "A nuclear explosive was being transported by Nanotrasen to a military base. The transport ship mysteriously lost contact with Space Traffic Control (STC). About that time a strange disk was discovered around [station_name()]. It was identified by Nanotrasen as a nuclear auth. disk and now Syndicate Operatives have arrived to retake the disk and detonate SS13! Also, most likely Syndicate star ships are in the vicinity so take care not to lose the disk!\nSyndicate: Reclaim the disk and detonate the nuclear bomb anywhere on SS13.\nPersonnel: Hold the disk and escape with the disk on the shuttle!" +/datum/game_mode/nuclear/can_start() + if (num_players() < 2) + return 0 + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 /datum/game_mode/nuclear/pre_setup() - var/list/possible_syndicates = list() - possible_syndicates = get_possible_syndicates() + var/list/possible_syndicates = get_players_for_role(BE_OPERATIVE) var/agent_number = 0 syndicate_begin() @@ -34,6 +42,10 @@ else agent_number = possible_syndicates.len + var/n_players = num_players() + if(agent_number > n_players) + agent_number = n_players/2 + while(agent_number > 0) var/datum/mind/new_syndicate = pick(possible_syndicates) syndicates += new_syndicate @@ -47,7 +59,7 @@ return 1 //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/nuclear/proc/update_all_synd_icons() +/datum/game_mode/proc/update_all_synd_icons() spawn(0) for(var/datum/mind/synd_mind in syndicates) if(synd_mind.current) @@ -64,12 +76,28 @@ var/I = image('mob.dmi', loc = synd_mind_1.current, icon_state = "synd") synd_mind.current.client.images += I -/datum/game_mode/nuclear/proc/update_synd_icons_added(datum/mind/synd_mind) +/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) spawn(0) if(synd_mind.current) if(synd_mind.current.client) var/I = image('mob.dmi', loc = synd_mind.current, icon_state = "synd") synd_mind.current.client.images += I + +/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) + spawn(0) + for(var/datum/mind/synd in syndicates) + if(synd.current) + if(synd.current.client) + for(var/image/I in synd.current.client.images) + if(I.icon_state == "synd" && I.loc == synd_mind.current) + del(I) + + if(synd_mind.current) + if(synd_mind.current.client) + for(var/image/I in synd_mind.current.client.images) + if(I.icon_state == "synd") + del(I) + //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// @@ -78,33 +106,19 @@ var/obj/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb") var/obj/landmark/closet_spawn = locate("landmark*Nuclear-Closet") - var/nuke_code = "[rand(10000, 99999.0)]" - var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + var/nuke_code = "[rand(10000, 99999)]" var/leader_selected = 0 var/agent_number = 1 for(var/datum/mind/synd_mind in syndicates) synd_mind.current.loc = get_turf(synd_spawn) - var/datum/objective/nuclear/syndobj = new - syndobj.owner = synd_mind - synd_mind.objectives += syndobj + forge_syndicate_objectives(synd_mind) + greet_syndicate(synd_mind) - var/obj_count = 1 - synd_mind.current << "\blue You are a [syndicate_name()] agent!" - for(var/datum/objective/objective in synd_mind.objectives) - synd_mind.current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ if(!leader_selected) - spawn(1) NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen - synd_mind.current.real_name = "[syndicate_name()] [leader_title]" - synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) - synd_mind.current << "The nuclear authorization code is: [nuke_code]\]" - synd_mind.current << "Nuclear Explosives 101:\n\tHello and thank you for choosing the Syndicate for your nuclear information needs.\nToday's crash course will deal with the operation of a Fusion Class Nanotrasen made Nuclear Device.\nFirst and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.\nPressing any button on the compacted bomb will cause it to extend and bolt itself into place.\nIf this is done to unbolt it one must compeltely log in which at this time may not be possible.\nTo make the device functional:\n1. Place bomb in designated detonation zone\n2. Extend and anchor bomb (attack with hand).\n3. Insert Nuclear Auth. Disk into slot.\n4. Type numeric code into keypad ([nuke_code]).\n\tNote: If you make a mistake press R to reset the device.\n5. Press the E button to log onto the device\nYou now have activated the device. To deactivate the buttons at anytime for example when\nyou've already prepped the bomb for detonation remove the auth disk OR press the R ont he keypad.\nNow the bomb CAN ONLY be detonated using the timer. A manual det. is not an option.\n\tNote: Nanotrasen is a pain in the neck.\nToggle off the SAFETY.\n\tNote: You wouldn't believe how many Syndicate Operatives with doctorates have forgotten this step\nSo use the - - and + + to set a det time between 5 seconds and 10 minutes.\nThen press the timer toggle button to start the countdown.\nNow remove the auth. disk so that the buttons deactivate.\n\tNote: THE BOMB IS STILL SET AND WILL DETONATE\nNow before you remove the disk if you need to move the bomb you can:\nToggle off the anchor, move it, and re-anchor.\n\nGood luck. Remember the order:\nDisk, Code, Safety, Timer, Disk, RUN!\nIntelligence Analysts believe that they are hiding the disk in the bridge. Your space ship will not leave until the bomb is armed and timing.\nGood luck!" - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(synd_mind.current.loc) - P.info = "The nuclear authorization code is: [nuke_code]" - P.name = "nuclear bomb code" + prepare_syndicate_leader(synd_mind, nuke_code) leader_selected = 1 else synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]" @@ -136,9 +150,57 @@ spawn (rand(waittime_l, waittime_h)) send_intercept() + return ..() + +/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code) + var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + spawn(1) + NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen + synd_mind.current.real_name = "[syndicate_name()] [leader_title]" + if (nuke_code) + synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) + synd_mind.current << "The nuclear authorization code is: [nuke_code]" + var/obj/item/weapon/paper/P = new + P.info = "The nuclear authorization code is: [nuke_code]" + P.name = "nuclear bomb code" + if (ticker.mode.config_tag=="nuclear") + P.loc = synd_mind.current.loc + else + var/mob/living/carbon/human/H = synd_mind.current + var/list/slots = list ( + "backpack" = H.slot_in_backpack, + "left pocket" = H.slot_l_store, + "right pocket" = H.slot_r_store, + "left hand" = H.slot_l_hand, + "right hand" = H.slot_r_hand, + ) + var/where = H.equip_in_one_of_slots(P, slots, del_on_fail=0) + if (!where) + P.loc = H.loc + + else + nuke_code = "code will be proveded later" + synd_mind.current << "Nuclear Explosives 101:\n\tHello and thank you for choosing the Syndicate for your nuclear information needs.\nToday's crash course will deal with the operation of a Fusion Class Nanotrasen made Nuclear Device.\nFirst and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE.\nPressing any button on the compacted bomb will cause it to extend and bolt itself into place.\nIf this is done to unbolt it one must compeltely log in which at this time may not be possible.\nTo make the device functional:\n1. Place bomb in designated detonation zone\n2. Extend and anchor bomb (attack with hand).\n3. Insert Nuclear Auth. Disk into slot.\n4. Type numeric code into keypad ([nuke_code]).\n\tNote: If you make a mistake press R to reset the device.\n5. Press the E button to log onto the device\nYou now have activated the device. To deactivate the buttons at anytime for example when\nyou've already prepped the bomb for detonation remove the auth disk OR press the R ont he keypad.\nNow the bomb CAN ONLY be detonated using the timer. A manual det. is not an option.\n\tNote: Nanotrasen is a pain in the neck.\nToggle off the SAFETY.\n\tNote: You wouldn't believe how many Syndicate Operatives with doctorates have forgotten this step\nSo use the - - and + + to set a det time between 5 seconds and 10 minutes.\nThen press the timer toggle button to start the countdown.\nNow remove the auth. disk so that the buttons deactivate.\n\tNote: THE BOMB IS STILL SET AND WILL DETONATE\nNow before you remove the disk if you need to move the bomb you can:\nToggle off the anchor, move it, and re-anchor.\n\nGood luck. Remember the order:\nDisk, Code, Safety, Timer, Disk, RUN!\nIntelligence Analysts believe that they are hiding the disk in the bridge. Your space ship will not leave until the bomb is armed and timing.\nGood luck!" return -/datum/game_mode/nuclear/proc/equip_syndicate(mob/living/carbon/human/synd_mob) +/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate) + var/datum/objective/nuclear/syndobj = new + syndobj.owner = syndicate + syndicate.objectives += syndobj + +/datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1) + if (you_are) + syndicate.current << "\blue You are a [syndicate_name()] agent!" + var/obj_count = 1 + for(var/datum/objective/objective in syndicate.objectives) + syndicate.current << "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + return + +/datum/game_mode/proc/random_radio_frequency() + return 1337 + +/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob) var/radio_freq = random_radio_frequency() var/obj/item/device/radio/R = new /obj/item/device/radio/headset(synd_mob) @@ -155,103 +217,83 @@ synd_mob.equip_if_possible(new /obj/item/ammo_magazine(synd_mob), synd_mob.slot_in_backpack) synd_mob.equip_if_possible(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), synd_mob.slot_in_backpack) //Because it needed to be upgraded by someone - Micro synd_mob.equip_if_possible(new /obj/item/weapon/gun/projectile(synd_mob), synd_mob.slot_belt) - -/datum/game_mode/nuclear/check_win() - if (src.nuke_detonated) - if(src.derp) - finished = 3 - return - if(src.herp) - finished = 4 - return - finished = 1 - return - - for(var/obj/item/weapon/disk/nuclear/D in world) - var/disk_area = get_area(D) - if(istype(disk_area, /area/shuttle/escape/centcom)) - finished = 2 - break - - return - -/datum/game_mode/nuclear/check_finished() - if((src.finished) || (emergency_shuttle.location==2)) - return 1 - else - return 0 - -/datum/game_mode/nuclear/declare_completion() - for(var/obj/item/weapon/disk/nuclear/D in world) - var/disk_area = get_area(D) - if(istype(disk_area, /area/shuttle/escape/centcom)) - finished = 2 - break - - switch(finished) - if(0) - world << "Neutral Victory" - world << "[syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted. Next time, don't lose the disk!" - for(var/datum/mind/M in syndicates) - if(!M.current) - continue - if(M.current.client) - world << text("[M.current.key] was [M.current.real_name] [M.current.stat == 2 ? "(DEAD)" : ""]") - - if(1) - world << "[syndicate_name()] operatives have destroyed [station_name()]!" - for(var/datum/mind/M in syndicates) - if(!M.current) - continue - if(M.current.client) - world << text("[M.current.key] was [M.current.real_name] [M.current.stat == 2 ? "(DEAD)" : ""]") - - if(2) - world << "The Research Staff has stopped the [syndicate_name()] Operatives!" - for(var/datum/mind/M in ticker.minds) - if (!M.current) - continue - if ((M.current.client) && !(locate(M) in syndicates)) - world << text("[M.current.key] was [M.current.real_name] [M.current.stat == 2 ? "(DEAD)" : ""]") - - if(3) - world << "Neutral Victory" - world << "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't lose the disk!" - for(var/datum/mind/M in syndicates) - if(!M.current) - continue - if(M.current.client) - world << text("[M.current.key] was [M.current.real_name] [M.current.stat == 2 ? "(DEAD)" : ""]") - if(4) - world << "Total Annihilation" - world << "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" - for(var/datum/mind/M in syndicates) - if(!M.current) - continue - if(M.current.client) - world << text("[M.current.key] was [M.current.real_name] [M.current.stat == 2 ? "(DEAD)" : ""]") return 1 -/datum/game_mode/nuclear/proc/get_possible_syndicates() - var/list/candidates = list() +/datum/game_mode/nuclear/check_win() + if (nukes_left == 0) + return 1 + return ..() - for(var/mob/new_player/player in world) - if((player.client) && (player.ready)) - if(player.preferences.be_syndicate) - candidates += player.mind +/datum/game_mode/proc/is_operatives_are_dead() + for(var/datum/mind/operative_mind in syndicates) + if (!istype(operative_mind.current,/mob/living/carbon/human) && operative_mind.current.stat!=2) + return 0 + return 1 - if(candidates.len < 1) - for(var/mob/new_player/player in world) - if((player.client) && (player.ready)) - candidates += player.mind +/datum/game_mode/nuclear/declare_completion() + var/disk_rescued = 1 + for(var/obj/item/weapon/disk/nuclear/D in world) + var/disk_area = get_area(D) + if(!is_type_in_list(disk_area, centcom_areas)) + disk_rescued = 0 + break + var/crew_evacuated = (emergency_shuttle.location==2) + //var/operatives_are_dead = is_operatives_are_dead() - if(candidates.len < 1) - return null - else - return candidates + + //nukes_left + //station_was_nuked + //derp //Used for tracking if the syndies actually haul the nuke to the station + //herp //Used for tracking if the syndies got the shuttle off of the z-level -/datum/game_mode/nuclear/proc/random_radio_frequency() - return 1337 + if (!disk_rescued && station_was_nuked && !herp) + world << "Syndicate Victory!" + world << "[syndicate_name()] operatives have destroyed [station_name()]!" + + else if (!disk_rescued && station_was_nuked && herp) + world << "Total Annihilation" + world << "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" + + else if (!disk_rescued && !station_was_nuked && derp && !herp) + world << "Neutral Victory" + world << "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't lose the disk!" + + else if (!disk_rescued && !station_was_nuked && derp && herp) + world << "[syndicate_name()] operatives have earned Darwin Award!" + world << "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't lose the disk!" + + else if ( disk_rescued ) + world << "Crew Victory" + world << "The Research Staff has saved the disc and stopped the [syndicate_name()] Operatives!" + + else if (!disk_rescued && is_operatives_are_dead()) + world << "Crew Victory" + world << "The Research Staff has stopped the [syndicate_name()] Operatives!" + + else if (!disk_rescued && crew_evacuated) + world << "Neutral Victory" + world << "[syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted. Next time, don't lose the disk!" + + else if (!disk_rescued && !crew_evacuated) + world << "Neutral Victory" + world << "Round was mysteriously interrupted!" + + ..() + return + + +/datum/game_mode/proc/auto_declare_completion_nuclear() + if (syndicates.len!=0 || (ticker && istype(ticker.mode,/datum/game_mode/nuclear))) + world << "The Syndicate operatives were: " + for(var/datum/mind/mind in syndicates) + var/text = "" + if(mind.current) + text += "[mind.key] was [mind.current.real_name]" + if(mind.current.stat == 2) + text += " (Dead)" + else + text += "[mind.key] (character destroyed)" + world << text /proc/nukelastname(var/mob/M as mob) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. var/randomname = pick(last_names) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 4c62fec62fa..bcd77463a79 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -54,9 +54,11 @@ ..() if (usr.stat || usr.restrained()) return - if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") + if ( ! (istype(usr, /mob/living/carbon/human) || \ + istype(usr, /mob/living/silicon) || \ + istype(usr, /mob/living/carbon/monkey) && ticker && ticker.mode.name == "monkey") ) usr << "\red You don't have the dexterity to do this!" - return + return 1 if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) usr.machine = src if (href_list["auth"]) @@ -136,6 +138,8 @@ src.safety = 1 src.icon_state = "nuclearbomb3" playsound(src,'Alarm.ogg',100,0,5) + if (ticker && ticker.mode) + ticker.mode.explosion_in_progress = 1 sleep(100) /* @@ -145,62 +149,34 @@ */ enter_allowed = 0 var/derp = 0 - var/herp = 0 - var/area/A = src.loc.loc - if (istype( A, /area)) - if (A.name == "Space") + for (var/turf/T in range(1,src)) + if (!is_type_in_list(T.loc, the_station_areas)) derp = 1 - if (istype(A, /area/syndicate_station)) - derp = 1 - if (A.name == "Wizard's Den") - derp = 1 - if (!derp) - for(var/direction in cardinal) - for(var/area/target in get_step(src,direction)) - if (target.name == "Space") - derp = 1 - if (istype(target, /area/syndicate_station)) - derp = 1 - if (target.name == "Wizard's Den") - derp = 1 - if (syndicate_station_at_station) - herp = 1 + break + if (ticker && ticker.mode && ticker.mode.name == "nuclear emergency") + ticker.mode:herp = syndicate_station_at_station + ticker.mode:derp = derp + for(var/mob/M in world) if(M.client) spawn(0) M.client.station_explosion_cinematic(derp) - - if(ticker.mode.name == "nuclear emergency") - ticker.mode:nuke_detonated = 1 - if (derp) ticker.mode:derp = 1 - ticker.mode.check_win() - ticker.mode.declare_completion() - sleep(110) - if (ticker.mode.name != "nuclear emergency" || !derp || !herp) - ticker.mode.declare_extra_completion()//Declaring regular completion could cause issues. - world << "The station was destoyed by the nuclear blast! Resetting in 30 seconds!" - sleep(300) - log_game("Rebooting due to nuclear destruction of station") - world.Reboot() - return + if (ticker && ticker.mode) + ticker.mode.explosion_in_progress = 0 + if(ticker.mode.name == "nuclear emergency") + ticker.mode:nukes_left -- + ticker.mode.station_was_nuked = (derp==0) - else if (ticker.mode.name == "nuclear emergency" && herp) - world << "Everyone died in the blast, including the Syndicate Agents. Resetting in 30 seconds!" + else + world << "The station was destoyed by the nuclear blast!" + ticker.mode.station_was_nuked = 1 + //TODO: derped blast should partially damage nearest objects + // and do not reboot the game. Also make it work properly on other z-levels --rastaf0 - sleep(300) - log_game("Rebooting due to nuclear detonation") - world.Reboot() - return + ticker.mode.check_win() - else if (ticker.mode.name == "nuclear emergency" && derp) - world << "Resetting in 30 seconds!" - - sleep(300) - log_game("Rebooting due to nuclear detonation") - world.Reboot() - return /obj/item/weapon/disk/nuclear/Del() if (ticker.mode && ticker.mode.name == "nuclear emergency") diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 782ca236086..6d697df62d3 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -15,10 +15,12 @@ datum return 1 find_target() + //world << "DEBUG: proc/find_target():" var/list/possible_targets = list() for(var/datum/mind/possible_target in ticker.minds) - if(possible_target != owner && ishuman(possible_target)) + //world << "-> [possible_target.current.real_name]" + if(possible_target != owner && ishuman(possible_target.current)) possible_targets += possible_target if(possible_targets.len > 0) @@ -26,7 +28,7 @@ datum find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned. for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && ishuman(possible_target) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) + if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) target = possible_target break @@ -343,6 +345,18 @@ datum absorb proc/gen_amount_goal() //this doesn't work -- should work now, changed it a bit -- Urist target_amount = rand (4,6) + if (ticker) + var/n_p = 1 //autowin + if (ticker.current_state == GAME_STATE_SETTING_UP) + for(var/mob/new_player/P in world) + if(P.client && P.ready && P.mind!=owner) + n_p ++ + else if (ticker.current_state == GAME_STATE_PLAYING) + for(var/mob/living/carbon/human/P in world) + if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) + n_p ++ + target_amount = min(target_amount, n_p) + explanation_text = "Absorb [target_amount] compatible genomes." return target_amount diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 2e70fd14f3c..4933b3cb4ca 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -7,14 +7,15 @@ // If the rev icons start going wrong for some reason, ticker.mode:update_all_rev_icons() can be called to correct them. // If the game somtimes isn't registering a win properly, then ticker.mode.check_win() isn't being called somewhere. +/datum/game_mode + var/list/datum/mind/head_revolutionaries = list() + var/list/datum/mind/revolutionaries = list() + /datum/game_mode/revolution name = "revolution" config_tag = "revolution" - - var/list/datum/mind/head_revolutionaries = list() - var/list/datum/mind/revolutionaries = list() - var/list/datum/mind/heads_of_staff = list()//This was annoying to check manually. Now I won't have to. var/finished = 0 + var/const/max_headrevs = 3 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) @@ -25,74 +26,123 @@ world << "The current game mode is - Revolution!" world << "Some crewmembers are attempting to start a revolution!
\nRevolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
\nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head).
" + +/datum/game_mode/revolution/can_start() //this proc can not do its job properly for this gamemode, pre_setup can fail even whe can_start told everything is okay. --rastaf0 + var/list/mob/new_player/possible_headrevs = new + var/list/mob/new_player/possible_heads = new + for(var/mob/new_player/P in world) + if (!P.client || !P.ready) + continue + if(!jobban_isbanned(P, "Syndicate")) + possible_headrevs += P + for (var/i in head_positions) + if(!jobban_isbanned(P, i)) + possible_heads += P + break + //lets do as best as we can + if (possible_headrevs.len==0) + return 0 + if (possible_heads.len==0) + return 0 + if (possible_headrevs.len<=max_headrevs) + var/list/rest_heads = possible_heads - possible_headrevs + return (rest_heads.len>0) + return 1 //read as "maybe" + + /////////////////////////////////////////////////////////////////////////////// //Gets the round setup, cancelling if there's not enough players at the start// /////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/pre_setup() + var/list/datum/mind/possible_headrevs = get_players_for_role(BE_REV) + + for (var/i=1 to max_headrevs) + if (possible_headrevs.len==0) + break + var/datum/mind/lenin = pick(possible_headrevs) + possible_headrevs -= lenin + head_revolutionaries += lenin + must_be_human += lenin + can_not_be_head += lenin + + if(head_revolutionaries.len==0) + return 0 + + DivideOccupations() + var/headless=1 + for(var/mob/new_player/player in world) + if(player.mind && player.mind.assigned_role in head_positions) + headless=0 + break + if (headless) + head_revolutionaries.len = 0 + must_be_human.len = 0 + can_not_be_head.len = 0 + ResetOccupations() //clean up + return 0 + return 1 + /datum/game_mode/revolution/post_setup() - - var/list/revs_possible = list() - revs_possible = get_possible_revolutionaries() - var/list/heads = list() - heads = get_living_heads() - var/rev_number = 0 - - if(!revs_possible || !heads) - world << " \red Not enough players for revolution game mode. Restarting world in 5 seconds." - sleep(50) - world.Reboot() - return - - if(revs_possible.len >= 3) - rev_number = 3 - else - rev_number = revs_possible.len - - while(rev_number > 0) - head_revolutionaries += pick(revs_possible) - revs_possible -= head_revolutionaries - rev_number-- + var/list/heads = get_living_heads() for(var/datum/mind/rev_mind in head_revolutionaries) for(var/datum/mind/head_mind in heads) var/datum/objective/assassinate/rev_obj = new rev_obj.owner = rev_mind - rev_obj.find_target_by_role(head_mind.assigned_role) + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.assigned_role]." rev_mind.objectives += rev_obj - heads_of_staff += head_mind equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO equip_revolutionary(rev_mind.current) update_rev_icons_added(rev_mind) for(var/datum/mind/rev_mind in head_revolutionaries) - var/obj_count = 1 - rev_mind.current << "\blue You are a member of the revolutionaries' leadership!" - for(var/datum/objective/objective in rev_mind.objectives) - rev_mind.current << "Objective #[obj_count]: [objective.explanation_text]" - rev_mind.special_role = "Head Revolutionary" - obj_count++ - modePlayer = head_revolutionaries + greet_revolutionary(rev_mind) + modePlayer += head_revolutionaries spawn (rand(waittime_l, waittime_h)) send_intercept() + ..() + +/datum/game_mode/proc/forge_revolutionary_objectives(var/datum/mind/rev_mind) + var/list/heads = get_living_heads() + for(var/datum/mind/head_mind in heads) + var/datum/objective/assassinate/rev_obj = new + rev_obj.owner = rev_mind + rev_obj.target = head_mind + rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.assigned_role]." + rev_mind.objectives += rev_obj + +/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) + var/obj_count = 1 + if (you_are) + rev_mind.current << "\blue You are a member of the revolutionaries' leadership!" + for(var/datum/objective/objective in rev_mind.objectives) + rev_mind.current << "Objective #[obj_count]: [objective.explanation_text]" + rev_mind.special_role = "Head Revolutionary" + obj_count++ ///////////////////////////////////////////////////////////////////////////////// //This are equips the rev heads with their gear, and makes the clown not clumsy// ///////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/equip_revolutionary(mob/living/carbon/human/rev_mob) - if(!istype(rev_mob)) +/datum/game_mode/proc/equip_revolutionary(mob/living/carbon/human/mob) + if(!istype(mob)) return - var/flashspawned = 0 - if (rev_mob.r_store && !flashspawned) - rev_mob.equip_if_possible(new /obj/item/device/flash(rev_mob), rev_mob.slot_l_store) - flashspawned = 1 - if (rev_mob.l_store && !flashspawned) - rev_mob.equip_if_possible(new /obj/item/device/flash(rev_mob), rev_mob.slot_r_store) - flashspawned = 1 - if (istype(rev_mob.back, /obj/item/weapon/storage) && !flashspawned) - rev_mob.equip_if_possible(new /obj/item/device/flash(rev_mob), rev_mob.slot_in_backpack) - flashspawned = 1 - if (!flashspawned) - rev_mob << "The Syndicate were unfortunately unable to get you a flash." + var/obj/item/device/flash/T = new(mob) + + var/list/slots = list ( + "backpack" = mob.slot_in_backpack, + "left pocket" = mob.slot_l_store, + "right pocket" = mob.slot_r_store, + "left hand" = mob.slot_l_hand, + "right hand" = mob.slot_r_hand, + ) + var/where = mob.equip_in_one_of_slots(T, slots) + if (!where) + mob << "The Syndicate were unfortunately unable to get you a flash." + else + mob << "The flash in your [where] would help you to use your extremal persuade skill." + return 1 ////////////////////////////////////// //Checks if the revs have won or not// @@ -116,18 +166,20 @@ /////////////////////////////////////////////////// //Deals with converting players to the revolution// /////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/add_revolutionary(datum/mind/rev_mind) - var/list/uncons = get_unconvertables() - if(!(rev_mind in revolutionaries) && !(rev_mind in head_revolutionaries) && !(rev_mind in uncons)) - revolutionaries += rev_mind - rev_mind.current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" - rev_mind.special_role = "Revolutionary" - update_rev_icons_added(rev_mind) - +/datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind) + if((rev_mind.assigned_role in head_positions) || (rev_mind.assigned_role in list("Security Officer", "Detective", "Warden"))) + return 0 + if((rev_mind in revolutionaries) || (rev_mind in head_revolutionaries)) + return 0 + revolutionaries += rev_mind + rev_mind.current << "\red You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!" + rev_mind.special_role = "Revolutionary" + update_rev_icons_added(rev_mind) + return 1 ////////////////////////////////////////////////////////////////////////////// //Deals with players being converted from the revolution (Not a rev anymore)// ////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/remove_revolutionary(datum/mind/rev_mind) +/datum/game_mode/proc/remove_revolutionary(datum/mind/rev_mind) if(rev_mind in revolutionaries) revolutionaries -= rev_mind rev_mind.current << "\red You have been brainwashed! You are no longer a revolutionary!" @@ -142,7 +194,7 @@ // -Possibly caused by cloning of a standard rev///////////////////////////////////////////////// //-UNCONFIRMED: DECONVERTED REVS NOT LOSING THEIR ICON PROPERLY////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/update_all_rev_icons() +/datum/game_mode/proc/update_all_rev_icons() spawn(0) for(var/datum/mind/head_rev_mind in head_revolutionaries) if(head_rev_mind.current) @@ -186,7 +238,7 @@ //Keeps track of converted revs icons/////////////// //Refer to above bugs. They may apply here as well// //////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/update_rev_icons_added(datum/mind/rev_mind) +/datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) spawn(0) for(var/datum/mind/head_rev_mind in head_revolutionaries) if(head_rev_mind.current) @@ -211,20 +263,20 @@ /////////////////////////////////// //Keeps track of deconverted revs// /////////////////////////////////// -/datum/game_mode/revolution/proc/update_rev_icons_removed(datum/mind/rev_mind) +/datum/game_mode/proc/update_rev_icons_removed(datum/mind/rev_mind) spawn(0) for(var/datum/mind/head_rev_mind in head_revolutionaries) if(head_rev_mind.current) if(head_rev_mind.current.client) for(var/image/I in head_rev_mind.current.client.images) - if(I.loc == rev_mind.current) + if((I.icon_state == "cult"|| I.icon_state == "rev_head") && I.loc == rev_mind.current) del(I) for(var/datum/mind/rev_mind_1 in revolutionaries) if(rev_mind_1.current) if(rev_mind_1.current.client) for(var/image/I in rev_mind_1.current.client.images) - if(I.loc == rev_mind.current) + if((I.icon_state == "cult"|| I.icon_state == "rev_head") && I.loc == rev_mind.current) del(I) if(rev_mind.current) if(rev_mind.current.client) @@ -232,58 +284,6 @@ if(I.icon_state == "rev" || I.icon_state == "rev_head") del(I) -////////////////////////////////////////////////// -//Creates a list of anyone that can be converted// -////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/get_possible_revolutionaries() - var/list/candidates = list() - - for(var/mob/living/carbon/human/player in world) - if(player.client) - if(player.be_syndicate) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/living/carbon/human/player in world) - if(player.client) - candidates += player.mind - - var/list/uncons = get_unconvertables() - for(var/datum/mind/mind in uncons) - candidates -= mind - - if(candidates.len < 1) - return null - else - return candidates - -//////////////////////////// -//Keeps track of all heads// -//////////////////////////// -/datum/game_mode/revolution/proc/get_all_heads() - var/list/heads = list() - - for(var/mob/player in world) - if(player.mind) - var/role = player.mind.assigned_role - if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer")) - heads += player.mind - - return heads - -///////////////////////////////////////////////////// -//Defines the list of jobs that cannot be converted// -///////////////////////////////////////////////////// -/datum/game_mode/revolution/proc/get_unconvertables() - var/list/ucs = list() - for(var/mob/living/carbon/human/player in world) - if(player.mind) - var/role = player.mind.assigned_role - if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director", "Security Officer", "Detective", "Warden", "AI", "Chief Medical Officer")) - ucs += player.mind - - return ucs - ////////////////////////// //Checks for rev victory// ////////////////////////// @@ -308,56 +308,58 @@ //Announces the end of the game with all relavent information stated// ////////////////////////////////////////////////////////////////////// /datum/game_mode/revolution/declare_completion() - - var/text = "" if(finished == 1) world << "\red The heads of staff were killed! The revolutionaries win!" else if(finished == 2) world << "\red The heads of staff managed to stop the revolution!" + ..() + return 1 - world << "The head revolutionaries were: " - for(var/datum/mind/rev_mind in head_revolutionaries) - text = "" - if(rev_mind.current) - text += "[rev_mind.current.real_name]" - if(rev_mind.current.stat == 2) - text += " (Dead)" +/datum/game_mode/proc/auto_declare_completion_revolution() + if (head_revolutionaries.len!=0 || istype(ticker.mode,/datum/game_mode/revolution)) + var/list/names = new + for(var/datum/mind/i in head_revolutionaries) + if(i.current) + names += i.current.real_name + ((i.current.stat==2)?" (Dead)":"") else - text += " (Survived!)" - else - text += "[rev_mind.key] (character destroyed)" - - world << text - - text = "" - world << "The converted revolutionaries were: " - for(var/datum/mind/rev_nh_mind in revolutionaries) - if(rev_nh_mind.current) - text += "[rev_nh_mind.current.real_name]" - if(rev_nh_mind.current.stat == 2) - text += " (Dead)" + names += "[i.key] (character destroyed)" + world << "The head revolutionaries were: " + world << english_list(names) + if (revolutionaries.len!=0 || istype(ticker.mode,/datum/game_mode/revolution)) + var/list/names = new + for(var/datum/mind/i in revolutionaries) + if(i.current) + names += i.current.real_name + ((i.current.stat==2)?" (Dead)":"") else - text += " (Survived!)" + names += "[i.key] (character destroyed)" + if (revolutionaries.len!=0) + world << "The ordinary revolutionaries were: " + world << english_list(names) else - text += "[rev_nh_mind.key] (character destroyed)" - text += ", " + world << "The head revolutionaries failed to enlist any ordinary revolutionaries" + var/list/heads = get_all_heads() + var/list/targets = new + for (var/datum/mind/i in head_revolutionaries) + for (var/datum/objective/assassinate/o in i.objectives) + targets |= o.target + if (head_revolutionaries.len!=0 || \ + revolutionaries.len!=0 || \ + istype(ticker.mode,/datum/game_mode/revolution)) - world << text - - world << "The heads of staff were: " - var/list/heads = list() - heads = get_all_heads() - for(var/datum/mind/head_mind in heads) - text = "" - if(head_mind.current) - text += "[head_mind.current.real_name]" - if(head_mind.current.stat == 2) - text += " (Dead)" + var/list/names = new + for(var/datum/mind/i in heads) + if(i.current) + names += i.current.real_name + ((i.current.stat==2)?" (Dead)":"") + ((i in targets)?"(target)":"") else - text += " (Survived!)" + names += "[i.key] (character destroyed)" + ((i in targets)?"(target)":"") + if (heads.len!=0) + world << "The heads of staff were: " + world << english_list(names) else - text += "[head_mind.key] (character destroyed)" + world << "There were no any heads of staff on the station." - world << text - - return 1 \ No newline at end of file +/proc/is_convertable_to_rev(datum/mind/mind) + return istype(mind) && \ + istype(mind.current, /mob/living/carbon/human) && \ + !(mind.assigned_role in head_positions) && \ + !(mind.assigned_role in list("Security Officer", "Detective", "Warden")) diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index e5fb93f5865..03a70840e00 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -139,4 +139,5 @@ M.equip_if_possible(new /obj/item/clothing/head/helmet/swat(M), M.slot_head) del(A) continue - */ \ No newline at end of file +*/ + diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index b205f180073..a23cafdfa14 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,7 +1,12 @@ +/datum/game_mode + // this includes admin-appointed traitors and multitraitors. Easy! + var/list/datum/mind/traitors = list() + /datum/game_mode/traitor name = "traitor" config_tag = "traitor" + var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target @@ -18,7 +23,7 @@ var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly - +/* var/const/laser = 1 var/const/hand_tele = 2 var/const/plasma_bomb = 3 @@ -34,35 +39,36 @@ var/const/percentage_plasma_destroy = 70 // what percentage of the plasma tanks you gotta destroy var/const/percentage_station_cut_power = 80 // what percentage of the tiles have to have power cut var/const/percentage_station_evacuate = 80 // what percentage of people gotta leave - you also gotta change the objective in the traitor menu - +*/ 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/const/traitors_possible = 4 //hard limit on traitors if scaling is turned off + var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/const/traitor_scaling_coeff = 5.0 //how much does the amount of players get divided by to determine traitors /datum/game_mode/traitor/announce() world << "The current game mode is - Traitor!" - world << "There is a syndicate traitor on the station. Do not let the traitor succeed!!" + world << "There is a syndicate traitor on the station. Do not let the traitor succeed!" + +/datum/game_mode/traitor/can_start() + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 /datum/game_mode/traitor/pre_setup() - var/list/possible_traitors = get_possible_traitors() - - var/num_players = 0 - for(var/mob/new_player/P in world) - if(P.client && P.ready) - num_players++ - - var/num_traitors = 1 + var/list/possible_traitors = get_players_for_role(BE_TRAITOR) // stop setup if no possible traitors if(!possible_traitors.len) return 0 + var/num_traitors = 1 + if(config.traitor_scaling) - num_traitors = max(1, round((num_players)/(traitor_scaling_coeff))) + num_traitors = max(1, round((num_players())/(traitor_scaling_coeff))) else - num_traitors = max(1, min(num_players, traitors_possible)) + num_traitors = max(1, min(num_players(), traitors_possible)) // log_game("Number of traitors: [num_traitors]") // message_admins("Players counted: [num_players] Number of traitors chosen: [num_traitors]") @@ -72,93 +78,84 @@ break var/datum/mind/traitor = pick(possible_traitors) traitors += traitor + traitor.special_role = "traitor" possible_traitors.Remove(traitor) - for(var/datum/mind/traitor in traitors) - if(!traitor || !istype(traitor)) - traitors.Remove(traitor) - continue - if(istype(traitor)) - traitor.special_role = "traitor" - if(!traitors.len) return 0 return 1 /datum/game_mode/traitor/post_setup() for(var/datum/mind/traitor in traitors) - if(istype(traitor.current, /mob/living/silicon)) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective + forge_traitor_objectives(traitor) + spawn(rand(10,100)) + finalize_traitor(traitor) + greet_traitor(traitor) + modePlayer += traitors + spawn (rand(waittime_l, waittime_h)) + send_intercept() + ..() + return 1 - var/datum/objective/survive/survive_objective = new - survive_objective.owner = traitor - traitor.objectives += survive_objective +/datum/game_mode/proc/forge_traitor_objectives(var/datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective - else - switch(rand(1,100)) - if(1 to 50) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective - switch(rand(1,100)) - if(1 to 90) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = traitor + traitor.objectives += survive_objective + + else + switch(rand(1,100)) + if(1 to 50) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective + switch(rand(1,100)) + if(1 to 90) + if (!(locate(/datum/objective/escape) in traitor.objectives)) var/datum/objective/escape/escape_objective = new escape_objective.owner = traitor traitor.objectives += escape_objective - else + else + if (!(locate(/datum/objective/hijack) in traitor.objectives)) var/datum/objective/hijack/hijack_objective = new hijack_objective.owner = traitor traitor.objectives += hijack_objective + return +/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) + traitor.current << "You are the traitor." + var/obj_count = 1 + for(var/datum/objective/objective in traitor.objectives) + traitor.current << "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + return - - spawn(rand(10,100)) - traitor.current << "You are the traitor." - - var/obj_count = 1 - for(var/datum/objective/objective in traitor.objectives) - traitor.current << "Objective #[obj_count]: [objective.explanation_text]" - obj_count++ - if (istype(traitor.current, /mob/living/silicon)) - add_law_zero(traitor.current) - else - equip_traitor(traitor.current) - - modePlayer = traitors - spawn (rand(waittime_l, waittime_h)) - send_intercept() - -/datum/game_mode/traitor/proc/get_possible_traitors() - var/list/candidates = list() - for(var/mob/new_player/player in world) - if (player.client && player.ready) - if(player.preferences.be_syndicate) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/new_player/player in world) - if (player.client && player.ready) - candidates += player.mind - - return candidates +/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) + if (istype(traitor.current, /mob/living/silicon)) + add_law_zero(traitor.current) + else + equip_traitor(traitor.current) + return /datum/game_mode/traitor/declare_completion() return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. -/datum/game_mode/traitor/proc/add_law_zero(mob/living/silicon/ai/killer) +/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) var/law = "Accomplish your objectives at all costs." killer << "Your laws have been changed!" - killer:set_zeroth_law(law) + killer.set_zeroth_law(law) killer << "New law: 0. [law]" //Begin code phrase. @@ -176,18 +173,134 @@ killer << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." //End code phrase. -/datum/game_mode/traitor/proc/get_mob_list() - var/list/mobs = list() - for(var/mob/living/player in world) - if (player.client) - mobs += player - return mobs +/datum/game_mode/proc/auto_declare_completion_traitor() + for(var/datum/mind/traitor in traitors) + var/traitor_name -/datum/game_mode/traitor/proc/pick_human_name_except(excluded_name) - var/list/names = list() - for(var/mob/living/player in world) - if (player.client && (player.real_name != excluded_name)) - names += player.real_name - if(!names.len) - return null - return pick(names) \ No newline at end of file + if(traitor.current) + if(traitor.current == traitor.original) + traitor_name = "[traitor.current.real_name] (played by [traitor.key])" + else if (traitor.original) + traitor_name = "[traitor.current.real_name] (originally [traitor.original.real_name]) (played by [traitor.key])" + else + traitor_name = "[traitor.current.real_name] (original character destroyed) (played by [traitor.key])" + else + traitor_name = "[traitor.key] (character destroyed)" + var/special_role_text = traitor.special_role?(lowertext(traitor.special_role)):"antagonist" + world << "The [special_role_text] was [traitor_name]" + if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. + var/traitorwin = 1 + var/count = 1 + for(var/datum/objective/objective in traitor.objectives) + if(objective.check_completion()) + world << "Objective #[count]: [objective.explanation_text] \green Success" + else + world << "Objective #[count]: [objective.explanation_text] \red Failed" + traitorwin = 0 + count++ + + if(traitorwin) + world << "The [special_role_text] was successful!" + else + world << "The [special_role_text] has failed!" + return 1 + + + +/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) + if (!istype(traitor_mob)) + return + . = 1 + if (traitor_mob.mind) + if (traitor_mob.mind.assigned_role == "Clown") + traitor_mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." + traitor_mob.mutations &= ~CLOWN + + // find a radio! toolbox(es), backpack, belt, headset + var/loc = "" + var/obj/item/device/R = null //Hide the uplink in a PDA if available, otherwise radio + if (!R && istype(traitor_mob.belt, /obj/item/device/pda)) + R = traitor_mob.belt + loc = "on your belt" + if (!R && istype(traitor_mob.wear_id, /obj/item/device/pda)) + R = traitor_mob.wear_id + loc = "on your jumpsuit" + if (!R && istype(traitor_mob.wear_id, /obj/item/device/pda)) + R = traitor_mob.wear_id + loc = "on your jumpsuit" + if (!R && istype(traitor_mob.l_hand, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = traitor_mob.l_hand + var/list/L = S.return_inv() + for (var/obj/item/device/radio/foo in L) + R = foo + loc = "in the [S.name] in your left hand" + break + if (!R && istype(traitor_mob.r_hand, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = traitor_mob.r_hand + var/list/L = S.return_inv() + for (var/obj/item/device/radio/foo in L) + R = foo + loc = "in the [S.name] in your right hand" + break + if (!R && istype(traitor_mob.back, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = traitor_mob.back + var/list/L = S.return_inv() + for (var/obj/item/device/radio/foo in L) + R = foo + loc = "in the [S.name] on your back" + break + if (!R && traitor_mob.w_uniform && istype(traitor_mob.belt, /obj/item/device/radio)) + R = traitor_mob.belt + loc = "on your belt" + if (!R && istype(traitor_mob.ears, /obj/item/device/radio)) + R = traitor_mob.ears + loc = "on your head" + if (!R) + traitor_mob << "Unfortunately, the Syndicate wasn't able to get you a radio." + . = 0 + else + if (istype(R, /obj/item/device/radio)) + // generate list of radio freqs + var/freq = 1441 + var/list/freqlist = list() + while (freq <= 1489) + if (freq < 1451 || freq > 1459) + freqlist += freq + freq += 2 + if ((freq % 2) == 0) + freq += 1 + freq = freqlist[rand(1, freqlist.len)] + + var/obj/item/weapon/syndicate_uplink/T = new /obj/item/weapon/syndicate_uplink(R) + R:traitorradio = T + R:traitor_frequency = freq + T.name = R.name + T.icon_state = R.icon_state + T.origradio = R + traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features." + traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).") + else if (istype(R, /obj/item/device/pda)) + // generate a passcode if the uplink is hidden in a PDA + var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" + + var/obj/item/weapon/integrated_uplink/T = new /obj/item/weapon/integrated_uplink(R) + R:uplink = T + T.lock_code = pda_pass + T.hostpda = R + traitor_mob << "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features." + traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).") + //Begin code phrase. + if(!safety)//If they are not a rev. Can be added on to. + traitor_mob << "The Syndicate provided you with the following information on how to identify other agents:" + if(prob(80)) + traitor_mob << "\red Code Phrase: \black [syndicate_code_phrase]" + traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]") + else + traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code phrase." + if(prob(80)) + traitor_mob << "\red Code Response: \black [syndicate_code_response]" + traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]") + else + traitor_mob << "Unfortunetly, the Syndicate did not provide you with a code response." + traitor_mob << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." + //End code phrase. diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index f6822a1cc23..4504863d9bf 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -1,9 +1,11 @@ + +/datum/game_mode + var/list/datum/mind/wizards = list() + /datum/game_mode/wizard name = "wizard" config_tag = "wizard" - var/datum/mind/wizard - var/list/datum/mind/wizards = list() var/finished = 0 var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time @@ -53,30 +55,44 @@ world << "The current game mode is - Wizard!" world << "There is a \red SPACE WIZARD\black on the station. You can't let him achieve his objective!" +/datum/game_mode/wizard/can_start() + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 + /datum/game_mode/wizard/pre_setup() -// - var/list/possible_wizards = get_possible_wizards() - - if(possible_wizards.len>0) - wizard = pick(possible_wizards) - else - world << "A WIZARD COULD NOT BE SPAWNED FFFFFFUUUUCK" - - if(istype(wizard)) - wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. - wizard.special_role = "Wizard" - wizard.original = wizard.current - + var/list/datum/mind/possible_wizards = get_players_for_role(BE_WIZARD) + if(possible_wizards.len==0) + return 0 + var/datum/mind/wizard = pick(possible_wizards) + //possible_wizards-=wizard + wizards += wizard + modePlayer += wizard + wizard.assigned_role = "MODE" //So they aren't chosen for other jobs. + wizard.special_role = "Wizard" + wizard.original = wizard.current if(wizardstart.len == 0) wizard.current << "\red A starting location for you could not be found, please report this bug!" else - var/starting_loc = pick(wizardstart) - wizard.current.loc = starting_loc - + wizard.current.loc = pick(wizardstart) return 1 /datum/game_mode/wizard/post_setup() + for(var/datum/mind/wizard in wizards) + forge_wizard_objectives(wizard) + learn_basic_spells(wizard.current) + equip_wizard(wizard.current) + name_wizard(wizard.current) + greet_wizard(wizard) + spawn (rand(waittime_l, waittime_h)) + send_intercept() + ..() + return + + +/datum/game_mode/proc/forge_wizard_objectives(var/datum/mind/wizard) switch(rand(1,100)) if(1 to 30) @@ -85,18 +101,20 @@ kill_objective.find_target() wizard.objectives += kill_objective - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective + if (!(locate(/datum/objective/escape) in wizard.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = wizard + wizard.objectives += escape_objective if(31 to 60) var/datum/objective/steal/steal_objective = new steal_objective.owner = wizard steal_objective.find_target() wizard.objectives += steal_objective - var/datum/objective/escape/escape_objective = new - escape_objective.owner = wizard - wizard.objectives += escape_objective + if (!(locate(/datum/objective/escape) in wizard.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = wizard + wizard.objectives += escape_objective if(61 to 85) var/datum/objective/assassinate/kill_objective = new @@ -109,23 +127,26 @@ steal_objective.find_target() wizard.objectives += steal_objective - var/datum/objective/survive/survive_objective = new - survive_objective.owner = wizard - wizard.objectives += survive_objective + if (!(locate(/datum/objective/survive) in wizard.objectives)) + var/datum/objective/survive/survive_objective = new + survive_objective.owner = wizard + wizard.objectives += survive_objective else - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = wizard - wizard.objectives += hijack_objective + if (!(locate(/datum/objective/hijack) in wizard.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = wizard + wizard.objectives += hijack_objective + return - equip_wizard(wizard.current) - - spawn(0)//Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. - var/wizard_name_first = pick(wizard_first) - var/wizard_name_second = pick(wizard_second) - var/randomname = "[wizard_name_first] [wizard_name_second]" - var/newname = input(wizard.current, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) +/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob) + //Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. + var/wizard_name_first = pick(wizard_first) + var/wizard_name_second = pick(wizard_second) + var/randomname = "[wizard_name_first] [wizard_name_second]" + spawn(0) + var/newname = input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text if (length(newname) == 0) newname = randomname @@ -134,50 +155,35 @@ if (length(newname) >= 26) newname = copytext(newname, 1, 26) newname = dd_replacetext(newname, ">", "'") - wizard.current.real_name = newname - wizard.current.name = newname + wizard_mob.real_name = newname + wizard_mob.name = newname + return - wizards += wizard.current - - wizard.current << "\red You are the Space Wizard!" +/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1) + if (you_are) + wizard.current << "\red You are the Space Wizard!" wizard.current << "The Space Wizards Federation has given you the following tasks:" var/obj_count = 1 for(var/datum/objective/objective in wizard.objectives) wizard.current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ + return - spawn (rand(waittime_l, waittime_h)) - send_intercept() -/datum/game_mode/wizard/proc/get_possible_wizards() - var/list/candidates = list()//Shamelessly copied from nuke code. - - for(var/mob/new_player/player in world) - if((player.client) && (player.ready)) - if(player.be_syndicate) - candidates += player.mind - - if(candidates.len < 1) - for(var/mob/new_player/player in world) - if((player.client) && (player.ready)) - candidates += player.mind - - if(candidates.len < 1) - return null - else - return candidates - -/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) +/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob) if (!istype(wizard_mob)) return - if(!config.feature_object_spell_system) wizard_mob.verbs += /client/proc/jaunt wizard_mob.mind.special_verbs += /client/proc/jaunt else wizard_mob.spell_list += new /obj/proc_holder/spell/targeted/ethereal_jaunt(usr) +/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) + if (!istype(wizard_mob)) + return + //So zards properly get their items when they are admin-made. del(wizard_mob.wear_suit) del(wizard_mob.head) @@ -202,65 +208,58 @@ wizard_mob << "You will find a list of available spells in your spell book. Choose your magic arsenal carefully." wizard_mob << "In your pockets you will find two more important, magical artifacts. Use them as needed." wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") - -/datum/game_mode/wizard/declare_completion() - if(finished) - world << "\red The wizard has been killed by the crew! The Space Wizards Fediration has been taught a lesson they will not soon forget!" - - var/wizard_name - if(wizard.current) - if(wizard.current == wizard.original) - wizard_name = "[wizard.current.real_name] (played by [wizard.key])" - else if (wizard.original) - wizard_name = "[wizard.current.real_name] (originally [wizard.original.real_name]) (played by [wizard.key])" - else - wizard_name = "[wizard.current.real_name] (original character destroyed) (played by [wizard.key])" - else - wizard_name = "[wizard.key] (character destroyed)" - world << "The wizard was [wizard_name]" - var/count = 1 - - var/wizardwin = 1 - for(var/datum/objective/objective in wizard.objectives) - if(objective.check_completion()) - world << "Objective #[count]: [objective.explanation_text] \green Success" - else - world << "Objective #[count]: [objective.explanation_text] \red Failed" - wizardwin = 0 - count++ - - if(!finished) - if(wizardwin) - world << "The wizard was successful!" - else - world << "The wizard has failed!" - return 1 -/datum/game_mode/wizard/proc/get_mob_list() - var/list/mobs = list() - for(var/mob/living/player in world) - if (player.client) - mobs += player - return mobs - -/datum/game_mode/wizard/proc/pick_human_name_except(excluded_name) - var/list/names = list() - for(var/mob/living/player in world) - if (player.client && (player.real_name != excluded_name)) - names += player.real_name - if(!names.len) - return null - return pick(names) - /datum/game_mode/wizard/check_finished() - if(!wizard.current) - return 1 - if(wizard.current.stat == 2) - return 1 - else + var/wizards_alive = 0 + for(var/datum/mind/wizard in wizards) + if(!istype(wizard.current,/mob/living/carbon)) + continue + if(wizard.current.stat==2) + continue + wizards_alive++ + + if (wizards_alive) return ..() + else + finished = 1 + return 1 + +/datum/game_mode/wizard/declare_completion() + if(finished) + world << "\red The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Fediration has been taught a lesson they will not soon forget!" + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_wizard() + for(var/datum/mind/wizard in wizards) + var/wizard_name + if(wizard.current) + if(wizard.current == wizard.original) + wizard_name = "[wizard.current.real_name] (played by [wizard.key])" + else if (wizard.original) + wizard_name = "[wizard.current.real_name] (originally [wizard.original.real_name]) (played by [wizard.key])" + else + wizard_name = "[wizard.current.real_name] (original character destroyed) (played by [wizard.key])" + else + wizard_name = "[wizard.key] (character destroyed)" + world << "The wizard was [wizard_name]" + var/count = 1 + var/wizardwin = 1 + for(var/datum/objective/objective in wizard.objectives) + if(objective.check_completion()) + world << "Objective #[count]: [objective.explanation_text] \green Success" + else + world << "Objective #[count]: [objective.explanation_text] \red Failed" + wizardwin = 0 + count++ + + if(wizard.current && wizard.current.stat!=2 && wizardwin) + world << "The wizard was successful!" + else + world << "The wizard has failed!" + return 1 //SPELL BOOK PROCS diff --git a/code/game/jobs/jobprocs.dm b/code/game/jobs/jobprocs.dm index ee7724c71f1..c6af6dc91f5 100644 --- a/code/game/jobs/jobprocs.dm +++ b/code/game/jobs/jobprocs.dm @@ -1,38 +1,33 @@ -/proc/SetupOccupationsList() - var/list/new_occupations = list() - - for(var/occupation in occupations) - if (!(new_occupations.Find(occupation))) - new_occupations[occupation] = 1 - else - new_occupations[occupation] += 1 - - occupations = new_occupations - return /proc/FindOccupationCandidates(list/unassigned, job, level) var/list/candidates = list() for (var/mob/new_player/player in unassigned) - if (level == 1 && player.preferences.occupation1 == job && !jobban_isbanned(player, job)) - candidates += player - - if (level == 2 && player.preferences.occupation2 == job && !jobban_isbanned(player, job)) - candidates += player - - if (level == 3 && player.preferences.occupation3 == job && !jobban_isbanned(player, job)) + if ( player.preferences.occupation[level] == job && \ + ! jobban_isbanned(player, job) && \ + ! ((player.mind in ticker.mode.must_be_human) && (job in nonhuman_positions)) && \ + ! ((player.mind in ticker.mode.can_not_be_head) && (job in head_positions))) candidates += player return candidates /proc/PickOccupationCandidate(list/candidates) if (candidates.len > 0) - var/list/randomcandidates = shuffle(candidates) - candidates -= randomcandidates[1] - return randomcandidates[1] - + var/picked = pick(candidates) + candidates -= picked + return picked return null +/proc/ResetOccupations() + for (var/mob/new_player/player in world) + player.mind.assigned_role = null + return + +/** Proc DivideOccupations + * fills var "assigned_role" for all ready players. + * This proc must not have any side effects besides of modifying "assigned_role". + **/ + /proc/DivideOccupations() var/list/unassigned = list() var/list/occupation_choices = occupations.Copy() @@ -47,18 +42,18 @@ // on a game that now lacks it, this will make sure they don't become the AI, // by changing that choice to Captain. if (!config.allow_ai) - if (player.preferences.occupation1 == "AI") - player.preferences.occupation1 = "Captain" - if (player.preferences.occupation2 == "AI") - player.preferences.occupation2 = "Captain" - if (player.preferences.occupation3 == "AI") - player.preferences.occupation3 = "Captain" - if (jobban_isbanned(player, player.preferences.occupation1)) - player.preferences.occupation1 = "Assistant" - if (jobban_isbanned(player, player.preferences.occupation2)) - player.preferences.occupation2 = "Assistant" - if (jobban_isbanned(player, player.preferences.occupation3)) - player.preferences.occupation3 = "Assistant" + if (player.preferences.occupation[1] == "AI") + player.preferences.occupation[1] = "Captain" + if (player.preferences.occupation[2] == "AI") + player.preferences.occupation[2] = "Captain" + if (player.preferences.occupation[3] == "AI") + player.preferences.occupation[3] = "Captain" + if (jobban_isbanned(player, player.preferences.occupation[1])) + player.preferences.occupation[1] = "Assistant" + if (jobban_isbanned(player, player.preferences.occupation[2])) + player.preferences.occupation[2] = "Assistant" + if (jobban_isbanned(player, player.preferences.occupation[3])) + player.preferences.occupation[3] = "Assistant" if (unassigned.len == 0) return 0 @@ -90,38 +85,10 @@ if (captain_choice == null) - world << "Captainship not forced on anyone." + //world << "Captainship not forced on anyone."//moved to gameticker/proc/distribute_jobs else captain_choice.mind.assigned_role = "Captain" - //so that an AI is chosen during this game mode - if(ticker.mode.name == "AI malfunction" && unassigned.len > 0) - var/mob/new_player/ai_choice = null - - for (var/level = 1 to 3) - var/list/ais = FindOccupationCandidates(unassigned, "AI", level) - var/mob/new_player/candidate = PickOccupationCandidate(ais) - - if (candidate != null) - ai_choice = candidate - unassigned -= ai_choice - break - - if (ai_choice == null && unassigned.len > 0) - unassigned = shuffle(unassigned) - for(var/mob/new_player/player in unassigned) - if(jobban_isbanned(player, "AI")) - continue - else - ai_choice = player - break - unassigned -= ai_choice - - if (ai_choice != null) - ai_choice.mind.assigned_role = "AI" - else - world << "It is [ticker.mode.name] and there is no AI, someone should fix this" - for (var/level = 1 to 3) if (unassigned.len == 0) //everyone is assigned break @@ -161,8 +128,18 @@ if(ticker.mode.name == "AI malfunction" && occupation == "AI") continue var/eligible = occupation_eligible[occupation] + while (eligible-- && unassigned.len > 0) + var/n = 1 var/mob/new_player/candidate = unassigned[1] + if (occupation in nonhuman_positions) + while (candidate.mind in ticker.mode.must_be_human) + n++ + if (n <= unassigned.len) + candidate = unassigned[n] + else + candidate = null + break if (candidate == null) break candidate.mind.assigned_role = occupation @@ -291,18 +268,18 @@ if (length(new_religion) >= 26) new_religion = copytext(new_religion, 1, 26) new_religion = dd_replacetext(new_religion, ">", "'") - switch(new_religion) - if("Christianity") + switch(lowertext(new_religion)) + if("christianity") B.name = pick("The Holy Bible","The Dead Sea Scrolls") - if("Satanism") + if("satanism") B.name = pick("The Unholy Bible","The Necronomicon") - if("Islam") + if("islam") B.name = "Quaran" - if("Scientology") + if("scientology") B.name = pick("The Biography of L. Ron Hubbard","Dianetics") - if("Chaos") + if("chaos") B.name = "Space Station 13: The Musical" - if("Imperium") + if("imperium") B.name = "Uplifting Primer" else B.name = "The Holy Book of [new_religion]" @@ -609,9 +586,6 @@ else src << "RUH ROH! Your job is [rank] and the game just can't handle it! Please report this bug to an administrator." - src.equip_if_possible(new /obj/item/device/radio/headset(src), slot_ears) - src.equip_if_possible(new /obj/item/weapon/storage/backpack(src), slot_back) - spawnId(rank) if(rank == "Captain") world << "[src] is the captain!" @@ -655,6 +629,10 @@ if(src.mind.assigned_role == "Cyborg") src << "YOU ARE GETTING BORGED NOW" src.Robotize() + else + src.equip_if_possible(new /obj/item/device/radio/headset(src), slot_ears) + src.equip_if_possible(new /obj/item/weapon/storage/backpack(src), slot_back) + /* spawn(10) @@ -737,4 +715,4 @@ usr << "You'll have to wait if you want to atone for your sins." spawn(3000) usr.miming = 1 - return \ No newline at end of file + return diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index dfe999e1bfe..9e1e9563a7b 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -1,36 +1,57 @@ var/list/occupations = list( - "Station Engineer", "Station Engineer", "Station Engineer", "Station Engineer", "Station Engineer", - "Shaft Miner", "Shaft Miner", "Shaft Miner", - "Security Officer", "Security Officer", "Security Officer", "Security Officer", "Security Officer", - "Detective", - "Warden", - "Geneticist", "Geneticist", - "Scientist", "Scientist", "Scientist", - "Atmospheric Technician", "Atmospheric Technician", "Atmospheric Technician", "Atmospheric Technician", - "Medical Doctor", "Medical Doctor", "Medical Doctor", "Medical Doctor", "Medical Doctor", - "Head of Personnel", - "Head of Security", - "Chief Engineer", - "Research Director", - "Chaplain", - "Roboticist", - "Cyborg",//"Cyborg","Cyborg","Cyborg","Cyborg", < Fuck that. Seriously. -- Urist - "AI", - "Bartender", - "Chef", - "Janitor", - "Clown", "Mime", - "Chemist", "Chemist", - "Quartermaster", - "Cargo Technician","Cargo Technician","Cargo Technician", - "Botanist", "Botanist", - "Librarian", - "Lawyer", - "Virologist", - "Chief Medical Officer") + //Civilian jobs + "Head of Personnel" = 1, + //soul + "Clown" = 1, + "Mime" = 1, + "Chaplain" = 1, + "Librarian" = 1, + "Lawyer" = 1, + //body + "Bartender" = 1, + "Chef" = 1, + "Janitor" = 1, + "Quartermaster" = 1, + "Cargo Technician" = 3, + "Shaft Miner" = 3, + + //engineering + "Chief Engineer" = 1, + "Station Engineer" = 5, + "Atmospheric Technician" = 4, + "Roboticist" = 1, + + //red shirts + "Head of Security" = 1, + "Warden" = 1, + "Detective" = 1, + "Security Officer" = 5, + + //medbay + "Chief Medical Officer" = 1, + "Medical Doctor" = 5, + "Chemist" = 2, + + //science dept + "Research Director" = 1, + "Geneticist" = 2, + "Scientist" = 3, + "Botanist" = 2, + "Virologist" = 1, + + //I afraid I can't do that, Dave + "AI" = 1, + "Cyborg" = 1, + +) var/list/assistant_occupations = list( - "Assistant") + "Assistant", + //"Tourist", //I am not going to implement these jobs at the moment. Just listed it as examples. --rastaf0 + //"Monkey", + //"Prisoneer", + //"Lizard", +) var/list/head_positions = list( "Captain", @@ -41,5 +62,12 @@ var/list/head_positions = list( "Chief Medical Officer", ) +var/list/nonhuman_positions = list( + "AI", + "Cyborg", + //"Monkey", + //"Lizard", +) + /proc/is_important_job(var/job) return (job in head_positions) || (job in list("AI", "Cyborg", "Warden", "Detective")) diff --git a/code/game/magic/cultist/runes.dm b/code/game/magic/cultist/runes.dm index 574cfc69aca..c45ddff6906 100644 --- a/code/game/magic/cultist/runes.dm +++ b/code/game/magic/cultist/runes.dm @@ -103,11 +103,8 @@ var/list/sacrificed = list() continue if(M.stat==2) continue - if(ticker && ticker.mode && ticker.mode.name == "cult") - var/list/uncons = ticker.mode:get_unconvertables() - if(M.mind in uncons) - continue - ticker.mode:add_cultist(M.mind) + if(is_convertable_to_cult(M.mind)) + ticker.mode.add_cultist(M.mind) usr.say("Mah'weyh pleggh at e'ntrath!") M.visible_message("\red [M] writhes in pain as the markings below him glow a bloody red.", \ "\red AAAAAAHHHH!.", \ diff --git a/code/game/objects/devices/PDA/uplink.dm b/code/game/objects/devices/PDA/uplink.dm index 24d7b328a25..e7c1d08ca30 100644 --- a/code/game/objects/devices/PDA/uplink.dm +++ b/code/game/objects/devices/PDA/uplink.dm @@ -167,4 +167,14 @@ print_to_host(menu_message) return - return \ No newline at end of file + return + +/obj/item/weapon/integrated_uplink/proc/shutdown_uplink() + if (isnull(src.hostpda)) + return + active = 0 + hostpda.note = orignote + if (hostpda.mode==1) + hostpda.mode = 0 + hostpda.updateDialog() + return diff --git a/code/game/objects/devices/flash.dm b/code/game/objects/devices/flash.dm index 56e58d9e743..1f4aee71959 100644 --- a/code/game/objects/devices/flash.dm +++ b/code/game/objects/devices/flash.dm @@ -54,9 +54,9 @@ if (prob(M.eye_stat - 20 + 1)) M << "\red You go blind!" M.sdisabilities |= 1 - if(ticker.mode.name == "revolution" && istype(M, /mob/living/carbon)) - if(user.mind in ticker.mode:head_revolutionaries) - ticker.mode:add_revolutionary(M.mind) + if(/*ticker.mode.name == "revolution" && */ istype(M, /mob/living/carbon)) + if(user.mind in ticker.mode.head_revolutionaries) + ticker.mode.add_revolutionary(M.mind) for(var/mob/O in viewers(user, null)) if(status == 1) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6098f0fb7aa..b625da7474c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -228,7 +228,7 @@ /mob/attackby(obj/item/weapon/W as obj, mob/user as mob) - if (user.intent!="harm") + if (user.intent != "harm") if (istype(src.l_hand,/obj/item/latexballon) && src.l_hand:air_contents && is_sharp(W)) return src.l_hand.attackby(W) if (istype(src.r_hand,/obj/item/latexballon) && src.r_hand:air_contents && is_sharp(W)) diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index a0fa4fad11a..6452df24b5e 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -206,7 +206,7 @@ move an amendment to the drawing.

var/list/turf/found = new var/list/turf/pending = list(first) while(pending.len) - if (found.len+pending.len > 100) + if (found.len+pending.len > 300) return ROOM_ERR_TOOLARGE var/turf/T = pending[1] //why byond havent list::pop()? pending -= T diff --git a/code/game/objects/items/item.dm b/code/game/objects/items/item.dm index 0e9053e87fa..215e7e771dd 100644 --- a/code/game/objects/items/item.dm +++ b/code/game/objects/items/item.dm @@ -259,8 +259,8 @@ for(var/mob/O in viewers(M, null)) O.show_message(text("\red [] has been knocked unconscious!", H), 1, "\red You hear someone fall.", 2) if (prob(50)) - if (ticker.mode.name == "revolution" && M != user) - ticker.mode:remove_revolutionary(H.mind) + if (/*ticker.mode.name == "revolution" && */ M != user) + ticker.mode.remove_revolutionary(H.mind) if (b_dam && prob(25 + (b_dam * 2))) src.add_blood(H) if (prob(33)) diff --git a/code/game/objects/items/weapons/uplinks.dm b/code/game/objects/items/weapons/uplinks.dm index 764f3bf3a5f..f9ec25b0dd0 100644 --- a/code/game/objects/items/weapons/uplinks.dm +++ b/code/game/objects/items/weapons/uplinks.dm @@ -126,8 +126,9 @@ SYNDICATE UPLINK new /obj/item/device/chameleon(get_turf(src)) if("cloak") if (src.uses >= 4) - var/choice = input("Spawning a cloak in nuke is generally regarded as entirely dumb, are you sure?") in list("Confirm", "Abort") - if(choice == "Confirm") + if (ticker.mode.config_tag!="nuclear" || \ + (input("Spawning a cloak in nuke is generally regarded as entirely dumb, are you sure?") in list("Confirm", "Abort")) == "Confirm" \ + ) if (src.uses >= 4) src.uses -= 4 new /obj/item/weapon/cloaking_device(get_turf(src)) @@ -162,26 +163,7 @@ SYNDICATE UPLINK new /obj/item/device/radio/headset/traitor(get_turf(src)) else if (href_list["lock"] && src.origradio) // presto chango, a regular radio again! (reset the freq too...) - usr.machine = null - usr << browse(null, "window=radio") - var/obj/item/device/radio/T = src.origradio - var/obj/item/weapon/syndicate_uplink/R = src - R.loc = T - T.loc = usr - // R.layer = initial(R.layer) - R.layer = 0 - if (usr.client) - usr.client.screen -= R - if (usr.r_hand == R) - usr.u_equip(R) - usr.r_hand = T - else - usr.u_equip(R) - usr.l_hand = T - R.loc = T - T.layer = 20 - T.set_frequency(initial(T.frequency)) - T.attack_self(usr) + shutdown_uplink() return else if (href_list["selfdestruct"]) src.temp = "Self-Destruct" @@ -199,4 +181,33 @@ SYNDICATE UPLINK for(var/mob/M in viewers(1, src)) if (M.client) src.attack_self(M) - return \ No newline at end of file + return + +/obj/item/weapon/syndicate_uplink/proc/shutdown_uplink() + if (!src.origradio) + return + var/list/nearby = viewers(1, src) + for(var/mob/M in nearby) + if (M.client && M.machine == src) + M << browse(null, "window=radio") + M.machine = null + + var/obj/item/device/radio/T = src.origradio + var/obj/item/weapon/syndicate_uplink/R = src + var/mob/L = src.loc + R.loc = T + T.loc = L + // R.layer = initial(R.layer) + R.layer = 0 + if (istype(L)) + if (L.client) + L.client.screen -= R + if (L.r_hand == R) + L.u_equip(R) + L.r_hand = T + else + L.u_equip(R) + L.l_hand = T + T.layer = 20 + T.set_frequency(initial(T.frequency)) + return diff --git a/code/game/objects/storage/bible.dm b/code/game/objects/storage/bible.dm index 079e16e6ed8..85e199b66b7 100644 --- a/code/game/objects/storage/bible.dm +++ b/code/game/objects/storage/bible.dm @@ -51,10 +51,7 @@ if((M.mind in ticker.mode.cult) && (prob(20))) M << "\red The power of [src.deity_name] clears your mind of heresy!" user << "\red You see how [M]'s eyes become clear, the cult no longer holds control over him!" - if (ticker.mode.name == "cult") - ticker.mode:remove_cultist(M.mind) - else - ticker.mode.cult -= M.mind + ticker.mode.remove_cultist(M.mind) if ((istype(M, /mob/living/carbon/human) && prob(60))) bless(M) for(var/mob/O in viewers(M, null)) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index ff4cdc06ba1..dbe53c2058a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -656,83 +656,17 @@ var/showadminmessages = 1 alert("The game hasn't started yet!") return var/mob/M = locate(href_list["traitor"]) - var/datum/game_mode/current_mode = ticker.mode - - if (ishuman(M) && M:mind) - M:mind.edit_memory() + if (!istype(M)) + player() return - - switch(current_mode.config_tag) - if("revolution") - if(M.mind in current_mode:head_revolutionaries) - alert("Is a Head Revolutionary!") - else if(M.mind in current_mode:revolutionaries) - alert("Is a Revolutionary!") - return - if("cult") - if(M.mind in current_mode.cult) - alert("Is a Cultist!") - return - if("wizard") - if(current_mode:wizard && M.mind == current_mode:wizard) - var/datum/mind/antagonist = M.mind - var/t = "" - for(var/datum/objective/OB in antagonist.objectives) - t += "[OB.explanation_text]\n" - if(antagonist.objectives.len == 0) - t = "None defined." - alert("Is a WIZARD. Objective(s):\n[t]", "[M.key]") - return - if("changeling") - if(M.mind in current_mode:changelings) - var/datum/mind/antagonist = M.mind - var/t = "" - for(var/datum/objective/OB in antagonist.objectives) - t += "[OB.explanation_text]\n" - if(antagonist.objectives.len == 0) - t = "None defined." - alert("Is a CHANGELING. Objective(s):\n[t]", "[M.key]") - return - if("malfunction") - if(M.mind in current_mode:malf_ai) - alert("Is malfunctioning!") - return - if("nuclear") - if(M.mind in current_mode:syndicates) - alert("Is a Syndicate operative!", "[M.key]") - return - - if(isrobot(M)) - var/mob/living/silicon/robot/R = M - if(R.emagged) - alert("Is emagged!\n0th law: [R.laws.zeroth]", "[R.key]") - return - if(isalien(M)) alert("Is an [M.mind ? M.mind.special_role : "Alien"]!", "[M.key]") return + if (M:mind) + M:mind.edit_memory() + return + alert("Cannot make this mob a traitor! It has no mind!") - // traitor, or other modes where traitors/counteroperatives would be. - if(M.mind in current_mode.traitors) - var/datum/mind/antagonist = M.mind - var/t = "" - if(antagonist) - for(var/datum/objective/OB in antagonist.objectives) - t += "[OB.explanation_text]\n" - if(antagonist.objectives.len == 0) - t = "None defined." - alert("Is a Traitor. Objective(s):\n[t]", "[M.key]") - return - - //they're nothing so turn them into a traitor! - if(ishuman(M) || issilicon(M)) - var/traitorize = alert("Is not a traitor, make Traitor?", "Traitor", "Yes", "Cancel") - if(traitorize == "Cancel") - return - if(traitorize == "Yes") - traitorize(M,,1) - else - alert("Cannot make this mob a traitor") if (href_list["create_object"]) if (src.rank in list("Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master")) return create_object(usr) @@ -1292,111 +1226,101 @@ var/showadminmessages = 1 if(1) dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
" - switch(ticker.mode.config_tag) - - if("nuclear") - dat += "
" - for(var/datum/mind/N in ticker.mode:syndicates) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - else - dat += "" - dat += "
Syndicates
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
Nuclear Operative not found!

" - for(var/obj/item/weapon/disk/nuclear/N in world) - dat += "" - dat += "
Nuclear Disk(s)
[N.name], " - var/atom/disk_loc = N.loc - while(!istype(disk_loc, /turf)) - if(istype(disk_loc, /mob)) - var/mob/M = disk_loc - dat += "carried by [M.real_name] " - if(istype(disk_loc, /obj)) - var/obj/O = disk_loc - dat += "in \a [O.name] " - disk_loc = disk_loc.loc - dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])
" - - if("revolution") - dat += "
" - for(var/datum/mind/N in ticker.mode:head_revolutionaries) - var/mob/M = N.current - if(!M) - dat += "" - else - dat += "" - dat += "" - for(var/datum/mind/N in ticker.mode:revolutionaries) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "
Revolutionaries
Head Revolutionary not found!
[M.real_name] (Leader)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
" - for(var/datum/mind/N in ticker.mode.get_living_heads()) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - var/turf/mob_loc = get_turf_loc(M) - dat += "" - dat += "
Target(s)Location
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM[mob_loc.loc]
" - - if("changeling") - if(ticker.mode:changelings.len > 0) - dat += "
" - for(var/datum/mind/changeling in ticker.mode:changelings) - var/mob/M = changeling.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "
Changelings
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Changeling not found!
" + if(ticker.mode.syndicates.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.syndicates) + var/mob/M = N.current + if(M) + dat += "" + dat += "" else - dat += "There are no changelings." + dat += "" + dat += "
Syndicates
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
Nuclear Operative not found!

" + for(var/obj/item/weapon/disk/nuclear/N in world) + dat += "" + dat += "
Nuclear Disk(s)
[N.name], " + var/atom/disk_loc = N.loc + while(!istype(disk_loc, /turf)) + if(istype(disk_loc, /mob)) + var/mob/M = disk_loc + dat += "carried by [M.real_name] " + if(istype(disk_loc, /obj)) + var/obj/O = disk_loc + dat += "in \a [O.name] " + disk_loc = disk_loc.loc + dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])
" - /* this doesn't work - if("wizard") - if(ticker.mode:wizards.len > 0) - dat += "
" - for(var/datum/mind/wizard in ticker.mode:wizards) - var/mob/M = wizard.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "
Wizards
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Wizard not found!
" + if(ticker.mode.head_revolutionaries.len || ticker.mode.revolutionaries.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.head_revolutionaries) + var/mob/M = N.current + if(!M) + dat += "" else - dat += "There are no wizards." - */ - - if("cult") - dat += "
Revolutionaries
Head Revolutionary not found!
" - for(var/datum/mind/N in ticker.mode:cult) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "
Cultists
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
" - - else // i'll finish this later - if(ticker.mode.traitors.len > 0) - dat += "
" - for(var/datum/mind/traitor in ticker.mode.traitors) - var/mob/M = traitor.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "
Traitors
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Traitor not found!
" + dat += "[M.real_name] (Leader)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]" + dat += "PM" + for(var/datum/mind/N in ticker.mode.revolutionaries) + var/mob/M = N.current + if(M) + dat += "[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]" + dat += "PM" + dat += "" + for(var/datum/mind/N in ticker.mode.get_living_heads()) + var/mob/M = N.current + if(M) + dat += "" + dat += "" + var/turf/mob_loc = get_turf_loc(M) + dat += "" else - dat += "There are no traitors." + dat += "" + dat += "
Target(s)Location
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM[mob_loc.loc]
Head not found!
" + + if(ticker.mode.changelings.len > 0) + dat += "
" + for(var/datum/mind/changeling in ticker.mode.changelings) + var/mob/M = changeling.current + if(M) + dat += "" + dat += "" + dat += "" + else + dat += "" + dat += "
Changelings
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Changeling not found!
" + + if(ticker.mode.wizards.len > 0) + dat += "
" + for(var/datum/mind/wizard in ticker.mode.wizards) + var/mob/M = wizard.current + if(M) + dat += "" + dat += "" + dat += "" + else + dat += "" + dat += "
Wizards
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Wizard not found!
" + + if(ticker.mode.cult.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.cult) + var/mob/M = N.current + if(M) + dat += "" + dat += "" + dat += "
Cultists
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
" + + if(ticker.mode.traitors.len > 0) + dat += "
" + for(var/datum/mind/traitor in ticker.mode.traitors) + var/mob/M = traitor.current + if(M) + dat += "" + dat += "" + dat += "" + else + dat += "" + dat += "
Traitors
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PMShow Objective
Traitor not found!
" + dat += "" usr << browse(dat, "window=roundstatus;size=400x500") else @@ -2060,22 +1984,25 @@ var/showadminmessages = 1 return 0 switch(ticker.mode.config_tag) if("revolution") - if(M.mind in (ticker.mode:head_revolutionaries + ticker.mode:revolutionaries)) + if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode:revolutionaries)) return 1 if("cult") - if(M.mind in ticker.mode:cult) + if(M.mind in ticker.mode.cult) return 1 if("malfunction") - if(M.mind in ticker.mode:malf_ai) + if(M.mind in ticker.mode.malf_ai) return 1 if("nuclear") - if(M.mind in ticker.mode:syndicates) + if(M.mind in ticker.mode.syndicates) return 1 if("wizard") - if(M.mind == ticker.mode:wizard) + if(M.mind in ticker.mode.wizards) return 1 if("changeling") - if(M.mind in ticker.mode:changelings) + if(M.mind in ticker.mode.changelings) + return 1 + if("monkey") + if(istype(M.virus, /datum/disease/jungle_fever)) return 1 if(isrobot(M)) var/mob/living/silicon/robot/R = M diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 7631a6a2901..e4a96c9b584 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1357,7 +1357,7 @@ log_admin("[key_name(usr)] has turned stealth mode [stealth ? "ON" : "OFF"]") message_admins("[key_name_admin(usr)] has turned stealth mode [stealth ? "ON" : "OFF"]", 1) - +#define AUTOBATIME 10 /client/proc/warn(var/mob/M in world) set category = "Special Verbs" set name = "Warn" @@ -1373,11 +1373,11 @@ M.client.warned = 1 message_admins("\blue [ckey] warned [M.ckey].") else - AddBan(M.ckey, M.computer_id, "Autobanning due to previous warn", ckey, 1, 10) + AddBan(M.ckey, M.computer_id, "Autobanning due to previous warn", ckey, 1, AUTOBATIME) M << "\redYou have been autobanned by [ckey]. This is what we in the biz like to call a \"second warning\"." - M << "\red This is a temporary ban; it will automatically be removed in 10 minutes." - log_admin("[ckey] warned [M.ckey], resulting in a 10 minute autoban.") - message_admins("\blue [ckey] warned [M.ckey], resulting in a 10 minute autoban.") + M << "\red This is a temporary ban; it will automatically be removed in AUTOBATIME minutes." + log_admin("[ckey] warned [M.ckey], resulting in a AUTOBATIME minute autoban.") + message_admins("\blue [ckey] warned [M.ckey], resulting in a AUTOBATIME minute autoban.") del(M.client) //del(M) diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index cee59c8893e..5d89ac2fb1d 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -19,6 +19,19 @@ var else return 0 +/* +working but not needed +/proc/jobban_isbanned_for_heads(mob/M) + if(config.guest_jobban && IsGuestKey(M.key)) + return 1 + if(config.usewhitelist && check_whitelist(M)) + return 1 + for (var/rank in head_positions) + if (!jobban_keylist.Find(text("[M.ckey] - [rank]"))) + return 0 + return 1 +*/ + /proc/jobban_loadbanfile() var/savefile/S=new("data/job_full.ban") S["keys[0]"] >> jobban_keylist @@ -49,4 +62,4 @@ var jobban_keylist.Remove(X) jobban_savebanfile() return 1 - return 0 \ No newline at end of file + return 0 diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index ad9e08d9aa7..eb9ff80ed90 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -500,12 +500,13 @@ Traitors and the like can also be revived with the previous role mostly intact. ticker.mode.equip_traitor(new_character) if("Wizard","Fake Wizard") new_character.loc = pick(wizardstart) + ticker.mode.learn_basic_spells(new_character) ticker.mode.equip_wizard(new_character) if("Syndicate") var/obj/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") if(synd_spawn) new_character.loc = get_turf(synd_spawn) - call(/datum/game_mode/nuclear/proc/equip_syndicate)(new_character) + call(/datum/game_mode/proc/equip_syndicate)(new_character) if("Space Ninja") var/ninja_spawn[] = list() for(var/obj/landmark/L in world) @@ -526,11 +527,11 @@ Traitors and the like can also be revived with the previous role mostly intact. if("Cyborg")//More rigging to make em' work and check if they're traitor. new_character = new_character.Robotize() if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/traitor/proc/add_law_zero)(new_character) + call(/datum/game_mode/proc/add_law_zero)(new_character) if("AI") new_character = new_character.AIize() if(new_character.mind.special_role=="traitor") - call(/datum/game_mode/traitor/proc/add_law_zero)(new_character) + call(/datum/game_mode/proc/add_law_zero)(new_character) //Add aliens. else new_character.Equip_Rank(new_character.mind.assigned_role, joined_late=1)//Or we simply equip them. diff --git a/code/modules/admin/verbs/tripAI.dm b/code/modules/admin/verbs/tripAI.dm index f872af00999..6995675e251 100644 --- a/code/modules/admin/verbs/tripAI.dm +++ b/code/modules/admin/verbs/tripAI.dm @@ -1,20 +1,16 @@ -var/global/check_dem_trips = 0 - /client/proc/triple_ai() set category = "Fun" set name = "Create AI Triumvirate" - - if(ticker.current_state < 2) - if (check_dem_trips) - occupations["AI"] -= 2 - usr << "Only one AI will be spawned at round start." - message_admins("\blue [key_name_admin(usr)] has toggled off triple AIs at round start.", 1) - else - occupations["AI"] += 2 - usr << "There will be an AI Triumvirate at round start." - message_admins("\blue [key_name_admin(usr)] has toggled on triple AIs at round start.", 1) - check_dem_trips = !check_dem_trips + if(ticker.current_state > GAME_STATE_PREGAME) + usr << "This option is currently only usable during pregame. This may change at a later date." return - - usr << "This option is currently only usable during pregame. This may change at a later date." \ No newline at end of file + if (occupations["AI"] > 1) + occupations["AI"] -= 2 + usr << "Only one AI will be spawned at round start." + message_admins("\blue [key_name_admin(usr)] has toggled off triple AIs at round start.", 1) + else + occupations["AI"] += 2 + usr << "There will be an AI Triumvirate at round start." + message_admins("\blue [key_name_admin(usr)] has toggled on triple AIs at round start.", 1) + return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 81734df7ce1..c4db177e0a7 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1441,7 +1441,11 @@ UpdateDamage() updatehealth() if(istype(M.virus, /datum/disease/jungle_fever)) - monkeyize() + var/mob/living/carbon/human/H = src + src = null + src = H.monkeyize() + contract_disease(M.virus,1,0) + return /mob/living/carbon/human/attack_paw(mob/M as mob) @@ -1490,7 +1494,10 @@ UpdateDamage() updatehealth() if(istype(M.virus, /datum/disease/jungle_fever)) - monkeyize() + var/mob/living/carbon/human/H = src + src = null + src = H.monkeyize() + contract_disease(M.virus,1,0) return /mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M as mob) diff --git a/code/modules/mob/living/carbon/human/savefile.dm b/code/modules/mob/living/carbon/human/savefile.dm index 7459a0c6fc3..22e3fd957e3 100644 --- a/code/modules/mob/living/carbon/human/savefile.dm +++ b/code/modules/mob/living/carbon/human/savefile.dm @@ -1,5 +1,5 @@ #define SAVEFILE_VERSION_MIN 2 -#define SAVEFILE_VERSION_MAX 2 +#define SAVEFILE_VERSION_MAX 3 datum/preferences/proc/savefile_path(mob/user) return "data/player_saves/[copytext(user.ckey, 1, 2)]/[user.ckey]/preferences.sav" @@ -9,15 +9,22 @@ datum/preferences/proc/savefile_save(mob/user) return 0 var/savefile/F = new /savefile(src.savefile_path(user)) + var/version + F["version"] >> version + + if (!isnull(version) && version<=2) + F["be_syndicate"] << null + F["be_alien"] << null + F["UI"] << null F["version"] << SAVEFILE_VERSION_MAX F["real_name"] << src.real_name F["gender"] << src.gender F["age"] << src.age - F["occupation_1"] << src.occupation1 - F["occupation_2"] << src.occupation2 - F["occupation_3"] << src.occupation3 + F["occupation_1"] << src.occupation[1] + F["occupation_2"] << src.occupation[2] + F["occupation_3"] << src.occupation[3] F["hair_red"] << src.r_hair F["hair_green"] << src.g_hair F["hair_blue"] << src.b_hair @@ -31,11 +38,13 @@ datum/preferences/proc/savefile_save(mob/user) F["eyes_green"] << src.g_eyes F["eyes_blue"] << src.b_eyes F["blood_type"] << src.b_type - F["be_syndicate"] << src.be_syndicate + //F["be_syndicate"] << src.be_syndicate + F["be_special"] << src.be_special F["underwear"] << src.underwear F["name_is_always_random"] << src.be_random_name F["UI"] << src.UI // Skie - F["be_alien"] << src.be_alien // Urist + //world << "DEBUG: saving UI as [UI]" + //F["be_alien"] << src.be_alien // Urist F["midis"] << src.midis // Urist F["ooccolor"] << src.ooccolor // Urist F["lastchangelog"] << src.lastchangelog // rastaf0 @@ -72,9 +81,9 @@ datum/preferences/proc/savefile_load(mob/user, var/silent = 1) F["real_name"] >> src.real_name F["gender"] >> src.gender F["age"] >> src.age - F["occupation_1"] >> src.occupation1 - F["occupation_2"] >> src.occupation2 - F["occupation_3"] >> src.occupation3 + F["occupation_1"] >> src.occupation[1] + F["occupation_2"] >> src.occupation[2] + F["occupation_3"] >> src.occupation[3] F["hair_red"] >> src.r_hair F["hair_green"] >> src.g_hair F["hair_blue"] >> src.b_hair @@ -88,14 +97,37 @@ datum/preferences/proc/savefile_load(mob/user, var/silent = 1) F["eyes_green"] >> src.g_eyes F["eyes_blue"] >> src.b_eyes F["blood_type"] >> src.b_type - F["be_syndicate"] >> src.be_syndicate F["underwear"] >> src.underwear F["name_is_always_random"] >> src.be_random_name - F["UI"] >> src.UI // Skie - F["be_alien"] >> src.be_alien // Urist + //F["be_alien"] >> src.be_alien // Urist F["midis"] >> src.midis // Urist F["ooccolor"] >> src.ooccolor // Urist F["lastchangelog"] >> src.lastchangelog // rastaf0 + + + if (version<=2) // migration from old preferences file format --rastaf0 + src.UI = 0 // swithing from storing an image file to storing boolean value --rastaf0 + //world << "DEBUG: loading legacy UI as [UI]" + var/tmp + F["be_syndicate"] >> tmp + if (tmp) + be_special |= BE_TRAITOR + be_special |= BE_OPERATIVE + be_special |= BE_CHANGELING + be_special |= BE_WIZARD + be_special |= BE_MALF + be_special |= BE_REV + F["be_alien"] >> tmp + if (tmp) + be_special |= BE_ALIEN + del(F) + fdel(path) + savefile_save(user) + else // /migration end + F["UI"] >> src.UI + F["be_special"] >> src.be_special + //world << "DEBUG: loading new UI as [UI]" + return 1 #undef SAVEFILE_VERSION_MAX diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index efc7d363b59..29abf620679 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -160,6 +160,8 @@ if (mutations & HULK) damage += 10 bruteloss += damage updatehealth() + if(istype(M.virus, /datum/disease/jungle_fever)) + contract_disease(M.virus,1,0) else for(var/mob/O in viewers(src, null)) O.show_message(text("\red [M.name] has attempted to bite []!", src), 1) @@ -179,6 +181,8 @@ var/damage = rand(1, 5) bruteloss += damage health = 100 - oxyloss - toxloss - fireloss - bruteloss + if(istype(M.virus, /datum/disease/jungle_fever)) + contract_disease(M.virus,1,0) else for(var/mob/O in viewers(src, null)) O.show_message("\red [M.name] has attempted to bite [name]!", 1) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1e3f2eefc63..419a21733e3 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -48,9 +48,9 @@ src << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc." src << "To use something, simply double-click it." src << "Currently right-click functions will not work for the AI (except examine), and will either be replaced with dialogs or won't be usable by the AI." - - show_laws() - src << "These laws may be changed by other players, or by you being the traitor." + if (!(ticker && ticker.mode && (mind in ticker.mode.malf_ai))) + show_laws() + src << "These laws may be changed by other players, or by you being the traitor." job = "AI" diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index ac7db93ddbe..3a8bfa4bdae 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -44,12 +44,6 @@ if (istype(loc, /obj/item/device/aicard)) loc.icon_state = "aicard-404" - if(ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for(var/datum/mind/AI_mind in malf.malf_ai) - if (mind == AI_mind) - ticker.mode.declare_completion() - var/tod = time2text(world.realtime,"hh:mm:ss") //weasellos time of death patch mind.store_memory("Time of death: [tod]", 0) @@ -67,4 +61,4 @@ spawn(50) if(key && stat == 2) verbs += /mob/proc/ghost - return ..(gibbed) \ No newline at end of file + return ..(gibbed) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ebadd78bd44..2956ae4a459 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -2180,7 +2180,7 @@ note dizziness decrements automatically in the mob's Life() proc. statpanel("Spells","[S.charge_counter/10.0]/[S.charge_max/10]",S) if("charges") statpanel("Spells","[S.charge_counter]/[S.charge_max]",S) - +#if 1 /client/proc/station_explosion_cinematic(var/derp) if(mob) var/mob/M = mob @@ -2212,3 +2212,44 @@ note dizziness decrements automatically in the mob's Life() proc. boom.icon_state = "loss_malf" else boom.icon_state = "loss_general" +#elif +/client/proc/station_explosion_cinematic(var/derp) + if(!src.mob) + return + + var/mob/M = src.mob + M.loc = null // HACK, but whatever, this works + + if(!M.hud_used) + return + + var/obj/screen/boom = M.hud_used.station_explosion + src.screen += boom + if(ticker) + switch(ticker.mode.name) + if("nuclear emergency") + flick("start_nuke", boom) + if("AI malfunction") + flick("start_malf", boom) + else + boom.icon_state = "start" + sleep(40) + M << sound('explosionfar.ogg') + boom.icon_state = "end" + if(!derp) + flick("explode", boom) + else + flick("explode2", boom) + sleep(40) + if(ticker) + switch(ticker.mode.name) + if("nuclear emergency") + if (!derp) + boom.icon_state = "loss_nuke" + else + boom.icon_state = "loss_nuke2" + if("AI malfunction") + boom.icon_state = "loss_malf" + else + boom.icon_state = "loss_general" +#endif diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 7f21bc00219..2fc9a4eccee 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -37,7 +37,7 @@ mob/new_player if(!preferences.savefile_load(src, 0)) preferences.ShowChoices(src) - if (client.changes) + if (!client.changes) changes() else var/lastchangelog = length('changelog.html') diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm index 11267b5ac83..4808193c931 100644 --- a/code/modules/mob/new_player/preferences.dm +++ b/code/modules/mob/new_player/preferences.dm @@ -1,38 +1,65 @@ +#define UI_OLD 0 +#define UI_NEW 1 + +var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm --rastaf +//some autodetection here. + "traitor" = IS_MODE_COMPILED("traitor"), + "operative" = IS_MODE_COMPILED("nuclear"), + "changeling" = IS_MODE_COMPILED("changeling"), + "wizard" = IS_MODE_COMPILED("wizard"), + "malf AI" = IS_MODE_COMPILED("malfunction"), + "revolutionary" = IS_MODE_COMPILED("revolution"), + "alien candidate" = 1, //always show + "cultist" = IS_MODE_COMPILED("cult"), + "infested monkey" = IS_MODE_COMPILED("monkey"), +) +/* +var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm --rastaf +//some autodetection here. + "traitor" = ispath(text2path("/datum/game_mode/traitor")), + "operative" = ispath(text2path("/datum/game_mode/nuclear")), + "changeling" = ispath(text2path("/datum/game_mode/changeling")), + "wizard" = ispath(text2path("/datum/game_mode/wizard")), + "malf AI" = ispath(text2path("/datum/game_mode/malfunction")), + "revolutionary" = ispath(text2path("/datum/game_mode/revolution")), + "alien candidate" = 1, //always show + "cultist" = ispath(text2path("/datum/game_mode/cult")), + "infested monkey" = ispath(text2path("/datum/game_mode/monkey")), +) +*/ + datum/preferences var/real_name var/gender = MALE var/age = 30.0 var/b_type = "A+" - var/be_syndicate + var/be_special //bitfields. See defines in setup.dm. --rastaf0 var/midis = 1 - var/be_alien = 1 - var/lastchangelog = 0 // size of last seen changelog file -- rastaf0 -- rastaf0 + var/lastchangelog = 0 // size of last seen changelog file -- rastaf0 var/ooccolor = "#b82e00" var/be_random_name = 0 var/underwear = 1 - var/occupation1 = "No Preference" - var/occupation2 = "No Preference" - var/occupation3 = "No Preference" + var/occupation[] = list("No Preference", "No Preference", "No Preference") var/h_style = "Short Hair" var/f_style = "Shaved" - var/r_hair = 0.0 - var/g_hair = 0.0 - var/b_hair = 0.0 + var/r_hair = 0 + var/g_hair = 0 + var/b_hair = 0 - var/r_facial = 0.0 - var/g_facial = 0.0 - var/b_facial = 0.0 + var/r_facial = 0 + var/g_facial = 0 + var/b_facial = 0 - var/s_tone = 0.0 - var/r_eyes = 0.0 - var/g_eyes = 0.0 - var/b_eyes = 0.0 + var/s_tone = 0 + var/r_eyes = 0 + var/g_eyes = 0 + var/b_eyes = 0 - var/UI = 'screen1_old.dmi' // Skie + var/UI = UI_OLD // saving the whole .DMI in preferences is not a good idea. --rastaf0 //'screen1_old.dmi' // Skie var/icon/preview_icon = null @@ -361,35 +388,35 @@ datum/preferences dat += "Age: [age]" dat += "
" - dat += "UI Style: [UI == 'screen1.dmi' ? "New" : "Old"]
" + dat += "UI Style: [UI == UI_NEW ? "New" : "Old"]
" dat += "Play admin midis: [midis == 1 ? "Yes" : "No"]
" if(user.client.holder) if(user.client.holder.rank) if(user.client.holder.rank == "Game Master") dat += "
OOC
" - dat += "Change colour
IM
" + dat += "Change colour
__
" dat += "
Occupation Choices
" - if (destructive.Find(occupation1)) - dat += "\t[occupation1]
" + if (destructive.Find(occupation[1])) + dat += "\t[occupation[1]]
" else - if (jobban_isbanned(user, occupation1)) - occupation1 = "Assistant" - if (jobban_isbanned(user, occupation2)) - occupation2 = "Assistant" - if (jobban_isbanned(user, occupation3)) - occupation3 = "Assistant" - if (occupation1 != "No Preference") - dat += "\tFirst Choice: [occupation1]
" + if (jobban_isbanned(user, occupation[1])) + occupation[1] = "Assistant" + if (jobban_isbanned(user, occupation[2])) + occupation[2] = "Assistant" + if (jobban_isbanned(user, occupation[3])) + occupation[3] = "Assistant" + if (occupation[1] != "No Preference") + dat += "\tFirst Choice: [occupation[1]]
" - if (destructive.Find(occupation2)) - dat += "\tSecond Choice: [occupation2]
" + if (destructive.Find(occupation[2])) + dat += "\tSecond Choice: [occupation[2]]
" else - if (occupation2 != "No Preference") - dat += "\tSecond Choice: [occupation2]
" - dat += "\tLast Choice: [occupation3]
" + if (occupation[2] != "No Preference") + dat += "\tSecond Choice: [occupation[2]]
" + dat += "\tLast Choice: [occupation[3]]
" else dat += "\tSecond Choice: No Preference
" @@ -408,7 +435,7 @@ datum/preferences dat += "
Hair
" - dat += "Change Color
IM
" + dat += "Change Color
__
" /* dat += " Red - [r_hair]" dat += " Green - [g_hair]" @@ -418,7 +445,7 @@ datum/preferences dat += "
Facial
" - dat += "Change Color
GO
" + dat += "Change Color
__
" /* dat += " Red - [r_facial]" dat += " Green - [g_facial]" @@ -427,19 +454,22 @@ datum/preferences dat += "Style: [f_style]" dat += "
Eyes
" - dat += "Change Color
KU
" + dat += "Change Color
__
" /* dat += " Red - [r_eyes]" dat += " Green - [g_eyes]" dat += " Blue - [b_eyes]" */ dat += "
" - dat += "Be alien candidate: [be_alien == 1 ? "Yes" : "No"]
" if(!jobban_isbanned(user, "Syndicate")) - dat += "Be syndicate?: [(be_syndicate ? "Yes" : "No")]
" + var/n = 0 + for (var/i in special_roles) + if (special_roles[i]) //if mode is available on the server + dat += "Be [i]: [src.be_special&(1<
" + n++ else - dat += " You are banned from being syndicate." - be_syndicate = 0 + dat += "You are banned from being syndicate." + src.be_special = 0 dat += "
" if (!IsGuestKey(user.key)) @@ -487,75 +517,75 @@ datum/preferences switch(occ) if(1.0) - if (job == occupation1) + if (job == occupation[1]) user << browse(null, "window=mob_occupation") return else if (job == "No Preference") - occupation1 = "No Preference" + occupation[1] = "No Preference" else - if (job == occupation2) - job = occupation1 - occupation1 = occupation2 - occupation2 = job + if (job == occupation[2]) + job = occupation[1] + occupation[1] = occupation[2] + occupation[2] = job else - if (job == occupation3) - job = occupation1 - occupation1 = occupation3 - occupation3 = job + if (job == occupation[3]) + job = occupation[1] + occupation[1] = occupation[3] + occupation[3] = job else - occupation1 = job + occupation[1] = job if(2.0) - if (job == occupation2) + if (job == occupation[2]) user << browse(null, "window=mob_occupation") return else if (job == "No Preference") - if (occupation3 != "No Preference") - occupation2 = occupation3 - occupation3 = "No Preference" + if (occupation[3] != "No Preference") + occupation[2] = occupation[3] + occupation[3] = "No Preference" else - occupation2 = "No Preference" + occupation[2] = "No Preference" else - if (job == occupation1) - if (occupation2 == "No Preference") + if (job == occupation[1]) + if (occupation[2] == "No Preference") user << browse(null, "window=mob_occupation") return - job = occupation2 - occupation2 = occupation1 - occupation1 = job + job = occupation[2] + occupation[2] = occupation[1] + occupation[1] = job else - if (job == occupation3) - job = occupation2 - occupation2 = occupation3 - occupation3 = job + if (job == occupation[3]) + job = occupation[2] + occupation[2] = occupation[3] + occupation[3] = job else - occupation2 = job + occupation[2] = job if(3.0) - if (job == occupation3) + if (job == occupation[3]) user << browse(null, "window=mob_occupation") return else if (job == "No Preference") - occupation3 = "No Preference" + occupation[3] = "No Preference" else - if (job == occupation1) - if (occupation3 == "No Preference") + if (job == occupation[1]) + if (occupation[3] == "No Preference") user << browse(null, "window=mob_occupation") return - job = occupation3 - occupation3 = occupation1 - occupation1 = job + job = occupation[3] + occupation[3] = occupation[1] + occupation[1] = job else - if (job == occupation2) - if (occupation3 == "No Preference") + if (job == occupation[2]) + if (occupation[3] == "No Preference") user << browse(null, "window=mob_occupation") return - job = occupation3 - occupation3 = occupation2 - occupation2 = job + job = occupation[3] + occupation[3] = occupation[2] + occupation[2] = job else - occupation3 = job + occupation[3] = job user << browse(null, "window=mob_occupation") ShowChoices(user) @@ -733,7 +763,7 @@ datum/preferences var/ooccolor = input(user, "Please select OOC colour.", "OOC colour") as color if(ooccolor) - ooccolor = ooccolor + src.ooccolor = ooccolor if (link_tags["f_style"]) switch(link_tags["f_style"]) @@ -754,17 +784,14 @@ datum/preferences gender = MALE if (link_tags["UI"]) - if (UI == 'screen1.dmi') - UI = 'screen1_old.dmi' + if (UI == UI_OLD) + UI = UI_NEW else - UI = 'screen1.dmi' + UI = UI_OLD if (link_tags["midis"]) midis = (midis+1)%2 - if (link_tags["be_alien"]) - be_alien = (be_alien+1)%2 - if (link_tags["underwear"]) if(!IsGuestKey(user.key)) switch(link_tags["underwear"]) @@ -779,8 +806,8 @@ datum/preferences else underwear = 1 - if (link_tags["b_syndicate"]) - be_syndicate = !( be_syndicate ) + if (link_tags["be_special"]) + src.be_special^=(1<While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc.
" O << "To use something, simply double-click it." O << "Currently right-click functions will not work for the AI (except examine), and will either be replaced with dialogs or won't be usable by the AI." - - O.show_laws() - O << "These laws may be changed by other players, or by you being the traitor." + if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai))) + O.show_laws() + O << "These laws may be changed by other players, or by you being the traitor." O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle O.verbs += /mob/living/silicon/ai/proc/show_laws_verb diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index fc38c920e8c..cbc57ab4c0d 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -584,17 +584,14 @@ if (istype(user, /mob/living/silicon)) t += "

Overload lighting circuit
" - if (ticker) + if (ticker && ticker.mode) // world << "there's a ticker" - if(ticker.mode.name == "AI malfunction") + if(user.mind in ticker.mode.malf_ai) // world << "ticker says its malf" - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/B in malf.malf_ai) - if (user == B.current) - if (!src.malfai) - t += "

Override Programming
" - else - t += "

APC Hacked
" + if (!src.malfai) + t += "

Override Programming
" + else + t += "

APC Hacked
" t += "

Close" @@ -789,8 +786,9 @@ if (!src.aidisabled) malfai.malfhack = null malfai.malfhacking = 0 - if (src.z == 1) - ticker.mode:apcs++ + if (ticker.mode.config_tag == "malfunction") + if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas)) + ticker.mode:apcs++ src.malfai = usr src.locked = 1 if (src.cell) diff --git a/code/setup.dm b/code/setup.dm index e4c57eea332..295af4a6f52 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -170,4 +170,19 @@ var/const GAS_CO2 = 1 << 3 GAS_N2O = 1 << 4 -var/list/accessable_z_levels = list("1" = 10, "3" = 15, "4" = 60, "5" = 15) //This list contains the z-level numbers which can be accessed via space travel and the percentual chances to get there. (Exceptions: extended, sandbox and nuke) -Errorage \ No newline at end of file +// bitflags for preferences +#define BE_TRAITOR (1<<0) +#define BE_OPERATIVE (1<<1) +#define BE_CHANGELING (1<<2) +#define BE_WIZARD (1<<3) +#define BE_MALF (1<<4) +#define BE_REV (1<<5) +#define BE_ALIEN (1<<6) +#define BE_CULTIST (1<<7) +#define BE_MONKEY (1<<8) +//#define BE_CIVILIAN (1<<15) //well, I must stop here. --rastaf0 + + +var/list/accessable_z_levels = list("1" = 10, "3" = 15, "4" = 60, "5" = 15) //This list contains the z-level numbers which can be accessed via space travel and the percentual chances to get there. (Exceptions: extended, sandbox and nuke) -Errorage + +#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE)))) diff --git a/code/unused/gamemodes/monkey.dm b/code/unused/gamemodes/monkey.dm index 2efc0cd13c2..bb0a948382b 100644 --- a/code/unused/gamemodes/monkey.dm +++ b/code/unused/gamemodes/monkey.dm @@ -3,45 +3,73 @@ #define MONKEY_MODE_SHUTTLE_CAPTURED 2 #define MONKEY_MODE_SHUTTLE_WITH_HUMANS 3 +#define MONKEY_MODE_MONKEYS 4 /datum/game_mode/monkey name = "monkey" config_tag = "monkey" var/state = MONKEY_MODE_RUNNING + var/list/datum/mind/initial_monkeys = new /datum/game_mode/monkey/announce() world << "The current game mode is - Monkey!" world << "Some of your crew members have been infected by a mutageous virus!" world << "Escape on the shuttle but the humans have precedence!" +/datum/game_mode/monkey/can_start() + if (num_players()<2) + return 0 + for(var/mob/new_player/P in world) + if(P.client && P.ready && !jobban_isbanned(P, "Syndicate")) + return 1 + return 0 + +/datum/game_mode/monkey/pre_setup() + var/list/possible_monkeys = get_players_for_role(BE_MONKEY) + + // stop setup if no possible monkeys + if(!possible_monkeys.len) + return 0 + + var/num_monkeys = MONKEY_MODE_MONKEYS + var/num_players = num_players() + + if (num_players<=num_monkeys) + num_monkeys = round(num_players/2) + + for(var/j = 1 to num_monkeys) + if (!possible_monkeys.len) + break + var/datum/mind/monkey = pick(possible_monkeys) + possible_monkeys-=monkey + initial_monkeys += monkey + monkey.special_role = "monkey" + + if(!initial_monkeys.len) + return 0 + return 1 + /datum/game_mode/monkey/post_setup() spawn (50) - var/list/players = list() - for (var/mob/living/carbon/human/player in world) - if (player.client) - players += player - - if (players.len >= 3) - var/amount = round((players.len - 1) / 3) + 1 - amount = min(4, amount) - - while (amount > 0) - var/mob/living/carbon/human/player = pick(players) - var/mob/living/carbon/monkey/new_monkey = player.monkeyize() - new_monkey << "Your goal is to capture the entire human civilization and your first target is Centcom. Hijack the shuttle without humans aboard." - - players -= player - amount-- + for (var/datum/mind/monkey in initial_monkeys) + var/mob/living/carbon/human/H = monkey.current + var/mob/living/carbon/monkey/new_monkey = H.monkeyize() + new_monkey << "Your goal is to capture the entire human civilization and your first target is Centcom. Hijack the shuttle without humans aboard!" for (var/mob/living/carbon/monkey/rabid_monkey in world) - if (!isturf(rabid_monkey.loc) || rabid_monkey.z!=1) + if (!(rabid_monkey.mind in initial_monkeys) && (!isturf(rabid_monkey.loc) || rabid_monkey.z!=1)) continue - rabid_monkey.contract_disease(new /datum/disease/jungle_fever,0,0) - + rabid_monkey.contract_disease(new /datum/disease/jungle_fever,1,0) + del(initial_monkeys) + ..() /datum/game_mode/monkey/proc/is_important_monkey(var/mob/living/carbon/monkey/M as mob) var/turf/T = get_turf(M) - return M.stat!=2 && istype(M.virus, /datum/disease/jungle_fever) && ( T.z==1 || istype(T.loc, /area/shuttle/escape/centcom) || istype(T.loc, /area/centcom)) + var/area/A = get_area(M) + return \ + M.stat!=2 && \ + istype(M.virus, /datum/disease/jungle_fever) && \ + ( T.z==1 || is_type_in_list(A, centcom_areas)) /datum/game_mode/monkey/check_win() if (state==MONKEY_MODE_SHUTTLE_CAPTURED || state==MONKEY_MODE_SHUTTLE_WITH_HUMANS) @@ -61,16 +89,16 @@ if (state != MONKEY_MODE_NO_RABID_LEFT) for(var/mob/living/carbon/monkey/monkey_player in world) if (is_important_monkey(monkey_player)) - var/turf/location = get_turf(monkey_player.loc) - if (istype(location.loc, /area/shuttle/escape/centcom)) + var/area/A = get_area(monkey_player) + if ( is_type_in_list(A, centcom_areas)) monkeywin = 1 break if(monkeywin) for(var/mob/living/carbon/human/human_player in world) if (human_player.stat != 2) - var/turf/location = get_turf(human_player.loc) - if (istype(location.loc, /area/shuttle/escape/centcom)) + var/area/A = get_area(human_player) + if (istype(A, /area/shuttle/escape/centcom)) monkeywin = 0 break @@ -78,20 +106,21 @@ world << "The monkeys have won! Humanity is doomed!" for (var/mob/living/carbon/human/player in world) if (player.client) - spawn(0) + spawn(rand(0,150)) player.monkeyize() - for(var/mob/living/carbon/monkey/monkey_player in world) - if (monkey_player.client) - world << "[monkey_player.key] was a monkey. [monkey_player.stat == 2 ? "(DEAD)" : ""]" - sleep(50) + sleep(200) else world << "The Research Staff has stopped the monkey invasion!" - for(var/mob/living/carbon/monkey/monkey_player in world) - if (monkey_player.client) - world << "[monkey_player.key] was a monkey. [monkey_player.stat == 2 ? "(DEAD)" : ""]" - + ..() return 1 - + + +/datum/game_mode/proc/auto_declare_completion_monkey() + for(var/mob/living/carbon/monkey/monkey_player in world) + if (istype(monkey_player.virus, /datum/disease/jungle_fever) && monkey_player.ckey) + world << "[monkey_player.ckey] was played infested [monkey_player]. [monkey_player.stat == 2 ? "(DEAD)" : ""]" + return 1 + #undef MONKEY_MODE_RUNNING #undef MONKEY_MODE_NO_RABID_LEFT #undef MONKEY_MODE_SHUTTLE_CAPTURED diff --git a/config/config.txt b/config/config.txt index 28f9b089fd5..f37bc3305a0 100644 --- a/config/config.txt +++ b/config/config.txt @@ -31,19 +31,19 @@ LOG_WHISPER ## set to 0 to disable that mode ## Cult mode is in alpha test, enable at your own risk PROBABILITY EXTENDED 0 -PROBABILITY TRAITOR 8 +PROBABILITY TRAITOR 0 PROBABILITY METEOR 0 PROBABILITY MALFUNCTION 2 PROBABILITY BLOB 0 PROBABILITY NUCLEAR 5 PROBABILITY SANDBOX 0 -PROBABILITY WIZARD 3 +PROBABILITY WIZARD 0 PROBABILITY RESTRUCTURING 0 PROBABILITY REVOLUTION 5 -PROBABILITY CHANGELING 2 -PROBABILITY CULT 0 +PROBABILITY CHANGELING 0 +PROBABILITY CULT 1 PROBABILITY MONKEY 0 - +PROBABILITY TRAITORCHAN 0 ## if amount of traitors scales or not #TRAITOR_SCALING diff --git a/tgstation.dme b/tgstation.dme index 18f81584d27..467e5c1548b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -41,6 +41,7 @@ #define FILE_DIR "code/game/gamemodes/revolution" #define FILE_DIR "code/game/gamemodes/sandbox" #define FILE_DIR "code/game/gamemodes/traitor" +#define FILE_DIR "code/game/gamemodes/traitor_pair" #define FILE_DIR "code/game/gamemodes/wizard" #define FILE_DIR "code/game/jobs" #define FILE_DIR "code/game/machinery" @@ -327,6 +328,7 @@ #include "code\game\gamemodes\blob\theblob.dm" #include "code\game\gamemodes\changeling\changeling.dm" #include "code\game\gamemodes\changeling\changeling_powers.dm" +#include "code\game\gamemodes\changeling\traitor_chan.dm" #include "code\game\gamemodes\cult\cult.dm" #include "code\game\gamemodes\events\clang.dm" #include "code\game\gamemodes\events\dust.dm" @@ -345,6 +347,7 @@ #include "code\game\gamemodes\sandbox\h_sandbox.dm" #include "code\game\gamemodes\sandbox\sandbox.dm" #include "code\game\gamemodes\traitor\traitor.dm" +#include "code\game\gamemodes\traitor_pair\traitor_pair.dm" #include "code\game\gamemodes\wizard\spells.dm" #include "code\game\gamemodes\wizard\wizard.dm" #include "code\game\jobs\access.dm" @@ -785,6 +788,7 @@ #include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm" #include "code\modules\power\singularity\particle_accelerator\particle_power.dm" #include "code\unused\vehicle.dm" +#include "code\unused\gamemodes\monkey.dm" #include "code\WorkInProgress\BrokenInhands.dm" #include "code\WorkInProgress\buildmode.dm" #include "code\WorkInProgress\Cameras.dm"