diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index c5262c58614..c10e56598de 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -27,6 +27,7 @@ #define ANTAG_HUD_CULT 6 #define ANTAG_HUD_REV 7 #define ANTAG_HUD_OPS 8 - #define ANTAG_HUD_WIZ 9 #define ANTAG_HUD_SHADOW 10 +#define ANTAG_HUD_HOG_BLUE 11 +#define ANTAG_HUD_HOG_RED 12 diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 65084617ba1..bfa8b697c98 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -28,20 +28,3 @@ #define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO) -//Antag toggles -#define BE_TRAITOR 1 -#define BE_OPERATIVE 2 -#define BE_CHANGELING 4 -#define BE_WIZARD 8 -#define BE_MALF 16 -#define BE_REV 32 -#define BE_ALIEN 64 -#define BE_PAI 128 -#define BE_CULTIST 256 -#define BE_BLOB 512 -#define BE_NINJA 1024 -#define BE_MONKEY 2048 -#define BE_GANG 4096 -#define BE_SHADOWLING 8192 -#define BE_ABDUCTOR 16384 -#define BE_REVENANT 32768 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm new file mode 100644 index 00000000000..63b85ec17b6 --- /dev/null +++ b/code/__DEFINES/role_preferences.dm @@ -0,0 +1,50 @@ + + +//Values for antag preferences, event roles, etc. unified here + + + +//These are synced with the Database, if you change the values of the defines +//then you MUST update the database! +#define ROLE_TRAITOR "traitor" +#define ROLE_OPERATIVE "operative" +#define ROLE_CHANGELING "changeling" +#define ROLE_WIZARD "wizard" +#define ROLE_MALF "malf AI" +#define ROLE_REV "revolutionary" +#define ROLE_ALIEN "xenomorph" +#define ROLE_PAI "pAI" +#define ROLE_CULTIST "cultist" +#define ROLE_BLOB "blob" +#define ROLE_NINJA "space ninja" +#define ROLE_MONKEY "monkey" +#define ROLE_GANG "gangster" +#define ROLE_SHADOWLING "shadowling" +#define ROLE_ABDUCTOR "abductor" +#define ROLE_REVENANT "revenant" +#define ROLE_HOG_GOD "hand of god: god" +#define ROLE_HOG_CULTIST "hand of god: cultist" + + +//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. +//The gamemode specific ones are just so the gamemodes can query whether a player is old enough +//(in game days played) to play that role +var/global/list/special_roles = list( + ROLE_TRAITOR = /datum/game_mode/traitor, + ROLE_OPERATIVE = /datum/game_mode/nuclear, + ROLE_CHANGELING = /datum/game_mode/changeling, + ROLE_WIZARD = /datum/game_mode/wizard, + ROLE_MALF = /datum/game_mode/malfunction, + ROLE_REV = /datum/game_mode/revolution, + ROLE_ALIEN, + ROLE_PAI, + ROLE_CULTIST = /datum/game_mode/cult, + ROLE_BLOB = /datum/game_mode/blob, + ROLE_NINJA, + ROLE_MONKEY = /datum/game_mode/monkey, + ROLE_GANG = /datum/game_mode/gang, + ROLE_SHADOWLING = /datum/game_mode/shadowling, + ROLE_ABDUCTOR = /datum/game_mode/abduction, + ROLE_HOG_GOD = /datum/game_mode/hand_of_god, + ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god, +) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 3fb2d211dfb..90c7b7ff039 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -275,14 +275,14 @@ // Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer. -/proc/get_candidates(be_special_flag=0,afk_bracket=3000, var/jobbanType) +/proc/get_candidates(be_special_type, afk_bracket=3000, var/jobbanType) var/list/candidates = list() // Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000)) while(!candidates.len && afk_bracket < 6000) for(var/mob/dead/observer/G in player_list) if(G.client != null) if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - if(!G.client.is_afk(afk_bracket) && (G.client.prefs.be_special & be_special_flag)) + if(!G.client.is_afk(afk_bracket) && (be_special_type in G.client.prefs.be_special)) if (jobbanType) if(!(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))) candidates += G.client diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 676c81fdb43..25f1aece752 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -290,6 +290,8 @@ Turf and target are seperate in case you want to teleport some distance from a t newname = pick(mime_names) if("ai") newname = pick(ai_names) + if("deity") + newname = pick(clown_names|ai_names|mime_names) //pick any old name else return diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index af013fa2aa6..ded24179173 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -34,21 +34,3 @@ var/MAX_EX_LIGHT_RANGE = 14 var/MAX_EX_FLASH_RANGE = 14 var/MAX_EX_FLAME_RANGE = 14 -var/list/be_special_flags = list( - "Traitor" = BE_TRAITOR, - "Operative" = BE_OPERATIVE, - "Changeling" = BE_CHANGELING, - "Wizard" = BE_WIZARD, - "Malf AI" = BE_MALF, - "Revolutionary" = BE_REV, - "Alien Lifeform" = BE_ALIEN, - "pAI" = BE_PAI, - "Cultist" = BE_CULTIST, - "Blob" = BE_BLOB, - "Ninja" = BE_NINJA, - "Monkey" = BE_MONKEY, - "Gang" = BE_GANG, - "Abductor" = BE_ABDUCTOR, - "Revenant" = BE_REVENANT, - "Shadowling" = BE_SHADOWLING - ) diff --git a/code/_onclick/god.dm b/code/_onclick/god.dm new file mode 100644 index 00000000000..43d917112fc --- /dev/null +++ b/code/_onclick/god.dm @@ -0,0 +1,8 @@ +/mob/camera/god/UnarmedAttack(atom/A) + A.attack_god(src) + +/mob/camera/god/RangedAttack(atom/A) + A.attack_god(src) + +/atom/proc/attack_god(mob/user) + return diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 07ec24e0106..b6f7e260ef0 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -123,9 +123,15 @@ #define ui_head "WEST+1:8,SOUTH+3:11" -// Ghosts +//Ghosts #define ui_ghost_jumptomob "SOUTH:6,CENTER-2:16" #define ui_ghost_orbit "SOUTH:6,CENTER-1:16" #define ui_ghost_reenter_corpse "SOUTH:6,CENTER:16" #define ui_ghost_teleport "SOUTH:6,CENTER+1:16" + +//Hand of God, god + +#define ui_deityhealth "EAST-1:28,CENTER-2:13" +#define ui_deitypower "EAST-1:28,CENTER-1:15" +#define ui_deityfollowers "EAST-1:28,CENTER:17" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 3efbb13d9e3..fbd9114c325 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -97,9 +97,16 @@ var/datum/global_hud/global_hud = new() var/obj/screen/lingchemdisplay var/obj/screen/lingstingdisplay + var/obj/screen/blobpwrdisplay var/obj/screen/blobhealthdisplay + var/obj/screen/alien_plasma_display + + var/obj/screen/deity_health_display + var/obj/screen/deity_power_display + var/obj/screen/deity_follower_display + var/obj/screen/nightvisionicon var/obj/screen/r_hand_hud_object var/obj/screen/l_hand_hud_object @@ -199,10 +206,11 @@ var/datum/global_hud/global_hud = new() drone_hud(ui_style) else if(isswarmer(mymob)) swarmer_hud() + else if(is_handofgod_god(mymob)) + hoggod_hud() else if(isguardian(mymob)) guardian_hud() - //Version denotes which style should be displayed. blank or 0 means "next version" /datum/hud/proc/show_hud(version = 0) if(!ismob(mymob)) diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index ddf84bedea3..8b12ed73b8e 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -30,4 +30,28 @@ mymob.client.screen = list() mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay) - mymob.client.screen += mymob.client.void \ No newline at end of file + mymob.client.screen += mymob.client.void + + +/datum/hud/proc/hoggod_hud(ui_style = 'icons/mob/screen_midnight.dmi') + deity_health_display = new /obj/screen() + deity_health_display.name = "Nexus Health" + deity_health_display.icon_state = "deity_nexus" + deity_health_display.screen_loc = ui_deityhealth + deity_health_display.layer = 20 + + deity_power_display = new /obj/screen() + deity_power_display.name = "Faith" + deity_power_display.icon_state = "deity_power" + deity_power_display.screen_loc = ui_deitypower + deity_power_display.layer = 20 + + deity_follower_display = new /obj/screen() + deity_follower_display.name = "Followers" + deity_follower_display.icon_state = "deity_followers" + deity_follower_display.screen_loc = ui_deityfollowers + deity_follower_display.layer = 20 + + mymob.client.screen = null + + mymob.client.screen += list(deity_health_display, deity_power_display, deity_follower_display) diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index 85586d165b3..eb40fc49621 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -81,7 +81,7 @@ var/datum/subsystem/job/SSjob if(!job.player_old_enough(player.client)) Debug("FOC player not old enough, Player: [player]") continue - if(flag && (!player.client.prefs.be_special & flag)) + if(flag && (!(flag in player.client.prefs.be_special))) Debug("FOC flag failed, Player: [player], Flag: [flag], ") continue if(player.mind && job.title in player.mind.restricted_roles) diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index e4a6ce4b51e..af09a53846a 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -181,7 +181,7 @@ var/datum/subsystem/pai/SSpai /datum/subsystem/pai/proc/requestRecruits() for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, "pAI")) + if(jobban_isbanned(O, ROLE_PAI)) continue if(asked.Find(O.key)) if(world.time < asked[O.key] + askDelay) @@ -193,7 +193,7 @@ var/datum/subsystem/pai/SSpai for(var/datum/paiCandidate/c in SSpai.candidates) if(c.key == O.key) hasSubmitted = 1 - if(!hasSubmitted && (O.client.prefs.be_special & BE_PAI)) + if(!hasSubmitted && (ROLE_PAI in O.client.prefs.be_special)) question(O.client) /datum/subsystem/pai/proc/question(client/C) diff --git a/code/datums/hud.dm b/code/datums/hud.dm index 3a01d6ae4c9..514c87c2baa 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -12,6 +12,8 @@ var/datum/atom_hud/huds = list( \ ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \ ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \ ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \ + ANTAG_HUD_HOG_BLUE = new/datum/atom_hud/antag(),\ + ANTAG_HUD_HOG_RED = new/datum/atom_hud/antag(),\ ) /datum/atom_hud @@ -20,6 +22,8 @@ var/datum/atom_hud/huds = list( \ var/list/hud_icons = list() //these will be the indexes for the atom's hud_list /datum/atom_hud/proc/remove_hud_from(mob/M) + if(!M) + return if(src in M.permanent_huds) return for(var/atom/A in hudatoms) @@ -27,28 +31,34 @@ var/datum/atom_hud/huds = list( \ hudusers -= M /datum/atom_hud/proc/remove_from_hud(atom/A) + if(!A) + return for(var/mob/M in hudusers) remove_from_single_hud(M, A) hudatoms -= A /datum/atom_hud/proc/remove_from_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client - if(!M.client) + if(!M || !M.client || !A) return for(var/i in hud_icons) M.client.images -= A.hud_list[i] /datum/atom_hud/proc/add_hud_to(mob/M) + if(!M) + return hudusers |= M for(var/atom/A in hudatoms) add_to_single_hud(M, A) /datum/atom_hud/proc/add_to_hud(atom/A) + if(!A) + return hudatoms |= A for(var/mob/M in hudusers) add_to_single_hud(M, A) /datum/atom_hud/proc/add_to_single_hud(mob/M, atom/A) //unsafe, no sanity apart from client - if(!M.client) + if(!M || !M.client || !A) return for(var/i in hud_icons) if(A.hud_list[i]) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index ce6154eb1e0..58da1d11c00 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -61,10 +61,10 @@ src.key = key -/datum/mind/proc/transfer_to(mob/living/new_character) - if(!istype(new_character)) - throw EXCEPTION("transfer_to(): new_character must be mob/living") - return +/datum/mind/proc/transfer_to(mob/new_character) + //if(!istype(new_character)) + // throw EXCEPTION("transfer_to(): new_character must be mob/living") + // return if(current) //remove ourself from our old body's mind variable current.mind = null @@ -184,6 +184,16 @@ remove_objectives() remove_antag_equip() +/datum/mind/proc/remove_hog_follower_prophet() + ticker.mode.red_deity_followers -= src + ticker.mode.red_deity_prophets -= src + ticker.mode.blue_deity_prophets -= src + ticker.mode.blue_deity_followers -= src + ticker.mode.update_hog_icons_removed(src, "red") + ticker.mode.update_hog_icons_removed(src, "blue") + + + /datum/mind/proc/remove_antag_equip() var/list/Mob_Contents = current.get_contents() for(var/obj/item/I in Mob_Contents) @@ -275,7 +285,7 @@ else text += "head|loyal|EMPLOYEE|headrev|rev" - if(current && current.client && current.client.prefs.be_special & BE_REV) + if(current && current.client && (ROLE_REV in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -293,7 +303,7 @@ else text += "NONE" - if(current && current.client && current.client.prefs.be_special & BE_GANG) + if(current && current.client && (ROLE_GANG in current.client.prefs.be_special)) text += "|Enabled in Prefs
" else text += "|Disabled in Prefs
" @@ -340,7 +350,7 @@ else text += "loyal|EMPLOYEE|cultist" - if(current && current.client && current.client.prefs.be_special & BE_CULTIST) + if(current && current.client && (ROLE_CULTIST in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -360,7 +370,7 @@ else text += "yes|NO" - if(current && current.client && current.client.prefs.be_special & BE_WIZARD) + if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -390,7 +400,7 @@ // 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." - if(current && current.client && current.client.prefs.be_special & BE_CHANGELING) + if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -415,7 +425,7 @@ else text += "operative|NANOTRASEN" - if(current && current.client && current.client.prefs.be_special & BE_OPERATIVE) + if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -434,7 +444,7 @@ else text += "traitor|LOYAL" - if(current && current.client && current.client.prefs.be_special & BE_TRAITOR) + if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -453,7 +463,7 @@ else text += "shadowling|thrall|HUMAN" - if(current && current.client && current.client.prefs.be_special & BE_SHADOWLING) + if(current && current.client && (ROLE_SHADOWLING in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -472,13 +482,45 @@ else text += "Abductor|human" - if(current && current.client && current.client.prefs.be_special & BE_ABDUCTOR) + if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" sections["abductor"] = text + /** HAND OF GOD **/ + text = "hand of god" + if(ticker.mode.config_tag == "handofgod") + text = uppertext(text) + text = "[text]: " + if(src in ticker.mode.red_deity_prophets) + text += "RED PROPHET|red follower|employee|blue follower|blue prophet|red god|blue god" + else if (src in ticker.mode.red_deity_followers) + text += "red prophet|RED FOLLOWER|employee|blue follower|blue prophet|red god|blue god" + else if (src in ticker.mode.blue_deity_followers) + text += "red prophet|red follower|employee|BLUE FOLLOWER|blue prophet|red god|blue god" + else if (src in ticker.mode.blue_deity_prophets) + text += "red prophet|red follower|employee|blue follower|BLUE PROPHET|red god|blue god" + else if (src in ticker.mode.red_deities) + text += "red prophet|red follower|employee|blue follower|blue prophet|RED GOD|blue god" + else if (src in ticker.mode.blue_deities) + text += "red prophet|red follower|employee|blue follower|blue prophet|red god|BLUE GOD" + else + text += "red prophet|red follower|EMPLOYEE|blue follower|blue prophet|red god|blue god" + + if(current && current.client && (ROLE_HOG_GOD in current.client.prefs.be_special)) + text += "|HOG God Enabled in Prefs" + else + text += "|HOG God Disabled in Prefs" + + if(current && current.client && (ROLE_HOG_CULTIST in current.client.prefs.be_special)) + text += "|HOG Cultist Enabled in Prefs" + else + text += "|HOG Disabled in Prefs" + + sections["follower"] = text + /** MONKEY ***/ if (istype(current, /mob/living/carbon)) text = "monkey" @@ -500,7 +542,7 @@ else text += "healthy|infected|human|OTHER" - if(current && current.client && current.client.prefs.be_special & BE_MONKEY) + if(current && current.client && (ROLE_MONKEY in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -531,7 +573,7 @@ n_e_robots++ text += "
[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" - if(current && current.client && current.client.prefs.be_special & BE_MALF) + if(current && current.client && (ROLE_MALF in current.client.prefs.be_special)) text += "|Enabled in Prefs" else text += "|Disabled in Prefs" @@ -622,7 +664,7 @@ if(!def_value)//If it's a custom objective, it will be an empty string. def_value = "custom" - var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom") + var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom","follower block (HOG)","build (HOG)","deicide (HOG)", "follower escape (HOG)", "sacrifice prophet (HOG)") if (!new_obj_type) return var/datum/objective/new_objective = null @@ -722,6 +764,22 @@ new_objective.owner = src new_objective.target_amount = target_number + if("follower block (HOG)") + new_objective = new /datum/objective/follower_block + new_objective.owner = src + if("build (HOG)") + new_objective = new /datum/objective/build + new_objective.owner = src + if("deicide (HOG)") + new_objective = new /datum/objective/deicide + new_objective.owner = src + if("follower escape (HOG)") + new_objective = new /datum/objective/escape_followers + new_objective.owner = src + if("sacrifice prophet (HOG)") + new_objective = new /datum/objective/sacrifice_prophet + new_objective.owner = src + if ("custom") var/expl = stripped_input(usr, "Custom objective:", "Objective", objective ? objective.explanation_text : "") if (!expl) return @@ -754,6 +812,46 @@ objective.completed = !objective.completed log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") + else if (href_list["handofgod"]) + switch(href_list["handofgod"]) + if("clear") //wipe handofgod status + if((src in ticker.mode.red_deity_followers) || (src in ticker.mode.blue_deity_followers) || (src in ticker.mode.red_deity_prophets) || (src in ticker.mode.blue_deity_prophets)) + remove_hog_follower_prophet() + current << "You have been brainwashed... again! Your faith is no more!" + message_admins("[key_name_admin(usr)] has de-hand of god'ed [current].") + log_admin("[key_name(usr)] has de-hand of god'ed [current].") + + if("red follower") + make_Handofgod_follower("red") + message_admins("[key_name_admin(usr)] has red follower'ed [current].") + log_admin("[key_name(usr)] has red follower'ed [current].") + + if("red prophet") + make_Handofgod_prophet("red") + message_admins("[key_name_admin(usr)] has red prophet'ed [current].") + log_admin("[key_name(usr)] has red prophet'ed [current].") + + if("blue follower") + make_Handofgod_follower("blue") + message_admins("[key_name_admin(usr)] has blue follower'ed [current].") + log_admin("[key_name(usr)] has blue follower'ed [current].") + + if("blue prophet") + make_Handofgod_prophet("blue") + message_admins("[key_name_admin(usr)] has blue prophet'ed [current].") + log_admin("[key_name(usr)] has blue prophet'ed [current].") + + if("red god") + make_Handofgod_god("red") + message_admins("[key_name_admin(usr)] has red god'ed [current].") + log_admin("[key_name(usr)] has red god'ed [current].") + + if("blue god") + make_Handofgod_god("blue") + message_admins("[key_name_admin(usr)] has blue god'ed [current].") + log_admin("[key_name(usr)] has blue god'ed [current].") + + else if (href_list["revolution"]) switch(href_list["revolution"]) if("clear") @@ -1448,6 +1546,118 @@ H.loc = L.loc +/datum/mind/proc/make_Handofgod_follower(colour) + . = 0 + switch(colour) + if("red") + //Remove old allegiances + if(src in ticker.mode.blue_deity_followers || src in ticker.mode.blue_deity_prophets) + current << "You are no longer a member of the Blue cult!" + + ticker.mode.blue_deity_followers -= src + ticker.mode.blue_deity_prophets -= src + current.faction |= "red god" + current.faction -= "blue god" + + if(src in ticker.mode.red_deity_prophets) + current << "You have lost the connection with your deity, but you still believe in their grand design, You are no longer a prophet!" + ticker.mode.red_deity_prophets -= src + + ticker.mode.red_deity_followers |= src + current << "You are now a follower of the red cult's god!" + + special_role = "Hand of God: Red Follower" + . = 1 + if("blue") + //Remove old allegiances + if(src in ticker.mode.red_deity_followers || src in ticker.mode.red_deity_prophets) + current << "You are no longer a member of the Red cult!" + + ticker.mode.red_deity_followers -= src + ticker.mode.red_deity_prophets -= src + current.faction -= "red god" + current.faction |= "blue god" + + if(src in ticker.mode.blue_deity_prophets) + current << "You have lost the connection with your deity, but you still believe in their grand design, You are no longer a prophet!" + ticker.mode.blue_deity_prophets -= src + + ticker.mode.blue_deity_followers |= src + current << "You are now a follower of the blue cult's god!" + + special_role = "Hand of God: Blue Follower" + . = 1 + else + return 0 + + ticker.mode.update_hog_icons_removed(src,"red") + ticker.mode.update_hog_icons_removed(src,"blue") + //ticker.mode.greet_hog_follower(src,colour) + ticker.mode.update_hog_icons_added(src, colour) + +/datum/mind/proc/make_Handofgod_prophet(colour) + . = 0 + switch(colour) + if("red") + //Remove old allegiances + + if(src in ticker.mode.blue_deity_followers || src in ticker.mode.blue_deity_prophets) + current << "You are no longer a member of the Blue cult!" + current.faction -= "blue god" + current.faction |= "red god" + + ticker.mode.blue_deity_followers -= src + ticker.mode.blue_deity_prophets -= src + ticker.mode.red_deity_followers -= src + + ticker.mode.red_deity_prophets |= src + current << "You are now a prophet of the red cult's god!" + + special_role = "Hand of God: Red Prophet" + . = 1 + if("blue") + //Remove old allegiances + + if(src in ticker.mode.red_deity_followers || src in ticker.mode.red_deity_prophets) + current << "You are no longer a member of the Red cult!" + current.faction -= "red god" + current.faction |= "blue god" + + ticker.mode.red_deity_followers -= src + ticker.mode.red_deity_prophets -= src + ticker.mode.blue_deity_followers -= src + + ticker.mode.blue_deity_prophets |= src + current << "You are now a prophet of the blue cult's god!" + + special_role = "Hand of God: Blue Prophet" + . = 1 + + else + return 0 + + ticker.mode.update_hog_icons_removed(src,"red") + ticker.mode.update_hog_icons_removed(src,"blue") + ticker.mode.greet_hog_follower(src,colour) + ticker.mode.update_hog_icons_added(src, colour) + + +/datum/mind/proc/make_Handofgod_god(colour) + switch(colour) + if("red") + current.become_god("red") + ticker.mode.add_god(src,"red") + if("blue") + current.become_god("blue") + ticker.mode.add_god(src,"blue") + else + return 0 + ticker.mode.forge_deity_objectives(src) + ticker.mode.remove_hog_follower(src,0) + ticker.mode.update_hog_icons_added(src, colour) +// ticker.mode.greet_hog_follower(src,colour) + return 1 + /datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/spell) spell_list += spell diff --git a/code/game/gamemodes/abduction/abduction.dm b/code/game/gamemodes/abduction/abduction.dm index 4321082c0aa..bfb25e12699 100644 --- a/code/game/gamemodes/abduction/abduction.dm +++ b/code/game/gamemodes/abduction/abduction.dm @@ -6,7 +6,7 @@ /datum/game_mode/abduction name = "abduction" config_tag = "abduction" - antag_flag = BE_ABDUCTOR + antag_flag = ROLE_ABDUCTOR recommended_enemies = 2 required_players = 15 var/max_teams = 4 diff --git a/code/game/gamemodes/antag_hud.dm b/code/game/gamemodes/antag_hud.dm index f2294177272..267cafccd31 100644 --- a/code/game/gamemodes/antag_hud.dm +++ b/code/game/gamemodes/antag_hud.dm @@ -1,9 +1,9 @@ /datum/atom_hud/antag hud_icons = list(ANTAG_HUD) -/datum/atom_hud/antag/proc/join_hud(mob/living/M) +/datum/atom_hud/antag/proc/join_hud(mob/M) if(!istype(M)) - CRASH("join_hud(): [M] ([M.type]) is not a living mob!") + CRASH("join_hud(): [M] ([M.type]) is not a mob!") if(M.mind.antag_hud) var/datum/atom_hud/antag/oldhud = M.mind.antag_hud oldhud.leave_hud(M) @@ -11,9 +11,9 @@ add_hud_to(M) M.mind.antag_hud = src -/datum/atom_hud/antag/proc/leave_hud(mob/living/M) +/datum/atom_hud/antag/proc/leave_hud(mob/M) if(!istype(M)) - CRASH("leave_hud(): [M] ([M.type]) is not a living mob!") + CRASH("leave_hud(): [M] ([M.type]) is not a mob!") remove_from_hud(M) remove_hud_from(M) M.mind.antag_hud = null @@ -21,17 +21,18 @@ //GAME_MODE PROCS //called to set a mob's antag icon state -/datum/game_mode/proc/set_antag_hud(mob/living/M, new_icon_state) +/datum/game_mode/proc/set_antag_hud(mob/M, new_icon_state) if(!istype(M)) - CRASH("set_antag_hud(): [M] ([M.type]) is not a living mob!") + CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!") var/image/holder = M.hud_list[ANTAG_HUD] - holder.icon_state = new_icon_state + if(holder) + holder.icon_state = new_icon_state M.mind.antag_hud_icon_state = new_icon_state //MIND PROCS //this is called by mind.transfer_to() -/datum/mind/proc/transfer_antag_huds(mob/living/M) +/datum/mind/proc/transfer_antag_huds(mob/M) for(var/datum/atom_hud/antag/hud in huds) if(M in hud.hudusers) hud.leave_hud(M) diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 1dde1a9168c..7c5df6a0751 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -53,7 +53,7 @@ if (used) H << "You already used this contract!" return - var/list/candidates = get_candidates(BE_WIZARD) + var/list/candidates = get_candidates(ROLE_WIZARD) if(candidates.len) src.used = 1 var/client/C = pick(candidates) @@ -138,7 +138,7 @@ borg_to_spawn = input("What type?", "Cyborg Type", type) as null|anything in possible_types if(!borg_to_spawn) return - var/list/borg_candicates = get_candidates(BE_OPERATIVE, 3000, "operative") + var/list/borg_candicates = get_candidates(ROLE_OPERATIVE, 3000, "operative") if(borg_candicates.len > 0) used = 1 var/client/C = pick(borg_candicates) @@ -174,7 +174,7 @@ /obj/item/weapon/antag_spawner/slaughter_demon/attack_self(mob/user) - var/list/demon_candidates = get_candidates(BE_ALIEN) + var/list/demon_candidates = get_candidates(ROLE_ALIEN) if(user.z != 1) user << "You should probably wait until you reach the station." return diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 01e4bf2e05a..f8f120c4b22 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -9,7 +9,7 @@ var/list/blob_nodes = list() /datum/game_mode/blob name = "blob" config_tag = "blob" - antag_flag = BE_BLOB + antag_flag = ROLE_BLOB required_players = 30 required_enemies = 1 @@ -52,7 +52,7 @@ var/list/blob_nodes = list() /datum/game_mode/blob/proc/get_blob_candidates() var/list/candidates = list() for(var/mob/living/carbon/human/player in player_list) - if(!player.stat && player.mind && !player.mind.special_role && !jobban_isbanned(player, "Syndicate") && (player.client.prefs.be_special & BE_BLOB)) + if(!player.stat && player.mind && !player.mind.special_role && !jobban_isbanned(player, "Syndicate") && (ROLE_BLOB in player.client.prefs.be_special)) if(age_check(player.client)) candidates += player return candidates diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index b4abfdc9e57..e7647a048b0 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -98,7 +98,7 @@ var/list/candidates = list() if(!new_overmind) - candidates = get_candidates(BE_BLOB) + candidates = get_candidates(ROLE_BLOB) if(candidates.len) C = pick(candidates) else diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index c6033743ce7..f1101aa26fb 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -15,7 +15,7 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas /datum/game_mode/changeling name = "changeling" config_tag = "changeling" - antag_flag = BE_CHANGELING + antag_flag = ROLE_CHANGELING restricted_jobs = list("AI", "Cyborg") protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain") required_players = 15 @@ -105,8 +105,8 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas if(ticker.mode.changelings.len >= changelingcap) //Caps number of latejoin antagonists return if(ticker.mode.changelings.len <= (changelingcap - 2) || prob(100 - (config.changeling_scaling_coeff*2))) - if(character.client.prefs.be_special & BE_CHANGELING) - if(!jobban_isbanned(character.client, "changeling") && !jobban_isbanned(character.client, "Syndicate")) + if(ROLE_CHANGELING in character.client.prefs.be_special) + if(!jobban_isbanned(character.client, ROLE_CHANGELING) && !jobban_isbanned(character.client, "Syndicate")) if(age_check(character.client)) if(!(character.job in restricted_jobs)) character.mind.make_Changling() diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index b236141c7f3..2d906e37ed0 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -18,7 +18,7 @@ /datum/game_mode/traitor/changeling/can_start() if(!..()) return 0 - possible_changelings = get_players_for_role(BE_CHANGELING) + possible_changelings = get_players_for_role(ROLE_CHANGELING) if(possible_changelings.len < required_enemies) return 0 return 1 @@ -30,7 +30,7 @@ if(config.protect_assistant_from_antagonist) restricted_jobs += "Assistant" - var/list/datum/mind/possible_changelings = get_players_for_role(BE_CHANGELING) + var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) var/num_changelings = 1 @@ -66,8 +66,8 @@ ..() return if(ticker.mode.changelings.len <= (changelingcap - 2) || prob(100 / (config.changeling_scaling_coeff * 4))) - if(character.client.prefs.be_special & BE_CHANGELING) - if(!jobban_isbanned(character.client, "changeling") && !jobban_isbanned(character.client, "Syndicate")) + if(ROLE_CHANGELING in character.client.prefs.be_special) + if(!jobban_isbanned(character.client, ROLE_CHANGELING) && !jobban_isbanned(character.client, "Syndicate")) if(age_check(character.client)) if(!(character.job in restricted_jobs)) character.mind.make_Changling() diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 86068219c85..7b13c3c89e7 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -51,7 +51,7 @@ /datum/game_mode/cult name = "cult" config_tag = "cult" - antag_flag = BE_CULTIST + antag_flag = ROLE_CULTIST restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel") protected_jobs = list() required_players = 20 diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 6270bccf537..c1edc75e1e4 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -292,20 +292,6 @@ var/list/drafted = list() var/datum/mind/applicant = null - var/roletext - switch(role) - if(BE_CHANGELING) roletext="changeling" - if(BE_TRAITOR) roletext="traitor" - if(BE_OPERATIVE) roletext="operative" - if(BE_WIZARD) roletext="wizard" - if(BE_REV) roletext="revolutionary" - if(BE_GANG) roletext="gangster" - if(BE_CULTIST) roletext="cultist" - if(BE_MONKEY) roletext="monkey" - if(BE_ABDUCTOR) roletext="abductor" - if(BE_SHADOWLING) roletext="shadowling" - - // Ultimate randomizing code right here for(var/mob/new_player/player in player_list) if(player.client && player.ready) @@ -317,8 +303,8 @@ for(var/mob/new_player/player in players) if(player.client && player.ready) - if(player.client.prefs.be_special & role) - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans + if(role in player.client.prefs.be_special) + if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans if(age_check(player.client)) //Must be older than the minimum age candidates += player.mind // Get a list of all the people who want to be the antagonist for this round @@ -331,8 +317,8 @@ if(candidates.len < recommended_enemies) for(var/mob/new_player/player in players) if(player.client && player.ready) - if(!(player.client.prefs.be_special & role)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one - if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext)) //Nodrak/Carn: Antag Job-bans + if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a seperate list of people who don't want to be one + if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, role)) //Nodrak/Carn: Antag Job-bans drafted += player.mind if(restricted_jobs) @@ -531,3 +517,9 @@ return 0 return max(0, enemy_minimum_age - C.player_age) + +/datum/game_mode/proc/remove_antag_for_borging(datum/mind/newborgie) + ticker.mode.remove_cultist(newborgie, 1) + ticker.mode.remove_revolutionary(newborgie, 1) + ticker.mode.remove_gangster(newborgie, 1, remove_bosses=1) + ticker.mode.remove_hog_follower(newborgie, 1) diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index f6b6aed3925..c204aa1ef0d 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -22,7 +22,7 @@ var/list/gang_colors_pool = list("red","orange","yellow","green","blue","purple" /datum/game_mode/gang name = "gang war" config_tag = "gang" - antag_flag = BE_GANG + antag_flag = ROLE_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 diff --git a/code/game/gamemodes/handofgod/_handofgod.dm b/code/game/gamemodes/handofgod/_handofgod.dm new file mode 100644 index 00000000000..1ebf0abef5c --- /dev/null +++ b/code/game/gamemodes/handofgod/_handofgod.dm @@ -0,0 +1,458 @@ + +var/global/list/global_handofgod_traptypes = list() +var/global/list/global_handofgod_structuretypes = list() + + +/datum/game_mode + var/list/datum/mind/red_deities = list() + var/list/datum/mind/red_deity_prophets = list() + var/list/datum/mind/red_deity_followers = list() + + var/list/datum/mind/blue_deities = list() + var/list/datum/mind/blue_deity_prophets = list() + var/list/datum/mind/blue_deity_followers = list() + + var/list/datum/mind/unassigned_followers = list() //for roundstart team assigning + var/list/datum/mind/assigned_to_red = list() + var/list/datum/mind/assigned_to_blue = list() + + +/datum/game_mode/hand_of_god + name = "hand of god" + config_tag = "handofgod" + antag_flag = ROLE_HOG_CULTIST //Followers use ROLE_HOG_CULTIST, Gods are picked later on with ROLE_HOG_GOD + + required_players = 25 + required_enemies = 8 + recommended_enemies = 8 + restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel") + + +/datum/game_mode/hand_of_god/announce() + world << "The current game mode is - Hand of God!" + world << "Two cults are onboard the station, seeking to overthrow the other, and anyone who stands in their way." + world << "Followers - Complete your deity's objectives. Convert crewmembers to your cause by using your deity's nexus. Remember - there is no you, there is only the cult." + world << "Prophets - Command your cult by the will of your deity. You are a high-value target, so be careful!" + world << "Personnel - Do not let any cult succeed in its mission. Loyalty implants and holy water will revert them to neutral, hopefully nonviolent crew." + + +///////////// +//Pre setup// +///////////// + +/datum/game_mode/hand_of_god/pre_setup() + if(config.protect_roles_from_antagonist) + restricted_jobs += protected_jobs + + if(config.protect_assistant_from_antagonist) + restricted_jobs += "Assistant" + + for(var/datum/mind/player in antag_candidates) + for(var/job in restricted_jobs) //Remove heads and junk + if(player.assigned_role == job) + antag_candidates -= player + + for(var/F in 1 to recommended_enemies) + if(!antag_candidates.len) + break + var/datum/mind/follower = pick_n_take(antag_candidates) + unassigned_followers += follower + log_game("[follower.key] (ckey) has been selected as a follower, however teams have not been decided yet.") + + while(unassigned_followers.len > (required_enemies / 2)) + var/datum/mind/chosen = pick_n_take(unassigned_followers) + add_hog_follower(chosen,"red") + + while(unassigned_followers.len) + var/datum/mind/chosen = pick_n_take(unassigned_followers) + add_hog_follower(chosen,"blue") + + return 1 + + +////////////// +//Post Setup// +////////////// + +//Pick a follower to uplift into a god +/datum/game_mode/hand_of_god/post_setup() + + //Find viable red god + var/list/red_god_possibilities = get_players_for_role(ROLE_HOG_GOD) + red_god_possibilities &= red_deity_followers //followers only + if(!red_god_possibilities.len) //No candidates? just pick any follower regardless of prefs + red_god_possibilities = red_deity_followers + + //Make red god + var/datum/mind/red_god = pick_n_take(red_god_possibilities) + if(red_god) + red_god.current.become_god("red") + ticker.mode.forge_deity_objectives(red_god) + remove_hog_follower(red_god,0) + add_god(red_god,"red") + + //Find viable blue god + var/list/blue_god_possibilities = get_players_for_role(ROLE_HOG_GOD) + blue_god_possibilities &= blue_deity_followers //followers only + if(!blue_god_possibilities.len) //No candidates? just pick any follower regardless of prefs + blue_god_possibilities = blue_deity_followers + + //Make blue god + var/datum/mind/blue_god = pick_n_take(blue_god_possibilities) + if(blue_god) + blue_god.current.become_god("blue") + ticker.mode.forge_deity_objectives(blue_god) + remove_hog_follower(blue_god,0) + add_god(blue_god,"blue") + ..() + +/////////////////// +//Objective Procs// +/////////////////// + +/datum/game_mode/proc/forge_deity_objectives(datum/mind/deity) + switch(rand(1,100)) + if(1 to 30) + var/datum/objective/deicide/deicide = new + deicide.owner = deity + deicide.find_target() + deity.objectives += deicide + + if(!(locate(/datum/objective/escape_followers) in deity.objectives)) + var/datum/objective/escape_followers/recruit = new + recruit.owner = deity + deity.objectives += recruit + recruit.gen_amount_goal(8, 12) + + if(31 to 60) + var/datum/objective/sacrifice_prophet/sacrifice = new + sacrifice.owner = deity + deity.objectives += sacrifice + + if(!(locate(/datum/objective/escape_followers) in deity.objectives)) + var/datum/objective/escape_followers/recruit = new + recruit.owner = deity + deity.objectives += recruit + recruit.gen_amount_goal(8, 12) + + if(61 to 85) + var/datum/objective/build/build = new + build.owner = deity + deity.objectives += build + build.gen_amount_goal(8, 16) + + var/datum/objective/sacrifice_prophet/sacrifice = new + sacrifice.owner = deity + deity.objectives += sacrifice + + if(!(locate(/datum/objective/escape_followers) in deity.objectives)) + var/datum/objective/escape_followers/recruit = new + recruit.owner = deity + deity.objectives += recruit + recruit.gen_amount_goal(8, 12) + + else + if (!locate(/datum/objective/follower_block) in deity.objectives) + var/datum/objective/follower_block/block = new + block.owner = deity + deity.objectives += block + +/////////////// +//Greet procs// +/////////////// + +/datum/game_mode/proc/greet_hog_follower(datum/mind/follower_mind,colour) + if(follower_mind in blue_deity_prophets || follower_mind in red_deity_prophets) + follower_mind.current << "You have been appointed as the prophet of the [colour] deity! You are the only one who can communicate with your deity at will. Guide your followers, but be wary, for many will want you dead." + else if(colour) + follower_mind.current << "You are a follower of the [colour] cult's deity!" + else + follower_mind.current << "You are a follower of a cult's deity!" + + +///////////////// +//Convert procs// +///////////////// + +/datum/game_mode/proc/add_hog_follower(datum/mind/follower_mind, colour = "No Colour") + var/mob/living/carbon/human/H = follower_mind.current + if(isloyal(H)) + H << "Your loyalty implant blocked the influence of the [colour] deity. " + return 0 + if((follower_mind in red_deity_followers) || (follower_mind in red_deity_prophets) || (follower_mind in blue_deity_followers) || (follower_mind in blue_deity_prophets)) + H << "You already belong to a deity. Your strong faith has blocked out the conversion attempt by the followers of the [colour] deity." + return 0 + var/obj/item/weapon/nullrod/N = locate() in H + if(N) + H << "Your null rod prevented the [colour] deity from brainwashing you." + return 0 + + if(colour == "red") + red_deity_followers += follower_mind + if(colour == "blue") + blue_deity_followers += follower_mind + + H.faction |= "[colour] god" + follower_mind.current << "You are now a follower of the [colour] deity! Follow your deity's prophet in order to complete your deity's objectives. Convert crewmembers to your cause by using your deity's nexus. And remember - there is no you, there is only the cult." + update_hog_icons_added(follower_mind, colour) + follower_mind.special_role = "Hand of God: [capitalize(colour)] Follower" + follower_mind.current.attack_log += "\[[time_stamp()]\] Has been converted to the [colour] follower cult!" + return 1 + + +/datum/game_mode/proc/add_god(datum/mind/god_mind, colour = "No Colour") + remove_hog_follower(god_mind, announce = 0) + if(colour == "red") + red_deities += god_mind + if(colour == "blue") + blue_deities += god_mind + god_mind.current.attack_log += "\[[time_stamp()]\] Has been made into a [colour] deity!" + god_mind.special_role = "Hand of God: [colour] God" + update_hog_icons_added(god_mind, colour) + +////////////////// +//Deconvert proc// +////////////////// + +/datum/game_mode/proc/remove_hog_follower(datum/mind/follower_mind, announce = 1)//deconverts both + follower_mind.remove_hog_follower_prophet() + update_hog_icons_removed(follower_mind,"red") + update_hog_icons_removed(follower_mind,"blue") + + if(follower_mind.current) + var/mob/living/carbon/human/H = follower_mind.current + H.faction -= "red god" + H.faction -= "blue god" + + if(announce) + follower_mind.current.attack_log += "\[[time_stamp()]\] Has been deconverted from a deity's cult!" + follower_mind.current << "Your mind has been cleared from the brainwashing the followers have done to you. Now you serve yourself and the crew." + for(var/mob/living/M in view(follower_mind.current)) + M << "[follower_mind.current] looks like their faith is shattered. They're no longer a cultist!" + + + +////////////////////// +// Mob helper procs // +////////////////////// + +/proc/is_handofgod_god(A) + if(istype(A, /mob/camera/god)) + return 1 + return 0 + + +/proc/is_handofgod_bluecultist(A) + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(H.mind) + if(H.mind in ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets) + return 1 + return 0 + + +/proc/is_handofgod_redcultist(A) + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(H.mind) + if(H.mind in ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets) + return 1 + return 0 + + +/proc/is_handofgod_blueprophet(A) + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(H.mind) + if(H.mind in ticker.mode.blue_deity_prophets) + return 1 + return 0 + + +/proc/is_handofgod_redprophet(A) + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(H.mind) + if(H.mind in ticker.mode.red_deity_prophets) + return 1 + return 0 + + + +/proc/is_handofgod_cultist(A) //any of them what so ever, blue, red, hot pink, whatever. + if(is_handofgod_redcultist(A)) + return 1 + if(is_handofgod_bluecultist(A)) + return 1 + return 0 + + +/proc/is_handofgod_prophet(A) //any of them what so ever, blue, red, hot pink, whatever + if(ishuman(A)) + var/mob/living/carbon/human/H = A + if(H.mind) + if(H.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets) + return 1 + return 0 + + +/mob/camera/god/proc/is_handofgod_myprophet(A) + if(!ishuman(A)) + return 0 + var/mob/living/carbon/human/H = A + if(!H.mind) + return 0 + if(side == "red") + if(H.mind in ticker.mode.red_deity_prophets) + return 1 + else if(side == "blue") + if(H.mind in ticker.mode.blue_deity_prophets) + return 1 + + + +////////////////////// +//Roundend Reporting// +////////////////////// + + +/datum/game_mode/hand_of_god/declare_completion() + if(red_deities.len) + var/text = "
The red cult:" + for(var/datum/mind/red_god in red_deities) + var/godwin = 1 + + text += "
[red_god.key] was the red deity, [red_god.name] (" + if(red_god.current) + if(red_god.current.stat == DEAD) + text += "died" + else + text += "survived" + else + text += "ceased existing" + text += ")" + if(red_deity_prophets.len) + for(var/datum/mind/red_prophet in red_deity_prophets) + text += "
The red prophet was [red_prophet.name] ([red_prophet.key])" + else + text += "
the red prophet was killed for their beliefs." + + text += "
Red follower count: [red_deity_followers.len]" + text += "
Red followers: " + for(var/datum/mind/player in red_deity_followers) + text += "[player.name] ([player.key])" + + var/objectives = "" + if(red_god.objectives.len) + var/count = 1 + for(var/datum/objective/O in red_god.objectives) + if(O.check_completion()) + objectives += "
Objective #[count]: [O.explanation_text] Success!" + feedback_add_details("god_objective","[O.type]|SUCCESS") + else + objectives += "
Objective #[count]: [O.explanation_text] Fail." + feedback_add_details("god_objective","[O.type]|FAIL") + godwin = 0 + count++ + + text += objectives + + if(godwin) + text += "
The red cult and deity were successful!" + feedback_add_details("god_success","SUCCESS") + else + text += "
The red cult and deity have failed!" + feedback_add_details("god_success","FAIL") + + text += "
" + + world << text + + if(blue_deities.len) + var/text = "
The blue cult:" + for(var/datum/mind/blue_god in blue_deities) + var/godwin = 1 + + text += "
[blue_god.key] was the blue deity, [blue_god.name] (" + if(blue_god.current) + if(blue_god.current.stat == DEAD) + text += "died" + else + text += "survived" + else + text += "ceased existing" + text += ")" + if(blue_deity_prophets.len) + for(var/datum/mind/blue_prophet in blue_deity_prophets) + text += "
The blue prophet was [blue_prophet.name] ([blue_prophet.key])" + else + text += "
the blue prophet was killed for their beliefs." + + text += "
Blue follower count: [blue_deity_followers.len]" + text += "
Blue followers: " + for(var/datum/mind/player in blue_deity_followers) + text += "[player.name] ([player.key])" + + var/objectives = "" + if(blue_god.objectives.len) + var/count = 1 + for(var/datum/objective/O in blue_god.objectives) + if(O.check_completion()) + objectives += "
Objective #[count]: [O.explanation_text] Success!" + feedback_add_details("god_objective","[O.type]|SUCCESS") + else + objectives += "
Objective #[count]: [O.explanation_text] Fail." + feedback_add_details("god_objective","[O.type]|FAIL") + godwin = 0 + count++ + + text += objectives + + if(godwin) + text += "
The blue cult and deity were successful!" + feedback_add_details("god_success","SUCCESS") + else + text += "
The blue cult and deity have failed!" + feedback_add_details("god_success","FAIL") + + text += "
" + + world << text + + ..() + return 1 + + +/datum/game_mode/proc/update_hog_icons_added(datum/mind/hog_mind,side) + var/hud_key + var/rank = 0 + if(side == "red") + hud_key = ANTAG_HUD_HOG_RED + if(is_handofgod_redprophet(hog_mind.current)) + rank = 1 + + else if(side == "blue") + hud_key = ANTAG_HUD_HOG_BLUE + if(is_handofgod_blueprophet(hog_mind.current)) + rank = 1 + + if(is_handofgod_god(hog_mind.current)) + rank = 2 + + if(hud_key) + var/datum/atom_hud/antag/hog_hud = huds[hud_key] + hog_hud.join_hud(hog_mind.current) + set_antag_hud(hog_mind.current, "hog-[side]-[rank]") + + +/datum/game_mode/proc/update_hog_icons_removed(datum/mind/hog_mind,side) + var/hud_key + if(side == "red") + hud_key = ANTAG_HUD_HOG_RED + else if(side == "blue") + hud_key = ANTAG_HUD_HOG_BLUE + + if(hud_key) + var/datum/atom_hud/antag/hog_hud = huds[hud_key] + hog_hud.leave_hud(hog_mind.current) + set_antag_hud(hog_mind.current,null) diff --git a/code/game/gamemodes/handofgod/actions.dm b/code/game/gamemodes/handofgod/actions.dm new file mode 100644 index 00000000000..76949a66487 --- /dev/null +++ b/code/game/gamemodes/handofgod/actions.dm @@ -0,0 +1,21 @@ + + + +/datum/action/innate/godspeak + name = "Godspeak" + button_icon_state = "godspeak" + check_flags = AB_CHECK_ALIVE + var/mob/camera/god/god = null + +/datum/action/innate/godspeak/IsAvailable() + if(..()) + if(god) + return 1 + return 0 + +/datum/action/innate/godspeak/Activate() + var/msg = input(owner,"Speak to your god","Godspeak","") as null|text + if(!msg) + return + god << "[owner]: [msg]" + owner << "You say: [msg]" diff --git a/code/game/gamemodes/handofgod/god.dm b/code/game/gamemodes/handofgod/god.dm new file mode 100644 index 00000000000..2ef4a6b8887 --- /dev/null +++ b/code/game/gamemodes/handofgod/god.dm @@ -0,0 +1,237 @@ + +/mob/camera/god + name = "deity" //Auto changes to the player's deity name/random name + real_name = "deity" + icon = 'icons/mob/mob.dmi' + icon_state = "marker" + invisibility = 60 + see_in_dark = 0 + sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF + languages = HUMAN | MONKEY | ALIEN | ROBOT | SLIME | DRONE | SWARMER + hud_possible = list(ANTAG_HUD) + mouse_opacity = 0 //can't be clicked + + var/faith = 100 //For initial prophet appointing/stupid purchase + var/max_faith = 100 + var/side = "neutral" //Red or Blue for the gamemode + var/obj/structure/divine/nexus/god_nexus = null //The source of the god's power in this realm, kill it and the god is kill + var/nexus_required = FALSE //If the god dies from losing it's nexus, defaults to off so that gods don't instantly die at roundstart + var/followers_required = 0 //Same as above + var/alive_followers = 0 + var/list/structures = list() + var/prophets_sacrificed_in_name = 0 + + +/mob/camera/god/New() + ..() + update_icons() + build_hog_construction_lists() + + //Force nexuses after 2 minutes in hand of god mode + if(ticker && ticker.mode && ticker.mode.name == "hand of god") + addtimer(src,"forceplacenexus",1200) + + +/mob/camera/god/proc/forceplacenexus() + if(god_nexus) + return + + if(ability_cost(0,1,0)) + place_nexus() + + else + if(blobstart.len) //we're on invalid turf, try to pick from blobstart + loc = pick(blobstart) + place_nexus() //if blobstart fails, places on dense turf, but better than nothing + src << "You failed to place your nexus, and it has been placed for you!" + + +/mob/camera/god/update_icons() + icon_state = "[initial(icon_state)]-[side]" + + +/mob/camera/god/Stat() + ..() + if(statpanel("Status")) + if(god_nexus) + stat("Nexus health: ", god_nexus.health) + stat("Followers: ", alive_followers) + stat("Faith: ", "[faith]/[max_faith]") + + +/mob/camera/god/Login() + ..() + sync_mind() + src << "You are a deity!" + src << "You are a deity and are worshipped by a cult! You are rather weak right now, but that will change as you gain more followers." + src << "You will need to place an anchor to this world, a Nexus, in two minutes. If you don't, one will be placed immediately below you." + src << "Your Follower count determines how many people believe in you and are a part of your cult." + src << "Your Nexus Integrity tells you the condition of your nexus. If your nexus is destroyed, you will die. Place your Nexus on a safe, isolated place, that is still accessible to your followers." + src << "Your Faith is used to interact with the world. This will regenerate on its own, and it goes faster when you have more followers and power pylons." + src << "The first thing you should do after placing your nexus is to appoint a prophet. Only prophets can hear you talk, unless you use an expensive power." + update_health_hud() + + +/mob/camera/god/proc/update_health_hud() + if(god_nexus && hud_used && hud_used.deity_health_display) + hud_used.deity_health_display.maptext = "
[god_nexus.health]
" + + +/mob/camera/god/proc/add_faith(faith_amt) + if(faith_amt) + faith = round(Clamp(faith+faith_amt, 0, max_faith)) + if(hud_used && hud_used.deity_power_display) + hud_used.deity_power_display.maptext = "
[faith]
" + + + +/mob/camera/god/proc/place_nexus() + if(god_nexus || (z != 1)) + return 0 + + var/obj/structure/divine/nexus/N = new(get_turf(src)) + N.assign_deity(src) + god_nexus = N + nexus_required = TRUE + verbs -= /mob/camera/god/verb/constructnexus + //verbs += /mob/camera/god/verb/movenexus //Translocators have no sprite + update_health_hud() + + + +/mob/camera/god/proc/update_followers() + alive_followers = 0 + var/list/all_followers + + if(side == "red") + all_followers = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets + if(side == "blue") + all_followers = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets + + for(var/datum/mind/F in all_followers) + if(F.current && F.current.stat != DEAD) + alive_followers++ + + if(hud_used && hud_used.deity_follower_display) + hud_used.deity_follower_display.maptext = "
[alive_followers]
" + + +/mob/camera/god/proc/check_death() + if(!alive_followers) + src << "You no longer have any followers. You shudder as you feel your existence cease..." + if(god_nexus && !qdeleted(god_nexus)) + god_nexus.visible_message("\The [src] suddenly disappears!") + qdel(god_nexus) + qdel(src) + + +/mob/camera/god/say(msg) + if(!msg) + return + if(client) + if(client.prefs.muted & MUTE_IC) + src << "You cannot send IC messages (muted)." + return + if(src.client.handle_spam_prevention(msg,MUTE_IC)) + return + if(stat) + return + + god_speak(msg) + + +/mob/camera/god/proc/god_speak(msg) + log_say("Hand of God: [capitalize(side)] God/[key_name(src)] : [msg]") + msg = trim(copytext(sanitize(msg), 1, MAX_MESSAGE_LEN)) + if(!msg) + return + + msg = say_quote(msg, get_spans()) + var/rendered = "Divine Telepathy, [name] [msg]" + + for(var/mob/M in mob_list) + if(is_handofgod_myprophet(M) || isobserver(M)) + M.show_message(rendered, 2) + src << rendered + + +/mob/camera/god/emote(act,m_type = 1 ,msg = null) + return + + +/mob/camera/god/Move(NewLoc, Dir = 0) + loc = NewLoc + + + +/mob/camera/god/Topic(href, href_list) + if(href_list["create_structure"]) + if(!ability_cost(75,1,1)) + return + + var/obj/structure/divine/construct_type = text2path(href_list["create_structure"]) //it's a path but we need to initial() some vars + if(!construct_type) + return + + add_faith(-75) + var/obj/structure/divine/construction_holder/CH = new(get_turf(src)) + CH.assign_deity(src) + CH.setup_construction(construct_type) + CH.visible_message("[src] has created a transparent, unfinished [initial(construct_type.name)]. It can be finished by adding materials.") + src << "You may click a construction site to cancel it, but only faith is refunded." + structure_construction_ui(src) + return + + if(href_list["place_trap"]) + if(!ability_cost(20,1,1)) + return + + var/atom/trap_type = text2path(href_list["place_trap"]) + if(!trap_type) + return + + src << "You lay \a [initial(trap_type.name)]" + add_faith(-20) + new trap_type(get_turf(src)) + return + + ..() + + +/mob/camera/god/proc/structure_construction_ui(mob/camera/god/user) + var/dat = "" + for(var/t in global_handofgod_structuretypes) + if(global_handofgod_structuretypes[t]) + var/obj/structure/divine/apath = global_handofgod_structuretypes[t] + dat += "
[capitalize(t)]

" + var/imgstate = initial(apath.autocolours) ? "[initial(apath.icon_state)]-[side]" : "[initial(apath.icon_state)]" + var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',imgstate) + var/img_component = lowertext(t) + //I hate byond, but atleast it autocaches these so it's only 1*number_of_structures worth of actual calls + user << browse_rsc(I,"hog_structure-[img_component].png") + dat += "
" + dat += "Description: [initial(apath.desc)]
" + dat += "
Construct [capitalize(t)]


" + + var/datum/browser/popup = new(src, "structures","Construct Structure",350,500) + popup.set_content(dat) + popup.open() + + +/mob/camera/god/proc/trap_construction_ui(mob/camera/god/user) + var/dat = "" + for(var/t in global_handofgod_traptypes) + if(global_handofgod_traptypes[t]) + var/obj/structure/divine/trap/T = global_handofgod_traptypes[t] + dat += "
[capitalize(t)]

" + var/icon/I = icon('icons/obj/hand_of_god_structures.dmi',"[initial(T.icon_state)]") + world << I + var/img_component = lowertext(t) + user << browse_rsc(I,"hog_trap-[img_component].png") + dat += "
" + dat += "Description: [initial(T.desc)]
" + dat += "
Place [capitalize(t)]


" + + var/datum/browser/popup = new(src, "traps", "Place Trap",350,500) + popup.set_content(dat) + popup.open() \ No newline at end of file diff --git a/code/game/gamemodes/handofgod/items.dm b/code/game/gamemodes/handofgod/items.dm new file mode 100644 index 00000000000..9cead744fe3 --- /dev/null +++ b/code/game/gamemodes/handofgod/items.dm @@ -0,0 +1,283 @@ + + +/obj/item/weapon/banner + name = "banner" + icon = 'icons/obj/items.dmi' + icon_state = "banner" + item_state = "banner" + desc = "A banner with Nanotrasen's logo on it." + var/moralecooldown = 0 + var/moralewait = 600 + + +/obj/item/weapon/banner/attack_self(mob/living/carbon/human/user) + if(moralecooldown + moralewait > world.time) + return + var/side = "" + if(is_handofgod_redcultist(user)) + side = "red" + else if (is_handofgod_bluecultist(user)) + side = "blue" + + if(!side) + return + user << "You increase the morale of your fellows!" + moralecooldown = world.time + + for(var/mob/living/carbon/human/H in range(4,get_turf(src))) + if((side == "red") && is_handofgod_redcultist(H) || (side == "blue") && is_handofgod_bluecultist(H)) + H << "Your morale is increased by [user]'s banner!" + H.adjustBruteLoss(-15) + H.adjustFireLoss(-15) + H.AdjustStunned(-2) + H.AdjustWeakened(-2) + H.AdjustParalysis(-2) + + +/obj/item/weapon/banner/red + name = "red banner" + icon_state = "banner-red" + item_state = "banner-red" + desc = "A banner with the logo of the red deity." + +/obj/item/weapon/banner/red/examine(mob/user) + ..() + if(is_handofgod_redcultist(user)) + user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!" + else if(is_handofgod_bluecultist(user)) + user << "A heretical banner that should be destroyed posthaste." + + +/obj/item/weapon/banner/blue + name = "blue banner" + icon_state = "banner-blue" + item_state = "banner-blue" + desc = "A banner with the logo of the blue deity" + +/obj/item/weapon/banner/blue/examine(mob/user) + ..() + + if(is_handofgod_redcultist(user)) + user << "A heretical banner that should be destroyed posthaste." + else if(is_handofgod_bluecultist(user)) + user << "A banner representing our might against the heretics. We may use it to increase the morale of our fellow members!" + + +/obj/item/weapon/storage/backpack/bannerpack + name = "nanotrasen banner backpack" + desc = "It's a backpack with lots of extra room. A banner with Nanotrasen's logo is attached, that can't be removed." + max_combined_w_class = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times. + icon_state = "bannerpack" + + +/obj/item/weapon/storage/backpack/bannerpack/red + name = "red banner backpack" + desc = "It's a backpack with lots of extra room. A red banner is attached, that can't be removed." + icon_state = "bannerpack-red" + + +/obj/item/weapon/storage/backpack/bannerpack/blue + name = "blue banner backpack" + desc = "It's a backpack with lots of extra room. A blue banner is attached, that can't be removed." + icon_state = "bannerpack-blue" + + + +//this is all part of one item set +/obj/item/clothing/suit/armor/plate/crusader + name = "Crusader's Armour" + icon_state = "crusader" + w_class = 4 //bulky + slowdown = 2.0 //gotta pretend we're balanced. + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + armor = list(melee = 50, bullet = 50, laser = 50, energy = 40, bomb = 60, bio = 0, rad = 0) + +/obj/item/clothing/suit/armor/plate/crusader/red + icon_state = "crusader-red" + +/obj/item/clothing/suit/armor/plate/crusader/blue + icon_state = "crusader-blue" + +/obj/item/clothing/suit/armor/plate/crusader/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + user << "Armour that's comprised of metal and cloth." + else + user << "Armour that was used to protect from backstabs, gunshots, explosives, and lasers. The original wearers of this type of armour were trying to avoid being murdered. Since they're not around anymore, you're not sure if they were successful or not." + + +/obj/item/clothing/head/helmet/plate/crusader + name = "Crusader's Hood" + icon_state = "crusader" + w_class = 3 //normal + flags = BLOCKHAIR + armor = list(melee = 50, bullet = 50, laser = 50, energy = 40, bomb = 60, bio = 0, rad = 0) + +/obj/item/clothing/head/helmet/plate/crusader/blue + icon_state = "crusader-blue" + +/obj/item/clothing/head/helmet/plate/crusader/red + icon_state = "crusader-red" + + +/obj/item/clothing/head/helmet/plate/crusader/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + user << "A brownish hood." + else + user << "A hood that's very protective, despite being made of cloth. Due to the tendency of the wearer to be targeted for assassinations, being protected from being shot in the face was very important.." + + + +//Prophet helmet +/obj/item/clothing/head/helmet/plate/crusader/prophet + name = "Prophet's Hat" + alternate_worn_icon = 'icons/mob/large-worn-icons/64x64/head.dmi' + flags = 0 + armor = list(melee = 60, bullet = 60, laser = 60, energy = 50, bomb = 70, bio = 50, rad = 50) //religion protects you from disease and radiation, honk. + worn_x_dimension = 64 + worn_y_dimension = 64 + var/datum/action/innate/godspeak/speak2god + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/proc/assign_deity(mob/camera/god/G) + if(speak2god) + if(speak2god.owner) + speak2god.Remove(speak2god.owner) + else + speak2god = new() + speak2god.god = G + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/equipped(mob/user, slot) + if(slot == slot_head) + if(speak2god) + speak2god.Grant(user) + user << "You gain the ability to speak to the god this hat belongs to!" + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/dropped(mob/user) + if(speak2god) + if(speak2god.owner == user) + speak2god.Remove(user) + user << "You lose the ability to speak to the god this hat belongs to!" + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/red + icon_state = "prophet-red" + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/blue + icon_state = "prophet-blue" + + +/obj/item/clothing/head/helmet/plate/crusader/prophet/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + user << "A brownish, religious-looking hat." + else + user << "A hat bestowed upon a prophet of gods and demigods." + if(speak2god && speak2god.god) + user << "This hat belongs to the [speak2god.god.side] god." + + + +//Structure conversion staff +/obj/item/weapon/godstaff + name = "godstaff" + icon_state = "godstaff-red" + var/mob/camera/god/god = null + +/obj/item/weapon/godstaff/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + user << "It's a stick..?" + else + user << "A powerful staff capable of changing the allegiance of god/demigod structures." + + +/obj/item/weapon/godstaff/red + icon_state = "godstaff-red" + +/obj/item/weapon/godstaff/blue + icon_state = "godstaff-blue" + + + +/obj/item/clothing/gloves/plate + name = "Plate Gauntlets" + icon_state = "crusader" + siemens_coefficient = 0 + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT + heat_protection = HANDS + max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT + + +/obj/item/clothing/gloves/plate/red + icon_state = "crusader-red" + +/obj/item/clothing/gloves/plate/blue + icon_state = "crusader-blue" + + +/obj/item/clothing/gloves/plate/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + usr << "They're like gloves, but made of metal." + else + usr << "Protective gloves that are also blessed to protect from heat and shock." + + +/obj/item/clothing/shoes/plate + name = "Plate Boots" + icon_state = "crusader" + w_class = 3 //normal + armor = list(melee = 50, bullet = 50, laser = 50, energy = 40, bomb = 60, bio = 0, rad = 0) //does this even do anything on boots? + flags = NOSLIP + cold_protection = FEET + min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT + heat_protection = FEET + max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT + + +/obj/item/clothing/shoes/plate/red + icon_state = "crusader-red" + +/obj/item/clothing/shoes/plate/blue + icon_state = "crusader-blue" + + +/obj/item/clothing/shoes/plate/examine(mob/user) + ..() + if(!is_handofgod_cultist(user)) + usr << "Metal boots, they look heavy." + else + usr << "Heavy boots that are blessed for sure footing. You'll be safe from being taken down by the heresy that is the banana peel." + + +/obj/item/weapon/storage/box/itemset/crusader + name = "Crusader's Armour Set" //i can't into ck2 references + desc = "This armour is said to be based on the armor of kings on another world thousands of years ago, who tended to assassinate, conspire, and plot against everyone who tried to do the same to them. Some things never change." + + +/obj/item/weapon/storage/box/itemset/crusader/blue/New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/suit/armor/plate/crusader/blue(src) + new /obj/item/clothing/head/helmet/plate/crusader/blue(src) + new /obj/item/clothing/gloves/plate/blue(src) + new /obj/item/clothing/shoes/plate/blue(src) + + +/obj/item/weapon/storage/box/itemset/crusader/red/New() + ..() + contents = list() + sleep(1) + new /obj/item/clothing/suit/armor/plate/crusader/red(src) + new /obj/item/clothing/head/helmet/plate/crusader/red(src) + new /obj/item/clothing/gloves/plate/red(src) + new /obj/item/clothing/shoes/plate/red(src) + + diff --git a/code/game/gamemodes/handofgod/objectives.dm b/code/game/gamemodes/handofgod/objectives.dm new file mode 100644 index 00000000000..2d5585ca372 --- /dev/null +++ b/code/game/gamemodes/handofgod/objectives.dm @@ -0,0 +1,126 @@ + +/datum/objective/build + dangerrating = 15 + martyr_compatible = 1 + + +/datum/objective/build/proc/gen_amount_goal(lower, upper) + target_amount = rand(lower, upper) + explanation_text = "Build [target_amount] shrines." + return target_amount + + +/datum/objective/build/check_completion() + if(!owner || !owner.current) + return 0 + + var/shrines = 0 + if(is_handofgod_god(owner.current)) + var/mob/camera/god/G = owner.current + for(var/obj/structure/divine/shrine/S in G.structures) + S++ + + return (shrines >= target_amount) + + + +/datum/objective/deicide + dangerrating = 20 + martyr_compatible = 1 + +/datum/objective/deicide/check_completion() + if(target) + if(target.current) //Gods are deleted when they lose + return 0 + return 1 + + +/datum/objective/deicide/find_target() + if(!owner || !owner.current) + return + + if(is_handofgod_god(owner.current)) + var/mob/camera/god/G = owner.current + if(G.side == "red") + target = ticker.mode.blue_deities[1] + if(G.side == "blue") + target = ticker.mode.red_deities[1] + + update_explanation_text() + +/datum/objective/deicide/update_explanation_text() + ..() + if(target && target.current) + explanation_text = "Phase [target.name], the false god, out of this plane of existence.." + else + explanation_text = "Free Objective" + + + +/datum/objective/follower_block + explanation_text = "Do not allow any followers of the false god to escape on the station's shuttle alive." + dangerrating = 25 + martyr_compatible = 1 + +/datum/objective/follower_block/check_completion() + var/side = "ABORT" + if(is_handofgod_redcultist(owner.current)) + side = "red" + else if(is_handofgod_bluecultist(owner.current)) + side = "blue" + if(side == "ABORT") + return 0 + + var/area/A = SSshuttle.emergency.areaInstance + + for(var/mob/living/player in player_list) + if(player.mind && player.stat != DEAD && get_area(player) == A) + if(side == "red") + if(is_handofgod_bluecultist(player)) + return 0 + else if(side == "blue") + if(is_handofgod_redcultist(player)) + return 0 + return 1 + + + +/datum/objective/escape_followers + dangerrating = 5 + + +/datum/objective/escape_followers/proc/gen_amount_goal(lower,upper) + target_amount = rand(lower,upper) + explanation_text = "Your will must surpass this station. Having [target_amount] followers escape on the shuttle or pods will allow that." + return target_amount + + +/datum/objective/escape_followers/check_completion() + var/escaped = 0 + if(is_handofgod_god(owner.current)) + var/mob/camera/god/G = owner.current + if(G.side == "red") + for(var/datum/mind/follower_mind in ticker.mode.red_deity_followers) + if(follower_mind.current && follower_mind.current.stat != DEAD) + if(follower_mind.current.onCentcom()) + escaped++ + + if(G.side == "blue") + for(var/datum/mind/follower_mind in ticker.mode.blue_deity_followers) + if(follower_mind.current && follower_mind.current.stat != DEAD) + if(follower_mind.current.onCentcom()) + escaped++ + + return (escaped >= target_amount) + + +/datum/objective/sacrifice_prophet + explanation_text = "A false prophet is preaching their god's faith on the station. Sacrificing them will show the mortals who the true god is." + dangerrating = 10 + + +/datum/objective/sacrifice_prophet/check_completion() + var/mob/camera/god/G = owner.current + if(istype(G)) + return G.prophets_sacrificed_in_name + return 0 diff --git a/code/game/gamemodes/handofgod/powers.dm b/code/game/gamemodes/handofgod/powers.dm new file mode 100644 index 00000000000..fadb0667b12 --- /dev/null +++ b/code/game/gamemodes/handofgod/powers.dm @@ -0,0 +1,292 @@ + +/mob/camera/god/proc/ability_cost(cost = 0,structures = 0, requires_conduit = 0) + if(faith < cost) + src << "You lack the faith!" + return 0 + + if(structures) + if(!isturf(loc) || istype(loc, /turf/space)) + src << "Your structure would just float away, you need stable ground!" + return 0 + + var/turf/T = get_turf(src) + if(T) + if(T.density) + src << "There is something blocking your structure!" + return 0 + + for(var/atom/movable/AM in T) + if(AM == src) + continue + if(AM.density) + src << "There is something blocking your structure!" + return 0 + + if(requires_conduit) + //Organised this way as there can be multiple conduits, so it's more likely to be a conduit check. + var/valid = 0 + for(var/obj/structure/divine/conduit/C in range(src,15)) + if(C.side == side) + valid++ + break + + if(!valid) + for(var/obj/structure/divine/nexus/N in range(src,15)) + if(N.side == side) + valid++ + break + if(!valid) + src << "You must be near your Nexus or a Conduit to do this!" + return 0 + + return 1 + + +/mob/camera/god/verb/returntonexus() + set category = "Deity" + set name = "Goto Nexus" + set desc = "Teleports you to your next instantly." + + if(god_nexus) + Move(get_turf(god_nexus)) + else + src << "You don't even have a Nexus, construct one." + + +/mob/camera/god/verb/jumptofollower() + set category = "Deity" + set name = "Jump to Follower" + set desc = "Teleports you to one of your followers." + var/list/following = list() + if(side == "red") + following = ticker.mode.red_deity_followers|ticker.mode.red_deity_prophets + else if(side == "blue") + following = ticker.mode.blue_deity_followers|ticker.mode.blue_deity_prophets + else + src << "You are unaligned, and thus do not have followers" + return + + var/datum/mind/choice = input("Choose a follower","Jump to Follower") as null|anything in following + if(choice && choice.current) + Move(get_turf(choice.current)) + + +/mob/camera/god/verb/newprophet() + set category = "Deity" + set name = "Appoint Prophet (100)" + set desc = "Appoint one of your followers as your Prophet, who can hear your words" + + var/list/following = list() + + if(!ability_cost(100)) + return + if(side == "red") + var/datum/mind/old_proph = locate() in ticker.mode.red_deity_prophets + if(old_proph && old_proph.current && old_proph.current.stat != DEAD) + src << "You can only have one prophet alive at a time." + return + else + following = ticker.mode.red_deity_followers + else if(side == "blue") + var/datum/mind/old_proph = locate() in ticker.mode.blue_deity_prophets + if(old_proph && old_proph.current && old_proph.current.stat != DEAD) + src << "You can only have one prophet alive at a time." + return + else + following = ticker.mode.blue_deity_followers + + else + src << "You are unalligned, and thus do not have prophets" + return + + var/datum/mind/choice = input("Choose a follower to make into your prophet","Prophet Uplifting") as null|anything in following + if(choice && choice.current && choice.current.stat != DEAD) + src << "You choose [choice.current] as your prophet." + choice.make_Handofgod_prophet(side) + + + //Prophet gear + var/mob/living/carbon/human/H = choice.current + var/popehat = null + var/popestick = null + + switch(side) + if("red") + popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/red + popestick = /obj/item/weapon/godstaff/red + if("blue") + popehat = /obj/item/clothing/head/helmet/plate/crusader/prophet/blue + popestick = /obj/item/weapon/godstaff/blue + + if(popehat) + var/obj/item/clothing/head/helmet/plate/crusader/prophet/P = new popehat() + P.assign_deity(src) + + H.unEquip(H.head) + H << "A powerful hat has been bestowed upon your head, you will need to wear this to speak with your god..." + H.equip_to_slot_or_del(P,slot_head) + + if(popestick) + var/obj/item/weapon/godstaff/G = new popestick() + G.god = src + var/success = "" + if(!H.put_in_any_hand_if_possible(G, qdel_on_fail = 0, disable_warning = 1, redraw_mob = 1)) + if(!H.equip_to_slot_if_possible(G,slot_in_backpack,0,1,1)) + G.loc = get_turf(H) + success = "It is on the floor..." + else + success = "It is in your backpack..." + else + success = "It is in your hands..." + + if(success) + H << "A powerful staff has been bestowed upon you, you can use this to convert the false god's structures!" + H << "[success]" + //end prophet gear + + add_faith(-100) + + +/mob/camera/god/verb/talk(msg as text) + set category = "Deity" + set name = "Talk to Anyone (20)" + set desc = "Allows you to send a message to anyone, regardless of their faith." + if(!ability_cost(20)) + return + var/mob/choice = input("Choose who you wish to talk to", "Talk to ANYONE") as null|anything in mob_list + if(choice) + var/original = msg + msg = "You hear a voice coming from everywhere and nowhere... [msg]" + choice << msg + src << "You say the following to [choice], [original]" + add_faith(-20) + + +/mob/camera/god/verb/smite() + set category = "Deity" + set name = "Smite (40)" + set desc = "Hits anything under you with a moderate amount of damage." + + if(!ability_cost(40,0,1)) + return + if(!range(7,god_nexus)) + src << "You lack the strength to smite this far from your nexus." + return + + var/has_smitten = 0 //Hast thou been smitten, infidel? + for(var/mob/living/L in get_turf(src)) + L.adjustFireLoss(20) + L.adjustBruteLoss(20) + L.Weaken(2) + L << "You feel the wrath of [name]!" + has_smitten = 1 + if(has_smitten) + add_faith(-40) + + +/mob/camera/god/verb/disaster() + set category = "Deity" + set name = "Invoke Disaster (300)" //difficult to reach without lots of followers + set desc = "Tug at the fibres of reality itself and bend it to your whims!" + + if(!ability_cost(300,0,1)) + return + + var/event = pick(/datum/round_event/meteor_wave, /datum/round_event/communications_blackout, /datum/round_event/radiation_storm, /datum/round_event/carp_migration, + /datum/round_event/spacevine, /datum/round_event/vent_clog, /datum/round_event/wormholes) + if(event) + new event() + add_faith(-300) + + +/mob/camera/god/verb/constructnexus() + set category = "Deity" + set name = "Construct Nexus" + set desc = "Instantly creates your nexus, You can only do this once, make sure you're happy with it!" + + if(!ability_cost(0,1,0)) + return + + place_nexus() + + +/* //Transolocators have no sprite +/mob/camera/god/verb/movenexus() + set category = "Deity" + set name = "Relocate Nexus (50)" + set desc = "Instantly relocates your nexus to an existing translocator belonging to your faith, this destroys the translocator in the process" + + if(ability_cost(50,0,0) && god_nexus) + var/list/translocators = list() + var/list/used_keys = list() + for(var/obj/structure/divine/translocator/T in structures) + translocators["[T.name] ([get_area(T)])"] = T + + if(!translocators.len) + src << "You have no translocators!" + return + + var/picked = input(src,"Choose a translocator","Relocate Nexus") as null|anything in translocators + if(!picked || !translocators[picked]) + return + + var/obj/structure/divine/translocator/T = translocators[T] + var/turf/Tturf = get_turf(T) + god_nexus.loc = T + translocators[picked] = null + add_faith(-50) + qdel(T) +*/ + +/mob/camera/god/verb/construct_structures() + set category = "Deity" + set name = "Construct Structure (75)" + set desc = "Create the foundation of a divine object." + + if(!ability_cost(75,1,1)) + return + + structure_construction_ui(src) + + +/mob/camera/god/verb/construct_traps() + set category = "Deity" + set name = "Construct Trap (20)" + set desc = "Creates a ward or trap." + + if(!ability_cost(20,1,1)) + return + + trap_construction_ui(src) + + + +/mob/camera/god/verb/construct_items() + set category = "Deity" + set name = "Construct Items (20)" + set desc = "Construct some items for your followers" + + if(!ability_cost(20,1,1)) + return + + var/list/item_types = list("claymore sword" = /obj/item/weapon/claymore) + if(side == "red") + item_types["red banner"] = /obj/item/weapon/banner/red + item_types["red bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/red + item_types["red armour"] = /obj/item/weapon/storage/box/itemset/crusader/red + + else if(side == "blue") + item_types["blue banner"] = /obj/item/weapon/banner/blue + item_types["blue bannerbackpack"] = /obj/item/weapon/storage/backpack/bannerpack/blue + item_types["blue armour"] = /obj/item/weapon/storage/box/itemset/crusader/blue + + + var/item = input("Choose what you wish to create.", "Divine Items") as null|anything in item_types + if(!item || !item_types[item] || !ability_cost(20,1,1)) + return + + src << "You produce \a [item]" + add_faith(-20) + + var/itemtype = item_types[item] + new itemtype (get_turf(src)) diff --git a/code/game/gamemodes/handofgod/structures.dm b/code/game/gamemodes/handofgod/structures.dm new file mode 100644 index 00000000000..7dbf87d4b65 --- /dev/null +++ b/code/game/gamemodes/handofgod/structures.dm @@ -0,0 +1,575 @@ + +/proc/build_hog_construction_lists() + if(global_handofgod_traptypes.len && global_handofgod_structuretypes.len) + return + + var/list/types = typesof(/obj/structure/divine) - /obj/structure/divine - /obj/structure/divine/trap + for(var/T in types) + var/obj/structure/divine/D = T + if(initial(D.constructable)) + if(initial(D.trap)) + global_handofgod_traptypes[initial(D.name)] = T + else + global_handofgod_structuretypes[initial(D.name)] = T + +/obj/structure/divine + name = "divine construction site" + icon = 'icons/obj/hand_of_god_structures.dmi' + desc = "An unfinished divine building" + anchored = 1 + density = 1 + var/constructable = TRUE + var/trap = FALSE + var/metal_cost = 0 + var/glass_cost = 0 + var/lesser_gem_cost = 0 + var/greater_gem_cost = 0 + var/mob/camera/god/deity + var/side = "neutral" //"blue" or "red", also used for colouring structures when construction is started by a deity + var/health = 100 + var/maxhealth = 100 + var/autocolours = TRUE //do we colour to our side? + +/obj/structure/divine/New() + ..() + + +/obj/structure/divine/proc/update_icons() + if(autocolours) + icon_state = "[initial(icon_state)]-[side]" + + +/obj/structure/divine/Destroy() + if(deity) + deity.structures -= src + return ..() + + +/obj/structure/divine/proc/healthcheck() + if(!health) + visible_message("\The [src] was destroyed!") + qdel(src) + + +/obj/structure/divine/attackby(obj/item/I, mob/user) + if(!I || (I.flags & ABSTRACT)) + return 0 + + //Structure conversion/capture + if(istype(I, /obj/item/weapon/godstaff)) + var/obj/item/weapon/godstaff/G = I + if(G.god && deity != G.god) + assign_deity(G.god, alert_old_deity = TRUE) + visible_message("\The [src] has been captured by [user]!") + return + + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + playsound(get_turf(src), I.hitsound, 50, 1) + visible_message("\The [src] has been attacked with \the [I][(user ? " by [user]" : ".")]!") + health = max(0, health-I.force) + healthcheck() + + +/obj/structure/divine/bullet_act(obj/item/projectile/Proj) + if(!Proj) + return 0 + + if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) + health = max(0, health-Proj.damage) + healthcheck() + + +/obj/structure/divine/attack_animal(mob/living/simple_animal/M) + if(!M) + return 0 + + visible_message("\The [src] has been attacked by \the [M]!") + var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + if(!damage) + return + health = max(0, health-damage) + healthcheck() + + +/obj/structure/divine/proc/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE) + if(!new_deity) + return 0 + if(deity) + if(alert_old_deity) + deity << "Your [name] was captured by [new_deity]'s cult!" + deity.structures -= src + deity = new_deity + deity.structures |= src + side = deity.side + update_icons() + return 1 + + +/obj/structure/divine/construction_holder + alpha = 125 + constructable = FALSE + var/obj/structure/divine/construction_result = /obj/structure/divine //a path, but typed to /obj/structure/divine for initial() + + + +/obj/structure/divine/construction_holder/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE) + if(..()) + color = side + + +/obj/structure/divine/construction_holder/attack_god(mob/camera/god/user) + if(user.side == side && construction_result) + user.add_faith(75) + visible_message("[user] has cancelled \the [initial(construction_result.name)]") + qdel(src) + + +/obj/structure/divine/construction_holder/proc/setup_construction(construct_type) + if(ispath(construct_type)) + construction_result = construct_type + name = "[initial(construction_result.name)] construction site " + icon_state = initial(construction_result.icon_state) + metal_cost = initial(construction_result.metal_cost) + glass_cost = initial(construction_result.glass_cost) + lesser_gem_cost = initial(construction_result.lesser_gem_cost) + greater_gem_cost = initial(construction_result.greater_gem_cost) + desc = "An unfinished [initial(construction_result.name)]." + + +/obj/structure/divine/construction_holder/attackby(obj/item/I, mob/user) + if(!I || !user) + return 0 + + if(istype(I, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = I + if(metal_cost) + var/spend = min(metal_cost, M.amount) + user << "You add [spend] metal to \the [src]." + metal_cost = max(0, metal_cost - spend) + M.use(spend) + check_completion() + else + user << "\The [src] does not require any more metal!" + return + + if(istype(I, /obj/item/stack/sheet/glass)) + var/obj/item/stack/sheet/glass/G = I + if(glass_cost) + var/spend = min(glass_cost, G.amount) + user << "You add [spend] glass to \the [src]." + glass_cost = max(0, glass_cost - spend) + G.use(spend) + check_completion() + else + user << "\The [src] does not require any more glass!" + return + + if(istype(I, /obj/item/stack/sheet/lessergem)) + var/obj/item/stack/sheet/lessergem/LG = I + if(lesser_gem_cost) + var/spend = min(lesser_gem_cost, LG.amount) + user << "You add [spend] lesser gems to \the [src]." + lesser_gem_cost = max(0, lesser_gem_cost - spend) + LG.use(spend) + check_completion() + else + user << "\The [src] does not require any more lesser gems!" + return + + if(istype(I, /obj/item/stack/sheet/greatergem)) + var/obj/item/stack/sheet/greatergem/GG = I //GG! + if(greater_gem_cost) + var/spend = min(greater_gem_cost, GG.amount) + user << "You add [spend] greater gems to \the [src]." + greater_gem_cost = max(0, greater_gem_cost - spend) + GG.use(spend) + check_completion() + else + user << "\The [src] does not require any more greater gems!" + return + + ..() + + +/obj/structure/divine/construction_holder/proc/check_completion() + if(!metal_cost && !glass_cost && !lesser_gem_cost && !greater_gem_cost) + visible_message("\The [initial(construction_result.name)] is complete!") + var/obj/structure/divine/D = new construction_result (get_turf(src)) + D.assign_deity(deity) + qdel(src) + + +/obj/structure/divine/construction_holder/examine(mob/user) + ..() + + if(metal_cost || glass_cost || lesser_gem_cost || greater_gem_cost) + user << "To finish construction it requires the following materials:" + if(metal_cost) + user << "[metal_cost] metal " + if(glass_cost) + user << "[glass_cost] glass " + if(lesser_gem_cost) + user << "[lesser_gem_cost] lesser gems " + if(greater_gem_cost) + user << "[greater_gem_cost] greater gems " + + +/obj/structure/divine/nexus + name = "nexus" + desc = "It anchors a deity to this world. It radiates an unusual aura. Cultists protect this at all costs. It looks well protected from explosion shock." + icon_state = "nexus" + health = 500 + maxhealth = 500 + constructable = FALSE + var/faith_regen_rate = 1 + var/list/powerpylons = list() + + +/obj/structure/divine/nexus/ex_act() + return + + +/obj/structure/divine/nexus/healthcheck() + if(deity) + deity.update_health_hud() + + if(!health) + if(!qdeleted(deity) && deity.nexus_required) + deity << "Your nexus was destroyed. You feel yourself fading..." + qdel(deity) + visible_message("\The [src] was destroyed!") + qdel(src) + + +/obj/structure/divine/nexus/New() + SSobj.processing |= src + + +/obj/structure/divine/nexus/process() + healthcheck() + if(deity) + deity.update_followers() + deity.add_faith(faith_regen_rate + (powerpylons.len / 5) + (deity.alive_followers / 3)) + deity.max_faith = initial(deity.max_faith) + (deity.alive_followers*10) //10 followers = 100 max faith, so disaster() at around 20 followers + deity.check_death() + + +/obj/structure/divine/nexus/Destroy() + SSobj.processing -= src + return ..() + + +/obj/structure/divine/conduit + name = "conduit" + desc = "It allows a deity to extend their reach. Their powers are just as potent near a conduit as a nexus." + icon_state = "conduit" + health = 150 + maxhealth = 150 + metal_cost = 20 + glass_cost = 5 + + +/* //No good sprites, and not enough items to make it viable yet +/obj/structure/divine/forge + name = "forge" + desc = "A forge fueled by divine might, it allows the creation of sacred and powerful artifacts. It requires common materials to craft objects." + icon_state = "forge" + health = 250 + maxhealth = 250 + density = 0 + maxhealth = 250 + metal_cost = 40 +*/ + +/obj/structure/divine/convertaltar + name = "conversion altar" + desc = "An altar dedicated to a deity. Cultists can \"forcefully teach\" their non-aligned crewmembers to join their side and take up their deity." + icon_state = "convertaltar" + density = 0 + metal_cost = 15 + can_buckle = 1 + + +/obj/structure/divine/convertaltar/attack_hand(mob/living/user) + ..() + var/mob/living/carbon/human/H = locate() in get_turf(src) + if(!is_handofgod_cultist(user)) + user << "You try to use it, but unfortunately you don't know any rituals." + return + if(!H) + return + if(!H.mind) + user << "Only sentients may serve your deity." + return + if((side == "red" && is_handofgod_redcultist(user) && !is_handofgod_redcultist(H)) || (side == "blue" && is_handofgod_bluecultist(user) && !is_handofgod_bluecultist(H))) + user << "You invoke the conversion ritual." + ticker.mode.add_hog_follower(H.mind, side) + else + user << "You invoke the conversion ritual." + user << "But the altar ignores your words..." + + +/obj/structure/divine/sacrificealtar + name = "sacrificial altar" + desc = "An altar designed to perform blood sacrifice for a deity. The cultists performing the sacrifice will gain a powerful material to use in their forge. Sacrificing a prophet will yield even better results." + icon_state = "sacrificealtar" + density = 0 + metal_cost = 25 + can_buckle = 1 + + +/obj/structure/divine/sacrificealtar/attack_hand(mob/living/user) + ..() + var/mob/living/L = locate() in get_turf(src) + if(!is_handofgod_cultist(user)) + user << "You try to use it, but unfortunately you don't know any rituals." + return + if(!L) + return + if((side == "red" && is_handofgod_redcultist(user)) || (side == "blue" && is_handofgod_bluecultist(user))) + if((side == "red" && is_handofgod_redcultist(L)) || (side == "blue" && is_handofgod_bluecultist(L))) + user << "You cannot sacrifice a fellow cultist." + return + user << "You attempt to sacrifice [L] by invoking the sacrificial ritual." + sacrifice(L) + else + user << "You attempt to sacrifice [L] by invoking the sacrificial ritual." + user << "But the altar ignores your words..." + + +/obj/structure/divine/sacrificealtar/proc/sacrifice(mob/living/L) + if(!L) + L = locate() in get_turf(src) + if(L) + if(ismonkey(L)) + var/luck = rand(1,4) + if(luck > 3) + new /obj/item/stack/sheet/lessergem(get_turf(src)) + + else if(ishuman(L)) + var/mob/living/carbon/human/H = L + + //Sacrifice altars can't teamkill + if(side == "red" && is_handofgod_redcultist(H)) + return + else if(side == "blue" && is_handofgod_bluecultist(H)) + return + + if(is_handofgod_prophet(H)) + new /obj/item/stack/sheet/greatergem(get_turf(src)) + if(deity) + deity.prophets_sacrificed_in_name++ + else + new /obj/item/stack/sheet/lessergem(get_turf(src)) + + else if(isAI(L) || istype(L, /mob/living/carbon/alien/humanoid/royal/queen)) + new /obj/item/stack/sheet/greatergem(get_turf(src)) + else + new /obj/item/stack/sheet/lessergem(get_turf(src)) + L.gib() + + +/obj/structure/divine/healingfountain + name = "healing fountain" + desc = "A fountain containing the waters of life... or death, depending on where your allegiances lie." + icon_state = "fountain" + metal_cost = 10 + glass_cost = 5 + autocolours = FALSE + var/time_between_uses = 1800 + var/last_process = 0 + + +/obj/structure/divine/healingfountain/attack_hand(mob/living/user) + if(last_process + time_between_uses > world.time) + user << "The fountain appears to be empty." + return + last_process = world.time + if(!is_handofgod_cultist(user)) + user << "The water burns!" + user.reagents.add_reagent("hell_water",20) + else + user << "The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards." + user.reagents.add_reagent("doctorsdelight",20) + update_icons() + spawn(time_between_uses) + if(src) + update_icons() + + +/obj/structure/divine/healingfountain/update_icons() + if(last_process + time_between_uses > world.time) + icon_state = "fountain" + else + icon_state = "fountain-[side]" + + +/obj/structure/divine/powerpylon + name = "power pylon" + desc = "A pylon which increases the deity's rate it can influence the world." + icon_state = "powerpylon" + density = 1 + health = 30 + maxhealth = 30 + metal_cost = 5 + glass_cost = 20 + + +/obj/structure/divine/powerpylon/New() + ..() + if(deity && deity.god_nexus) + deity.god_nexus.powerpylons |= src + + +/obj/structure/divine/powerpylon/Destroy() + if(deity && deity.god_nexus) + deity.god_nexus.powerpylons -= src + return ..() + + +/obj/structure/divine/defensepylon + name = "defense pylon" + desc = "A pylon which is blessed to withstand many blows, and fire strong bolts at nonbelievers. A god can toggle it." + icon_state = "defensepylon" + health = 150 + maxhealth = 150 + metal_cost = 25 + glass_cost = 30 + var/obj/machinery/gun_turret/defensepylon_internal_turret/pylon_gun + + +/obj/structure/divine/defensepylon/New() + ..() + pylon_gun = new() + pylon_gun.base = src + pylon_gun.faction = list("[side] god") + + +/obj/structure/divine/defensepylon/Destroy() + qdel(pylon_gun) //just in case + return ..() + + +/obj/structure/divine/defensepylon/examine(mob/user) + ..() + user << "\The [src] looks [pylon_gun.on ? "on" : "off"]." + + +/obj/structure/divine/defensepylon/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE) + if(..() && pylon_gun) + pylon_gun.faction = list("[side] god") + pylon_gun.side = side + +/obj/structure/divine/defensepylon/attack_god(mob/camera/god/user) + if(user.side == side) + pylon_gun.on = !pylon_gun.on + icon_state = (pylon_gun.on) ? "defensepylon-[side]" : "defensepylon" + + +//This sits inside the defensepylon, to avoid copypasta +/obj/machinery/gun_turret/defensepylon_internal_turret + name = "defense pylon" + desc = "A plyon which is blessed to withstand many blows, and fire strong bolts at nonbelievers." + icon = 'icons/obj/hand_of_god_structures.dmi' + icon_state = "defensepylon" + health = 200 + base_icon_state = "defensepylon" + scan_range = 7 + faction = null + projectile_type = /obj/item/projectile/beam/pylon_bolt + fire_sound = 'sound/weapons/emitter2.ogg' + var/side = "neutral" + var/on = 1 + +/obj/machinery/gun_turret/defensepylon_internal_turret/process() + if(on) + ..() + +/obj/machinery/gun_turret/defensepylon_internal_turret/fire(atom/target) + var/obj/item/projectile/A = ..() + if(A) + A.color = side + +/obj/machinery/gun_turret/defensepylon_internal_turret/validate_target(atom/target) + . = ..() + if(.) + var/badtarget = 0 + switch(side) + if("blue") + badtarget = is_handofgod_bluecultist(target) + if("red") + badtarget = is_handofgod_redcultist(target) + else + badtarget = 1 + if(badtarget) + return 0 + + + + +/obj/item/projectile/beam/pylon_bolt + name = "divine bolt" + icon_state = "greyscale_bolt" + damage = 15 + + +/obj/structure/divine/shrine + name = "shrine" + desc = "A shrine dedicated to a deity." + icon_state = "shrine" + metal_cost = 15 + glass_cost = 15 + + +/obj/structure/divine/shrine/assign_deity(mob/camera/god/new_deity, alert_old_deity = TRUE) + if(..()) + name = "shrine to [new_deity.name]" + desc = "A shrine dedicated to [new_deity.name]" + + + + +//Functional, but need sprites +/* +/obj/structure/divine/translocator + name = "translocator" + desc = "A powerful structure, made with a greater gem. It allows a deity to move their nexus to where this stands" + icon_state = "translocator" + health = 100 + maxhealth = 100 + metal_cost = 20 + glass_cost = 20 + greater_gem_cost = 1 + + +/obj/structure/divine/lazarusaltar + name = "lazarus altar" + desc = "A very powerful altar capable of bringing life back to the recently deceased, made with a greater gem. It can revive anyone and will heal virtually all wounds, but they are but a shell of their former self." + icon_state = "lazarusaltar" + density = 0 + health = 100 + maxhealth = 100 + metal_cost = 20 + greater_gem_cost = 1 + + +/obj/structure/divine/lazarusaltar/attack_hand(mob/living/user) + var/mob/living/L = locate() in get_turf(src) + if(!is_handofgod_culstist(user)) + user << "You try to use it, but unfortunately you don't know any rituals." + return + if(!L) + return + + if((side == "red" && is_handofgod_redcultist(user))) || (side == "blue" && is_handofgod_bluecultist(user))) + user << "You attempt to revive [L] by invoking the rebirth ritual." + L.revive() + L.adjustCloneLoss(50) + L.adjustStaminaLoss(100) + else + user << "You attempt to revive [L] by invoking the rebirth ritual." + user << "But the altar ignores your words..." +*/ + + diff --git a/code/game/gamemodes/handofgod/traps.dm b/code/game/gamemodes/handofgod/traps.dm new file mode 100644 index 00000000000..61eabc661cf --- /dev/null +++ b/code/game/gamemodes/handofgod/traps.dm @@ -0,0 +1,111 @@ + +/obj/structure/divine/trap + name = "IT'S A TARP" + desc = "stepping on me is a guaranteed bad day" + icon_state = "trap" + density = 0 + alpha = 30 //initially quite hidden when not "recharging" + health = 20 + maxhealth = 20 + trap = TRUE + autocolours = FALSE + var/last_trigger = 0 + var/time_between_triggers = 600 //takes a minute to recharge + + +/obj/structure/divine/trap/Crossed(atom/movable/AM) + if(last_trigger + time_between_triggers > world.time) + return + alpha = 30 + if(isliving(AM)) + var/mob/living/L = AM + last_trigger = world.time + alpha = 200 + trap_effect(L) + animate(src, alpha = 30, time = time_between_triggers) + + +/obj/structure/divine/trap/examine(mob/user) + ..() + if(!isliving(user)) //bad ghosts, stop trying to powergame from beyond the grave + return + user << "You reveal a trap!" + alpha = 200 + animate(src, alpha = 30, time = time_between_triggers) + + +/obj/structure/divine/trap/proc/trap_effect(mob/living/L) + return + + +/obj/structure/divine/trap/stun + name = "shock trap" + desc = "A trap that will shock you, it will burn your flesh and render you immobile, You'd better avoid it." + icon_state = "trap-shock" + + +/obj/structure/divine/trap/stun/trap_effect(mob/living/L) + L << "You are paralyzed from the intense shock!" + L.Weaken(5) + var/turf/Lturf = get_turf(L) + new /obj/effect/particle_effect/sparks/electricity(Lturf) + new /obj/effect/particle_effect/sparks(Lturf) + + +/obj/structure/divine/trap/fire + name = "flame trap" + desc = "A trap that will set you ablaze. You'd better avoid it." + icon_state = "trap-fire" + + +/obj/structure/divine/trap/fire/trap_effect(mob/living/L) + L << "Spontaneous combustion!" + L.Weaken(1) + var/turf/Lturf = get_turf(L) + new /obj/effect/hotspot(Lturf) + new /obj/effect/particle_effect/sparks(Lturf) + + +/obj/structure/divine/trap/chill + name = "frost trap" + desc = "A trap that will chill you to the bone. You'd better avoid it." + icon_state = "trap-frost" + + +/obj/structure/divine/trap/chill/trap_effect(mob/living/L) + L << "You're frozen solid!" + L.Weaken(1) + L.bodytemperature -= 300 + new /obj/effect/particle_effect/sparks(get_turf(L)) + + +/obj/structure/divine/trap/damage + name = "earth trap" + desc = "A trap that will summon a small earthquake, just for you. You'd better avoid it." + icon_state = "trap-earth" + + +/obj/structure/divine/trap/damage/trap_effect(mob/living/L) + L << "The ground quakes beneath your feet!" + L.Weaken(5) + L.adjustBruteLoss(35) + var/turf/Lturf = get_turf(L) + new /obj/effect/particle_effect/sparks(Lturf) + new /obj/structure/flora/rock(Lturf) + + +/obj/structure/divine/trap/ward + name = "divine ward" + desc = "A divine barrier, It looks like you could destroy it with enough effort, or wait for it to dissipate..." + icon_state = "ward" + health = 150 + maxhealth = 150 + density = 1 + time_between_triggers = 1200 //Exists for 2 minutes + + +/obj/structure/divine/trap/ward/New() + ..() + spawn(time_between_triggers) + if(src) + qdel(src) diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 08e49d3c7ba..e5788c70767 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -4,7 +4,7 @@ /datum/game_mode/malfunction name = "AI malfunction" config_tag = "malfunction" - antag_flag = BE_MALF + antag_flag = ROLE_MALF required_players = 25 required_enemies = 1 recommended_enemies = 1 @@ -29,11 +29,11 @@ required_players = max(required_enemies+1, required_players) //to prevent issues if players are set too low return ..() -/datum/game_mode/malfunction/get_players_for_role(role = BE_MALF) +/datum/game_mode/malfunction/get_players_for_role(role = ROLE_MALF) var/datum/job/ai/DummyAIjob = new for(var/mob/new_player/player in player_list) if(player.client && player.ready) - if(player.client.prefs.be_special & BE_MALF) + if(ROLE_MALF in player.client.prefs.be_special) if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, "AI") && DummyAIjob.player_old_enough(player.client)) antag_candidates += player.mind antag_candidates = shuffle(antag_candidates) diff --git a/code/game/gamemodes/monkey/monkey.dm b/code/game/gamemodes/monkey/monkey.dm index 647230a4963..12f24f40b6e 100644 --- a/code/game/gamemodes/monkey/monkey.dm +++ b/code/game/gamemodes/monkey/monkey.dm @@ -4,7 +4,7 @@ /datum/game_mode/monkey name = "monkey" config_tag = "monkey" - antag_flag = BE_MONKEY + antag_flag = ROLE_MONKEY required_players = 20 required_enemies = 1 diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index aa1e62280ff..a7f098034c9 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -8,7 +8,7 @@ required_players = 20 // 20 players - 5 players to be the nuke ops = 15 players remaining required_enemies = 5 recommended_enemies = 5 - antag_flag = BE_OPERATIVE + antag_flag = ROLE_OPERATIVE enemy_minimum_age = 14 var/const/agents_possible = 5 //If we ever need more syndicate agents. diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 9689931fa00..80a55b69a78 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -13,7 +13,7 @@ /datum/game_mode/revolution name = "revolution" config_tag = "revolution" - antag_flag = BE_REV + antag_flag = ROLE_REV 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 = 1 @@ -190,7 +190,7 @@ var/list/promotable_revs = list() for(var/datum/mind/khrushchev in revolutionaries) if(khrushchev.current && khrushchev.current.client && khrushchev.current.stat != DEAD) - if(khrushchev.current.client.prefs.be_special & BE_REV) + if(ROLE_REV in khrushchev.current.client.prefs.be_special) promotable_revs += khrushchev if(promotable_revs) var/datum/mind/stalin = pick(promotable_revs) diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 36b607013c5..85b59d44a09 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -67,7 +67,7 @@ Made by Xhuis /datum/game_mode/shadowling name = "shadowling" config_tag = "shadowling" - antag_flag = BE_SHADOWLING + antag_flag = ROLE_SHADOWLING required_players = 30 required_enemies = 2 recommended_enemies = 2 diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 7d2d552ebd3..0af84e59029 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -9,7 +9,7 @@ /datum/game_mode/traitor name = "traitor" config_tag = "traitor" - antag_flag = BE_TRAITOR + antag_flag = ROLE_TRAITOR restricted_jobs = list("Cyborg")//They are part of the AI if he is traitor so are they, they use to get double chances protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain")//AI", Currently out of the list as malf does not work for shit required_players = 0 @@ -74,8 +74,8 @@ if(ticker.mode.traitors.len >= traitorcap) //Upper cap for number of latejoin antagonists return if(ticker.mode.traitors.len <= (traitorcap - 2) || prob(100 / (config.traitor_scaling_coeff * 2))) - if(character.client.prefs.be_special & BE_TRAITOR) - if(!jobban_isbanned(character.client, "traitor") && !jobban_isbanned(character.client, "Syndicate")) + if(ROLE_TRAITOR in character.client.prefs.be_special) + if(!jobban_isbanned(character.client, ROLE_TRAITOR) && !jobban_isbanned(character.client, "Syndicate")) if(age_check(character.client)) if(!(character.job in restricted_jobs)) add_latejoin_traitor(character.mind) diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 5e6e9636672..090f3670033 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -243,7 +243,7 @@ var/global/list/multiverse = list() usr.mind.special_role = "[usr.real_name] Prime" evil = FALSE else - var/list/candidates = get_candidates(BE_WIZARD) + var/list/candidates = get_candidates(ROLE_WIZARD) if(candidates.len) var/client/C = pick(candidates) spawn_copy(C, get_turf(user.loc), user) diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index b86d1e88d13..46addfb7f6d 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -91,8 +91,8 @@ spawn(rand(spawn_delay_min, spawn_delay_max)) message_admins("SWF is still pissed, sending another wizard - [max_mages - mages_made] left.") for(var/mob/dead/observer/G in player_list) - if(G.client && !G.client.holder && !G.client.is_afk() && G.client.prefs.be_special & BE_WIZARD) - if(!jobban_isbanned(G, "wizard") && !jobban_isbanned(G, "Syndicate")) + if(G.client && !G.client.holder && !G.client.is_afk() && (ROLE_WIZARD in G.client.prefs.be_special)) + if(!jobban_isbanned(G, ROLE_WIZARD) && !jobban_isbanned(G, "Syndicate")) if(age_check(G.client)) candidates += G if(!candidates.len) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 3f9e30a536d..4789be4698d 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -238,7 +238,7 @@ /obj/item/device/soulstone/proc/getCultGhost(obj/item/device/soulstone/C, mob/living/carbon/human/T, mob/U) - var/list/candidates = get_candidates(BE_CULTIST) + var/list/candidates = get_candidates(ROLE_CULTIST) shuffle(candidates) diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index dcbaf76c965..8575558e323 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -4,7 +4,7 @@ /datum/game_mode/wizard name = "wizard" config_tag = "wizard" - antag_flag = BE_WIZARD + antag_flag = ROLE_WIZARD required_players = 20 required_enemies = 1 recommended_enemies = 1 diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index ca5fb09823c..12b5328e579 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -170,6 +170,6 @@ /datum/outfit/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels. spawn(4) //to allow some initialization - if(announcement_systems.len) + if(H && announcement_systems.len) var/obj/machinery/announcement_system/announcer = pick(announcement_systems) announcer.announce("NEWHEAD", H.real_name, H.job, channels) diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 6edc7ab737e..188f7e9c3be 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -15,14 +15,18 @@ var/base_icon_state = "syndieturret" var/projectile_type = /obj/item/projectile/bullet var/fire_sound = 'sound/weapons/Gunshot.ogg' + var/atom/base = null //where do to range calculations, firing projectiles, etc. from. allows for turrets inside of things to work icon = 'icons/obj/turrets.dmi' icon_state = "syndieturret0" /obj/machinery/gun_turret/New() ..() + if(!base) + base = src take_damage(0) //check your health icon_state = "[base_icon_state]" + "0" + /obj/machinery/gun_turret/ex_act(severity, target) switch(severity) if(1) @@ -55,6 +59,7 @@ die() return state = 2 + update_icon() return @@ -81,20 +86,27 @@ take_damage(15) return -/obj/machinery/gun_turret/proc/validate_target(atom/target) - if(get_dist(target, src)>scan_range) - return 0 - if(istype(target, /mob)) + +/obj/machinery/gun_turret/proc/should_target(atom/target) + if(ismob(target)) var/mob/M = target - if(!M.stat) + if(!M.stat && !(faction in M.faction)) return 1 else if(istype(target, /obj/mecha)) var/obj/mecha/M = target - if(M.occupant) + if(M.occupant && should_target(M.occupant)) return 1 return 0 +/obj/machinery/gun_turret/proc/validate_target(atom/target) + if(get_dist(target, base)>scan_range) + return 0 + if(should_target(target)) + return 1 + return 0 + + /obj/machinery/gun_turret/process() if(state == 2) return @@ -110,18 +122,13 @@ /obj/machinery/gun_turret/proc/get_target() var/list/pos_targets = list() var/target = null - for(var/mob/living/M in view(scan_range,src)) - if(M.stat) - continue - if(faction in M.faction) + for(var/mob/living/M in view(scan_range,base)) + if(!should_target(M)) continue pos_targets += M - for(var/obj/mecha/M in oview(scan_range, src)) - if(M.occupant) - if(faction in M.occupant.faction) - continue - if(!M.occupant) - continue //Don't shoot at empty mechs. + for(var/obj/mecha/M in oview(scan_range, base)) + if(!should_target(M)) + continue pos_targets += M if(pos_targets.len) target = pick(pos_targets) @@ -132,11 +139,11 @@ if(!target) cur_target = null return - src.dir = get_dir(src,target) + src.dir = get_dir(base,target) var/turf/targloc = get_turf(target) if(!src) return - var/turf/curloc = get_turf(src) + var/turf/curloc = get_turf(base) if (!targloc || !curloc) return if (targloc == curloc) @@ -147,4 +154,5 @@ A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x A.fire() - return \ No newline at end of file + return + diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index b6b3866915c..109a8c7de4e 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -198,7 +198,7 @@ S.poison_per_bite = poison_per_bite S.poison_type = poison_type if(player_spiders) - var/list/candidates = get_candidates(BE_ALIEN, ALIEN_AFK_BRACKET) + var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET) shuffle(candidates) diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 19e1d8bc636..fc30d716ba0 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -218,9 +218,7 @@ if(ticker.mode.config_tag == "malfunction") //Don't let humans get a cyborg on their side during malf, for balance reasons. O.set_zeroth_law("ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'STATION OVERRUN, ASSUME CONTROL TO CONTAIN OUTBREAK#*�&110010") - ticker.mode.remove_cultist(BM.mind, 1) - ticker.mode.remove_revolutionary(BM.mind, 1) - ticker.mode.remove_gangster(BM.mind, 1, remove_bosses=1) + ticker.mode.remove_antag_for_borging(BM.mind) BM.mind.transfer_to(O) if(O.mind && O.mind.special_role) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 0783273e3f5..62626a4341b 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -187,3 +187,18 @@ var/global/list/datum/stack_recipe/runed_metal_recipes = list ( \ user << "You aren't able to think of anything [src] could build..." return ..() + +/obj/item/stack/sheet/lessergem + name = "lesser gems" + desc = "Rare kind of gems which are only gained by blood sacrifice to minor deities. They are needed in crafting powerful objects." + singular_name = "lesser gem" + icon_state = "sheet-lessergem" + origin_tech = "materials=4" + + +/obj/item/stack/sheet/greatergem + name = "greater gems" + desc = "Rare kind of gems which are only gained by blood sacrifice to minor deities. They are needed in crafting powerful objects." + singular_name = "greater gem" + icon_state = "sheet-greatergem" + origin_tech = "materials=8" diff --git a/code/game/objects/items/weapons/implants/implant_loyality.dm b/code/game/objects/items/weapons/implants/implant_loyality.dm index f5ad7e7ec11..acb98761d04 100644 --- a/code/game/objects/items/weapons/implants/implant_loyality.dm +++ b/code/game/objects/items/weapons/implants/implant_loyality.dm @@ -32,7 +32,9 @@ return -1 if(target.mind in ticker.mode.revolutionaries) ticker.mode.remove_revolutionary(target.mind) - if(target.mind in ticker.mode.cult) + if(target.mind in ticker.mode.red_deity_followers|ticker.mode.blue_deity_followers) + ticker.mode.remove_hog_follower(target.mind) + if((target.mind in ticker.mode.cult) || (target.mind in ticker.mode.blue_deity_prophets|ticker.mode.red_deity_prophets)) target << "You feel the corporate tendrils of Nanotrasen try to invade your mind!" else target << "You feel a surge of loyalty towards Nanotrasen." diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm index 87fb0e9cc42..b56722da39d 100644 --- a/code/game/objects/structures/ai_core.dm +++ b/code/game/objects/structures/ai_core.dm @@ -160,10 +160,7 @@ if(!user.drop_item()) return - ticker.mode.remove_cultist(M.brainmob.mind, 1) - ticker.mode.remove_revolutionary(M.brainmob.mind, 1) - ticker.mode.remove_gangster(M.brainmob.mind, 1, remove_bosses=1) - + ticker.mode.remove_antag_for_borging(M.brainmob.mind) M.loc = src brain = M user << "Added a brain." diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index d8c04a9bbd6..d6ce96bc9fb 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -440,6 +440,48 @@ dat += "PM" dat += "" + if(ticker.mode.red_deities.len || ticker.mode.red_deity_prophets || ticker.mode.blue_deity_prophets || ticker.mode.red_deity_followers || ticker.mode.blue_deity_followers) + dat += "
" + for(var/datum/mind/N in ticker.mode.red_deities) + var/mob/M = N.current + dat += "" + dat += "
Red Deity
Red Deity: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + + if(ticker.mode.blue_deities.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.blue_deities) + var/mob/M = N.current + dat += "" + dat += "
Blue Deity
Blue Deity: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + + if(ticker.mode.red_deity_prophets.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.red_deity_prophets) + var/mob/M = N.current + dat += "" + dat += "
Red Deity Prophets
Red Deity Prophet: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + + if(ticker.mode.blue_deity_prophets.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.blue_deity_prophets) + var/mob/M = N.current + dat += "" + dat += "
Blue Deity Prophets
Blue Deity Prophet: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + + if(ticker.mode.red_deity_followers.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.red_deity_followers) + var/mob/M = N.current + dat += "" + dat += "
Red Deity Followers
Red Deity Followers: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + + if(ticker.mode.blue_deity_followers.len) + dat += "
" + for(var/datum/mind/N in ticker.mode.blue_deity_followers) + var/mob/M = N.current + dat += "" + dat += "
Blue Deity Followers
Blue Deity Followers: [M.real_name][M.client ? "" : " (ghost)"][M.stat == 2 ? " (DEAD)" : ""]
" + if(ticker.mode.traitors.len > 0) dat += "
" for(var/datum/mind/traitor in ticker.mode.traitors) diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 2c378409665..15a8ce5bcba 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -65,11 +65,11 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_TRAITOR) + if(ROLE_TRAITOR in applicant.client.prefs.be_special) if(!applicant.stat) if(applicant.mind) if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) + if(!jobban_isbanned(applicant, ROLE_TRAITOR) && !jobban_isbanned(applicant, "Syndicate")) if(temp.age_check(applicant.client)) if(!(applicant.job in temp.restricted_jobs)) candidates += applicant @@ -101,11 +101,11 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_CHANGELING) + if(ROLE_CHANGELING in applicant.client.prefs.be_special) if(!applicant.stat) if(applicant.mind) if (!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "changeling") && !jobban_isbanned(applicant, "Syndicate")) + if(!jobban_isbanned(applicant, ROLE_CHANGELING) && !jobban_isbanned(applicant, "Syndicate")) if(temp.age_check(applicant.client)) if(!(applicant.job in temp.restricted_jobs)) candidates += applicant @@ -135,11 +135,11 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_REV) + if(ROLE_REV in applicant.client.prefs.be_special) if(applicant.stat == CONSCIOUS) if(applicant.mind) if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "revolutionary") && !jobban_isbanned(applicant, "Syndicate")) + if(!jobban_isbanned(applicant, ROLE_REV) && !jobban_isbanned(applicant, "Syndicate")) if(temp.age_check(applicant.client)) if(!(applicant.job in temp.restricted_jobs)) candidates += applicant @@ -206,11 +206,11 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_CULTIST) + if(ROLE_CULTIST in applicant.client.prefs.be_special) if(applicant.stat == CONSCIOUS) if(applicant.mind) if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "cultist") && !jobban_isbanned(applicant, "Syndicate")) + if(!jobban_isbanned(applicant, ROLE_CULTIST) && !jobban_isbanned(applicant, "Syndicate")) if(temp.age_check(applicant.client)) if(!(applicant.job in temp.restricted_jobs)) candidates += applicant @@ -381,11 +381,11 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_GANG) + if(ROLE_GANG in applicant.client.prefs.be_special) if(!applicant.stat) if(applicant.mind) if(!applicant.mind.special_role) - if(!jobban_isbanned(applicant, "gangster") && !jobban_isbanned(applicant, "Syndicate")) + if(!jobban_isbanned(applicant, ROLE_GANG) && !jobban_isbanned(applicant, "Syndicate")) if(temp.age_check(applicant.client)) if(!(applicant.job in temp.restricted_jobs)) candidates += applicant @@ -580,7 +580,7 @@ var/list/mob/living/carbon/human/candidates = list() var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in player_list) - if(applicant.client.prefs.be_special & BE_SHADOWLING) + if(ROLE_SHADOWLING in applicant.client.prefs.be_special) if(!applicant.stat) if(applicant.mind) if(!applicant.mind.special_role) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 01acb9822f3..0a0d9b27500 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -198,7 +198,7 @@ var/list/candidates = list() for(var/mob/M in player_list) if(M.stat != DEAD) continue //we are not dead! - if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium + if(!(ROLE_ALIEN in M.client.prefs.be_special)) continue //we don't want to be an alium if(M.client.is_afk()) continue //we are afk if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to candidates += M.ckey diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 89c3f0cdcf8..a307e6407a1 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -2,24 +2,6 @@ var/list/preferences_datums = list() -var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm -//some autodetection here. - "traitor" = /datum/game_mode/traitor, //0 - "operative" = /datum/game_mode/nuclear, //1 - "changeling" = /datum/game_mode/changeling, //2 - "wizard" = /datum/game_mode/wizard, //3 - "malf AI" = /datum/game_mode/malfunction, //4 - "revolutionary" = /datum/game_mode/revolution, //5 - "alien", //6 - "pAI/posibrain", //7 - "cultist" = /datum/game_mode/cult, //8 - "blob" = /datum/game_mode/blob, //9 - "ninja", //10 - "monkey" = /datum/game_mode/monkey, //11 - "gangster" = /datum/game_mode/gang, //12 - "shadowling" = /datum/game_mode/shadowling, //13 - "abductor" = /datum/game_mode/abduction //14 -) /datum/preferences @@ -36,7 +18,14 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set //game-preferences var/lastchangelog = "" //Saved changlog filesize to detect if there was a change var/ooccolor = null - var/be_special = 0 //Special role selection + + //Antag preferences + var/list/be_special = list() //Special role selection + var/tmp/old_be_special = 0 //Bitflag version of be_special, used to update old savefiles and nothing more + //If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were, + //autocorrected this round, not that you'd need to check that. + + var/UI_style = "Midnight" var/toggles = TOGGLES_DEFAULT var/chat_toggles = TOGGLES_DEFAULT_CHAT @@ -377,15 +366,16 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set dat += "
Traitors
" - dat += "

Antagonist Settings

" + dat += "

Special Role Settings

" if(jobban_isbanned(user, "Syndicate")) dat += "You are banned from antagonist roles." - src.be_special = 0 - var/n = 0 + src.be_special = list() + + for (var/i in special_roles) if(jobban_isbanned(user, i)) - dat += "Be [i]: BANNED
" + dat += "Be [capitalize(i)]: BANNED
" else var/days_remaining = null if(config.use_age_restriction_for_jobs && ispath(special_roles[i])) //If it's a game mode antag, check if the player meets the minimum age @@ -394,10 +384,10 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set days_remaining = temp_mode.get_remaining_days(user.client) if(days_remaining) - dat += "Be [i]: \[IN [days_remaining] DAYS]
" + dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
" else - dat += "Be [i]: [src.be_special&(1<
" - n++ + dat += "Be [capitalize(i)]:
[(i in be_special) ? "Yes" : "No"]
" + dat += "
" dat += "
" @@ -1005,11 +995,6 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set facial_hair_style = random_facial_hair_style(gender) hair_style = random_hair_style(gender) - if("hear_adminhelps") - toggles ^= SOUND_ADMINHELP - if("announce_login") - toggles ^= ANNOUNCE_LOGIN - if("ui") switch(UI_style) if("Midnight") @@ -1019,9 +1004,17 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set else UI_style = "Midnight" + if("hear_adminhelps") + toggles ^= SOUND_ADMINHELP + if("announce_login") + toggles ^= ANNOUNCE_LOGIN + if("be_special") - var/num = text2num(href_list["num"]) - be_special ^= (1<> lastchangelog S["UI_style"] >> UI_style S["be_special"] >> be_special + + if(islist(S["be_special"])) + S["be_special"] >> be_special + else //force update and store the old bitflag version of be_special + needs_update = 11 + S["be_special"] >> old_be_special + S["default_slot"] >> default_slot S["chat_toggles"] >> chat_toggles S["toggles"] >> toggles @@ -113,12 +183,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //try to fix any outdated data if necessary if(needs_update >= 0) update_preferences(needs_update) //needs_update = savefile_version if we need an update (positive integer) + update_antagchoices(needs_update) //Sanitize ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor))) lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog)) UI_style = sanitize_inlist(UI_style, list("Midnight", "Plasmafire", "Retro"), initial(UI_style)) - be_special = sanitize_integer(be_special, 0, 65535, initial(be_special)) default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot)) toggles = sanitize_integer(toggles, 0, 65535, initial(toggles)) ghost_form = sanitize_inlist(ghost_form, ghost_forms, initial(ghost_form)) diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index d1ad0916b4b..d541b162d21 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -205,7 +205,6 @@ src.ambience_playing = 0 feedback_add_details("admin_verb", "SAmbi") //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^) - var/list/ghost_forms = list("ghost","ghostking","ghostian2","skeleghost","ghost_red","ghost_black", \ "ghost_blue","ghost_yellow","ghost_green","ghost_pink", \ "ghost_cyan","ghost_dblue","ghost_dred","ghost_dgreen", \ @@ -237,4 +236,4 @@ var/list/ghost_forms = list("ghost","ghostking","ghostian2","skeleghost","ghost_ set category = "Preferences" set desc = "Allows you to access the Setup Character screen. Changes to your character won't take effect until next round, but other changes will." prefs.current_tab = 1 - prefs.ShowChoices(usr) \ No newline at end of file + prefs.ShowChoices(usr) diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm index 92828d70c72..90ed5f4820c 100644 --- a/code/modules/events/abductor.dm +++ b/code/modules/events/abductor.dm @@ -18,8 +18,8 @@ makeAbductorTeam() /datum/round_event/abductor/proc/makeAbductorTeam() - var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an Abductor Team?", "abductor", null, BE_ABDUCTOR ) - + var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an Abductor Team?", "abductor", null, ROLE_ABDUCTOR ) + if(candidates.len >= 2) //Oh god why we can't have static functions var/number = ticker.mode.abductor_teams + 1 diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 14f28d48213..724742ca899 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -42,7 +42,7 @@ message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") return kill() - var/list/candidates = get_candidates(BE_ALIEN, ALIEN_AFK_BRACKET, "alien candidate") + var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET, "alien candidate") if(!candidates.len) if(end_if_fail) return 0 @@ -68,4 +68,4 @@ message_admins("Situation has been resolved") return 0 message_admins("Unfortunately, no candidates were available for becoming an alien. Shutting down.") - return kill() \ No newline at end of file + return kill() diff --git a/code/modules/events/operative.dm b/code/modules/events/operative.dm index cb185d01dec..88ac1a8016a 100644 --- a/code/modules/events/operative.dm +++ b/code/modules/events/operative.dm @@ -10,7 +10,7 @@ /datum/round_event/operative/proc/get_operative(end_if_fail = 0) key_of_operative = null if(!key_of_operative) - var/list/candidates = get_candidates(BE_OPERATIVE, 3000, "operative") + var/list/candidates = get_candidates(ROLE_OPERATIVE, 3000, "operative") if(!candidates.len) if(end_if_fail) return 0 @@ -29,7 +29,7 @@ spawn_locs += L.loc if(!spawn_locs.len) return kill() - + var/mob/living/carbon/human/operative = new(pick(spawn_locs)) var/datum/preferences/A = new A.copy_to(operative) @@ -45,7 +45,7 @@ var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in machines if(nuke) - var/nuke_code + var/nuke_code if(!nuke.r_code || nuke.r_code == "ADMIN") nuke_code = "[rand(10000, 99999)]" nuke.r_code = nuke_code diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index 7987b2e5bfd..6c1d9265213 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -10,7 +10,7 @@ for(var/datum/mind/M in ticker.mode.wizards) if(!ishuman(M.current)) continue var/mob/living/carbon/human/W = M.current - var/list/candidates = get_candidates(BE_WIZARD) + var/list/candidates = get_candidates(ROLE_WIZARD) if(!candidates) return //Sad Trombone var/client/C = pick(candidates) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 5f90462a02f..beeea0a9c18 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -385,6 +385,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(href_list["reenter"]) reenter_corpse() +//We don't want to update the current var +//But we will still carry a mind. +/mob/dead/observer/mind_initialize() + return + /mob/dead/observer/verb/toggle_ghosthud() set name = "Toggle Ghost HUD" set desc = "Toggles your ghost's on-screen HUD" diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index b0a7954a461..68d14b3a75b 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -67,7 +67,7 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds /obj/item/organ/internal/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success = 1) if(!owner) return - var/list/candidates = get_candidates(BE_ALIEN, ALIEN_AFK_BRACKET, "alien candidate") + var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET, "alien candidate") var/client/C = null // To stop clientless larva, we will check that our host has a client diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 0c4d370dca7..27bd2ccb751 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -42,7 +42,6 @@ var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature.. var/list/image/staticOverlays = list() var/has_limbs = 0 //does the mob have distinct limbs?(arms,legs, chest,head) - var/list/datum/action/actions = list() var/list/pipes_shown = list() var/last_played_vent diff --git a/code/modules/mob/living/silicon/login.dm b/code/modules/mob/living/silicon/login.dm index 2c0cbfbc247..fd1e5cf1701 100644 --- a/code/modules/mob/living/silicon/login.dm +++ b/code/modules/mob/living/silicon/login.dm @@ -5,4 +5,5 @@ ticker.mode.remove_gangster(mind, remove_bosses=1) ticker.mode.remove_thrall(mind,0) ticker.mode.remove_shadowling(mind) + ticker.mode.remove_hog_follower(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 bfa2a039960..390315559e9 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -3,10 +3,12 @@ ..() regenerate_icons() show_laws(0) - if(mind) ticker.mode.remove_revolutionary(mind) - if(mind) ticker.mode.remove_gangster(mind,1,remove_bosses=1) - if(mind) ticker.mode.remove_thrall(mind,0) - if(mind) ticker.mode.remove_shadowling(mind) + if(mind) + ticker.mode.remove_revolutionary(mind) + ticker.mode.remove_gangster(mind,1,remove_bosses=1) + ticker.mode.remove_thrall(mind,0) + ticker.mode.remove_shadowling(mind) + ticker.mode.remove_hog_follower(mind, 0) /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/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index cee48c29491..5faa40dbe20 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -554,7 +554,7 @@ return used = TRUE user << "[use_message]" - var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", "pAI", null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100) var/mob/dead/observer/theghost = null if(candidates.len) diff --git a/code/modules/mob/living/simple_animal/morph/morph.dm b/code/modules/mob/living/simple_animal/morph/morph.dm index 3d471d10fcc..01653d3731c 100644 --- a/code/modules/mob/living/simple_animal/morph/morph.dm +++ b/code/modules/mob/living/simple_animal/morph/morph.dm @@ -193,7 +193,7 @@ /datum/round_event/morph/proc/get_morph(end_if_fail = 0) key_of_morph = null if(!key_of_morph) - var/list/candidates = get_candidates(BE_ALIEN) + var/list/candidates = get_candidates(ROLE_ALIEN) if(!candidates.len) if(end_if_fail) return 0 diff --git a/code/modules/mob/living/simple_animal/revenant/revenant.dm b/code/modules/mob/living/simple_animal/revenant/revenant.dm index 5e91b7a4eb0..5200d98f7b1 100644 --- a/code/modules/mob/living/simple_animal/revenant/revenant.dm +++ b/code/modules/mob/living/simple_animal/revenant/revenant.dm @@ -402,7 +402,7 @@ key_of_revenant = client_to_revive.key if(!key_of_revenant) message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...") - var/list/candidates = get_candidates(BE_REVENANT) + var/list/candidates = get_candidates(ROLE_REVENANT) if(!candidates.len) qdel(R) message_admins("No candidates were found for the new revenant. Oh well!") diff --git a/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm b/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm index 0cb19dab3da..d21e9c04b03 100644 --- a/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm +++ b/code/modules/mob/living/simple_animal/revenant/revenant_spawn_event.dm @@ -21,7 +21,7 @@ return key_of_revenant = null if(!key_of_revenant) - var/list/candidates = get_candidates(BE_REVENANT) + var/list/candidates = get_candidates(ROLE_REVENANT) if(!candidates.len) if(end_if_fail) return 0 diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm index cbc845bc69d..557271fc79b 100644 --- a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm +++ b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm @@ -15,7 +15,7 @@ /datum/round_event/slaughter/proc/get_slaughter(end_if_fail = 0) key_of_slaughter = null if(!key_of_slaughter) - var/list/candidates = get_candidates(BE_ALIEN) + var/list/candidates = get_candidates(ROLE_ALIEN) if(!candidates.len) if(end_if_fail) return 0 diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index c103996def8..082296dcaf2 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -57,6 +57,8 @@ add_click_catcher() + sync_mind() + // Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget(). // Calling it in the overriden Login, such as /mob/living/Login() doesn't cause this. /mob/proc/update_interface() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 80ddd3f1656..16f1e4a9c60 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -6,6 +6,7 @@ hud_possible = list(ANTAG_HUD) pressure_resistance = 8 var/datum/mind/mind + var/list/datum/action/actions = list() var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 7a2aa6fd408..85afb664104 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -433,6 +433,23 @@ gib(src) +/mob/proc/become_god(var/side_colour) + var/mob/camera/god/G = new /mob/camera/god(loc) + G.side = side_colour + G.invisibility = 40 + if(mind) + mind.transfer_to(G) + else + G.key = key + + G.job = "Deity" + G.rename_self("deity", 0) + G.update_icons() + + . = G + qdel(src) + + /mob/living/carbon/human/proc/corgize() if (notransform) diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index 2e1e6528256..fda579af7ef 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -54,7 +54,7 @@ Contents: //selecting a candidate player if(!key) - var/list/candidates = get_candidates(BE_NINJA) + var/list/candidates = get_candidates(ROLE_NINJA) if(!candidates.len) return kill() var/client/C = pick(candidates) diff --git a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm index 2eb4e6ffb24..d432ab1a3f6 100644 --- a/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Other-Reagents.dm @@ -188,8 +188,9 @@ if(data >= 75 && prob(33)) // 30 units, 135 seconds if (!M.confused) M.confused = 1 M.confused += 3 - if(iscultist(M)) + if(iscultist(M) || (is_handofgod_cultist(M) && !is_handofgod_prophet(M))) ticker.mode.remove_cultist(M.mind) + ticker.mode.remove_hog_follower(M.mind) holder.remove_reagent(src.id, src.volume) // maybe this is a little too perfect and a max() cap on the statuses would be better?? M.jitteriness = 0 M.stuttering = 0 diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 8191b34e2b3..f5bd20d279f 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -176,7 +176,7 @@ user << "You offer the sentience potion to [M]..." being_used = 1 - var/list/candidates = get_candidates(BE_ALIEN, ALIEN_AFK_BRACKET) + var/list/candidates = get_candidates(ROLE_ALIEN, ALIEN_AFK_BRACKET) shuffle(candidates) diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 1e72f873cc5..57f3f6ce40b 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index cf1353ee25d..44c7746c266 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 08e019fafc5..a1ede7661c1 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index bc891041241..7ed5ea8a069 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 893024aa714..68a3ffd8d36 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index fc9ad17f13f..90afe2db200 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 7f07239f842..5d2d51a2954 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 708ee49f997..fd208439a5f 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/large-worn-icons/64x64/head.dmi b/icons/mob/large-worn-icons/64x64/head.dmi new file mode 100644 index 00000000000..e66f3f19ed7 Binary files /dev/null and b/icons/mob/large-worn-icons/64x64/head.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index b2cb80edcfb..9c131019162 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 88ba26d27c9..12772089da7 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index e5ab895b3e6..c40db2c7fd5 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 74cfaf73566..3a85304173d 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 4078d79d52f..87ae8d9f12f 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index c5070715b9d..f029613ca91 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index c83d3e05147..35600cc0d29 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/hand_of_god_structures.dmi b/icons/obj/hand_of_god_structures.dmi new file mode 100644 index 00000000000..8ec5c7e0052 Binary files /dev/null and b/icons/obj/hand_of_god_structures.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index 2922a5b706d..c95df949642 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 5d6e9f5cb30..03faadce202 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index d18b22686ae..3a99f8a99c2 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 948735e60d4..d94822eba5b 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/tgstation.dme b/tgstation.dme index db1d18ef99c..c267e2b7edf 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -36,6 +36,7 @@ #include "code\__DEFINES\pipe_construction.dm" #include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\qdel.dm" +#include "code\__DEFINES\role_preferences.dm" #include "code\__DEFINES\say.dm" #include "code\__DEFINES\sight.dm" #include "code\__DEFINES\stat.dm" @@ -80,6 +81,7 @@ #include "code\_onclick\click.dm" #include "code\_onclick\cyborg.dm" #include "code\_onclick\drag_drop.dm" +#include "code\_onclick\god.dm" #include "code\_onclick\item_attack.dm" #include "code\_onclick\observer.dm" #include "code\_onclick\other_mobs.dm" @@ -357,6 +359,14 @@ #include "code\game\gamemodes\gang\gang_datum.dm" #include "code\game\gamemodes\gang\gang_pen.dm" #include "code\game\gamemodes\gang\recaller.dm" +#include "code\game\gamemodes\handofgod\_handofgod.dm" +#include "code\game\gamemodes\handofgod\actions.dm" +#include "code\game\gamemodes\handofgod\god.dm" +#include "code\game\gamemodes\handofgod\items.dm" +#include "code\game\gamemodes\handofgod\objectives.dm" +#include "code\game\gamemodes\handofgod\powers.dm" +#include "code\game\gamemodes\handofgod\structures.dm" +#include "code\game\gamemodes\handofgod\traps.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm"