diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 8f118599e67..1bc3a639cbd 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -27,3 +27,4 @@ #define BE_BLOB 512 #define BE_NINJA 1024 #define BE_MONKEY 2048 +#define BE_GANG 4096 \ No newline at end of file diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 5d3a5f8030b..062be18c68d 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -45,5 +45,6 @@ var/list/be_special_flags = list( "Cultist" = BE_CULTIST, "Blob" = BE_BLOB, "Ninja" = BE_NINJA, - "Monkey" = BE_MONKEY + "Monkey" = BE_MONKEY, + "Gang" = BE_GANG ) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index ef0b79ac279..64daf57b074 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -161,6 +161,10 @@ datum/mind remove_objectives() remove_antag_equip() + proc/remove_gang() + ticker.mode.remove_gangster(src,0,1) + remove_objectives() + proc/remove_malf() if(src in ticker.mode.malf_ai) ticker.mode.malf_ai -= src @@ -196,6 +200,7 @@ datum/mind remove_cultist() remove_rev() remove_malf() + remove_gang() proc/show_memory(mob/recipient, window=1) if(!recipient) @@ -224,6 +229,7 @@ datum/mind var/list/sections = list( "revolution", + "gang", "cult", "wizard", "changeling", @@ -243,7 +249,7 @@ datum/mind if (assigned_role in command_positions) text += "HEAD|loyal|employee|headrev|rev" else if (src in ticker.mode.head_revolutionaries) - text = "head|loyal|employee|HEADREV|rev" + text += "head|loyal|employee|HEADREV|rev" text += "
Flash: give" var/list/L = current.get_contents() @@ -267,6 +273,55 @@ datum/mind text += "head|loyal|EMPLOYEE|headrev|rev" sections["revolution"] = text + /** GANG ***/ + text = "gang" + if (ticker.mode.config_tag=="gang") + text = uppertext(text) + text = "[text]: " + if (src in ticker.mode.A_bosses) + text += "loyal|none|(A) gangster BOSS|(B) gangster boss" + text += "
Flash & Recaller: give" + + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (flash) + if(!flash.broken) + text += "|take equipment." + else + text += "|take equipment|repair flash." + else + text += "." + + if (objectives.len==0) + text += "
Objectives are empty! Set to kill all rival gang leaders." + + else if (src in ticker.mode.B_bosses) + text += "loyal|none|(A) gangster boss|(B) gangster BOSS" + text += "
Flash & Recaller: give" + + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (flash) + if(!flash.broken) + text += "
take equipment." + else + text += "
take equipment|repair flash." + else + text += "." + + if (objectives.len==0) + text += "
Objectives are empty! Set to kill all rival gang leaders." + + else if (src in ticker.mode.A_gangsters) + text += "loyal|none|(A) GANGSTER boss|(B) gangster boss" + else if (src in ticker.mode.B_gangsters) + text += "loyal|none|(A) gangster boss|(B) GANGSTER boss" + else if(isloyal(current)) + text += "LOYAL|none|(A) gangster boss|(B) gangster boss" + else + text += "loyal|NONE|(A) gangster boss|(B) gangster boss" + sections["gang"] = text + /** CULT ***/ text = "cult" if (ticker.mode.config_tag=="cult") @@ -448,7 +503,7 @@ datum/mind out += "Announce objectives

" - usr << browse(out, "window=edit_memory[src]") + usr << browse(out, "window=edit_memory[src];size=400x500") Topic(href, href_list) if(!check_rights(R_ADMIN)) return @@ -684,6 +739,84 @@ datum/mind if (fail) usr << "\red Reequipping revolutionary goes wrong!" + else if (href_list["gang"]) + switch(href_list["gang"]) + if("clear") + remove_gang() + message_admins("[key_name_admin(usr)] has de-gang'ed [current].") + log_admin("[key_name(usr)] has de-gang'ed [current].") + + if("agang") + if(src in ticker.mode.A_gangsters) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.add_gangster(src,"A",0) + message_admins("[key_name_admin(usr)] has added [current] to the [ticker.mode.A_name] Gang (A).") + log_admin("[key_name(usr)] has added [current] to the [ticker.mode.A_name] Gang (A).") + + if("aboss") + if(src in ticker.mode.A_bosses) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.A_bosses += src + src.special_role = "[ticker.mode.A_name] Gang (A) Boss" + ticker.mode.update_gang_icons_added(src, "A") + current << "You are a [ticker.mode.A_name] Gang Boss!" + message_admins("[key_name_admin(usr)] has added [current] to the [ticker.mode.A_name] Gang (A) leadership.") + log_admin("[key_name(usr)] has added [current] to the [ticker.mode.A_name] Gang (A) leadership.") + + if("bgang") + if(src in ticker.mode.B_gangsters) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.add_gangster(src,"B",0) + message_admins("[key_name_admin(usr)] has added [current] to the [ticker.mode.B_name] Gang (B).") + log_admin("[key_name(usr)] has added [current] to the [ticker.mode.B_name] Gang (B).") + + if("bboss") + if(src in ticker.mode.B_bosses) + return + ticker.mode.remove_gangster(src, 0, 2) + ticker.mode.B_bosses += src + src.special_role = "[ticker.mode.B_name] Gang (B) Boss" + ticker.mode.update_gang_icons_added(src, "B") + current << "You are a [ticker.mode.B_name] Gang Boss!" + message_admins("[key_name_admin(usr)] has added [current] to the [ticker.mode.B_name] Gang (B) leadership.") + log_admin("[key_name(usr)] has added [current] to the [ticker.mode.B_name] Gang (B) leadership.") + + if("autoobjective") + ticker.mode.forge_gang_objectives(src) + ticker.mode.greet_gang(src,0) + usr << "Unable to equip flash!" + if(1) + usr << "Unable to equip recaller!" + if(0) + usr << "Unable to equip both flash and recaller!" + + if("takeequip") + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + usr << "\red Deleting flash failed!" + qdel(flash) + var/obj/item/device/recaller/recaller = locate() in L + if (!recaller) + usr << "\red Deleting recaller failed!" + qdel(recaller) + + if("repairflash") + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + if (!flash) + usr << "\red Repairing flash failed!" + else + flash.broken = 0 + else if (href_list["cult"]) switch(href_list["cult"]) if("clear") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 7d6f10c52cc..fa326af8566 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -225,6 +225,7 @@ if(BE_OPERATIVE) roletext="operative" if(BE_WIZARD) roletext="wizard" if(BE_REV) roletext="revolutionary" + if(BE_GANG) roletext="gangster" if(BE_CULTIST) roletext="cultist" if(BE_MONKEY) roletext="monkey" diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm new file mode 100644 index 00000000000..69d376cabfd --- /dev/null +++ b/code/game/gamemodes/gang/gang.dm @@ -0,0 +1,447 @@ +//gang.dm +//Gang War Game Mode + +/datum/game_mode + var/list/datum/mind/A_bosses = list() //gang A bosses + var/list/datum/mind/A_gangsters = list() //gang A Members + var/list/datum/mind/B_bosses = list() //gang B bosses + var/list/datum/mind/B_gangsters = list() //gang B Members + var/A_name = "Waffle" + var/B_name = "Donk" + +/datum/game_mode/gang + name = "gang war" + config_tag = "gang" + antag_flag = BE_GANG + restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") + required_players = 20 + required_enemies = 2 + recommended_enemies = 4 + + var/finished = 0 + var/checkwin_counter = 0 +/////////////////////////// +//Announces the game type// +/////////////////////////// +/datum/game_mode/gang/announce() + world << "The current game mode is - Gang War!" + world << "A violent turf war has erupted on the station!
\nGangsters - Take over the station by killing the rival gang's bosses! Recruit gangsters by flashing them!
\nSecurity - Protect the Crew! Identify and stop the mob bosses!
" + + +/////////////////////////////////////////////////////////////////////////////// +//Gets the round setup, cancelling if there's not enough players at the start// +/////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/gang/pre_setup() + + var/gang_name_pool = list("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Donk", "Gene", "Gib") + A_name = pick(gang_name_pool) + gang_name_pool -= A_name + B_name = pick(gang_name_pool) + + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs)//Removing heads and such from the list + if(player.assigned_role == job) + antag_candidates -= player + + if(antag_candidates.len > 2) + assign_bosses() + if(antag_candidates.len > 20) + assign_bosses() + + if(!A_bosses.len || !B_bosses.len) + return 0 + + return 1 + + +/datum/game_mode/gang/post_setup() + spawn(rand(10,100)) + for(var/datum/mind/boss_mind in A_bosses) + update_gang_icons_added(boss_mind, "A") + forge_gang_objectives(boss_mind, "A") + greet_gang(boss_mind) + equip_gang(boss_mind.current) + + for(var/datum/mind/boss_mind in B_bosses) + update_gang_icons_added(boss_mind, "B") + forge_gang_objectives(boss_mind, "B") + greet_gang(boss_mind) + equip_gang(boss_mind.current) + + modePlayer += A_bosses + modePlayer += B_bosses + ..() + + +/datum/game_mode/gang/process() + checkwin_counter++ + if(checkwin_counter >= 5) + if(!finished) + ticker.mode.check_win() + checkwin_counter = 0 + return 0 + +/datum/game_mode/gang/proc/assign_bosses() + var/datum/mind/boss = pick(antag_candidates) + A_bosses += boss + antag_candidates -= boss + boss.special_role = "[A_name] Gang (A) Boss" + log_game("[boss.key] (ckey) has been selected as a boss for the [A_name] Gang (A)") + + boss = pick(antag_candidates) + B_bosses += boss + antag_candidates -= boss + boss.special_role = "[B_name] Gang (B) Boss" + log_game("[boss.key] (ckey) has been selected as a boss for the [B_name] Gang (B)") + +/datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind) + var/datum/objective/rival_obj = new + rival_obj.owner = boss_mind + rival_obj.explanation_text = "Assassinate or exile the [(boss_mind in A_bosses) ? B_name : A_name] Gang's bosses." + boss_mind.objectives += rival_obj + + +/datum/game_mode/proc/greet_gang(var/datum/mind/boss_mind, var/you_are=1) + var/obj_count = 1 + if (you_are) + boss_mind.current << "You are a [(boss_mind in A_bosses) ? A_name : B_name] Gang Boss!" + for(var/datum/objective/objective in boss_mind.objectives) + boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + +/////////////////////////////////////////////////////////////////////////// +//This equips the bosses with their gear, and makes the clown not clumsy// +/////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/equip_gang(mob/living/carbon/human/mob) + if(!istype(mob)) + return + + if (mob.mind) + if (mob.mind.assigned_role == "Clown") + mob << "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." + mob.mutations.Remove(CLUMSY) + + + var/obj/item/device/flash/T = new(mob) + var/obj/item/device/recaller/recaller = new(mob) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + + . = 0 + + var/where = mob.equip_in_one_of_slots(T, slots) + if (!where) + mob << "Your Syndicate benefactors were unfortunately unable to get you a flash." + else + mob << "The flash in your [where] will help you to persuade the crew to work for you. Keep in mind that your underlings can only identify their bosses, but not each other." + . += 1 + + var/where2 = mob.equip_in_one_of_slots(recaller, slots) + if (!where2) + mob << "Your Syndicate benefactors were unfortunately unable to get you a Recaller." + else + mob << "The Recaller in your [where2] will allow you to prevent the station from prematurely evacuating. Use it to recall the emergency shuttle from anywhere on the station." + . += 2 + + mob.update_icons() + + return . + +///////////////////////////////////////////// +//Checks if the either gang have won or not// +///////////////////////////////////////////// +/datum/game_mode/gang/check_win() + var/A_victory = check_gang_victory(B_bosses) //Check if B bosses are dead or exiled + var/B_victory = check_gang_victory(A_bosses) //Check if A bosses are dead or exiled + + if(A_victory && B_victory) + finished = "Draw" //Both teams fail. Allow for draws in case they're all incapacitated at the same time. + + else if(A_victory) + finished = "A" //Gang A wins + + else if(B_victory) + finished = "B" //Gang B wins + +/////////////////////////////// +//Checks if the round is over// +/////////////////////////////// +/datum/game_mode/gang/check_finished() + if(finished) + return finished + return 0 + +/////////////////////////////////////////// +//Deals with converting players to a gang// +/////////////////////////////////////////// +/datum/game_mode/proc/add_gangster(datum/mind/gangster_mind, var/gang, var/check = 1) + if(check && isloyal(gangster_mind.current)) //Check to see if the potential gangster is implanted + return 0 + if((gangster_mind in A_bosses) || (gangster_mind in A_gangsters) || (gangster_mind in B_bosses) || (gangster_mind in B_gangsters)) + return 0 + if(gang == "A") + A_gangsters += gangster_mind + else + B_gangsters += gangster_mind + gangster_mind.current << "You are now a member of the [gang=="A" ? A_name : B_name] Gang!" + gangster_mind.current << "Help your bosses take over the station by defeating their rivals. You can identify your bosses by the brown \"B\" icons, but only they know who is in your gang! Work with your boss to avoid attacking your own gang." + gangster_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [gang=="A" ? "[A_name] Gang (A)" : "[B_name] Gang (B)"]!" + gangster_mind.special_role = "[gang=="A" ? "[A_name] Gang (A)" : "[B_name] Gang (B)"]" + update_gang_icons_added(gangster_mind,gang) + return 1 +////////////////////////////////////////////////////////////// +//Deals with players going straight (Not a gangster anymore)// +////////////////////////////////////////////////////////////// +/datum/game_mode/proc/remove_gangster(datum/mind/gangster_mind, var/beingborged, var/silent) + var/gang + + if(gangster_mind in A_bosses) + A_bosses -= gangster_mind + gang = "A" + + else if(gangster_mind in A_gangsters) + A_gangsters -= gangster_mind + gang = "A" + + else if(gangster_mind in B_bosses) + B_bosses -= gangster_mind + gang = "B" + + else if(gangster_mind in B_gangsters) + B_gangsters -= gangster_mind + gang = "B" + + if(!gang) //not a valid gangster + return + + gangster_mind.special_role = null + if(silent < 2) + gangster_mind.current.attack_log += "\[[time_stamp()]\] Has reformed and defected from the [gang=="A" ? "[A_name] Gang (A)" : "[B_name] Gang (B)"]!" + + if(beingborged) + if(!silent) + gangster_mind.current.visible_message("The frame beeps contentedly from the MMI before initalizing it.") + gangster_mind.current << "The frame's firmware detects and deletes your criminal behavior! You are no longer a gangster!" + message_admins("[key_name_admin(gangster_mind.current)] ? has been borged while being a member of the [gang=="A" ? "[A_name] Gang (A)" : "[B_name] Gang (B)"] Gang.") + else + if(!silent) + gangster_mind.current.visible_message("[gangster_mind.current] looks like they've given up the life of crime!") + gangster_mind.current << "You have been reformed! You are no longer a gangster!" + + update_gang_icons_removed(gangster_mind) + + +///////////////////////////////////////////////////////////////////////////////////////////////// +//Keeps track of players having the correct icons//////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/update_all_gang_icons() + spawn(0) + var/list/all_gangsters = A_bosses + B_bosses + A_gangsters + B_gangsters + + //Delete all gang icons + for(var/datum/mind/gang_mind in all_gangsters) + if(gang_mind.current) + if(gang_mind.current.client) + for(var/image/I in gang_mind.current.client.images) + if(I.icon_state == "gangster" || I.icon_state == "gang_boss") + del(I) + + update_gang_icons("A") + update_gang_icons("B") + +/datum/game_mode/proc/update_gang_icons(var/gang) + var/list/bosses + var/list/gangsters + if(gang == "A") + bosses = A_bosses + gangsters = A_gangsters + else if(gang == "B") + bosses = B_bosses + gangsters = B_gangsters + else + world << "ERROR: Invalid gang in update_gang_icons()" + + //Update gang icons for boss' visions + for(var/datum/mind/boss_mind in bosses) + if(boss_mind.current) + if(boss_mind.current.client) + for(var/datum/mind/gangster_mind in gangsters) + if(gangster_mind.current) + var/I = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gangster") + boss_mind.current.client.images += I + for(var/datum/mind/boss2_mind in bosses) + if(boss2_mind.current) + var/I = image('icons/mob/mob.dmi', loc = boss2_mind.current, icon_state = "gang_boss") + boss_mind.current.client.images += I + + //Update boss and self icons for gangsters' visions + for(var/datum/mind/gangster_mind in gangsters) + if(gangster_mind.current) + if(gangster_mind.current.client) + for(var/datum/mind/boss_mind in bosses) + if(boss_mind.current) + var/I = image('icons/mob/mob.dmi', loc = boss_mind.current, icon_state = "gang_boss") + gangster_mind.current.client.images += I + //Tag themselves to see + var/K + if(gangster_mind in bosses) //If the new gangster is a boss himself + K = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gang_boss") + else + K = image('icons/mob/mob.dmi', loc = gangster_mind.current, icon_state = "gangster") + gangster_mind.current.client.images += K + +///////////////////////////////////////////////// +//Assigns icons when a new gangster is recruited// +///////////////////////////////////////////////// +/datum/game_mode/proc/update_gang_icons_added(datum/mind/recruit_mind, var/gang) + var/list/bosses + if(gang == "A") + bosses = A_bosses + else if(gang == "B") + bosses = B_bosses + if(!gang) + world << "ERROR: Invalid gang in update_gang_icons_added()" + + spawn(0) + for(var/datum/mind/boss_mind in bosses) + //Tagging the new gangster for the bosses to see + if(boss_mind.current) + if(boss_mind.current.client) + var/I + if(recruit_mind in bosses) //If the new gangster is a boss himself + I = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gang_boss") + else + I = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gangster") + boss_mind.current.client.images += I + //Tagging every boss for the new gangster to see + if(recruit_mind.current) + if(recruit_mind.current.client) + var/image/J = image('icons/mob/mob.dmi', loc = boss_mind.current, icon_state = "gang_boss") + recruit_mind.current.client.images += J + //Tag themselves to see + if(recruit_mind.current) + if(recruit_mind.current.client) + var/K + if(recruit_mind in bosses) //If the new gangster is a boss himself + K = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gang_boss") + else + K = image('icons/mob/mob.dmi', loc = recruit_mind.current, icon_state = "gangster") + recruit_mind.current.client.images += K + +//////////////////////////////////////// +//Keeps track of deconverted gangsters// +//////////////////////////////////////// +/datum/game_mode/proc/update_gang_icons_removed(datum/mind/defector_mind) + var/list/all_gangsters = A_bosses + B_bosses + A_gangsters + B_gangsters + + spawn(0) + //Remove defector's icon from gangsters' visions + for(var/datum/mind/boss_mind in all_gangsters) + if(boss_mind.current) + if(boss_mind.current.client) + for(var/image/I in boss_mind.current.client.images) + if((I.icon_state == "gangster" || I.icon_state == "gang_boss") && I.loc == defector_mind.current) + del(I) + + //Remove gang icons from defector's vision + if(defector_mind.current) + if(defector_mind.current.client) + for(var/image/I in defector_mind.current.client.images) + if(I.icon_state == "gangster" || I.icon_state == "gang_boss") + del(I) + +/////////////////////////// +//Checks for gang victory// +/////////////////////////// +/datum/game_mode/gang/proc/check_gang_victory(var/list/boss_list) + if(!boss_list.len) + return 0 + for(var/datum/mind/boss_mind in boss_list) + if(boss_mind.current) + if(boss_mind.current.stat == DEAD || !ishuman(boss_mind.current) || !boss_mind.current.ckey || !boss_mind.current.client) + return 1 + var/turf/T = get_turf(boss_mind.current) + if(T && (T.z != 1)) //If they leave the station they count as dead for this + return 1 + return 0 + return 1 + +////////////////////////////////////////////////////////////////////// +//Announces the end of the game with all relavent information stated// +////////////////////////////////////////////////////////////////////// +/datum/game_mode/gang/declare_completion() + if(!finished) + world << "The station was evacuated before either gang could claim it!" + if(finished == "Draw") + world << "All gang bosses have been killed or exiled!" + else + world << "The [finished=="A" ? A_name : B_name] Gang defeated their rivals!" + ..() + return 1 + +/datum/game_mode/proc/auto_declare_completion_gang() + var/winner + var/datum/game_mode/gang/game_mode = ticker.mode + if(istype(game_mode)) + winner = game_mode.finished + + var/num_ganga = 0 + var/list/agang = A_gangsters + A_bosses + for(var/datum/mind/agangster in agang) + if(agangster.current) + if(agangster.current in living_mob_list) + num_ganga++ + + var/num_gangb = 0 + var/list/bgang = B_gangsters + B_bosses + for(var/datum/mind/bgangster in bgang) + if(bgangster.current) + if(bgangster.current in living_mob_list) + num_gangb++ + + if(A_bosses.len || A_gangsters.len) + if(winner == "A" || winner == "B") + world << "
The [A_name] Gang was [winner=="A" ? "victorious!" : "defeated."]" + world << "[TAB][A_name] Gang strength: [round((num_ganga/living_mob_list.len)*100, 0.1)]%" + world << "
The [A_name] Gang bosses were:" + gang_membership_report(A_bosses) + world << "
The [A_name] Gangsters were:" + gang_membership_report(A_gangsters) + + if(B_bosses.len || B_gangsters.len) + if(winner == "A" || winner == "B") + world << "
The [B_name] Gang was [winner=="B" ? "victorious!" : "defeated."]" + world << "[TAB][B_name] Gang strength: [round((num_gangb/living_mob_list.len)*100, 0.1)]%" + world << "
The [B_name] Gang bosses were:" + gang_membership_report(B_bosses) + world << "
The [B_name] Gangsters were:" + gang_membership_report(B_gangsters) + +/datum/game_mode/proc/gang_membership_report(var/list/membership) + var/text = "" + for(var/datum/mind/gang_mind in membership) + text += "
[gang_mind.key] was [gang_mind.name] (" + if(gang_mind.current) + if(gang_mind.current.stat == DEAD) + text += "died" + else if(gang_mind.current.z != 1) + text += "fled the station" + else + text += "survived" + if(gang_mind.current.real_name != gang_mind.name) + text += " as [gang_mind.current.real_name]" + else + text += "body destroyed" + text += ")" + text += "
" + + world << text \ No newline at end of file diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm index 35b5f42c699..0b64acb7eb4 100644 --- a/code/game/gamemodes/intercept_report.dm +++ b/code/game/gamemodes/intercept_report.dm @@ -61,6 +61,10 @@ src.text = "" src.build_rev(correct_person) return src.text + if("gang") + src.text = "" + src.build_gang(correct_person) + return src.text if("cult") src.text = "" src.build_cult(correct_person) @@ -220,6 +224,10 @@ src.text += "
However, if this information is acted on without substantial evidence, those responsible will face severe repercussions." */ +/datum/intercept_text/proc/build_gang(datum/mind/correct_person) + src.text += "

Syndicate forces may be supplying opposing criminal organizations within your sector in an attempt at destabilizing our operations." + src.text += "Ensure law and order is maintained on the station and be on the lookout for violent confrontations between station factions." + src.text += "Forced labor on the mining asteroid is recommended for anyone convicted of heading a criminal organization." /datum/intercept_text/proc/build_wizard(datum/mind/correct_person) var/SWF_desc = pick(SWF_names) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 30cc57e9c7f..a3c9a89af8d 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -90,7 +90,7 @@ datum/objective/mutiny/check_completion() datum/objective/mutiny/update_explanation_text() ..() if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [!target_role_type ? target.assigned_role : target.special_role]." + explanation_text = "Assassinate or exile [target.current.real_name], the [!target_role_type ? target.assigned_role : target.special_role]." else explanation_text = "Free Objective" diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 383fcb9c653..437e73eace5 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -79,10 +79,11 @@ rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." rev_mind.objectives += rev_obj - // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO - // Removing revolutionary uplinks. -Pete - equip_revolutionary(rev_mind.current) - update_rev_icons_added(rev_mind) + spawn(rand(10,100)) + // equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO + // Removing revolutionary uplinks. -Pete + equip_revolutionary(rev_mind.current) + update_rev_icons_added(rev_mind) for(var/datum/mind/rev_mind in head_revolutionaries) greet_revolutionary(rev_mind) @@ -107,7 +108,7 @@ var/datum/objective/mutiny/rev_obj = new rev_obj.owner = rev_mind rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.name], the [head_mind.assigned_role]." + rev_obj.explanation_text = "Assassinate or exile [head_mind.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) @@ -200,7 +201,8 @@ rev_mind.current.attack_log += "\[[time_stamp()]\] Has renounced the revolution!" if(beingborged) - rev_mind.current << "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing from the moment you were flashed until now." + rev_mind.current << "\red The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you." + message_admins("[key_name_admin(rev_mind.current)] ? has been borged while being a member of the revolution.") else rev_mind.current << "\red You have been brainwashed! You are no longer a revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you..." @@ -268,20 +270,36 @@ /datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) spawn(0) for(var/datum/mind/head_rev_mind in head_revolutionaries) + + //Tagging the new rev for revheads to see if(head_rev_mind.current) if(head_rev_mind.current.client) - var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") + var/I + if(rev_mind in head_revolutionaries) //If the new rev is a head rev + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") + else + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") head_rev_mind.current.client.images += I + + //Tagging the revheads for new rev to see if(rev_mind.current) if(rev_mind.current.client) var/image/J = image('icons/mob/mob.dmi', loc = head_rev_mind.current, icon_state = "rev_head") rev_mind.current.client.images += J for(var/datum/mind/rev_mind_1 in revolutionaries) + + //Tagging the new rev for fellow revs to see if(rev_mind_1.current) if(rev_mind_1.current.client) - var/I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") + var/I + if(rev_mind in head_revolutionaries) //If the new rev is a head rev + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev_head") + else + I = image('icons/mob/mob.dmi', loc = rev_mind.current, icon_state = "rev") rev_mind_1.current.client.images += I + + //Tagging fellow revs for the new rev to see if(rev_mind.current) if(rev_mind.current.client) var/image/J = image('icons/mob/mob.dmi', loc = rev_mind_1.current, icon_state = "rev") @@ -340,7 +358,7 @@ /datum/game_mode/revolution/declare_completion() if(finished == 1) feedback_set_details("round_end_result","win - heads killed") - world << "\red The heads of staff were killed or abandoned the station! The revolutionaries win!" + world << "\red The heads of staff were killed or exiled! The revolutionaries win!" else if(finished == 2) feedback_set_details("round_end_result","loss - rev heads killed") world << "\red The heads of staff managed to stop the revolution!" @@ -421,10 +439,4 @@ text += "" text += "
" - world << text - -/proc/is_convertable_to_rev(datum/mind/mind) - return istype(mind) && \ - istype(mind.current, /mob/living/carbon/human) && \ - !(mind.assigned_role in command_positions) && \ - !(mind.assigned_role in list("Security Officer", "Detective", "Warden")) + world << text \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index ec9da16ba30..58884d1ee05 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -174,17 +174,15 @@ // -- Mode/mind specific stuff goes here - switch(ticker.mode.name) - if("revolution") - if((H.mind in ticker.mode:revolutionaries) || (H.mind in ticker.mode:head_revolutionaries)) - ticker.mode.update_all_rev_icons() //So the icon actually appears - if("nuclear emergency") - if(H.mind in ticker.mode.syndicates) - ticker.mode.update_all_synd_icons() - if("cult") - if (H.mind in ticker.mode.cult) - ticker.mode.add_cultist(src.occupant.mind) - ticker.mode.update_all_cult_icons() //So the icon actually appears + if((H.mind in ticker.mode.revolutionaries) || (H.mind in ticker.mode.head_revolutionaries)) + ticker.mode.update_all_rev_icons() //So the icon actually appears + if((H.mind in ticker.mode.A_bosses) || ((H.mind in ticker.mode.A_gangsters) || (H.mind in ticker.mode.B_bosses)) || (H.mind in ticker.mode.B_gangsters)) + ticker.mode.update_all_gang_icons() + if(H.mind in ticker.mode.syndicates) + ticker.mode.update_all_synd_icons() + if (H.mind in ticker.mode.cult) + ticker.mode.add_cultist(src.occupant.mind) + ticker.mode.update_all_cult_icons() //So the icon actually appears // -- End mode specific stuff diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 169d8ef70a9..f41a70a2032 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -143,6 +143,7 @@ ticker.mode.remove_cultist(M.brainmob.mind, 1) ticker.mode.remove_revolutionary(M.brainmob.mind, 1) + ticker.mode.remove_gangster(M.brainmob.mind, 1) user.drop_item() M.loc = src diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 7ab878e4c54..2d60a854cad 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -624,6 +624,7 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 emergency_shuttle.recall(signal_origin) log_game("[key_name(user)] has recalled the shuttle.") message_admins("[key_name_admin(user)] has recalled the shuttle.", 1) + return 1 return /obj/machinery/computer/communications/proc/post_status(var/command, var/data1, var/data2) diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index df97a6ab825..a2c5b5112b6 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -74,21 +74,22 @@ flick("e_flash", M.flash) if(ishuman(M) && ishuman(user) && M.stat != DEAD) - if(user.mind && user.mind in ticker.mode.head_revolutionaries) + if(user.mind && ((user.mind in ticker.mode.head_revolutionaries) || (user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses))) if(M.client) if(M.stat == CONSCIOUS) - var/revsafe = 0 - if(isloyal(M)) - revsafe = 1 M.mind_initialize() //give them a mind datum if they don't have one. -// if(M.mind.has_been_rev) -// revsafe = 2 - if(!revsafe) - M.mind.has_been_rev = 1 - ticker.mode.add_revolutionary(M.mind) - else if(revsafe == 1) - user << "Something seems to be blocking the flash!" - else + M.mind.has_been_rev = 1 + var/resisted + if(user.mind in ticker.mode.head_revolutionaries) + if(!ticker.mode.add_revolutionary(M.mind)) + resisted = 1 + if(user.mind in ticker.mode.A_bosses) + if(!ticker.mode.add_gangster(M.mind,"A")) + resisted = 1 + if(user.mind in ticker.mode.B_bosses) + if(!ticker.mode.add_gangster(M.mind,"B")) + resisted = 1 + if(resisted) user << "This mind seems resistant to the flash!" else user << "They must be conscious before you can convert them!" diff --git a/code/game/objects/items/devices/recaller.dm b/code/game/objects/items/devices/recaller.dm new file mode 100644 index 00000000000..b95614c3034 --- /dev/null +++ b/code/game/objects/items/devices/recaller.dm @@ -0,0 +1,42 @@ +//Recaller device +//Allows gang leaders to recall the shuttle +/obj/item/device/recaller + name = "suspicious device" + desc = "A strange device of sorts. Hard to really make out what it actually does just by looking." + icon_state = "recaller" + item_state = "walkietalkie" + throwforce = 0 + w_class = 1.0 + throw_speed = 3 + throw_range = 7 + flags = CONDUCT + var/recalling = 0 + +/obj/item/device/recaller/attack_self(mob/user) + if(recalling) + return + if((user.mind in ticker.mode.A_bosses) || (user.mind in ticker.mode.B_bosses)) + var/turf/userturf = get_turf(user) + if(userturf.z != 1) + user << "Error: Device out of range of station communication arrays." + return + + if(emergency_shuttle.location==0) + if (emergency_shuttle.online) + recalling = 1 + user << "Generating shuttle recall order with codes retrieved from last call signal..." + sleep(10) + user << "Shuttle recall order generated." + sleep(5) + user << "Accessing station long-range communication arrays..." + sleep(10) + user << "Comm arrays accessed." + sleep(5) + user << "Broadcasting recall signal..." + sleep(20) + recalling = 0 + if(!cancel_call_proc(user)) + user << "No response recieved. Emergency shuttle cannot be recalled at this time." + return + + user << "Emergency shuttle cannot be recalled at this time." \ No newline at end of file diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index f88936e66d9..f7c8c2a4e71 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -196,7 +196,7 @@ user << "\red Sticking a dead brain into the frame would sort of defeat the purpose." return - if(M.brainmob.mind in ticker.mode.head_revolutionaries) + if((M.brainmob.mind in ticker.mode.head_revolutionaries) || (M.brainmob.mind in ticker.mode.A_bosses) || (M.brainmob.mind in ticker.mode.B_bosses)) user << "\red The frame's firmware lets out a shrill sound, and flashes 'Abnormal Memory Engram'. It refuses to accept the MMI." return diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 860766ddeb4..fac7c352b25 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -365,7 +365,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" for(var/j in nonhuman_positions) output += "" - for(var/j in list("traitor","changeling","operative","revolutionary","cultist","wizard")) + for(var/j in list("traitor","changeling","operative","revolutionary", "gangster","cultist","wizard")) output += "" output += "" output += "Reason:

" diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index d9b91ef9f84..1d17c674f9a 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -430,6 +430,38 @@ dat += "Head not found!" dat += "" + if(ticker.mode.A_bosses.len || ticker.mode.A_gangsters.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.A_bosses) + var/mob/M = N.current + if(!M) + dat += "" + else + dat += "" + dat += "" + for(var/datum/mind/N in ticker.mode.A_gangsters) + var/mob/M = N.current + if(M) + dat += "" + dat += "" + dat += "
[ticker.mode.A_name] Gang Members
Gang Boss not found!
[M.real_name] (Boss)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
" + + if(ticker.mode.B_bosses.len || ticker.mode.B_gangsters.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.B_bosses) + var/mob/M = N.current + if(!M) + dat += "" + else + dat += "" + dat += "" + for(var/datum/mind/N in ticker.mode.B_gangsters) + var/mob/M = N.current + if(M) + dat += "" + dat += "" + dat += "
[ticker.mode.B_name] Gang Members
Gang Boss not found!
[M.real_name] (Boss)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
[M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""]PM
" + if(ticker.mode.changelings.len > 0) dat += "
" for(var/datum/mind/changeling in ticker.mode.changelings) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index e0375d13081..dede8d1be7d 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -558,6 +558,12 @@ jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + //Gangster + if(jobban_isbanned(M, "gangster") || isbanned_dept) + jobs += "" + else + jobs += "" + //Cultist if(jobban_isbanned(M, "cultist") || isbanned_dept) jobs += "" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 392768a0f8a..52efcd293d7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -16,7 +16,8 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set "pAI candidate" = 1, // 7 "cultist" = IS_MODE_COMPILED("cult"), // 8 "blob" = IS_MODE_COMPILED("blob"), // 9 - "monkey" = IS_MODE_COMPILED("monkey") // 10 + "monkey" = IS_MODE_COMPILED("monkey"), // 10 + "gangster" = IS_MODE_COMPILED("gang") // 11 ) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 3b2fc03923e..d3c5fdea595 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -817,20 +817,19 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) mind.transfer_to(podman) mind.active = oldactive // -- Mode/mind specific stuff goes here. TODO! Broken :( Should be merged into mob/living/Login - switch(ticker.mode.name) - if("revolution") - if(podman.mind in ticker.mode:revolutionaries) - ticker.mode:add_revolutionary(podman.mind) - ticker.mode:update_all_rev_icons() //So the icon actually appears - if(podman.mind in ticker.mode:head_revolutionaries) - ticker.mode:update_all_rev_icons() - if("nuclear emergency") - if(podman.mind in ticker.mode:syndicates) - ticker.mode:update_all_synd_icons() - if("cult") - if(podman.mind in ticker.mode:cult) - ticker.mode:add_cultist(podman.mind) - ticker.mode:update_all_cult_icons() //So the icon actually appears + if((podman.mind in ticker.mode.A_bosses) || (podman.mind in ticker.mode.A_gangsters) || (podman.mind in ticker.mode.B_bosses) || (podman.mind in ticker.mode.B_gangsters)) + ticker.mode.update_all_gang_icons() + if(podman.mind in ticker.mode:revolutionaries) + ticker.mode.add_revolutionary(podman.mind) + ticker.mode.update_all_rev_icons() //So the icon actually appears + if(podman.mind in ticker.mode:head_revolutionaries) + ticker.mode.add_revolutionary(podman.mind) + ticker.mode.update_all_rev_icons() + if(podman.mind in ticker.mode:syndicates) + ticker.mode:update_all_synd_icons() + if(podman.mind in ticker.mode:cult) + ticker.mode:add_cultist(podman.mind) + ticker.mode:update_all_cult_icons() //So the icon actually appears // -- End mode specific stuff diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 35afcd97f8d..35682a33ed6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -183,6 +183,7 @@ emp_act apply_effect(20, PARALYZE, armor) if(src != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(mind) + ticker.mode.remove_gangster(mind) if(bloody) //Apply blood if(wear_mask) wear_mask.add_blood(src) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index ee4865b6ca4..b047cb7ecdc 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -874,6 +874,7 @@ H.apply_effect(20, PARALYZE, armor) if(H != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(H.mind) + ticker.mode.remove_gangster(H.mind) if(bloody) //Apply blood if(H.wear_mask) diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index d19335d1f3e..c6f2e36db44 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -12,6 +12,11 @@ if("revolution") if((mind in ticker.mode.revolutionaries) || (src.mind in ticker.mode:head_revolutionaries)) ticker.mode.update_rev_icons_added(src.mind) + if("gang") + if((mind in ticker.mode.A_bosses) || (mind in ticker.mode.A_gangsters)) + ticker.mode.update_rev_icons_added(src.mind,"A") + if((mind in ticker.mode.B_bosses) || (mind in ticker.mode.B_gangsters)) + ticker.mode.update_rev_icons_added(src.mind,"B") if("cult") if(mind in ticker.mode:cult) ticker.mode.update_cult_icons_added(src.mind) diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 677d8fea567..f8bed180209 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -2,4 +2,5 @@ if(mind && ticker && ticker.mode) ticker.mode.remove_cultist(mind, 0) ticker.mode.remove_revolutionary(mind, 0) + ticker.mode.remove_gangster(mind, 0) ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index 99e69a84c53..3a8a144d0eb 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -4,6 +4,7 @@ regenerate_icons() show_laws(0) if(mind) ticker.mode.remove_revolutionary(mind) + if(mind) ticker.mode.remove_gangster(mind) /mob/living/silicon/robot/update_hotkey_mode() winset(src, null, "mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0") diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a4bf9852443..4e010f5a577 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -395,6 +395,9 @@ proc/is_special_character(mob/M) // returns 1 for special characters and 2 for h if("revolution") if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries)) return 2 + if("gang") + if((M.mind in ticker.mode.A_bosses) || (M.mind in ticker.mode.B_bosses) || (M.mind in ticker.mode.A_gangsters) || (M.mind in ticker.mode.B_gangsters)) + return 2 if("cult") if(M.mind in ticker.mode.cult) return 2 diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 5530db7dc60..648866f97d7 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 28451ff9fc2..2cfaf2b0015 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index db879f05ce4..5e66e0549d7 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 548d5fabb98..bbf82a9d89f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -276,6 +276,7 @@ #include "code\game\gamemodes\cult\runes.dm" #include "code\game\gamemodes\cult\talisman.dm" #include "code\game\gamemodes\extended\extended.dm" +#include "code\game\gamemodes\gang\gang.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" @@ -500,6 +501,7 @@ #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" #include "code\game\objects\items\devices\powersink.dm" +#include "code\game\objects\items\devices\recaller.dm" #include "code\game\objects\items\devices\scanners.dm" #include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\traitordevices.dm"
Changelings
[replacetext("Gangster", " ", " ")][replacetext("Gangster", " ", " ")][replacetext("Cultist", " ", " ")]